Question

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.

  1. How do I Set Idle, Get Input Report, Set Feature Report, Set Output Report?
  2. Why does the usb_bulk_read fail?
  3. What else do I need to do to set up communication with my device?
Was it helpful?

Solution 2

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:

usb_claim_interface

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.

SetReport / GetReport

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top