'I cannot mimic sniffed urb interruption using libusb for Ruby
Sniffed URB_INTERRUPTions
I sniffed communication between some application (SoundLab) and device (sonometer with usb). I found a packet responsible for returning current state:
USB URB
[Source: host]
[Destination: 1.1.2]
USBPcap pseudoheader length: 27
IRP ID: 0xffff858d126f4a60
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER (0x0009)
IRP information: 0x00, Direction: FDO -> PDO
0000 000. = Reserved: 0x00
.... ...0 = Direction: FDO -> PDO (0x0)
URB bus id: 1
Device address: 1
Endpoint: 0x02, Direction: OUT
0... .... = Direction: OUT (0)
.... 0010 = Endpoint number: 2
URB transfer type: URB_INTERRUPT (0x01)
Packet Data Length: 8
[bInterfaceClass: Unknown (0xffff)]
Leftover Capture Data: b331eb4d00000000
It is sent by application to endpoint number 2 (out), and then device sends urb interruption with data to endpoint number 1 (in):
USB URB
[Source: 1.1.1]
[Destination: host]
USBPcap pseudoheader length: 27
IRP ID: 0xffff858d10207af0
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER (0x0009)
IRP information: 0x01, Direction: PDO -> FDO
0000 000. = Reserved: 0x00
.... ...1 = Direction: PDO -> FDO (0x1)
URB bus id: 1
Device address: 1
Endpoint: 0x81, Direction: IN
1... .... = Direction: IN (1)
.... 0001 = Endpoint number: 1
URB transfer type: URB_INTERRUPT (0x01)
Packet Data Length: 8
[bInterfaceClass: Unknown (0xffff)]
Leftover Capture Data: 01a9009b90ddc0ff
Attempt to mimic interruptions with libusb
Now I want to mimic this in Linux, using libusb. I wrote this code where I can test different interruptions.
require 'libusb'
require 'pry'
vendor_id = 0x64bd
product_id = 0x74e3
module Messages
GET_STATE = ['b331eb4d00000000'].pack('H*')
end
usb = LIBUSB::Context.new
device = usb.devices(idVendor: vendor_id, idProduct: product_id).first
dev_handle = device.open
if dev_handle.kernel_driver_active?(0)
dev_handle.detach_kernel_driver(0)
end
dev_handle.claim_interface(0)
binding.pry
dev_handle.release_interface(0)
dev_handle.close
Then I run this in pry console:
dev_handle.interrupt_transfer(endpoint: 2, dataOut: Messages::GET_STATE)
And it returns 8. That is not what I expected.
URB_INTERRUPTions I see when I run my code
USB URB
[Source: host]
[Destination: 1.6.2]
URB id: 0xffff8802142fecc0
URB type: URB_SUBMIT ('S')
URB transfer type: URB_INTERRUPT (0x01)
Endpoint: 0x02, Direction: OUT
Device: 6
URB bus id: 1
Device setup request: not relevant ('-')
Data: present (0)
URB sec: 1559130571
URB usec: 534195
URB status: Operation now in progress (-EINPROGRESS) (-115)
URB length [bytes]: 8
Data length [bytes]: 8
[Response in: 126]
[bInterfaceClass: HID (0x03)]
Unused Setup Header
Interval: 8
Start frame: 0
Copy of Transfer Flags: 0x00000000
Number of ISO descriptors: 0
Leftover Capture Data: b331eb4d00000000
USB URB
[Source: 1.6.2]
[Destination: host]
URB id: 0xffff8802142fecc0
URB type: URB_COMPLETE ('C')
URB transfer type: URB_INTERRUPT (0x01)
Endpoint: 0x02, Direction: OUT
Device: 6
URB bus id: 1
Device setup request: not relevant ('-')
Data: not present ('>')
URB sec: 1559130571
URB usec: 534846
URB status: Success (0)
URB length [bytes]: 8
Data length [bytes]: 0
[Request in: 125]
[Time from request: 0.000651000 seconds]
[bInterfaceClass: HID (0x03)]
Unused Setup Header
Interval: 8
Start frame: 0
Copy of Transfer Flags: 0x00000000
Number of ISO descriptors: 0
Summary
In result I get URB_INTERRUPTions that are much different from what I saw on Windows. On Windows I had urb_interrupt to 2 (out) endpoint with data requesting state of device. Then device was sending urb_interrupt to 1 (in) endpoint with current state encoded in capture data. How can I mimic this with LIBUSB::DevHandle#interrupt_transfer? Here is documentation of this method: https://www.rubydoc.info/gems/libusb/LIBUSB/DevHandle#interrupt_transfer-instance_method.
Solution 1:[1]
I tried meld-ing the expected versus received USB output that you posted, and the main thing that stood out to me was that your 'actual' USB protocol captures showed one URB_INTERRUPT in (marked by the 'direction' field). In your 'actual' USB traffic dump, it looks like you have 2 URB_INTERRUPT outs.
I'm not an expert in the USB protocol (I came across this question while myself stumbling around for help reverse-engineering a USB driver as well), but from what I can tell, to get a URB_INTERRUPT 'in' (which is what you have in the expected output), you have to change the endpoint address to 0x82 instead of just 2.
This answer talks about this further: https://superuser.com/a/876773/618124
USB endpoints 0x00-0x7F are on the host, and the endpoints 0x80-0xFF are on the device (I think).
Give that shot and see if it works?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
