Preparations for Xbox360 wireless support

This commit is contained in:
Ingo Ruhnke 2008-05-01 09:15:40 +02:00
parent b07cf7f2be
commit aeea6bf669
16 changed files with 1001 additions and 271 deletions

306
PROTOCOL Normal file
View file

@ -0,0 +1,306 @@
===========================
[[ Protocol Descriptions ]]
===========================
General:
========
The following was learned through a combination of guessing and
looking at the Windows, MacOSX and Linux Kernel drivers. No gurantee
for correctness.
Use usb_interrupt_read() not usb_bulk_read(), the later one fails with
the Xbox360 guitar.
Xbox:
=====
The A, B, X, Y, black and white buttons on the Xbox pad are 8bit pressure sensitive.
Led: doesn't have LEDs
Rumble: { 0x00, 0x06, 0x00, l, 0x00, b };
^-- length of the message
struct XboxMsg
{
// --------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1;
unsigned int thumb_r :1;
// data[3] ------------------
unsigned int dummy :8;
unsigned int a :8;
unsigned int b :8;
unsigned int x :8;
unsigned int y :8;
unsigned int black :8;
unsigned int white :8;
unsigned int lt :8;
unsigned int rt :8;
// data[6] ------------------
int x1 :16;
int y1 :16;
// data[10] -----------------
int x2 :16;
int y2 :16;
} __attribute__((__packed__));
Xbox360 Controller
==================
The Xbox360 controller doesn't have pressure sensitive A,B,X,Y,LB,RB
buttons like the Xbox controller, only LT and RT are analog.
On first connect the controller sends:
len: 3 data: 0x01 0x03 0x0e
len: 3 data: 0x02 0x03 0x00
len: 3 data: 0x03 0x03 0x03
len: 3 data: 0x08 0x03 0x00
len: 20 data: 0x00 0x14 0x00 0x00 0x00 0x00 0x69 0xed 0x23 0xff 0x6b 0x00 0x15 0x03 0x00 0x00 0x00 0x00 0x00 0x00
len: 20 data: 0x00 0x14 0x00 0x00 0x00 0x00 0xfc 0xec 0x23 0xff 0x6b 0x00 0x15 0x03 0x00 0x00 0x00 0x00 0x00 0x00
The first four lines are unknown (guess: calibration data, serial
number, version number?), but seem to be always the same, the "len: 20" ones are event
data of the following form. The controller sends them two times on
each button press and also two times on first connect.
Commands send to the controller:
--------------------------------
,--------- type of message
v v-- length of message
LED: { 0x01, 0x03, LED_STATUS };
Rumble: { 0x00, 0x08, 0x00, large, small, 0x00, 0x00, 0x00 };
^ ^-- length of the message
`--------- type of message
struct Xbox360Msg
{
// -------------------------
unsigned int type :8; // always 0
unsigned int length :8; // always 0x14
// data[2] ------------------
unsigned int dpad_up :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1;
unsigned int thumb_r :1;
// data[3] ------------------
unsigned int lb :1;
unsigned int rb :1;
unsigned int guide :1;
unsigned int dummy1 :1; // always 0
unsigned int a :1;
unsigned int b :1;
unsigned int x :1;
unsigned int y :1;
// data[4] ------------------
unsigned int lt :8;
unsigned int rt :8;
// data[6] ------------------
int x1 :16;
int y1 :16;
// data[10] -----------------
int x2 :16;
int y2 :16;
// data[14]; ----------------
unsigned int dummy2 :32; // always 0
unsigned int dummy3 :16; // always 0
} __attribute__((__packed__));
Xbox360 Guitar
==============
The Xbox360 Guitar behaves the same as a regular Xbox360 controller
and talks the same protocol just with the meaning of a few buttons and
axis changed. The guitar doesn't have rumble support.
struct Xbox360GuitarMsg
{
// -------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1; // also strum-up
unsigned int dpad_down :1; // also strum-down
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1; // unused
unsigned int thumb_r :1; // unused
// data[3] ------------------
unsigned int orange :1; // 5
unsigned int rb :1; // unused
unsigned int guide :1;
unsigned int dummy1 :1; // unused
unsigned int green :1; // 1, A
unsigned int red :1; // 2, B
unsigned int blue :1; // 4, X
unsigned int yellow :1; // 3, Y
// data[4] ------------------
unsigned int lt :8; // unknown
unsigned int rt :8; // unknown
// data[6] ------------------
int x1 :16; // unused
int y1 :16; // unused
// data[10] -----------------
int whammy :16;
int tilt :16;
// data[14]; ----------------
unsigned int dummy2 :32; // unused
unsigned int dummy3 :16; // unused
} __attribute__((__packed__));
Xbox360 Wireless
================
Endpoint 1: Controller 1
Endpoint 2: Headset 1
Endpoint 3: Controller 1
Endpoint 4: Headset 1
Endpoint 5: Controller 1
Endpoint 6: Headset 1
Endpoint 7: Controller 4
Endpoint 8: Headset 1
v-- typo? might be 0x0c, i.e. length
Rumble: { 0x00, 0x01, 0x0f, 0xc0, 0x00, large, small, 0x00, 0x00, 0x00, 0x00, 0x00 }
^ ^--- ???
+--------- seems the same as in Event Data
LED: { 0x00, 0x00, 0x08, 0x40 + (mode % 0x0e), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
On connection:
--------------
len: 2 data: 0x08 0x80
len: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x1f 0x9f 0x70 0xc9 0x00 0x63 0xb0 0x00 0x05 0x13 0xa7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
len: 29 data: 0x00 0xf8 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Different connection:
---------------------
|||| |||| |||| |||| |||| |||| |||| _________________ Serial?_________ |||| |||| |||| _____ Battery?
29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd[0x55 0x40 0xf0 0x48 0xe4 0x5d 0x10]0x00 0x05 0x13[0x67]0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
len: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x1f 0x9f 0x70 0xc9 0x00 0x63 0xb0 0x00 0x05 0x13 0xe7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
len: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x1f 0x9f 0x70 0xc9 0x00 0x63 0xb0 0x00 0x05 0x13 0xa7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
When the controller connects it sends { 0x08 0x80 } -> 0000'1000 1000'0000
When the headset connects it sends: { 0x08 0xc0 } -> 0000'1000 1100'0000
When nothing is connected: { 0x08 0x00 } -> 0000'1000 0000'0000
Event data:
===========
+-------- always 0
| +---- 0x01 when a event message, 0x00 otherwise (battery status?), also 0xf8 and 0x0f (both on new connection)
| | +--- always 0xf0 (1111'0000)
| | |
| | | +-- length
v v v v v---- normal xbox event message, but one byte shorter + 5x 0x00 padding
len: 29 data: 0x00 0x01 0x00 0xf0 0x00 0x13 0x20 0x00 0x00 0x00 0xc1 0x08 0xc9 0xfc 0x67 0xf4 0xe5 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x01 0x00 0xf0 0x00 0x13 0x00 0x00 0x00 0x00 0xc1 0x08 0xc9 0xfc 0x67 0xf4 0xe5 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Battery Status Msg (maybe):
---------------------------
len: 29 data: 0x00 0xf8 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0xf8 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Battery Full(?):
len: 29 data: 0x00 0x00 0x00 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Controller without doing anything
2 data: 0x08 0x80
29 data: 0x00 0x00 0x00 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
____ battery ?
29 data: 0x00 0x00 0x00 0x13 0xe2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
29 data: 0x00 0x00 0x00 0x13 0xe6 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
29 data: 0x00 0x00 0x00 0x20 0x1d 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
29 data: 0x00 0x00 0x00 0x40 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
29 data: 0x00 0x00 0x00 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x1f 0x9f 0x70 0xc9 0x00 0x63 0xb0 0x00 0x05 0x13 0xe7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
29 data: 0x00 0xf8 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
---------------
len: 29 data: 0x00 0x01 0x00 0xf0 0x00 0x13 0x00 0x00 0x00 0x00 0x94 0xff 0xc0 0x02 0xa6 0x02 0xf0 0xf6 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x01 0x00 0xf0 0x00 0x13 0x00 0x00 0x00 0x00 0x14 0xfd 0xc0 0x02 0xa6 0x02 0xf0 0xf6 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Battery Message?:
len: 29 data: 0x00 0x00 0x00 0x13 0xa2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0x13 0xe2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0x13 0xe6 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// Charging?
len: 29 data: 0x00 0x00 0x00 0x13 0xe0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Unknown:
len: 29 data: 0x00 0xf8 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0x20 0x1d 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0x40 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x00 0x00 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0x01 0x00 0x13 0xa6 0x13 0x00 0x00 0x00 0x00 0xa9 0xfc 0x60 0x01 0x9d 0x00 0x61 0xf7 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - similar to normal event message
Init message
__________________________________ ____
len: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x1f 0x9f 0x70 0xc9 0x00 0x63 0xb0 0x00 0x05 0x13 0xa7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
len: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x1f 0x9f 0x70 0xc9 0x00 0x63 0xb0 0x00 0x05 0x13 0xe7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
C1n: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x55 0x40 0xf0 0x47 0xee 0x1a 0xb0 0x00 0x05 0x13 0xe1 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
C2n: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x55 0x40 0xf0 0x48 0xe4 0x5d 0x10 0x00 0x05 0x13 0xa7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
C3n: 29 data: 0x00 0x0f 0x00 0xf0 0xf0 0xcc 0xfd 0x55 0x40 0xf0 0x47 0x06 0x87 0xc0 0x00 0x05 0x13 0xa7 0x20 0x1d 0x30 0x03 0x40 0x01 0x50 0x01 0xff 0xff 0xff
len: 29 data: 0x00 0xf8 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0xf8 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 28 data: 0x00 0x01 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
# Request power-off?
len: 29 data: 0x00 0xf8 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
len: 29 data: 0x00 0xf8 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
# EOF #

View file

@ -1,12 +1,14 @@
# -*- python -*- # -*- python -*-
env = Environment(CPPFLAGS=["-g", "-O0", "-Wall"], LIBS=["usb"]) env = Environment(CPPFLAGS=["-g", "-O0", "-Wall"], LIBS=["usb"])
env.Program("xboxdrv", ["xboxdrv.cpp", "uinput.cpp"]) env.Program("xboxdrv", ["xboxdrv.cpp", "xboxmsg.cpp", "uinput.cpp"])
env.Program("inputdrv", env.Program("inputdrv",
["inputdrv.cpp", ["inputdrv.cpp",
"xbox360_driver.cpp", "xbox360_driver.cpp",
"evdev_driver.cpp", "evdev_driver.cpp",
"xbox360_usb_thread.cpp", "xbox360_usb_thread.cpp",
"xbox360_controller.cpp",
"xbox360_wireless_controller.cpp",
"control.cpp", "control.cpp",
"abs_to_rel.cpp", "abs_to_rel.cpp",
"abs_to_btn.cpp", "abs_to_btn.cpp",

15
TODO
View file

@ -1,3 +1,16 @@
Easy interface:
===============
--trigger-as-zaxis
--
--buttonmap A:B,B:B,X:X
Controller 1:
Data 2: 0x08 0x80
Controller 2:
Data 2: 0x08 0xc0
* a way to send keyboard combination sequences or more general event sequences * a way to send keyboard combination sequences or more general event sequences
* abs input must be normalized to min/max * abs input must be normalized to min/max
* rel input must be scaleable * rel input must be scaleable
@ -82,7 +95,7 @@ Unknown data: bytes: 3 Data: 0x01 0x03 0x00
// wire: { 0x00, 0x08, 0x00, large, small, 0x00, 0x00, 0x00 }; // wire: { 0x00, 0x08, 0x00, large, small, 0x00, 0x00, 0x00 };
// wireless: { 0x00, 0x01, 0x0f, 0xc0, 0x00, large, small, 0x00, 0x00, 0x00, 0x00, 0x00}; // wireless: { 0x00, 0x01, 0x0f, 0xc0, 0x00, large, small, 0x00, 0x00, 0x00, 0x00, 0x00 };
^^^^ typo? ^^^^ typo?
void Wireless360Controller::SetRumbleMotors(unsigned char large, unsigned char small) void Wireless360Controller::SetRumbleMotors(unsigned char large, unsigned char small)
{ {

View file

@ -22,13 +22,14 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/uinput.h> #include <linux/uinput.h>
#include "xboxmsg.hpp"
#include "uinput.hpp" #include "uinput.hpp"
uInput::uInput(GamepadType type, uInputCfg config_) uInput::uInput(GamepadType type, uInputCfg config_)
: fd(-1), config(config_) : fd(-1), config(config_)
{ {
// Open the input device // Open the input device
char* uinput_filename[] = { "/dev/input/uinput", "/dev/uinput", "/dev/misc/uinput" }; const char* uinput_filename[] = { "/dev/input/uinput", "/dev/uinput", "/dev/misc/uinput" };
const int uinput_filename_count = (sizeof(uinput_filename)/sizeof(char*)); const int uinput_filename_count = (sizeof(uinput_filename)/sizeof(char*));
for (int i = 0; i < uinput_filename_count; ++i) for (int i = 0; i < uinput_filename_count; ++i)

View file

@ -21,6 +21,10 @@
#include "xboxdrv.hpp" #include "xboxdrv.hpp"
class Xbox360Msg;
class Xbox360GuitarMsg;
class XboxMsg;
class uInputCfg class uInputCfg
{ {
public: public:

85
xbox360_controller.cpp Normal file
View file

@ -0,0 +1,85 @@
/* $Id$
** __ __ __ ___ __ __ __ __
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
** \/ \/ \/ \/ \/
** Copyright (C) 2007 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
** 02111-1307, USA.
*/
#include <stdexcept>
#include <sstream>
#include "xboxmsg.hpp"
#include "xbox360_controller.hpp"
Xbox360Controller::Xbox360Controller(struct usb_device* dev,
XPadDevice* dev_type)
{
struct usb_dev_handle* handle = usb_open(dev);
if (!handle)
{
throw std::runtime_error("Error opening Xbox360 controller");
}
else
{
if (usb_claim_interface(handle, 0) != 0) // FIXME: bInterfaceNumber shouldn't be hardcoded
{
throw std::runtime_error("Error couldn't claim the USB interface");
}
}
}
void
Xbox360Controller::set_rumble(uint8_t left, uint8_t right)
{
char rumblecmd[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 };
usb_interrupt_write(handle, 2, rumblecmd, 8, 0);
}
void
Xbox360Controller::set_led(uint8_t status)
{
char ledcmd[] = { 1, 3, status };
usb_interrupt_write(handle, 2, ledcmd, sizeof(ledcmd), 0);
}
void
Xbox360Controller::read(Xbox360Msg& msg)
{
uint8_t data[32];
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/);
if (ret < 0)
{ // Error
std::ostringstream str;
str << "USBError: " << ret << "\n" << usb_strerror();
throw std::runtime_error(str.str());
}
else if (ret == 0)
{
// happens with the Xbox360 controller every now and then, just
// ignore, seems harmless, so just ignore
}
else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14)
{
msg = (Xbox360Msg&)data;
}
}
/* EOF */

56
xbox360_controller.hpp Normal file
View file

@ -0,0 +1,56 @@
/* $Id$
** __ __ __ ___ __ __ __ __
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
** \/ \/ \/ \/ \/
** Copyright (C) 2007 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
** 02111-1307, USA.
*/
#ifndef HEADER_XBOX360_CONTROLLER_HPP
#define HEADER_XBOX360_CONTROLLER_HPP
#include <usb.h>
struct XPadDevice;
/** */
class Xbox360Controller
{
private:
struct usb_device* dev;
XPadDevice* dev_type;
struct usb_dev_handle* handle;
public:
Xbox360Controller(struct usb_device* dev,
XPadDevice* dev_type);
void set_rumble(uint8_t left, uint8_t right);
void set_led(uint8_t status);
void read(Xbox360Msg& msg);
private:
Xbox360Controller (const Xbox360Controller&);
Xbox360Controller& operator= (const Xbox360Controller&);
};
#endif
/* EOF */

View file

@ -29,6 +29,7 @@
#include <iostream> #include <iostream>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include "xboxmsg.hpp"
#include "log.hpp" #include "log.hpp"
#include "xbox360_usb_thread.hpp" #include "xbox360_usb_thread.hpp"
#include "xbox360_driver.hpp" #include "xbox360_driver.hpp"

View file

@ -31,6 +31,7 @@
#include "control.hpp" #include "control.hpp"
class Xbox360UsbThread; class Xbox360UsbThread;
class Xbox360Msg;
/** */ /** */
class Xbox360Driver : public Control class Xbox360Driver : public Control

View file

@ -29,6 +29,7 @@
#include <stdexcept> #include <stdexcept>
#include <boost/format.hpp> #include <boost/format.hpp>
#include "log.hpp" #include "log.hpp"
#include "xboxmsg.hpp"
#include "xbox360_usb_thread.hpp" #include "xbox360_usb_thread.hpp"
Xbox360UsbThread::Xbox360UsbThread(struct usb_device* dev) Xbox360UsbThread::Xbox360UsbThread(struct usb_device* dev)

View file

@ -0,0 +1,139 @@
/* $Id$
** __ __ __ ___ __ __ __ __
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
** \/ \/ \/ \/ \/
** Copyright (C) 2007 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
** 02111-1307, USA.
*/
#include <usb.h>
#include <assert.h>
#include <sstream>
#include <boost/format.hpp>
#include <stdexcept>
#include "xboxmsg.hpp"
#include "xbox360_wireless_controller.hpp"
Xbox360WirelessController::Xbox360WirelessController(struct usb_device* dev,
XPadDevice* dev_type,
int controller_id)
{
assert(controller_id >= 0 && controller_id < 4);
// FIXME: Is hardcoding those ok?
endpoint = controller_id*2 + 1;
interface = controller_id*2;
struct usb_dev_handle* handle = usb_open(dev);
if (!handle)
{
throw std::runtime_error("Xbox360WirelessController: Error opening Xbox360 controller");
}
else
{
if (usb_claim_interface(handle, interface) != 0) // FIXME: bInterfaceNumber shouldn't be hardcoded
{
throw std::runtime_error("Xbox360WirelessController: Error couldn't claim the USB interface");
}
}
}
void
Xbox360WirelessController::set_rumble(uint8_t left, uint8_t right)
{
// +-- typo? might be 0x0c, i.e. length
// v
char rumblecmd[] = { 0x00, 0x01, 0x0f, 0xc0, 0x00, left, right, 0x00, 0x00, 0x00, 0x00, 0x00 };
usb_interrupt_write(handle, endpoint, rumblecmd, sizeof(rumblecmd), 0);
}
void
Xbox360WirelessController::set_led(uint8_t status)
{
// +--- Why not just status?
// v
char ledcmd[] = { 0x00, 0x00, 0x08, 0x40 + (status % 0x0e), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
usb_interrupt_write(handle, endpoint, ledcmd, sizeof(ledcmd), 0);
}
void
Xbox360WirelessController::read(Xbox360Msg& msg)
{
uint8_t data[32];
int ret = usb_interrupt_read(handle, endpoint, (char*)data, sizeof(data), 0 /*Timeout*/);
if (ret < 0)
{ // Error
std::ostringstream str;
str << "USBError: " << ret << "\n" << usb_strerror();
throw std::runtime_error(str.str());
}
else if (ret == 2 && data[0] == 0x08)
{ // Connection Status Message
if (data[1] == 0x00)
{
// nothing connected
}
else if (data[1] == 0x80)
{
// controller connected
}
else if (data[1] == 0x40)
{
// headset connected
}
else if (data[1] == 0xc0)
{
// headset and controller connected
}
else
{
// unknown
}
}
else if (ret == 29) // Event Message
{
if (data[0] == 0x00 && data[1] == 0x0f && data[2] == 0x00 && data[3] == 0xf0)
{ // Initial Announc Message
std::string serial = (boost::format("%x:%x:%x:%x:%x:%x")
% data[7] % data[8] % data[9] % data[10] % data[11] % data[12] % data[13]).str();
battery_status = data[17];
}
else if (data[0] == 0x00 && data[1] == 0x01 && data[2] == 0x00 && data[3] == 0xf0 && data[4] == 0x00 && data[5] == 0x13)
{
msg = *reinterpret_cast<Xbox360Msg*>(&data[6]);
}
else if (data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x00 && data[3] == 0x13)
{ // Battery status
battery_status = data[4];
}
else
{
// unknown/junk
}
}
else
{
// unknown/junk
}
}
/* EOF */

View file

@ -0,0 +1,59 @@
/* $Id$
** __ __ __ ___ __ __ __ __
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
** \/ \/ \/ \/ \/
** Copyright (C) 2007 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
** 02111-1307, USA.
*/
#ifndef HEADER_XBOX360_WIRELESS_CONTROLLER_HPP
#define HEADER_XBOX360_WIRELESS_CONTROLLER_HPP
struct XPadDevice;
/** */
class Xbox360WirelessController
{
private:
struct usb_device* dev;
XPadDevice* dev_type;
struct usb_dev_handle* handle;
int endpoint;
int interface;
uint8_t battery_status;
std::string serial;
public:
Xbox360WirelessController(struct usb_device* dev,
XPadDevice* dev_type,
int controller_id);
void set_rumble(uint8_t left, uint8_t right);
void set_led(uint8_t status);
void read(Xbox360Msg& msg);
uint8_t get_battery_status() const;
private:
Xbox360WirelessController (const Xbox360WirelessController&);
Xbox360WirelessController& operator= (const Xbox360WirelessController&);
};
#endif
/* EOF */

View file

@ -21,8 +21,8 @@
#include <usb.h> #include <usb.h>
#include <unistd.h> #include <unistd.h>
#include <iostream> #include <iostream>
#include "uinput.hpp" #include "uinput.hpp"
#include "xboxmsg.hpp"
#include "xboxdrv.hpp" #include "xboxdrv.hpp"
@ -101,118 +101,6 @@ std::ostream& operator<<(std::ostream& out, const GamepadType& type)
} }
} }
std::ostream& operator<<(std::ostream& out, const Xbox360GuitarMsg& msg)
{
out << boost::format(" whammy:%6d tilt:%6d | up:%d down:%d left:%d right:%d | back:%d guide:%d start:%d | green:%d red:%d yellow:%d blue:%d orange:%d ")
% int(msg.whammy)
% int(msg.tilt)
% int(msg.dpad_up)
% int(msg.dpad_down)
% int(msg.dpad_left)
% int(msg.dpad_right)
% int(msg.back)
% int(msg.guide)
% int(msg.start)
% int(msg.green)
% int(msg.red)
% int(msg.yellow)
% int(msg.blue)
% int(msg.orange);
if (0)
out << boost::format("| dummy: %d %d %d %d %02hhx %02hhx %04hx %04hx %02x %02x")
% int(msg.thumb_l)
% int(msg.thumb_r)
% int(msg.rb)
% int(msg.dummy1)
% int(msg.lt)
% int(msg.rt)
% int16_t(msg.x1)
% int16_t(msg.y1)
% int(msg.dummy2)
% int(msg.dummy3);
return out;
}
std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg)
{
out << boost::format("S1:(%6d, %6d)")
% int(msg.x1) % int(msg.y1);
out << boost::format(" S2:(%6d, %6d)")
% int(msg.x2) % int(msg.y2);
out << boost::format(" [u:%d|d:%d|l:%d|r:%d]")
% int(msg.dpad_up)
% int(msg.dpad_down)
% int(msg.dpad_left)
% int(msg.dpad_right);
out << " back:" << msg.back;
out << " guide:" << msg.guide;
out << " start:" << msg.start;
out << " sl:" << msg.thumb_l;
out << " sr:" << msg.thumb_r;
out << " A:" << msg.a;
out << " B:" << msg.b;
out << " X:" << msg.x;
out << " Y:" << msg.y;
out << " LB:" << msg.lb;
out << " RB:" << msg.rb;
out << boost::format(" LT:%3d RT:%3d")
% int(msg.lt) % int(msg.rt);
if (0)
out << " Dummy: " << msg.dummy1 << " " << msg.dummy2 << " " << msg.dummy3;
return out;
}
std::ostream& operator<<(std::ostream& out, const XboxMsg& msg)
{
out << boost::format(" S1:(%6d, %6d) S2:(%6d, %6d) "
" [u:%d|d:%d|l:%d|r:%d] "
" start:%d back:%d "
" sl:%d sr:%d "
" A:%3d B:%3d X:%3d Y:%3d "
" black:%3d white:%3d "
" LT:%3d RT:%3d ")
% int(msg.x1) % int(msg.y1)
% int(msg.x2) % int(msg.y2)
% int(msg.dpad_up)
% int(msg.dpad_down)
% int(msg.dpad_left)
% int(msg.dpad_right)
% int(msg.start)
% int(msg.back)
% int(msg.thumb_l)
% int(msg.thumb_r)
% int(msg.a)
% int(msg.b)
% int(msg.x)
% int(msg.y)
% int(msg.black)
% int(msg.white)
% int(msg.lt)
% int(msg.rt);
return out;
}
void list_controller() void list_controller()
{ {
struct usb_bus* busses = usb_get_busses(); struct usb_bus* busses = usb_get_busses();
@ -638,6 +526,20 @@ void parse_command_line(int argc, char** argv, CommandLineOptions& opts)
} }
} }
void print_info(struct usb_device* dev,
XPadDevice* dev_type,
const CommandLineOptions& opts)
{
std::cout << "USB Device: " << dev->bus->dirname << ":" << dev->filename << std::endl;
std::cout << "Controller: " << boost::format("\"%s\" (idVendor: 0x%04x, idProduct: 0x%04x)")
% (dev_type ? dev_type->name : "unknown") % uint16_t(dev->descriptor.idVendor) % uint16_t(dev->descriptor.idProduct) << std::endl;
std::cout << "Controller Type: " << opts.gamepad_type << std::endl;
std::cout << "Deadzone: " << opts.deadzone << std::endl;
std::cout << "Rumble Debug: " << (opts.rumble ? "on" : "off") << std::endl;
std::cout << "Rumble Speed: " << "left: " << opts.rumble_l << " right: " << opts.rumble_r << std::endl;
std::cout << "LED Status: " << int(opts.led) << std::endl;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
srand(time(0)); srand(time(0));
@ -685,21 +587,13 @@ int main(int argc, char** argv)
} }
else else
{ {
// Could/should fork here to hande multiple controllers at once
if (opts.gamepad_type == GAMEPAD_UNKNOWN) if (opts.gamepad_type == GAMEPAD_UNKNOWN)
{ {
assert(dev_type); assert(dev_type);
opts.gamepad_type = dev_type->type; opts.gamepad_type = dev_type->type;
} }
std::cout << "USB Device: " << dev->bus->dirname << ":" << dev->filename << std::endl; print_info(dev, dev_type, opts);
std::cout << "Controller: " << boost::format("\"%s\" (idVendor: 0x%04x, idProduct: 0x%04x)")
% (dev_type ? dev_type->name : "unknown") % uint16_t(dev->descriptor.idVendor) % uint16_t(dev->descriptor.idProduct) << std::endl;
std::cout << "Controller Type: " << opts.gamepad_type << std::endl;
std::cout << "Deadzone: " << opts.deadzone << std::endl;
std::cout << "Rumble Debug: " << (opts.rumble ? "on" : "off") << std::endl;
std::cout << "Rumble Speed: " << "left: " << opts.rumble_l << " right: " << opts.rumble_r << std::endl;
std::cout << "LED Status: " << int(opts.led) << std::endl;
struct usb_dev_handle* handle = usb_open(dev); struct usb_dev_handle* handle = usb_open(dev);
if (!handle) if (!handle)
@ -759,8 +653,9 @@ int main(int argc, char** argv)
memset(old_data, 0, 20); memset(old_data, 0, 20);
while(!quit) while(!quit)
{ {
uint8_t data[20]; uint8_t data[32];
int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, 20, 0 /*Timeout*/); int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/);
if (ret < 0) if (ret < 0)
{ // Error { // Error
std::cout << "USBError: " << ret << "\n" << usb_strerror() << std::endl; std::cout << "USBError: " << ret << "\n" << usb_strerror() << std::endl;
@ -769,21 +664,9 @@ int main(int argc, char** argv)
} }
else if (ret == 0) else if (ret == 0)
{ {
// happen with the Xbox360 every now and then, just // happen with the Xbox360 controller every now
// ignore, seems harmless // and then, just ignore, seems harmless
} }
#if 0
else if (ret == 2 && data[1] == 0x80)
{ // wireless connect
}
else if (ret == 2 && data[1] == 0x80)
{ // wireless disconnect
}
else if (ret == 29 && data[1] == 0x01)
{
xpad_process_packet(xpad, 0, (char*) ((unsigned long)xpad->idata + 4));
}
#endif
else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14) else if (ret == 20 && data[0] == 0x00 && data[1] == 0x14)
{ {
if (memcmp(data, old_data, 20) == 0) if (memcmp(data, old_data, 20) == 0)

View file

@ -18,136 +18,6 @@
#ifndef HEADER_XBOX360_HPP #ifndef HEADER_XBOX360_HPP
#define HEADER_XBOX360_HPP #define HEADER_XBOX360_HPP
struct Xbox360Msg
{
// -------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1;
unsigned int thumb_r :1;
// data[3] ------------------
unsigned int lb :1;
unsigned int rb :1;
unsigned int guide :1;
unsigned int dummy1 :1;
unsigned int a :1;
unsigned int b :1;
unsigned int x :1;
unsigned int y :1;
// data[4] ------------------
unsigned int lt :8;
unsigned int rt :8;
// data[6] ------------------
int x1 :16;
int y1 :16;
// data[10] -----------------
int x2 :16;
int y2 :16;
// data[14]; ----------------
unsigned int dummy2 :32;
unsigned int dummy3 :16;
} __attribute__((__packed__));
struct Xbox360GuitarMsg
{
// -------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1; // also strum-up
unsigned int dpad_down :1; // also strum-down
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1; // unused
unsigned int thumb_r :1; // unused
// data[3] ------------------
unsigned int orange :1; // 5
unsigned int rb :1; // unused
unsigned int guide :1;
unsigned int dummy1 :1; // unused
unsigned int green :1; // 1, A
unsigned int red :1; // 2, B
unsigned int blue :1; // 4, X
unsigned int yellow :1; // 3, Y
// data[4] ------------------
unsigned int lt :8; // unknown
unsigned int rt :8; // unknown
// data[6] ------------------
int x1 :16; // unused
int y1 :16; // unused
// data[10] -----------------
int whammy :16;
int tilt :16;
// data[14]; ----------------
unsigned int dummy2 :32; // unused
unsigned int dummy3 :16; // unused
} __attribute__((__packed__));
struct XboxMsg
{
// --------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1;
unsigned int thumb_r :1;
// data[3] ------------------
unsigned int dummy :8;
unsigned int a :8;
unsigned int b :8;
unsigned int x :8;
unsigned int y :8;
unsigned int black :8;
unsigned int white :8;
unsigned int lt :8;
unsigned int rt :8;
// data[6] ------------------
int x1 :16;
int y1 :16;
// data[10] -----------------
int x2 :16;
int y2 :16;
} __attribute__((__packed__));
enum GamepadType { enum GamepadType {
GAMEPAD_UNKNOWN, GAMEPAD_UNKNOWN,

142
xboxmsg.cpp Normal file
View file

@ -0,0 +1,142 @@
/* $Id$
** __ __ __ ___ __ __ __ __
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
** \/ \/ \/ \/ \/
** Copyright (C) 2007 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
** 02111-1307, USA.
*/
#include <boost/format.hpp>
#include <iostream>
#include "xboxmsg.hpp"
std::ostream& operator<<(std::ostream& out, const Xbox360GuitarMsg& msg)
{
out << boost::format(" whammy:%6d tilt:%6d | up:%d down:%d left:%d right:%d | back:%d guide:%d start:%d | green:%d red:%d yellow:%d blue:%d orange:%d ")
% int(msg.whammy)
% int(msg.tilt)
% int(msg.dpad_up)
% int(msg.dpad_down)
% int(msg.dpad_left)
% int(msg.dpad_right)
% int(msg.back)
% int(msg.guide)
% int(msg.start)
% int(msg.green)
% int(msg.red)
% int(msg.yellow)
% int(msg.blue)
% int(msg.orange);
if (0)
out << boost::format("| dummy: %d %d %d %d %02hhx %02hhx %04hx %04hx %02x %02x")
% int(msg.thumb_l)
% int(msg.thumb_r)
% int(msg.rb)
% int(msg.dummy1)
% int(msg.lt)
% int(msg.rt)
% int16_t(msg.x1)
% int16_t(msg.y1)
% int(msg.dummy2)
% int(msg.dummy3);
return out;
}
std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg)
{
out << boost::format("S1:(%6d, %6d)")
% int(msg.x1) % int(msg.y1);
out << boost::format(" S2:(%6d, %6d)")
% int(msg.x2) % int(msg.y2);
out << boost::format(" [u:%d|d:%d|l:%d|r:%d]")
% int(msg.dpad_up)
% int(msg.dpad_down)
% int(msg.dpad_left)
% int(msg.dpad_right);
out << " back:" << msg.back;
out << " guide:" << msg.guide;
out << " start:" << msg.start;
out << " sl:" << msg.thumb_l;
out << " sr:" << msg.thumb_r;
out << " A:" << msg.a;
out << " B:" << msg.b;
out << " X:" << msg.x;
out << " Y:" << msg.y;
out << " LB:" << msg.lb;
out << " RB:" << msg.rb;
out << boost::format(" LT:%3d RT:%3d")
% int(msg.lt) % int(msg.rt);
if (0)
out << " Dummy: " << msg.dummy1 << " " << msg.dummy2 << " " << msg.dummy3;
return out;
}
std::ostream& operator<<(std::ostream& out, const XboxMsg& msg)
{
out << boost::format(" S1:(%6d, %6d) S2:(%6d, %6d) "
" [u:%d|d:%d|l:%d|r:%d] "
" start:%d back:%d "
" sl:%d sr:%d "
" A:%3d B:%3d X:%3d Y:%3d "
" black:%3d white:%3d "
" LT:%3d RT:%3d ")
% int(msg.x1) % int(msg.y1)
% int(msg.x2) % int(msg.y2)
% int(msg.dpad_up)
% int(msg.dpad_down)
% int(msg.dpad_left)
% int(msg.dpad_right)
% int(msg.start)
% int(msg.back)
% int(msg.thumb_l)
% int(msg.thumb_r)
% int(msg.a)
% int(msg.b)
% int(msg.x)
% int(msg.y)
% int(msg.black)
% int(msg.white)
% int(msg.lt)
% int(msg.rt);
return out;
}
/* EOF */

167
xboxmsg.hpp Normal file
View file

@ -0,0 +1,167 @@
/* $Id$
** __ __ __ ___ __ __ __ __
** / \ / \__| ____ __| _/_______/ |_|__| | | | ____
** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \
** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/
** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ >
** \/ \/ \/ \/ \/
** Copyright (C) 2007 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
** 02111-1307, USA.
*/
#ifndef HEADER_XBOXMSG_HPP
#define HEADER_XBOXMSG_HPP
#include <iosfwd>
struct Xbox360Msg
{
// -------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1;
unsigned int thumb_r :1;
// data[3] ------------------
unsigned int lb :1;
unsigned int rb :1;
unsigned int guide :1;
unsigned int dummy1 :1;
unsigned int a :1;
unsigned int b :1;
unsigned int x :1;
unsigned int y :1;
// data[4] ------------------
unsigned int lt :8;
unsigned int rt :8;
// data[6] ------------------
int x1 :16;
int y1 :16;
// data[10] -----------------
int x2 :16;
int y2 :16;
// data[14]; ----------------
unsigned int dummy2 :32;
unsigned int dummy3 :16;
} __attribute__((__packed__));
struct Xbox360GuitarMsg
{
// -------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1; // also strum-up
unsigned int dpad_down :1; // also strum-down
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1; // unused
unsigned int thumb_r :1; // unused
// data[3] ------------------
unsigned int orange :1; // 5
unsigned int rb :1; // unused
unsigned int guide :1;
unsigned int dummy1 :1; // unused
unsigned int green :1; // 1, A
unsigned int red :1; // 2, B
unsigned int blue :1; // 4, X
unsigned int yellow :1; // 3, Y
// data[4] ------------------
unsigned int lt :8; // unknown
unsigned int rt :8; // unknown
// data[6] ------------------
int x1 :16; // unused
int y1 :16; // unused
// data[10] -----------------
int whammy :16;
int tilt :16;
// data[14]; ----------------
unsigned int dummy2 :32; // unused
unsigned int dummy3 :16; // unused
} __attribute__((__packed__));
struct XboxMsg
{
// --------------------------
unsigned int type :8;
unsigned int length :8;
// data[2] ------------------
unsigned int dpad_up :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int dpad_right :1;
unsigned int start :1;
unsigned int back :1;
unsigned int thumb_l :1;
unsigned int thumb_r :1;
// data[3] ------------------
unsigned int dummy :8;
unsigned int a :8;
unsigned int b :8;
unsigned int x :8;
unsigned int y :8;
unsigned int black :8;
unsigned int white :8;
unsigned int lt :8;
unsigned int rt :8;
// data[6] ------------------
int x1 :16;
int y1 :16;
// data[10] -----------------
int x2 :16;
int y2 :16;
} __attribute__((__packed__));
std::ostream& operator<<(std::ostream& out, const Xbox360GuitarMsg& msg);
std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg);
std::ostream& operator<<(std::ostream& out, const XboxMsg& msg);
#endif
/* EOF */