2

I'm trying to use udev to give relevant names a USB-serial device but I'm having no luck.

    # lsusb -d 04e2:1412 -v
Bus 004 Device 028: ID 04e2:1412 Exar Corp. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 Common Class
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x04e2 Exar Corp.
  idProduct          0x1412 
  bcdDevice            0.02
  iManufacturer           0 
  iProduct                0 
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          141
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower               94mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       0 None
      iFunction               0 
    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              0 
      CDC Header:
        bcdCDC               1.10
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      CDC Call Management:
        bmCapabilities       0x01
          call management
        bDataInterface          1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 
      iInterface              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
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         2
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       0 None
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0 
      CDC Header:
        bcdCDC               1.10
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        2
        bSlaveInterface         3 
      CDC Call Management:
        bmCapabilities       0x01
          call management
        bDataInterface          3
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x86  EP 6 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        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     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Status:     0x0000
  (Bus Powered)

The udev rules I'm trying are:

    KERNEL=="ttyUSB[0-9]*", SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="01", ATTRS{idVendor}=="04e2", ATTRS{idProduct}=="1412",  ACTION=="add", SYMLINK+="test_USB0"
    KERNEL=="ttyUSB[0-9]*", SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="01", ATTRS{idVendor}=="04e2", ATTRS{idProduct}=="1412",  ACTION=="add", SYMLINK+="test_USB1"
    KERNEL=="ttyUSB[0-9]*", SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="02", ATTRS{idVendor}=="04e2", ATTRS{idProduct}=="1412",  ACTION=="add", SYMLINK+="test_USB2"
    KERNEL=="ttyUSB[0-9]*", SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="03", ATTRS{idVendor}=="04e2", ATTRS{idProduct}=="1412",  ACTION=="add", SYMLINK+="test_USB3"

When I used only the first udev rule without the bInterfaceNumber attribute, like so:

    KERNEL=="ttyUSB[0-9]*", SUBSYSTEMS=="usb", ATTRS{idVendor}=="04e2", ATTRS{idProduct}=="1412",  ACTION=="add", SYMLINK+="test_USB0"

It works ok. I can see the symbolic link /dev/test_USB0 created which points to /dev/ttyUSB0 but what about the other ttyUSB devices created when I plugged in this USB-serial device?

That was why I wanted to use the bInterfaceNumber attribute but when I put it in, nothing happened and it seemed to completely bypass my rule.

Can anyone help me with this?

yaobin
  • 125

2 Answers2

2

You can use ENV{ID_USB_INTERFACE_NUM}, defined in /lib64/udev/rules.d/60-persistent-serial.rules

Use udevadm test to check what environment available.

user.dz
  • 698
Alexander
  • 121
1

It looks like the rule didn't work because you mixed attributes from different parent devices.

The article Writing udev rules mentions this case in the section "udevinfo":

You may have noted the use of colour in the above examples. This is to demonstrate that while it is legal to combine the attributes from the device in question and a single parent device, you cannot mix-and-match attributes from multiple parent devices - your rule will not work.

The problem with lsusb -v is it lists the information of the device itself and its parent devices together so you can't tell whether the attributes come from the same parent device or from multiple parent devices.

However, if you use udevadm info (on Ubuntu) or udevinfo (as the author used), you should be able to print the hierarchy of the devices. In the article, the author gave the following example:

# udevinfo -a -p /sys/block/sda

looking at device '/block/sda': KERNEL=="sda" SUBSYSTEM=="block" ATTR{stat}==" 128535 2246 2788977 766188 73998 317300 3132216 5735004 0 516516 6503316" ATTR{size}=="234441648" ATTR{removable}=="0" ATTR{range}=="16" ATTR{dev}=="8:0"

looking at parent device '/devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0': KERNELS=="0:0:0:0" SUBSYSTEMS=="scsi" DRIVERS=="sd" ATTRS{ioerr_cnt}=="0x0" ATTRS{iodone_cnt}=="0x31737" ATTRS{iorequest_cnt}=="0x31737" ATTRS{iocounterbits}=="32" ATTRS{timeout}=="30" ATTRS{state}=="running" ATTRS{rev}=="3.42" ATTRS{model}=="ST3120827AS " ATTRS{vendor}=="ATA " ATTRS{scsi_level}=="6" ATTRS{type}=="0" ATTRS{queue_type}=="none" ATTRS{queue_depth}=="1" ATTRS{device_blocked}=="0"

looking at parent device '/devices/pci0000:00/0000:00:07.0': KERNELS=="0000:00:07.0" SUBSYSTEMS=="pci" DRIVERS=="sata_nv" ATTRS{vendor}=="0x10de" ATTRS{device}=="0x037f"

So the following rule would work because:

  • SUBSYSTEM=="block" comes from the device itself.
  • Both SUBSYSTEMS=="scsi" and ATTRS{model}=="ST3120827AS" come from the same parent device /devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0.
SUBSYSTEM=="block", SUBSYSTEMS=="scsi", ATTRS{model}=="ST3120827AS", NAME="my_hard_disk"

However, as the author said, the following rule would not work because ATTRS{model}=="ST3120827AS" and DRIVERS=="sata_nv" come from two different parent devices:

SUBSYSTEM=="block", ATTRS{model}=="ST3120827AS", DRIVERS=="sata_nv", NAME="my_hard_disk"

So I would suggest the OP to check the device hierarchy using udevadm info (or udevinfo) command to see if you are mixing attributes from different parent devices.

I happen to be working on a USB device today and the output of udevadm info (I'm using Ubuntu 18.04) showed me that the vendor ID and product ID belong to one parent device, but bInterfaceNumber belongs to another parent device. Therefore, when your rule only contained the vendor ID and product ID, it was the case of "single parent device" so it would work. When you added bInterfaceNumber into the rule, and if your USB device has a similar device hierarchy as my USB device, the rule would not work because it was a case of mixing multiple parent devices.

yaobin
  • 125