Preparations for Xbox360 wireless support
This commit is contained in:
parent
b07cf7f2be
commit
aeea6bf669
16 changed files with 1001 additions and 271 deletions
306
PROTOCOL
Normal file
306
PROTOCOL
Normal 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 #
|
|
@ -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",
|
||||
|
|
15
TODO
15
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)
|
||||
{
|
||||
|
|
|
@ -22,13 +22,14 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/uinput.h>
|
||||
#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)
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
#include "xboxdrv.hpp"
|
||||
|
||||
class Xbox360Msg;
|
||||
class Xbox360GuitarMsg;
|
||||
class XboxMsg;
|
||||
|
||||
class uInputCfg
|
||||
{
|
||||
public:
|
||||
|
|
85
xbox360_controller.cpp
Normal file
85
xbox360_controller.cpp
Normal 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
56
xbox360_controller.hpp
Normal 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 */
|
|
@ -29,6 +29,7 @@
|
|||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include "xboxmsg.hpp"
|
||||
#include "log.hpp"
|
||||
#include "xbox360_usb_thread.hpp"
|
||||
#include "xbox360_driver.hpp"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "control.hpp"
|
||||
|
||||
class Xbox360UsbThread;
|
||||
class Xbox360Msg;
|
||||
|
||||
/** */
|
||||
class Xbox360Driver : public Control
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <stdexcept>
|
||||
#include <boost/format.hpp>
|
||||
#include "log.hpp"
|
||||
#include "xboxmsg.hpp"
|
||||
#include "xbox360_usb_thread.hpp"
|
||||
|
||||
Xbox360UsbThread::Xbox360UsbThread(struct usb_device* dev)
|
||||
|
|
139
xbox360_wireless_controller.cpp
Normal file
139
xbox360_wireless_controller.cpp
Normal 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 */
|
59
xbox360_wireless_controller.hpp
Normal file
59
xbox360_wireless_controller.hpp
Normal 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 */
|
159
xboxdrv.cpp
159
xboxdrv.cpp
|
@ -21,8 +21,8 @@
|
|||
#include <usb.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
#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)
|
||||
|
|
130
xboxdrv.hpp
130
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,
|
||||
|
|
142
xboxmsg.cpp
Normal file
142
xboxmsg.cpp
Normal 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
167
xboxmsg.hpp
Normal 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 */
|
Loading…
Reference in a new issue