[libhid-discuss] Help with using hid_set_output_report

Charles Lepple clepple at ghz.cc
Sun Dec 28 04:54:44 UTC 2008


> Hey everyone,
>   I'm really confused and any suggestions would be very helpful.  I  
> have a device, and I know (from USB Snoopy on Windows) what data  
> packets I need to send to it.

You may be interested in this program:

http://iki.fi/lindi/usb/usbsnoop2libusb.pl

It generates a skeleton libusb application based on usbsnoop output.

>   When the software that comes with the device is started, 6  
> packets are sent/received (see first attachment).  Once I get the  
> first packet sent, I can worry about the rest later.  At this point  
> I'd just like to get the device to respond to correct report requests.
>
> bmRequestType = 0x22 -> Direction: Host-to-device, Type: Class,  
> Recipient: Endpoint
> bRequest = 0x09 -> HID SET_OUTPUT_REPORT
> wValue = 0x0200 -> Report type (0x02, aka Output report) and report  
> ID (0x00)
> wIndex = 0x0001 -> Sent to interface 1
> wLength = 0x0008 -> 8 bytes of data
>
> Data payload:
> 02 02 95 95 00 00 00 00
>
> Now, I know that I need to be using the set_output_report function  
> (at least I think this is correct, since it corresponds with the  
> constant HID_REPORT_SET 0x09).

Yup, hid_set_output_report() does send a control message with  
HID_REPORT_SET (0x09).

>   I have two basic questions:
> 1.  I partially understand the 'path' parameter in the  
> set_output_report, but I am not sure.  The source code calls  
> usblib's control_msg function, which I am familiar with.  It seems  
> that I need 0x22 as the second parameter in the usb_control_msg.   
> I'm not sure how to set this up properly using the HID path tree.   
> When I look at the usbmon output (Given the example code below), I  
> see 21 09 0200 0000 0040 being sent to the device - which is close,  
> but not what I need.  Is it possible that these values would work  
> anyway since they derive from the HID Path tree?

0x21 is USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE. I'm  
not sure why it wants to be "Recipient: Endpoint" as you indicated  
above.

If you can find a reference that says why 0x22 might be a valid  
option, you might be able to convince me to modify the code.

> 2.  Where do I input the values for the wValue and wIndex? I assume  
> that this derives from the hid_find_object (and hence HID path  
> tree), but I'm not sure if I trust the results since I am  
> unfamiliar with the path set up... See below.
>
> Here is the source code for the data packet being sent by  
> set_output_report (with my comments):
>   TRACE("looking up report ID...");
>   hidif->hid_data->Type = ITEM_OUTPUT;
>   hidif->hid_data->ReportID = 0;
>
>   hid_find_object(hidif, path, depth);
>   // Should I be using hid_find_object if I already know the  
> parameters?

This is an interesting question. If you already know the parameters,  
and if they don't match what libhid sends, it may be easier to just  
use libusb directly.

>
>   int len = usb_control_msg(hidif->dev_handle,
>       USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE, //  
> This should be 0x22, right?
>       HID_REPORT_SET, // 0x09
>       hidif->hid_data->ReportID + (HID_RT_OUTPUT << 8), // This  
> should be 0x0200?
>       hidif->interface, // Interface ID
>       (char*)buffer, size, USB_TIMEOUT); // Timeout
>
> If it is wise to use the path, rather than hardcode these values  
> (I'll explain this in a second), I believe my path values (give a  
> tree dump) are as follows.  Does this look right?
> parse tree of HIDInterface 002/005[0]:
>   path: 0xffa00001.0xffa00002; type: 0x80
>   path: 0xffa00001.0x00000000; type: 0x80
>   path: 0xffa00001.0x00000000; type: 0x80
> [... truncated ...]
>   path: 0xffa00001.0x00000000; type: 0x80
>   path: 0xffa00001.0xffa00003; type: 0x90
>   path: 0xffa00001.0x00000000; type: 0x90
> [... truncated ...]
>   path: 0xffa00001.0x00000000; type: 0x90
>
> PATH_IN =  [0xffa00001, 0xffa00002]
> PATH_OUT = [0xffa00001, 0xffa00003]
>
> The main reason that I am concerned over this is because initially  
> I tried using libusb, without libhid.  I found it impossible to  
> send the following control message (rejected by the kernel):
> control_msg(0x22, 0x09, (data), 0x0200, 0x0001, 64).  It says that  
> the request type is invalid (0x22) and will not allow the packet to  
> even reach the USB bus.  This leads me to believe that something  
> fishy is going on that I don't understand, and I need to use the  
> HID path method (maybe to generate a different request type?)

Unfortunately, I am a little suspicious of usbsnoopy's output here.  
What version are you using, and where did you get it?

You might try this one: http://www.pcausa.com/Utilities/UsbSnoop/ 
default.htm (SniffUSB 2.0) or http://benoit.papillault.free.fr/ 
usbsnoop/index.php.en (usbsnoop 1.8)

