USB cdc_acm 驱动程序未将数据接口分配给任何端口

Pie*_* B. 6 usb serial-port usb-device

我有一个模拟串行 USB 通信的 USB CDC-ACM 设备。CDC Communications 和Data 接口分别显示在2-1:1.0 (Comm) 和2-1:1.1 (Data) 接口描述符上,并且cdc_acm驱动程序正在正确加载。

我的问题是,只有通信接口被分配到/dev/ttyACMXcdc_acm驱动程序,但数据接口被忽略。它似乎会阻止设备正常工作(使用 ccTalk 协议的 GBA ST2 Bill Validator)。它在使用usbser.sys驱动程序的Windows 8+ 上运行良好。

With cdc_acm driver, dmesg and lsusb output is:

$ dmesg
[ 3484.982436] usb 2-1: new full-speed USB device number 4 using ohci-pci
[ 3485.251788] usb 2-1: New USB device found, idVendor=16f9, idProduct=0003
[ 3485.251792] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3485.251794] usb 2-1: Product: GBA ST2
[ 3485.251795] usb 2-1: Manufacturer: Astrosystems
[ 3485.251796] usb 2-1: SerialNumber: 06010010001
[ 3485.260103] cdc_acm 2-1:1.0: ttyACM0: USB ACM device

$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ohci-pci/12p, 12M
    |__ Port 1: Dev 4, If 0, Class=Communications, Driver=cdc_acm, 12M
    |__ Port 1: Dev 4, If 1, Class=CDC Data, Driver=cdc_acm, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/12p, 480M
Run Code Online (Sandbox Code Playgroud)

Showing that:

  • 2-1:1.0 is assigned to /dev/ttyACM0
  • 2-1:1.1 is ignored

By playing around with the usbserial driver to assign the Data interface to a /dev/ttyUSBX port I found that the following manipulation sometimes works:

  1. plug-in the device and have it use the cdc_acm driver. This cause the device to exit its sleep mode (the device leds becomes green)
  2. Switch to the usbserial driver using modprobe -r cdc_acm && modprobe usbserial vendor=0x16f9 product=0x0003, resulting in the Comm interface being ignored and Data interface assigned to a USB port
  3. If the device goes back to sleep mode, it needs to be re-plugged and initialized again from step 1

When using the usbserial driver:

  • 2-1:1.0 is ignored
  • 2-1:1.1 is assigned to /dev/ttyUSBX

Related dmesg and lsusb:

$ dmesg
[ 3688.481125] usbserial_generic 2-1:1.0: Generic device with no bulk out, not allowed.
[ 3688.481153] usbserial_generic: probe of 2-1:1.0 failed with error -5
[ 3688.481157] usbserial_generic 2-1:1.1: The "generic" usb-serial driver is only for testing and one-off prototypes.
[ 3688.481158] usbserial_generic 2-1:1.1: Tell linux-usb@vger.kernel.org to add your device to a proper driver.
[ 3688.481160] usbserial_generic 2-1:1.1: generic converter detected
[ 3688.481219] usb 2-1: generic converter now attached to ttyUSB0

$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ohci-pci/12p, 12M
    |__ Port 1: Dev 4, If 0, Class=Communications, Driver=, 12M
    |__ Port 1: Dev 4, If 1, Class=CDC Data, Driver=usbserial_generic, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/12p, 480M
Run Code Online (Sandbox Code Playgroud)

My guess is that the device use the CDC Communication interface to perform some sort of initialization, and then the CDC Data interface when in use.

How can I have both interfaces attached to a USB and/or ACM port? Should I implement my own driver (or extend the cdc_acm driver) to explicitely attach each descriptor to a USB or ACM port?

Here is a sample lsusb -v output showing the Communication interface on 2-1:1.0 and Data interface on 2-1:1.1:

Bus 002 Device 003: ID 16f9:0003
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            2 Communications
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x16f9
  idProduct          0x0003
  bcdDevice           14.06
  iManufacturer           1 Astrosystems
  iProduct                2 GBA ST2
  iSerial                 3 06010010001
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           62
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              4 GBA USB Serial Port
      CDC Header:
        bcdCDC               1.20
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              50
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0
      iInterface              4 GBA USB Serial Port
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Status:     0x0001
  Self Powered
Run Code Online (Sandbox Code Playgroud)