Anatoly Verkhovsky
2014-11-13 14:14:27 UTC
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
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