Reputation: 1982
I am trying to read data from a HID device. I have a USB sniffer capture that basically does:
Get Device Descriptor
Get Device Descriptor
Set Address
Get Configuration Descriptor
Get Configuration Descriptor
Set Configuration
Set Idle
Get Input Report
Get Input Report
Get Input Report
Get Input Report
Set Feature Report
Get Input Report
Set Feature Report
Get Input Report
Get Input Report
Set Output Report
Get Input Report
Set Feature Report
Input Report
Input Report
It appears that everything before the Input Report
is setup and that Input Report
is the regular data collection from the device.
In libusb, I am doing the following:
usb_init();
usb_find_busses();
usb_find_devices();
loop through busses
loop through devices
if correct vendor and correct product
handle = usb_open(device)
break
usb_set_configuration(dev_handle, 1)
// Endpoint 0 is a 'write endpoint', endpoint 1 is a 'read endpoint'.
endpoint = &device->config[0].interface[0].altsetting[0].endpoint[1]
usb_claim_interface(dev_handle, 0)
usb_set_altinterface(dev_handle, 0)
usb_bulk_read(dev_handle, endpoint->bEndpointAddress, buffer, endpoint->wMaxPacketSize, 1);
I am guessing that the driver and the code up to usb_set_configuration
corresponds with the sniffer analysis up to Set Configuration
.
Everything in the code succeeds until the usb_bulk_read
which fails.
Set Idle
, Get Input Report
, Set Feature Report
, Set Output Report
?usb_bulk_read
fail?Upvotes: 4
Views: 5024
Reputation: 1982
I'm new to libusb and USB in general, so I'm not sure if this is the right thing, but after looking at the output from a USB sniffer such as USBlyzer and tweaking several things I come up with the following protocol items:
When I claimed an interface (usb_claim_interface
) and then cancelled my application, I was in an inoperable state on subsequent runs. I tried various resets (usb_reset
and usb_resetep
), but I still could not get proper usage out of usb_control_msg
.
USBlyzer
showed that the relevant packets where Get Descriptor
, Select Configuration
, Set Report
, and Get Report
. Get Descriptor
and Select Configuration
are clearly associated with usb_get_descriptor
and usb_set_configuration
respectively.
Some Get Report
packets contained Feature Id
and others Input Id
. I was able to match these with usb_control_msg
with the following parameters, (libusb.c helped
me figure this out):
requesttype = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE
value = 0x01 (for GetReport)
index = id | (0x03 << 8) (for FeatureId)
Set Report
packets also used Feature Id
but Output Id
. From looking at the details it became clear that Input Id
matches (0x01 << 8) and Output Id
matches (0x02 << 8). So to get Set Report
I called usb_control_msg
with these adjusted params:
requesttype = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
value = 0x09 (for SetReport)
index = id | (0x03 << 8) (for FeatureId)
This may not be the "right" way to do all this, and I would certainly appreciate any deeper insight into what is happening with the various functions of the API. But this was able to get my host to capture all relevant data from the device.
Upvotes: 3
Reputation: 7711
HID device [...] usb_bulk_read
Ouch. USB Bulk read is only used on Bulk endpoints, and HID has none.
HID endpoints are interrupt endpoints, and thus need usb_interrupt_transfer()
. You did look at the endpoint descriptor, didn't you? It should declare the endpoint type as interrupt.
Upvotes: 3