Changes

7,889 bytes added ,  15:59, 19 May 2011
add IOS37's /dev/usb/hid info
Line 1: Line 1: −
==Description==
+
/dev/usb/hid is used as an alternative interface to talk to USB HID devices such as the Rock Band instruments, USB keyboard or HID compatible game controller. There are at least 2 different versions which use different IOCTLs; only the earlier version (version 4) is documented here. It is found in IOS37, 60 and possibly some others.
Addresses Human Interface Devices via the Wii's USB 2.0 ports. Used by Rock Band 1 and Rock Band 2 instruments.
+
 
 +
== List of IOCTLs ==
 +
All memory should be allocated from MEM2 and 32-byte aligned.
 +
This structure is used for most commands:
 +
<source lang="c">
 +
// all multi-byte values are big endian
 +
typedef struct {
 +
u8 padding[16]; // anything you want can go here
 +
s32 device_no;
 +
union {
 +
struct {
 +
u8 bmRequestType;
 +
u8 bmRequest;
 +
u16 wValue;
 +
u16 wIndex;
 +
u16 wLength;
 +
} control;
 +
struct {
 +
u32 endpoint;
 +
u32 dLength;
 +
} interrupt;
 +
struct {
 +
u8 bIndex;
 +
} string;
 +
};
 +
void *data; // virtual pointer, not physical!
 +
} req_args; // 32 bytes
 +
</source>
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Request number
 +
! Name
 +
! Input
 +
! Output
 +
! Notes
 +
|-
 +
| 0
 +
| GetDeviceChange
 +
| none
 +
| 0x600 bytes of device descriptors
 +
| Returns when a HID device is inserted/removed (or immediately when called for the first time). The return value will be -1 if forced to return by calling the Shutdown IOCTL.
 +
|-
 +
| 1
 +
| SetSuspend
 +
| 8 bytes
 +
| none
 +
| Not actually implemented in IOS, returns 0 regardless of arguments
 +
|-
 +
| 2
 +
| ControlMessage
 +
| 32 bytes of req_args
 +
| none
 +
| Read/Write a USB control message. device_no, bmRequestType, bmRequest, wValue, wIndex and wLength must be set (and data if wLength!=0).
 +
|-
 +
| 3
 +
| InterruptMessage(IN)
 +
| 32 bytes of req_args
 +
| none
 +
| Read an interrupt message from an endpoint. device_no, endpoint, dLength and data must be set.
 +
|-
 +
| 4
 +
| InterruptMessage(OUT)
 +
| 32 bytes of req_args
 +
| none
 +
| Send an interrupt message to an endpoint. device_no, endpoint, dLength and data must be set.
 +
|-
 +
| 5
 +
| GetUSString
 +
| 32 bytes of req_args
 +
| none
 +
| Retrieves a descriptor string using language 0x0409(US). device_no, bIndex and data must be set. The returned string will be converted from unicode to char, data should be 255 bytes long to allow for the maximum length string. The actual length will be the return value.
 +
|-
 +
| 6
 +
| GetVersion
 +
| none
 +
| 32 bytes (unused)
 +
| Gets the version of the /dev/usb/hid module (should return 0x40001).
 +
|-
 +
| 7
 +
| Shutdown
 +
| none
 +
| none
 +
| Forces any pending GetDeviceChange requests to return immediately.
 +
|-
 +
| 8
 +
| CancelInterrupt
 +
| ?
 +
| ?
 +
| Cancels any pending interrupt transfers for an endpoint.
 +
|}
 +
 
 +
== Detailed Description ==
 +
Unlike the regular [[../oh1 |IOS USB]] interface, all IPC commands are done via the /dev/usb/hid fd. There is no IOCTL to get a list of currently available devices, but there is an IOCTL that returns when a HID device is inserted or removed (it will also return immediately the first time it is called after IOS is loaded). It can also be forced to return immediately if the shutdown IOCTL is used, to ensure no dangling requests are left when your program exits.
 +
 
 +
=== GetDeviceChange ===
 +
<source lang="c">
 +
void *device_desc = memalign(32, 0x600); // should be from MEM2
 +
ios_ioctl_async(fd, /*GetDeviceChange*/0, NULL, 0, device_desc, 0x600, cb, device_desc); // cb will be called when there is a device change, with the device_desc buffer as a parameter
 +
</source>
 +
The device_desc buffer will contain a set of descriptors for each device. At the beginning of each device's section will be two 4 bytes values, containing the total size of this device's data and the device's id number (used for device_no in req_args). The size of each individual descriptor within the data is padded to 4 bytes, the total size includes this padding. A size value of 0xFFFFFFFF indicates there are no more devices. For example here is what is returned when a Rock Band music keyboard is attached:
 +
<nowiki>00000000  00 00 00 44 00 00 00 00 12 01 01 10 00 00 00 08
 +
00000010  1B AD 33 30 00 05 00 00 00 01 00 00 09 02 00 20
 +
00000020  01 01 00 80 32 00 00 00 09 04 00 00 02 03 00 00
 +
