From aeea6bf6691a94993182c4a6dfa8b6985d4053dd Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Thu, 1 May 2008 09:15:40 +0200 Subject: [PATCH] Preparations for Xbox360 wireless support --- PROTOCOL | 306 ++++++++++++++++++++++++++++++++ SConstruct | 4 +- TODO | 15 +- uinput.cpp | 3 +- uinput.hpp | 4 + xbox360_controller.cpp | 85 +++++++++ xbox360_controller.hpp | 56 ++++++ xbox360_driver.cpp | 1 + xbox360_driver.hpp | 1 + xbox360_usb_thread.cpp | 1 + xbox360_wireless_controller.cpp | 139 +++++++++++++++ xbox360_wireless_controller.hpp | 59 ++++++ xboxdrv.cpp | 159 +++-------------- xboxdrv.hpp | 130 -------------- xboxmsg.cpp | 142 +++++++++++++++ xboxmsg.hpp | 167 +++++++++++++++++ 16 files changed, 1001 insertions(+), 271 deletions(-) create mode 100644 PROTOCOL create mode 100644 xbox360_controller.cpp create mode 100644 xbox360_controller.hpp create mode 100644 xbox360_wireless_controller.cpp create mode 100644 xbox360_wireless_controller.hpp create mode 100644 xboxmsg.cpp create mode 100644 xboxmsg.hpp diff --git a/PROTOCOL b/PROTOCOL new file mode 100644 index 0000000..993d6f2 --- /dev/null +++ b/PROTOCOL @@ -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 # diff --git a/SConstruct b/SConstruct index 163eb26..eeac5fb 100644 --- a/SConstruct +++ b/SConstruct @@ -1,12 +1,14 @@ # -*- python -*- 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", ["inputdrv.cpp", "xbox360_driver.cpp", "evdev_driver.cpp", "xbox360_usb_thread.cpp", + "xbox360_controller.cpp", + "xbox360_wireless_controller.cpp", "control.cpp", "abs_to_rel.cpp", "abs_to_btn.cpp", diff --git a/TODO b/TODO index 1bd5435..ef9863f 100644 --- a/TODO +++ b/TODO @@ -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 * abs input must be normalized to min/max * 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 }; -// 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? void Wireless360Controller::SetRumbleMotors(unsigned char large, unsigned char small) { diff --git a/uinput.cpp b/uinput.cpp index 28483a1..31a0597 100644 --- a/uinput.cpp +++ b/uinput.cpp @@ -22,13 +22,14 @@ #include #include #include +#include "xboxmsg.hpp" #include "uinput.hpp" uInput::uInput(GamepadType type, uInputCfg config_) : fd(-1), config(config_) { // 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*)); for (int i = 0; i < uinput_filename_count; ++i) diff --git a/uinput.hpp b/uinput.hpp index d445e7c..a3c3477 100644 --- a/uinput.hpp +++ b/uinput.hpp @@ -21,6 +21,10 @@ #include "xboxdrv.hpp" +class Xbox360Msg; +class Xbox360GuitarMsg; +class XboxMsg; + class uInputCfg { public: diff --git a/xbox360_controller.cpp b/xbox360_controller.cpp new file mode 100644 index 0000000..f0709d8 --- /dev/null +++ b/xbox360_controller.cpp @@ -0,0 +1,85 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 Ingo Ruhnke +** +** 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 +#include +#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 */ diff --git a/xbox360_controller.hpp b/xbox360_controller.hpp new file mode 100644 index 0000000..65f3681 --- /dev/null +++ b/xbox360_controller.hpp @@ -0,0 +1,56 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 Ingo Ruhnke +** +** 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 + +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 */ diff --git a/xbox360_driver.cpp b/xbox360_driver.cpp index 49356c8..9f090c2 100644 --- a/xbox360_driver.cpp +++ b/xbox360_driver.cpp @@ -29,6 +29,7 @@ #include #include #include +#include "xboxmsg.hpp" #include "log.hpp" #include "xbox360_usb_thread.hpp" #include "xbox360_driver.hpp" diff --git a/xbox360_driver.hpp b/xbox360_driver.hpp index 7027ef4..5e96e93 100644 --- a/xbox360_driver.hpp +++ b/xbox360_driver.hpp @@ -31,6 +31,7 @@ #include "control.hpp" class Xbox360UsbThread; +class Xbox360Msg; /** */ class Xbox360Driver : public Control diff --git a/xbox360_usb_thread.cpp b/xbox360_usb_thread.cpp index 1bdc7e7..6117a06 100644 --- a/xbox360_usb_thread.cpp +++ b/xbox360_usb_thread.cpp @@ -29,6 +29,7 @@ #include #include #include "log.hpp" +#include "xboxmsg.hpp" #include "xbox360_usb_thread.hpp" Xbox360UsbThread::Xbox360UsbThread(struct usb_device* dev) diff --git a/xbox360_wireless_controller.cpp b/xbox360_wireless_controller.cpp new file mode 100644 index 0000000..02f7e6b --- /dev/null +++ b/xbox360_wireless_controller.cpp @@ -0,0 +1,139 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 Ingo Ruhnke +** +** 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 +#include +#include +#include +#include +#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(&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 */ diff --git a/xbox360_wireless_controller.hpp b/xbox360_wireless_controller.hpp new file mode 100644 index 0000000..155cbc6 --- /dev/null +++ b/xbox360_wireless_controller.hpp @@ -0,0 +1,59 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 Ingo Ruhnke +** +** 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 */ diff --git a/xboxdrv.cpp b/xboxdrv.cpp index 0dd7985..5ef610f 100644 --- a/xboxdrv.cpp +++ b/xboxdrv.cpp @@ -21,8 +21,8 @@ #include #include #include - #include "uinput.hpp" +#include "xboxmsg.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() { 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) { srand(time(0)); @@ -685,21 +587,13 @@ int main(int argc, char** argv) } else { - // Could/should fork here to hande multiple controllers at once if (opts.gamepad_type == GAMEPAD_UNKNOWN) { assert(dev_type); opts.gamepad_type = dev_type->type; } - 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; + print_info(dev, dev_type, opts); struct usb_dev_handle* handle = usb_open(dev); if (!handle) @@ -759,8 +653,9 @@ int main(int argc, char** argv) memset(old_data, 0, 20); while(!quit) { - uint8_t data[20]; - int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, 20, 0 /*Timeout*/); + uint8_t data[32]; + int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)data, sizeof(data), 0 /*Timeout*/); + if (ret < 0) { // Error std::cout << "USBError: " << ret << "\n" << usb_strerror() << std::endl; @@ -769,21 +664,9 @@ int main(int argc, char** argv) } else if (ret == 0) { - // happen with the Xbox360 every now and then, just - // ignore, seems harmless + // happen with the Xbox360 controller every now + // 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) { if (memcmp(data, old_data, 20) == 0) diff --git a/xboxdrv.hpp b/xboxdrv.hpp index 63286f9..99476a3 100644 --- a/xboxdrv.hpp +++ b/xboxdrv.hpp @@ -18,136 +18,6 @@ #ifndef 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 { GAMEPAD_UNKNOWN, diff --git a/xboxmsg.cpp b/xboxmsg.cpp new file mode 100644 index 0000000..8d5b459 --- /dev/null +++ b/xboxmsg.cpp @@ -0,0 +1,142 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 Ingo Ruhnke +** +** 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 +#include +#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 */ diff --git a/xboxmsg.hpp b/xboxmsg.hpp new file mode 100644 index 0000000..e9f0506 --- /dev/null +++ b/xboxmsg.hpp @@ -0,0 +1,167 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 Ingo Ruhnke +** +** 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 + +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 */