Я не могу имитировать прерывание обнюхенного urb, используя libusb для Ruby - PullRequest
1 голос
/ 29 мая 2019

Обнюхенный URB_INTERRUPTions

Я понюхал связь между каким-то приложением (SoundLab) и устройством (сонометр с usb). Я нашел пакет, отвечающий за возврат текущего состояния:

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

Он отправляется приложением на конечную точку № 2 (выход), а затем устройство отправляет прерывание urb с данными на конечную точку № 1 (вход):

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

Попытка имитировать прерывания с помощью libusb

Теперь я хочу имитировать это в Linux, используя libusb . Я написал этот код, где я могу тестировать различные прерывания.

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

Затем я запускаю это в pry консоли:

dev_handle.interrupt_transfer(endpoint: 2, dataOut: Messages::GET_STATE)

И он возвращает 8. Это не то, что я ожидал.

URB_INTERRUPTions, которые я вижу, когда запускаю свой код

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

Краткое описание

В результате я получаю URB_INTERRUPTions, которые сильно отличаются от того, что я видел в Windows. В Windows у меня был urb_interrupt до 2 (выходной) конечной точки с данными, запрашивающими состояние устройства. Затем устройство отправляло urb_interrupt в конечную точку 1 (in) с текущим состоянием, кодированным в данных захвата. Как я могу имитировать это с LIBUSB::DevHandle#interrupt_transfer? Вот документация этого метода: https://www.rubydoc.info/gems/libusb/LIBUSB/DevHandle#interrupt_transfer-instance_method.

...