>
> Any help would be wonderful.  I feel so close, but I know I am  
> missing something basic.  I do have libhid successfully reading  
> interrupt requests on 0x81 when I push a button on the device.  Its  
> just these control transfers and reports that I'm having trouble with.
>
> Thanks,
> Blaine
>
>
> USB Snoopy Output:
> [b]14   out down   0x00   9.839   CLASS_ENDPOINT   02 02 95 95 00  
> 00 00 00   [/b]
> URB Header (length: 80)
> SequenceNumber: 14
> Function: 001c (CLASS_ENDPOINT)
> PipeHandle: 00000000
> SetupPacket:
> 0000: 22 09 00 02 01 00 00 00
> bmRequestType: 22
>   DIR: Host-To-Device
>   TYPE: Class
>   RECIPIENT: Endpoint
> bRequest: 09
>
> TransferBuffer: 0x00000008 (8) length
> 0000: 02 02 95 95 00 00 00 00
>
> [b]14   out up   n/a   9.842   CONTROL_TRANSFER   -   0x00000000[/b]
> URB Header (length: 80)
> SequenceNumber: 14
> Function: 0008 (CONTROL_TRANSFER)
> PipeHandle: 82db2020
>
> SetupPacket:
> 0000: 22 09 00 02 01 00 08 00
> bmRequestType: 22
>   DIR: Host-To-Device
>   TYPE: Class
>   RECIPIENT: Endpoint
> bRequest: 09
> No TransferBuffer
>
> [b]10   in up   0x81   9.843   BULK_OR_INTERRUPT_TRANSFER   80 a9  
> 28 01 09 01 25 e0   0x00000000[/b]
> URB Header (length: 72)
> SequenceNumber: 10
> Function: 0009 (BULK_OR_INTERRUPT_TRANSFER)
> TransferFlags: 0x00000003
>
> TransferBuffer: 0x00000040 (64) length
> 0000: 80 a9 28 01 09 01 25 e0 8d 0e 02 00 00 00 00 00
> 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>
> [b]15   in down   0x81   9.843   BULK_OR_INTERRUPT_TRANSFER   -[/b]
> URB Header (length: 72)
> SequenceNumber: 15
> Function: 0009 (BULK_OR_INTERRUPT_TRANSFER)
> TransferFlags: 0x00000003
>
> No TransferBuffer
>
> [b]16   out down   0x00   9.845   CLASS_ENDPOINT   02 04 80 b5 01  
> 01 00 00   [/b]
> URB Header (length: 80)
> SequenceNumber: 16
> Function: 001c (CLASS_ENDPOINT)
> PipeHandle: 00000000
> SetupPacket:
> 0000: 22 09 00 02 01 00 00 00
> bmRequestType: 22
>   DIR: Host-To-Device
>   TYPE: Class
>   RECIPIENT: Endpoint
> bRequest: 09
>
> TransferBuffer: 0x00000008 (8) length
> 0000: 02 04 80 b5 01 01 00 00
>
> [b]16   out up   n/a   9.849   CONTROL_TRANSFER   -   0x00000000[/b]
> URB Header (length: 80)
> SequenceNumber: 16
> Function: 0008 (CONTROL_TRANSFER)
> PipeHandle: 82db2020
>
> SetupPacket:
> 0000: 22 09 00 02 01 00 08 00
> bmRequestType: 22
>   DIR: Host-To-Device
>   TYPE: Class
>   RECIPIENT: Endpoint
> bRequest: 09
>
> No TransferBuffer
>
>
>
>
>
>
> Device Information:
> lsusb -vvv, truncated to my device:
>
> Bus 002 Device 015: ID 0e20:0101
> Device Descriptor:
>   bLength                18
>   bDescriptorType         1
>   bcdUSB               1.10
>   bDeviceClass            0 (Defined at Interface level)
>   bDeviceSubClass         0
>   bDeviceProtocol         0
>   bMaxPacketSize0         8
>   idVendor           0x0e20
>   idProduct          0x0101
>   bcdDevice            3.03
>   iManufacturer           4 Pegasus Technologies Ltd.
>   iProduct               56 NoteTaker FW Ver 3.03
>   iSerial               100 0003-0003
>   bNumConfigurations      1
>   Configuration Descriptor:
>     bLength                 9
>     bDescriptorType         2
>     wTotalLength           59
>     bNumInterfaces          2
>     bConfigurationValue     1
>     iConfiguration          0
>     bmAttributes         0xa0
>       (Bus Powered)
>       Remote Wakeup
>     MaxPower              100mA
>     Interface Descriptor:
>       bLength                 9
>       bDescriptorType         4
>       bInterfaceNumber        0
>       bAlternateSetting       0
>       bNumEndpoints           1
>       bInterfaceClass         3 Human Interface Device
>       bInterfaceSubClass      0 No Subclass
>       bInterfaceProtocol      0 None
>       iInterface              0
>       Endpoint Descriptor:
>         bLength                 7
>         bDescriptorType         5
>         bEndpointAddress     0x81  EP 1 IN
>         bmAttributes            3
>           Transfer Type            Interrupt
>           Synch Type               None
>           Usage Type               Data
>         wMaxPacketSize     0x0040  1x 64 bytes
>         bInterval               1
>         ** UNRECOGNIZED:  09 21 10 01 00 01 22 24 00

Odd that your version of lsusb doesn't recognize this descriptor.

>     Interface Descriptor:
>       bLength                 9
>       bDescriptorType         4
>       bInterfaceNumber        1
>       bAlternateSetting       0
>       bNumEndpoints           1
>       bInterfaceClass         3 Human Interface Device
>       bInterfaceSubClass      0 No Subclass
>       bInterfaceProtocol      0 None
>       iInterface              0
>       Endpoint Descriptor:
>         bLength                 7
>         bDescriptorType         5
>         bEndpointAddress     0x82  EP 2 IN
>         bmAttributes            3
>           Transfer Type            Interrupt
>           Synch Type               None
>           Usage Type               Data
>         wMaxPacketSize     0x0006  1x 6 bytes
>         bInterval               1
>         ** UNRECOGNIZED:  09 21 10 01 00 01 22 87 00

Same here. A lot of useful information is not being displayed by lsusb.

> Device Status:     0x0001
>   Self Powered
>



More information about the libhid-discuss mailing list