Discussion:
[libhid-discuss] libhid with python: help appreciated
JamesPK
2011-09-08 10:45:36 UTC
Permalink
Hi,

Apologies for what might be a basic libhid question.

I'm running Ubuntu, and using libhid via Python to communicate with a
HID device (and have used 'lsusb' to glean all the details of the device).

I've started out with the example code here:
http://anonscm.debian.org/viewvc/libhid/trunk/swig/test_libhid.py .I
added the vendor and product ID and the example code itself worked FINE.

I then added some code to the example. From the 'snooping' on the
communication with the device under Windows it needs a control message
with an initialisation string to initialise the device, which I thought
would be:

INIT_SEQ='0x20 0x00 0x08 0x01 0x00 0x00 0x00 0x00'
ret = hid_interrupt_write(hid, 0, INIT_SEQ, 8)
if ret != HID_RET_SUCCESS:
log_error("hid_set_output_report", ret)

But when I added the above spinet to the example and run it I get:
(ALL messages fine up to here)
---------------------
NOTICE: hid_force_open(): successfully opened USB device 006/002[0].
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_dump_tree(): iterating the parse tree for USB device
006/002[0]...
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_interrupt_write(): writing interrupt report to device
006/002[0] ...
WARNING: hid_interrupt_write(): failed to perform interrupt write to
device 006/002[0]: error submitting URB: No such file or directory
---------------------

Any ideas/pointers would be much appreciated.

Thanks

James
Charles Lepple
2011-09-09 02:22:57 UTC
Permalink
BTW, please subscribe to the list:

http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/libhid-discuss

Thanks!
Post by JamesPK
Hi,
Apologies for what might be a basic libhid question.
I'm running Ubuntu, and using libhid via Python to communicate with
a HID device (and have used 'lsusb' to glean all the details of the
device).
I've started out with the example code here: http://anonscm.debian.org/viewvc/libhid/trunk/swig/test_libhid.py
.I added the vendor and product ID and the example code itself
worked FINE.
I then added some code to the example. From the 'snooping' on the
communication with the device under Windows it needs a control
message with an initialisation string to initialise the device,
Not to sound too nit-picky, but is it an actual USB control transfer,
or is it just a message that is being sent to the device?

