Discussion:
[pyusb-users] Help with writing a driver for USB HID device.
Anatoly Verkhovsky
2014-11-13 14:14:27 UTC
Permalink
Hi,

I'm writing a driver for a device. It was originally using MDB ICP, but
now it ships with a USB to MDB bridge, why they have chosen to do it as HID
rather then USB Serial i have no idea. So behind the usb there is a simple
serial protocol.

Here is what lsusb gives:

Bus 001 Device 027: ID 155d:0002
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x155d
idProduct 0x0002
bcdDevice 2.95
iManufacturer 1 (error)
iProduct 2 NRI-USB-HID-DEV-01
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 8 Main Configuration
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 5 Alternate Setting1
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 30
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 8
Device Status: 0x0001
Self Powered

I take it, this means one configuration, one interface, one end point. So
the data should be read from endpoint at address 0x82, and data should be
written to endpoint 0x00 with ctrl_transfer, is that correct?

Here is a SnoopyPro trace of control software running on windows, for
message sent to device:

URB Header (length: 80)
SequenceNumber: 21
Function: 001b (CLASS_INTERFACE)
PipeHandle: 00000000

SetupPacket:
0000: 22 09 00 03 00 00 00 00
bmRequestType: 22
DIR: Host-To-Device
TYPE: Class
RECIPIENT: Endpoint
bRequest: 09

TransferBuffer: 0x00000008 (8) length
0000: 03 02 85 0a 05 14 ff ff


The payload of this is [0x02 0x85 0x0a], that's the init command as
described in device docs. The device replies with this:

URB Header (length: 80)
SequenceNumber: 22
Function: 0008 (CONTROL_TRANSFER)
PipeHandle: 86d039cc

SetupPacket:
0000: a1 01 00 03 00 00 08 00
bmRequestType: a1
DIR: Device-To-Host
TYPE: Class
RECIPIENT: Interface
bRequest: 01

TransferBuffer: 0x00000008 (8) length
0000: 01 2e ff ff ff ff ff ff

Payload of this is [0x2E] again per spec. Now my goal is to reproduce this
simple exchange, once i have that i can go on to implement all other needed
commands.
I'm guessing that the protocol messages are prepended with message size
byte and padded up to 8 bytes with 0xFF or random data
Curiously snoopyPro generates traces even if the control application is not
loaded, i assume these messages don't make it to the actual device.

Here is the gist of my code:

dev = usb.core.find(idVendor=0x155d, idProduct=0x0002)
# check and remove kernel driver
dev.set_configuration()
dev.reset()
# bmRequestType, bRequest are taken from SnoopyPro trace.
res = dev.ctrl_transfer(0x22, 0x9, 0, 0, [0x02, 0x85, 0x0a], 1000)
data = dev.read(0x82, 32, timeout=10000)

ctrl_transfer fails with USBError(32, 'Pipe error') and
after couple of retries : USBError(19, 'No such device (it may have been
disconnected)')
i have also tried the whole byte string from the capture

res = dev.ctrl_transfer(0x22, 0x9, 0, 0, [0x03, 0x02, 0x85, 0x0a, 0x05,
0x14, 0xff, 0xff], 1000)

to same effect.

So what am i missing?
Why is the trace saying that host to device message is using function 0x1b
(Class interface) and device to host is using function 0x08 (control
transfer), shouldn't it be the other way around?

thanks,
Anatoli
Wander Lairson Costa
2014-12-27 01:40:38 UTC
Permalink
Hi,
Hi, sorry for the delay, but I was out most of the month.
I'm writing a driver for a device. It was originally using MDB ICP, but now
it ships with a USB to MDB bridge, why they have chosen to do it as HID
rather then USB Serial i have no idea. So behind the usb there is a simple
serial protocol.
[snip]
dev = usb.core.find(idVendor=0x155d, idProduct=0x0002)
# check and remove kernel driver
dev.set_configuration()
dev.reset()
iirc, reset is problematic in Windows (maybe a should log a warning
for this), what if you remove it?
# bmRequestType, bRequest are taken from SnoopyPro trace.
res = dev.ctrl_transfer(0x22, 0x9, 0, 0, [0x02, 0x85, 0x0a], 1000)
This seems to be a class request, so it is a HID class request?
data = dev.read(0x82, 32, timeout=10000)
ctrl_transfer fails with USBError(32, 'Pipe error') and
after couple of retries : USBError(19, 'No such device (it may have been
disconnected)')
In general, this kind of errors in Windows is due to the reset call.
i have also tried the whole byte string from the capture
res = dev.ctrl_transfer(0x22, 0x9, 0, 0, [0x03, 0x02, 0x85, 0x0a, 0x05,
0x14, 0xff, 0xff], 1000)
to same effect.
So what am i missing?
Why is the trace saying that host to device message is using function 0x1b
(Class interface) and device to host is using function 0x08 (control
transfer), shouldn't it be the other way around?
thanks,
Anatoli
------------------------------------------------------------------------------
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
_______________________________________________
pyusb-users mailing list
https://lists.sourceforge.net/lists/listinfo/pyusb-users
--
Best Regards,
Wander Lairson Costa
Loading...