00000030  00 00 00 00 07 05 02 03 00 40 01 00 07 05 81 03
 +
00000040  00 40 0A 00 FF FF FF FF 00 00 00 00 00 00 00 00
 +
... 0x5B0 bytes unused</nowiki>
 +
Breaking this down into 4-bytes words, it can be parsed as follows:
 +
<nowiki>u32 *desc = (u32*)device_desc;
 +
desc[0x00] = 0x44;      // size of this device's data
 +
desc[0x01] = 0;          // this device's id (used to issue commands to this device)
 +
// DEVICE DESCRIPTOR
 +
desc[0x02] = 0x12010110; // bLength=18, bDescriptorType=01, bcdUSB=1.10
 +
desc[0x03] = 0x00000008; // bDeviceClass=0, bDeviceSubClass=0, bDeviceProtocol=0, bMaxPacketSize=8
 +
desc[0x04] = 0x1BAD3330; // VID=0x1BAD, PID=0x3330
 +
desc[0x05] = 0x00050000; // bcdDevice=5, iManufacturer=0, iProduct=0
 +
desc[0x06] = 0x00010000; // iSerialNumber=0, bNumConfigurations=1, 2 bytes padding
 +
// CONFIGURATION DESCRIPTOR
 +
desc[0x07] = 0x09020020; // bLength=9, bDescriptorType=2, wTotalLength=32
 +
desc[0x08] = 0x01010080; // bNumInterfaces=1, bConfigurationValue=1, iConfiguration=0, bmAttributes=0x80
 +
desc[0x09] = 0x32000000; // bMaxPower=100ma (?), 3 bytes padding
 +
// INTERFACE DESCRIPTOR
 +
desc[0x0A] = 0x09040000; // bLength=9, bDescriptorType=4, bInterfaceNumber=0, bAlternateSetting=0
 +
desc[0x0B] = 0x02030000; // bNumEndpoints=2, bInterfaceClass=3(HID), bInterfaceSubClass=0, bInterfaceProtocol=0
 +
desc[0x0C] = 0x00000000; // iInterface, 3 bytes padding
 +
// ENDPOINT DESCRIPTOR (OUT)
 +
desc[0x0D] = 0x07050203; // bLength=7, bDescriptorType=5, bEndpointAddress=0x02, bmAttributes=0x03(Interrupt)
 +
desc[0x0E] = 0x00400100; // wMaxPacketSize=64, bInterval=1, 1 byte padding
 +
// ENDPOINT DESCRIPTOR (IN)
 +
desc[0x0F] = 0x07058103; // bLength=7, bDescriptorType=5, bEndpointAddress=0x81, bmAttributes=0x03(Interrupt)
 +
desc[0x10] = 0x00400A00; // wMaxPacketSize=64, bInterval=10, 1 byte padding
 +
// total size = 0x11*sizeof(u32) = 0x44. End of first device's data.
 +
desc[0x11] = 0xFFFFFFFF; // no more devices</nowiki>
 +
 
 +
=== SetSuspend ===
 +
This does nothing; supposedly it suspends or resumes a device, but it's not implemented in the IOS code.
 +
 
 +
=== ControlMessage ===
 +
Issues a control message to a device. Takes a filled out req_args struct as a parameter; device_no specifies the target device while control.bmRequestType, control.bmRequest, control.wValue, control.wIndex and control.wLength should be filled according to the message being sent. If there is extra input/output information associated with the message it should be pointed to by data (control.wLength should specify the length as per the USB standard).
 +
 
 +
=== InterruptMessage(IN) ===
 +
Fetches an interrupt message from the device. Takes a filled out req_args struct as a parameter; device_no specifies the target device, interrupt.endpoint specifies which interface endpoint should be used for the transfer, interrupt.dLength specifies the length of the transfer and data points to a destination buffer. The specified endpoint should be an IN endpoint.
 +
 
 +
=== InterruptMessage(OUT) ===
 +
Sends an interrupt message to the device. Same as above, but data points to a source buffer and the specified endpoint should be an OUT endpoint.
 +
 
 +
=== GetUSString ===
 +
Requests the specified string descriptor from the device and converts it from unicode. Takes a filled out req_args struct as a parameter; device_no specifies the target device, string.bIndex is the index of the string descriptor and data is the destination buffer. Data should be at least 255 bytes long to allow for the longest possible string. Any characters that cannot be represented correctly by a single byte will be translated to '?'. The return value specifies the length of the returned string.
 +
 
 +
=== GetVersion ===
 +
Retrieves the version of the /dev/usb/hid interface; currently this should return 0x40001. The output buffer is not used.
 +
 
 +
=== Shutdown ===
 +
Cancels a pending GetDeviceChange request, making it return immediately (the returned value will be -1). This is used to "clean up" the IOS state.
 +
 
 +
=== CancelInterrupt ===
 +
Similar to Shutdown, but forces a pending InterruptMessage IOCTL to return immediately.
 +
 
 +
[[Category:IOS API documentation]]