Difference between revisions of "DualShock 3"
(→Bluetooth) |
(→Notes) |
||
(11 intermediate revisions by one user not shown) | |||
Line 2: | Line 2: | ||
==USB== | ==USB== | ||
+ | |||
+ | ===Notes=== | ||
+ | |||
+ | There are some "class" specific data that are exchanged between the PS3 and DS3 when it connects, via control transfer. See [[DualShock 3#Other Initial Control Transfers|Other Initial Control Transfers]]. I suspect some of these are calibration or configuration values. Some of it probably have Bluetooth pairing info inside, which I might need to sniff Bluetooth traffic to see, because I can't obtain the PS3's MAC address easily yet. | ||
+ | |||
+ | The DS3 does not start sending reports until the PS button is pressed. | ||
+ | |||
+ | One report is sent every 10ms | ||
+ | |||
+ | ===Device Descriptor=== | ||
+ | <pre> | ||
+ | 0x12, // bLength | ||
+ | 0x01, // bDescriptorType (Device) | ||
+ | 0x00, 0x02, // bcdUSB 2.00 | ||
+ | 0x00, // bDeviceClass (Use class information in the Interface Descriptors) | ||
+ | 0x00, // bDeviceSubClass | ||
+ | 0x00, // bDeviceProtocol | ||
+ | 0x40, // bMaxPacketSize0 64 | ||
+ | 0x4C, 0x05, // idVendor 0x054C | ||
+ | 0x68, 0x02, // idProduct 0x0268 | ||
+ | 0x00, 0x01, // bcdDevice 1.00 | ||
+ | 0x01, // iManufacturer (String Index) | ||
+ | 0x02, // iProduct (String Index) | ||
+ | 0x00, // iSerialNumber (String Index) | ||
+ | 0x01, // bNumConfigurations 1 | ||
+ | </pre> | ||
+ | |||
+ | ===Configuration, Interface, Endpoints, HID=== | ||
+ | <pre> | ||
+ | 0x09, // bLength | ||
+ | 0x02, // bDescriptorType (Configuration) | ||
+ | 0x29, 0x00, // wTotalLength 41 | ||
+ | 0x01, // bNumInterfaces 1 | ||
+ | 0x01, // bConfigurationValue | ||
+ | 0x00, // iConfiguration (String Index) | ||
+ | 0x80, // bmAttributes | ||
+ | 0xFA, // bMaxPower 500mA | ||
+ | |||
+ | 0x09, // bLength | ||
+ | 0x04, // bDescriptorType (Interface) | ||
+ | 0x00, // bInterfaceNumber 0 | ||
+ | 0x00, // bAlternateSetting | ||
+ | 0x02, // bNumEndpoints 2 | ||
+ | 0x03, // bInterfaceClass | ||
+ | 0x00, // bInterfaceSubClass | ||
+ | 0x00, // bInterfaceProtocol | ||
+ | 0x00, // iInterface (String Index) | ||
+ | |||
+ | 0x09, // bLength | ||
+ | 0x21, // bDescriptorType (HID) | ||
+ | 0x11, 0x01, // bcdHID 1.17 | ||
+ | 0x00, // bCountryCode | ||
+ | 0x01, // bNumDescriptors | ||
+ | 0x22, // bDescriptorType[0] (HID) | ||
+ | 0x94, 0x00, // wDescriptorLength[0] 148 | ||
+ | |||
+ | 0x07, // bLength | ||
+ | 0x05, // bDescriptorType (Endpoint) | ||
+ | 0x02, // bEndpointAddress (OUT/H2D) | ||
+ | 0x03, // bmAttributes (Interrupt) | ||
+ | 0x40, 0x00, // wMaxPacketSize 64 | ||
+ | 0x01, // bInterval 1 (unit depends on device speed) | ||
+ | |||
+ | 0x07, // bLength | ||
+ | 0x05, // bDescriptorType (Endpoint) | ||
+ | 0x81, // bEndpointAddress (IN/D2H) | ||
+ | 0x03, // bmAttributes (Interrupt) | ||
+ | 0x40, 0x00, // wMaxPacketSize 64 | ||
+ | 0x01, // bInterval 1 (unit depends on device speed) | ||
+ | </pre> | ||
+ | |||
+ | ===HID Report Descriptor=== | ||
+ | <pre> | ||
+ | 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) | ||
+ | 0x09, 0x04, // Usage (Joystick) | ||
+ | 0xA1, 0x01, // Collection (Physical) | ||
+ | 0xA1, 0x02, // Collection (Application) | ||
+ | 0x85, 0x01, // Report ID (1) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x01, // Report Count (1) | ||
+ | 0x15, 0x00, // Logical Minimum (0) | ||
+ | 0x26, 0xFF, 0x00, // Logical Maximum (255) | ||
+ | 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
+ | // NOTE: reserved byte | ||
+ | 0x75, 0x01, // Report Size (1) | ||
+ | 0x95, 0x13, // Report Count (19) | ||
+ | 0x15, 0x00, // Logical Minimum (0) | ||
+ | 0x25, 0x01, // Logical Maximum (1) | ||
+ | 0x35, 0x00, // Physical Minimum (0) | ||
+ | 0x45, 0x01, // Physical Maximum (1) | ||
+ | 0x05, 0x09, // Usage Page (Button) | ||
+ | 0x19, 0x01, // Usage Minimum (0x01) | ||
+ | 0x29, 0x13, // Usage Maximum (0x13) | ||
+ | 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
+ | 0x75, 0x01, // Report Size (1) | ||
+ | 0x95, 0x0D, // Report Count (13) | ||
+ | 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) | ||
+ | 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
+ | // NOTE: 32 bit integer, where 0:18 are buttons and 19:31 are reserved | ||
+ | 0x15, 0x00, // Logical Minimum (0) | ||
+ | 0x26, 0xFF, 0x00, // Logical Maximum (255) | ||
+ | 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0xA1, 0x00, // Collection (Undefined) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x04, // Report Count (4) | ||
+ | 0x35, 0x00, // Physical Minimum (0) | ||
+ | 0x46, 0xFF, 0x00, // Physical Maximum (255) | ||
+ | 0x09, 0x30, // Usage (X) | ||
+ | 0x09, 0x31, // Usage (Y) | ||
+ | 0x09, 0x32, // Usage (Z) | ||
+ | 0x09, 0x35, // Usage (Rz) | ||
+ | 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
+ | // NOTE: four joysticks | ||
+ | 0xC0, // End Collection | ||
+ | 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x27, // Report Count (39) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x30, // Report Count (48) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x30, // Report Count (48) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | ||
+ | 0xC0, // End Collection | ||
+ | 0xA1, 0x02, // Collection (Application) | ||
+ | 0x85, 0x02, // Report ID (2) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x30, // Report Count (48) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | ||
+ | 0xC0, // End Collection | ||
+ | 0xA1, 0x02, // Collection (Application) | ||
+ | 0x85, 0xEE, // Report ID (238) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x30, // Report Count (48) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | ||
+ | 0xC0, // End Collection | ||
+ | 0xA1, 0x02, // Collection (Application) | ||
+ | 0x85, 0xEF, // Report ID (239) | ||
+ | 0x75, 0x08, // Report Size (8) | ||
+ | 0x95, 0x30, // Report Count (48) | ||
+ | 0x09, 0x01, // Usage (Pointer) | ||
+ | 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | ||
+ | 0xC0, // End Collection | ||
+ | 0xC0, // End Collection | ||
+ | |||
+ | // 148 bytes | ||
+ | </pre> | ||
+ | |||
+ | ====Sample HID Report==== | ||
+ | <pre> | ||
+ | 01 00 00 00 00 00 80 85 81 7D 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 16 | ||
+ | 00 00 00 00 33 46 77 01 DC 01 F7 01 EC 01 90 01 | ||
+ | EC | ||
+ | </pre> | ||
+ | |||
+ | ====HID Report Mapping==== | ||
+ | |||
+ | Byte 0 is the report ID | ||
+ | |||
+ | Byte 1 is reserved | ||
+ | |||
+ | Byte 2, 3, 4, and 5 contain button info. Active high (1 means pressed, 0 means released). See table: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | | bit || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0 | ||
+ | |- | ||
+ | | byte 2 || D Left || D Down || D Right || D Up || Start || R3 || L3 || Select | ||
+ | |- | ||
+ | | byte 3 || Square || X || Circle || Triangle || R1 || L1 || R2 || L2 | ||
+ | |- | ||
+ | | byte 4 || ? || ? || ? || ? || ? || ? || ? || PS | ||
+ | |- | ||
+ | | byte 5 || ? || ? || ? || ? || ? || ? || ? || ? | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | Byte 6 is left stick X axis; byte 7 is left stick Y axis; byte 8 is right stick X axis; byte 9 is right stick Y axis; top left is 0 | ||
+ | |||
+ | Byte 13 to byte 24 contains analog button data, 8 bits each, 0 is released and FF is fully pressed. The ordering follows the order of the bits shown in the table above. | ||
+ | |||
+ | Byte 40 and 41: accelerometer X axis, little endian 10 bit unsigned | ||
+ | |||
+ | Byte 42 and 43: accelerometer Y axis, little endian 10 bit unsigned | ||
+ | |||
+ | Byte 44 and 45: accelerometer Z axis, little endian 10 bit unsigned | ||
+ | |||
+ | Byte 46 and 47: gyroscope, little endian 10 bit unsigned | ||
+ | |||
+ | ===Other Initial Control Transfers=== | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0x01, 0x03, // wValue[0:15] = 0x0301 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 00 01 04 00 07 0C 01 02 18 18 18 18 09 0A 10 11 | ||
+ | 12 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 | ||
+ | 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xF2, 0x03, // wValue[0:15] = 0x03F2 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | F2 FF FF 00 00 06 F5 48 E2 49 00 03 50 81 D8 01 | ||
+ | 8A 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 | ||
+ | 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xF5, 0x03, // wValue[0:15] = 0x03F5 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 01 00 00 23 06 7C B9 0B E2 49 00 03 50 81 D8 01 | ||
+ | 8A 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 | ||
+ | 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xF5, 0x03, // wValue[0:15] = 0x03F5 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 01 00 00 23 06 7C B9 0B E2 49 00 03 50 81 D8 01 | ||
+ | 8A 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 | ||
+ | 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0x21, // bmRequestType: Dir: H2D, Type: Class, Recipient: Interface | ||
+ | 0x09, // bRequest | ||
+ | 0xEF, 0x03, // wValue[0:15] = 0x03EF | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x30, 0x00, // wLength = 48 | ||
+ | |||
+ | OUT: | ||
+ | 00 00 00 00 03 01 A0 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xEF, 0x03, // wValue[0:15] = 0x03EF | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 00 EF 04 00 07 03 01 A0 00 00 00 00 00 00 00 00 | ||
+ | 00 02 00 01 8E 02 00 01 8E 01 FF 01 8D 01 F8 00 | ||
+ | 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0x21, // bmRequestType: Dir: H2D, Type: Class, Recipient: Interface | ||
+ | 0x09, // bRequest | ||
+ | 0xEF, 0x03, // wValue[0:15] = 0x03EF | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x30, 0x00, // wLength = 48 | ||
+ | |||
+ | OUT: | ||
+ | 00 00 00 00 03 01 B0 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xEF, 0x03, // wValue[0:15] = 0x03EF | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 00 EF 04 00 07 03 01 B0 00 00 00 00 00 00 00 00 | ||
+ | 00 02 6D 02 6E 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xF8, 0x03, // wValue[0:15] = 0x03F8 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 00 01 00 00 07 03 01 B0 00 00 00 00 00 00 00 00 | ||
+ | 00 02 6D 02 6E 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0x21, // bmRequestType: Dir: H2D, Type: Class, Recipient: Interface | ||
+ | 0x09, // bRequest | ||
+ | 0x01, 0x02, // wValue[0:15] = 0x0201 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x30, 0x00, // wLength = 48 | ||
+ | |||
+ | OUT: | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | SETUP: | ||
+ | 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface | ||
+ | 0x01, // bRequest | ||
+ | 0xF7, 0x03, // wValue[0:15] = 0x03F7 | ||
+ | 0x00, 0x00, // wIndex = 0x00 | ||
+ | 0x40, 0x00, // wLength = 64 | ||
+ | |||
+ | IN: | ||
+ | 02 01 D4 02 E6 01 F1 FF 14 33 02 02 D3 01 E5 00 | ||
+ | 00 02 02 02 00 03 00 00 02 00 00 02 62 01 02 01 | ||
+ | 5E 00 32 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
+ | </pre> | ||
==Bluetooth== | ==Bluetooth== | ||
Line 12: | Line 371: | ||
[http://www.circuitsathome.com/mcu/hook-up-ps3-controller-to-usb-host-shield Hook up PS3 controller to USB Host shield] | [http://www.circuitsathome.com/mcu/hook-up-ps3-controller-to-usb-host-shield Hook up PS3 controller to USB Host shield] | ||
+ | |||
+ | [http://www.circuitsathome.com/category/mcu/arduino/usb-shield/bluetooth Circuits@Home USB Host Shield and Bluetooth] |
Latest revision as of 19:46, 17 November 2013
This page will document reverse engineering notes for the DualShock 3
Contents |
[edit] USB
[edit] Notes
There are some "class" specific data that are exchanged between the PS3 and DS3 when it connects, via control transfer. See Other Initial Control Transfers. I suspect some of these are calibration or configuration values. Some of it probably have Bluetooth pairing info inside, which I might need to sniff Bluetooth traffic to see, because I can't obtain the PS3's MAC address easily yet.
The DS3 does not start sending reports until the PS button is pressed.
One report is sent every 10ms
[edit] Device Descriptor
0x12, // bLength 0x01, // bDescriptorType (Device) 0x00, 0x02, // bcdUSB 2.00 0x00, // bDeviceClass (Use class information in the Interface Descriptors) 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol 0x40, // bMaxPacketSize0 64 0x4C, 0x05, // idVendor 0x054C 0x68, 0x02, // idProduct 0x0268 0x00, 0x01, // bcdDevice 1.00 0x01, // iManufacturer (String Index) 0x02, // iProduct (String Index) 0x00, // iSerialNumber (String Index) 0x01, // bNumConfigurations 1
[edit] Configuration, Interface, Endpoints, HID
0x09, // bLength 0x02, // bDescriptorType (Configuration) 0x29, 0x00, // wTotalLength 41 0x01, // bNumInterfaces 1 0x01, // bConfigurationValue 0x00, // iConfiguration (String Index) 0x80, // bmAttributes 0xFA, // bMaxPower 500mA 0x09, // bLength 0x04, // bDescriptorType (Interface) 0x00, // bInterfaceNumber 0 0x00, // bAlternateSetting 0x02, // bNumEndpoints 2 0x03, // bInterfaceClass 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0x00, // iInterface (String Index) 0x09, // bLength 0x21, // bDescriptorType (HID) 0x11, 0x01, // bcdHID 1.17 0x00, // bCountryCode 0x01, // bNumDescriptors 0x22, // bDescriptorType[0] (HID) 0x94, 0x00, // wDescriptorLength[0] 148 0x07, // bLength 0x05, // bDescriptorType (Endpoint) 0x02, // bEndpointAddress (OUT/H2D) 0x03, // bmAttributes (Interrupt) 0x40, 0x00, // wMaxPacketSize 64 0x01, // bInterval 1 (unit depends on device speed) 0x07, // bLength 0x05, // bDescriptorType (Endpoint) 0x81, // bEndpointAddress (IN/D2H) 0x03, // bmAttributes (Interrupt) 0x40, 0x00, // wMaxPacketSize 64 0x01, // bInterval 1 (unit depends on device speed)
[edit] HID Report Descriptor
0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Physical) 0xA1, 0x02, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) // NOTE: reserved byte 0x75, 0x01, // Report Size (1) 0x95, 0x13, // Report Count (19) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x35, 0x00, // Physical Minimum (0) 0x45, 0x01, // Physical Maximum (1) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x13, // Usage Maximum (0x13) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x01, // Report Size (1) 0x95, 0x0D, // Report Count (13) 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) // NOTE: 32 bit integer, where 0:18 are buttons and 19:31 are reserved 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Undefined) 0x75, 0x08, // Report Size (8) 0x95, 0x04, // Report Count (4) 0x35, 0x00, // Physical Minimum (0) 0x46, 0xFF, 0x00, // Physical Maximum (255) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x09, 0x32, // Usage (Z) 0x09, 0x35, // Usage (Rz) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) // NOTE: four joysticks 0xC0, // End Collection 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x75, 0x08, // Report Size (8) 0x95, 0x27, // Report Count (39) 0x09, 0x01, // Usage (Pointer) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xA1, 0x02, // Collection (Application) 0x85, 0x02, // Report ID (2) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xA1, 0x02, // Collection (Application) 0x85, 0xEE, // Report ID (238) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xA1, 0x02, // Collection (Application) 0x85, 0xEF, // Report ID (239) 0x75, 0x08, // Report Size (8) 0x95, 0x30, // Report Count (48) 0x09, 0x01, // Usage (Pointer) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection 0xC0, // End Collection // 148 bytes
[edit] Sample HID Report
01 00 00 00 00 00 80 85 81 7D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 16 00 00 00 00 33 46 77 01 DC 01 F7 01 EC 01 90 01 EC
[edit] HID Report Mapping
Byte 0 is the report ID
Byte 1 is reserved
Byte 2, 3, 4, and 5 contain button info. Active high (1 means pressed, 0 means released). See table:
bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 2 | D Left | D Down | D Right | D Up | Start | R3 | L3 | Select |
byte 3 | Square | X | Circle | Triangle | R1 | L1 | R2 | L2 |
byte 4 | ? | ? | ? | ? | ? | ? | ? | PS |
byte 5 | ? | ? | ? | ? | ? | ? | ? | ? |
Byte 6 is left stick X axis; byte 7 is left stick Y axis; byte 8 is right stick X axis; byte 9 is right stick Y axis; top left is 0
Byte 13 to byte 24 contains analog button data, 8 bits each, 0 is released and FF is fully pressed. The ordering follows the order of the bits shown in the table above.
Byte 40 and 41: accelerometer X axis, little endian 10 bit unsigned
Byte 42 and 43: accelerometer Y axis, little endian 10 bit unsigned
Byte 44 and 45: accelerometer Z axis, little endian 10 bit unsigned
Byte 46 and 47: gyroscope, little endian 10 bit unsigned
[edit] Other Initial Control Transfers
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0x01, 0x03, // wValue[0:15] = 0x0301 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 00 01 04 00 07 0C 01 02 18 18 18 18 09 0A 10 11 12 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xF2, 0x03, // wValue[0:15] = 0x03F2 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: F2 FF FF 00 00 06 F5 48 E2 49 00 03 50 81 D8 01 8A 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xF5, 0x03, // wValue[0:15] = 0x03F5 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 01 00 00 23 06 7C B9 0B E2 49 00 03 50 81 D8 01 8A 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xF5, 0x03, // wValue[0:15] = 0x03F5 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 01 00 00 23 06 7C B9 0B E2 49 00 03 50 81 D8 01 8A 13 00 00 00 00 04 00 02 02 02 02 00 00 00 04 04 04 04 00 00 04 00 01 02 07 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0x21, // bmRequestType: Dir: H2D, Type: Class, Recipient: Interface 0x09, // bRequest 0xEF, 0x03, // wValue[0:15] = 0x03EF 0x00, 0x00, // wIndex = 0x00 0x30, 0x00, // wLength = 48 OUT: 00 00 00 00 03 01 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xEF, 0x03, // wValue[0:15] = 0x03EF 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 00 EF 04 00 07 03 01 A0 00 00 00 00 00 00 00 00 00 02 00 01 8E 02 00 01 8E 01 FF 01 8D 01 F8 00 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0x21, // bmRequestType: Dir: H2D, Type: Class, Recipient: Interface 0x09, // bRequest 0xEF, 0x03, // wValue[0:15] = 0x03EF 0x00, 0x00, // wIndex = 0x00 0x30, 0x00, // wLength = 48 OUT: 00 00 00 00 03 01 B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xEF, 0x03, // wValue[0:15] = 0x03EF 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 00 EF 04 00 07 03 01 B0 00 00 00 00 00 00 00 00 00 02 6D 02 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xF8, 0x03, // wValue[0:15] = 0x03F8 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 00 01 00 00 07 03 01 B0 00 00 00 00 00 00 00 00 00 02 6D 02 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0x21, // bmRequestType: Dir: H2D, Type: Class, Recipient: Interface 0x09, // bRequest 0x01, 0x02, // wValue[0:15] = 0x0201 0x00, 0x00, // wIndex = 0x00 0x30, 0x00, // wLength = 48 OUT: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SETUP: 0xA1, // bmRequestType: Dir: D2H, Type: Class, Recipient: Interface 0x01, // bRequest 0xF7, 0x03, // wValue[0:15] = 0x03F7 0x00, 0x00, // wIndex = 0x00 0x40, 0x00, // wLength = 64 IN: 02 01 D4 02 E6 01 F1 FF 14 33 02 02 D3 01 E5 00 00 02 02 02 00 03 00 00 02 00 00 02 62 01 02 01 5E 00 32 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[edit] Bluetooth
There appears to be a ALPS module on the circuit. Unable to obtain any good datasheets or manuals at this time.