USB has the notion of Control endpoints (EP0 IN and OUT), and also
Interrupt endpoints. Not all devices have interrupt endpoints, but if
you post the output of 'lsusb -v' (run as root, preferably after
something like libhid has detached the kernel HID driver), we can see
which endpoints are available.
Post by JamesPK
INIT_SEQ='0x20 0x00 0x08 0x01 0x00 0x00 0x00 0x00'
ret = hid_interrupt_write(hid, 0, INIT_SEQ, 8)
log_error("hid_set_output_report", ret)
(ALL messages fine up to here)
---------------------
NOTICE: hid_force_open(): successfully opened USB device 006/002[0].
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_dump_tree(): iterating the parse tree for USB device
006/002[0]...
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_interrupt_write(): writing interrupt report to device
006/002[0] ...
WARNING: hid_interrupt_write(): failed to perform interrupt write to
device 006/002[0]: error submitting URB: No such file or directory
---------------------
Ah, I think I see what's going on: you passed endpoint 0 to
hid_interrupt_write() - it should be 1 or higher. Again, lsusb output
will pin this down.
Post by JamesPK
Any ideas/pointers would be much appreciated.
Thanks
James
_______________________________________________
libhid-discuss mailing list
libhid-discuss at lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/libhid-discuss
http://libhid.alioth.debian.org/
JamesPK
2011-09-09 13:37:28 UTC
Permalink
Post by Charles Lepple
Post by JamesPK
Hi,
Apologies for what might be a basic libhid question.
I'm running Ubuntu, and using libhid via Python to communicate with a
HID device (and have used 'lsusb' to glean all the details of the device).
http://anonscm.debian.org/viewvc/libhid/trunk/swig/test_libhid.py .I
added the vendor and product ID and the example code itself worked FINE.
I then added some code to the example. From the 'snooping' on the
communication with the device under Windows it needs a control
message with an initialisation string to initialise the device, which
Not to sound too nit-picky, but is it an actual USB control transfer,
or is it just a message that is being sent to the device?
USB has the notion of Control endpoints (EP0 IN and OUT), and also
Interrupt endpoints. Not all devices have interrupt endpoints, but if
you post the output of 'lsusb -v' (run as root, preferably after
something like libhid has detached the kernel HID driver), we can see
which endpoints are available.
Good question - I'm not sure if its a control message required??? I
expect it might just be a normal 'write' message (as on double checking
the on the windows output the 'request' filed was set as listed as 'set
report' )

Ok - 'lsusb -v' is at base of post.
Post by Charles Lepple
Post by JamesPK
ret = hid_interrupt_write(hid, 0, INIT_SEQ, 8)
log_error("hid_set_output_report", ret)
(ALL messages fine up to here)
---------------------
NOTICE: hid_force_open(): successfully opened USB device 006/002[0].
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_dump_tree(): iterating the parse tree for USB device
006/002[0]...
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_interrupt_write(): writing interrupt report to device
006/002[0] ...
WARNING: hid_interrupt_write(): failed to perform interrupt write to
device 006/002[0]: error submitting URB: No such file or directory
---------------------
Ah, I think I see what's going on: you passed endpoint 0 to
hid_interrupt_write() - it should be 1 or higher. Again, lsusb output
will pin this down.
Thanks.

James
-----------------------------------------------------------------
jamespk at hal:~/project/driver/hidapi$ sudo lsusb -v -d 0fde:ca01

Bus 006 Device 002: ID 0fde:ca01
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0fde
idProduct 0xca01
bcdDevice 3.02
iManufacturer 0
iProduct 1 Universal Bridge
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
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
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 34
Report Descriptor: (length is 34)
Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Main ): Input, data= [ 0x00 ] 0
Data Array Absolute No_Wrap Linear
Preferred_State No_Null_Position
Non_Volatile Bitfield
Item(Local ): Usage, data= [ 0x02 ] 2
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Main ): Output, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position
Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)
--------------------------------------------
Charles Lepple
2011-09-09 23:08:56 UTC
Permalink
Post by JamesPK
Post by Charles Lepple
Post by JamesPK
Hi,
Apologies for what might be a basic libhid question.
I'm running Ubuntu, and using libhid via Python to communicate
with a HID device (and have used 'lsusb' to glean all the details
of the device).
I've started out with the example code here: http://anonscm.debian.org/viewvc/libhid/trunk/swig/test_libhid.py
.I added the vendor and product ID and the example code itself
worked FINE.
I then added some code to the example. From the 'snooping' on the
communication with the device under Windows it needs a control
message with an initialisation string to initialise the device,
Not to sound too nit-picky, but is it an actual USB control
transfer, or is it just a message that is being sent to the device?
USB has the notion of Control endpoints (EP0 IN and OUT), and also
Interrupt endpoints. Not all devices have interrupt endpoints, but
if you post the output of 'lsusb -v' (run as root, preferably after
something like libhid has detached the kernel HID driver), we can
see which endpoints are available.
Good question - I'm not sure if its a control message required??? I
expect it might just be a normal 'write' message (as on double
checking the on the windows output the 'request' filed was set as
listed as 'set report' )
Again, with several endpoints possible, the destination of the message
matters. (Windows apparently masks this difference when reading or
writing to HID interfaces - it uses an interrupt endpoint if
available, otherwise it issues a request on EP0.)

From below, you only have "EP 1 IN" (plus the always-present EP0 IN/
OUT).

You probably want to use hid_set_output_report():

http://libhid.alioth.debian.org/doc/hid__exchange_8c.html#7eb62286840ff33db4f68d58682bc4ad

And the path is going to look like { 0xFF000001, 0xFF000002 } (depth 2
since there are two elements). See the comments in the example source
code (or the archives of this list) for the derivation.

An alternate way of approaching this is to use one of the tools which
converts USBSnoop (or similar) log files to sequences of direct libusb
calls. Since your HID device is simply using the HID transport layer
to pass 8-byte messages around, you might find it easier to just use
libusb directly.

Look under "USB sniff log parser": http://www.piclist.com/techref/usbs.htm
Post by JamesPK
Ok - 'lsusb -v' is at base of post.
Post by Charles Lepple
Post by JamesPK
ret = hid_interrupt_write(hid, 0, INIT_SEQ, 8)
log_error("hid_set_output_report", ret)
(ALL messages fine up to here)
---------------------
NOTICE: hid_force_open(): successfully opened USB device 006/002[0].
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_dump_tree(): iterating the parse tree for USB device
006/002[0]...
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_interrupt_write(): writing interrupt report to device
006/002[0] ...
WARNING: hid_interrupt_write(): failed to perform interrupt write
to device 006/002[0]: error submitting URB: No such file or
directory
---------------------
Ah, I think I see what's going on: you passed endpoint 0 to
hid_interrupt_write() - it should be 1 or higher. Again, lsusb
output will pin this down.
Thanks.
James
-----------------------------------------------------------------
jamespk at hal:~/project/driver/hidapi$ sudo lsusb -v -d 0fde:ca01
Bus 006 Device 002: ID 0fde:ca01
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0fde
idProduct 0xca01
bcdDevice 3.02
iManufacturer 0
iProduct 1 Universal Bridge
iSerial 0
bNumConfigurations 1
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 34
Report Descriptor: (length is 34)
Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Main ): Input, data= [ 0x00 ] 0
Data Array Absolute No_Wrap Linear
Preferred_State No_Null_Position
Non_Volatile Bitfield
^ Up to 8 bytes of input to the PC, probably requested on either EP 1
IN, or EP0 via the GetReport message.
Post by JamesPK
Item(Local ): Usage, data= [ 0x02 ] 2
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Main ): Output, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position
Non_Volatile Bitfield
^ Up to 8 bytes of output from the PC, accepted only on EP0 via the
SetReport message.
Post by JamesPK
Item(Main ): End Collection, data=none
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)
--------------------------------------------
JamesPK
2011-09-12 12:00:16 UTC
Permalink
Thanks for your help. I'll try out your suggestions.

James
Post by Charles Lepple
Post by JamesPK
Post by Charles Lepple
Post by JamesPK
Hi,
Apologies for what might be a basic libhid question.
I'm running Ubuntu, and using libhid via Python to communicate with
a HID device (and have used 'lsusb' to glean all the details of the
device).
http://anonscm.debian.org/viewvc/libhid/trunk/swig/test_libhid.py .I added
the vendor and product ID and the example code itself worked FINE.
I then added some code to the example. From the 'snooping' on the
communication with the device under Windows it needs a control
message with an initialisation string to initialise the device,
Not to sound too nit-picky, but is it an actual USB control
transfer, or is it just a message that is being sent to the device?
USB has the notion of Control endpoints (EP0 IN and OUT), and also
Interrupt endpoints. Not all devices have interrupt endpoints, but
if you post the output of 'lsusb -v' (run as root, preferably after
something like libhid has detached the kernel HID driver), we can
see which endpoints are available.
Good question - I'm not sure if its a control message required??? I
expect it might just be a normal 'write' message (as on double
checking the on the windows output the 'request' filed was set as
listed as 'set report' )
Again, with several endpoints possible, the destination of the message
matters. (Windows apparently masks this difference when reading or
writing to HID interfaces - it uses an interrupt endpoint if
available, otherwise it issues a request on EP0.)
From below, you only have "EP 1 IN" (plus the always-present EP0 IN/OUT).
http://libhid.alioth.debian.org/doc/hid__exchange_8c.html#7eb62286840ff33db4f68d58682bc4ad
And the path is going to look like { 0xFF000001, 0xFF000002 } (depth 2
since there are two elements). See the comments in the example source
code (or the archives of this list) for the derivation.
An alternate way of approaching this is to use one of the tools which
converts USBSnoop (or similar) log files to sequences of direct libusb
calls. Since your HID device is simply using the HID transport layer
to pass 8-byte messages around, you might find it easier to just use
libusb directly.
http://www.piclist.com/techref/usbs.htm
Post by JamesPK
Ok - 'lsusb -v' is at base of post.
Post by Charles Lepple
Post by JamesPK
ret = hid_interrupt_write(hid, 0, INIT_SEQ, 8)
log_error("hid_set_output_report", ret)
(ALL messages fine up to here)
---------------------
NOTICE: hid_force_open(): successfully opened USB device 006/002[0].
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_dump_tree(): iterating the parse tree for USB device
006/002[0]...
TRACE: hid_reset_parser(): resetting the HID parser for USB device
006/002[0]...
TRACE: hid_interrupt_write(): writing interrupt report to device
006/002[0] ...
WARNING: hid_interrupt_write(): failed to perform interrupt write
to device 006/002[0]: error submitting URB: No such file or directory
---------------------
Ah, I think I see what's going on: you passed endpoint 0 to
hid_interrupt_write() - it should be 1 or higher. Again, lsusb
output will pin this down.
Thanks.
James
-----------------------------------------------------------------
jamespk at hal:~/project/driver/hidapi$ sudo lsusb -v -d 0fde:ca01
Bus 006 Device 002: ID 0fde:ca01
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0fde
idProduct 0xca01
bcdDevice 3.02
iManufacturer 0
iProduct 1 Universal Bridge
iSerial 0
bNumConfigurations 1
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 34
Report Descriptor: (length is 34)
Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Main ): Input, data= [ 0x00 ] 0
Data Array Absolute No_Wrap Linear
Preferred_State No_Null_Position
Non_Volatile Bitfield
^ Up to 8 bytes of input to the PC, probably requested on either EP 1
IN, or EP0 via the GetReport message.
Post by JamesPK
Item(Local ): Usage, data= [ 0x02 ] 2
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Main ): Output, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position
Non_Volatile Bitfield
^ Up to 8 bytes of output from the PC, accepted only on EP0 via the
SetReport message.
Post by JamesPK
Item(Main ): End Collection, data=none
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)
--------------------------------------------
Loading...