udev: How do you identify the physical device that a sys device belongs to?

23,669

Okay, first I now understand what the documentation for $id means by

The name of the device matched while searching the devpath upwards for SUBSYSTEMS, KERNELS, DRIVERS and ATTRS.

...and it's not what I thought (which was formed by failing to understand the documentation combined with some experimentation).

By "The name of the device", it's talking about the same thing the KERNEL key matches. The documentation says about the KERNEL key is:

Match the name of the event device.

That is how you know "name" and "KERNEL" are related.

The "matched while searching the devpath upwards for SUBSYSTEMS, KERNELS, DRIVERS and ATTRS" part means that if you specified a "SUBSYSTEMS, KERNELS, DRIVERS, or ATTRS" match in the rule, it will walk up the device tree until it finds a match; the name of the matched device will be used.

So, in my first rule, it was matching with the ATTRS key, and that device happened to be the physical USB device.

Now for my other rule, I had to look at the tree and find something that would match the physical device but not anything below it. Here is my device tree:

# udevadm info --attribute-walk --name=/dev/cdc-wdm0

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/platform/atmel-ehci/usb1/1-1/1-1.7/1-1.7.2/1-1.7.2:1.5/usb/cdc-wdm0':
    KERNEL=="cdc-wdm0"
    SUBSYSTEM=="usb"
    DRIVER==""

  looking at parent device '/devices/platform/atmel-ehci/usb1/1-1/1-1.7/1-1.7.2/1-1.7.2:1.5':
    KERNELS=="1-1.7.2:1.5"
    SUBSYSTEMS=="usb"
    DRIVERS=="qmi_wwan"
    ATTRS{bInterfaceNumber}=="05"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="03"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceSubClass}=="f1"
    ATTRS{bInterfaceProtocol}=="ff"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/platform/atmel-ehci/usb1/1-1/1-1.7/1-1.7.2':
    KERNELS=="1-1.7.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}=="Pantech, Incorporated"
    ATTRS{bNumInterfaces}==" 6"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bMaxPower}=="500mA"
    ATTRS{urbnum}=="496"
    ATTRS{idVendor}=="106c"
    ATTRS{idProduct}=="3718"
    ATTRS{bcdDevice}=="0000"
    ATTRS{bDeviceClass}=="02"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="12"
    ATTRS{devpath}=="1.7.2"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Pantech, Incorporated"
    ATTRS{product}=="PANTECH UML290"

  looking at parent device '/devices/platform/atmel-ehci/usb1/1-1/1-1.7':
    KERNELS=="1-1.7"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{urbnum}=="188"
    ATTRS{idVendor}=="1a40"
    ATTRS{idProduct}=="0101"
    ATTRS{bcdDevice}=="0111"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="3"
    ATTRS{devpath}=="1.7"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="4"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{product}=="USB 2.0 Hub"

  looking at parent device '/devices/platform/atmel-ehci/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{urbnum}=="53"
    ATTRS{idVendor}=="1a40"
    ATTRS{idProduct}=="0201"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="2"
    ATTRS{devpath}=="1"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="7"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{product}=="USB 2.0 Hub [MTT]"

  looking at parent device '/devices/platform/atmel-ehci/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="26"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0002"
    ATTRS{bcdDevice}=="0206"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="3"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 2.6.39.4-acnbfx100 ehci_hcd"
    ATTRS{product}=="Atmel EHCI UHP HS"
    ATTRS{serial}=="atmel-ehci"
    ATTRS{authorized_default}=="1"

  looking at parent device '/devices/platform/atmel-ehci':
    KERNELS=="atmel-ehci"
    SUBSYSTEMS=="platform"
    DRIVERS=="atmel-ehci"
    ATTRS{companion}==""

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""

The device I want to match is /devices/platform/atmel-ehci/usb1/1-1/1-1.7/1-1.7.2'. You can see that the DRIVERS for that device is 'usb' and nothing below it will match that. The following rule solves my problem, should even be a generic solution since I'm pretty sure no endpoint of a device would be handled by the usb driver.

DRIVERS=="usb", KERNEL=="*cdc-wdm*", ENV{id}="$id", RUN="/usr/local/bin/modem_setup.sh"

And the is the result I was looking for all along:

# udevadm info --query=all --name=/dev/cdc-wdm0
P: /devices/platform/atmel-ehci/usb1/1-1/1-1.7/1-1.7.2/1-1.7.2:1.5/usb/cdc-wdm0
N: cdc-wdm0
E: DEVNAME=/dev/cdc-wdm0
E: DEVPATH=/devices/platform/atmel-ehci/usb1/1-1/1-1.7/1-1.7.2/1-1.7.2:1.5/usb/cdc-wdm0
E: MAJOR=180
E: MINOR=176
E: SUBSYSTEM=usb
E: USEC_INITIALIZED=12243969
E: id=1-1.7.2
Share:
23,669

Related videos on Youtube

Shawn J. Goff
Author by

Shawn J. Goff

I've grown up with computers around me my whole life. I started programming when I was a kid, and stuck with it ever since. I came across Linux around 1999 and have enjoyed working with it ever since. For a job, I get to write software that runs on embedded Linux devices. I do everything from working on low-level drivers to writing shell scripts and even web apps.

Updated on September 18, 2022

Comments

  • Shawn J. Goff
    Shawn J. Goff over 1 year

    I have several USB modems that each have several endpoints: lot of TTYs, a network interface, a cdc-wdm port, and some other things. I'm trying to group them together so that I know, for instance, ttyUSB3, ttyUSB4, wwan1, and cdc-wdm1 all belong to the same physical USB device.

    I thought $id was supposed to identify the physical device, so I tried adding $id to the environment with ENV{id}=$id. This seems to work for the network interfaces and serial ports, but not the cdc-wdm ports (id is unset for these ports).

    Here is some example data after adding the ENV{id}=$id rules:

    rule: SUBSYSTEM=="net", ATTRS{idVendor}=="106c", ATTRS{idProduct}=="3718", ENV{id}="$id"

    # udevadm info --query=all --path=/devices/platform/atmel-ehci/usb1/1-1/1-1.3/1-
    1.3:1.5/net/wwan0
    P: /devices/platform/atmel-ehci/usb1/1-1/1-1.3/1-1.3:1.5/net/wwan0
    E: DEVPATH=/devices/platform/atmel-ehci/usb1/1-1/1-1.3/1-1.3:1.5/net/wwan0
    E: DEVTYPE=wwan
    E: ID_BUS=usb
    E: ID_MODEL=PANTECH_UML290
    E: ID_MODEL_ENC=PANTECH\x20UML290
    E: ID_MODEL_ID=3718
    E: ID_REVISION=0000
    E: ID_SERIAL=Pantech__Incorporated_PANTECH_UML290
    E: ID_TYPE=generic
    E: ID_USB_DRIVER=qmi_wwan
    E: ID_USB_INTERFACES=:020201:0a0000:ffffff:fffdff:fffeff:fff1ff:
    E: ID_USB_INTERFACE_NUM=05
    E: ID_VENDOR=Pantech__Incorporated
    E: ID_VENDOR_ENC=Pantech\x2c\x20Incorporated
    E: ID_VENDOR_ID=106c
    E: IFINDEX=5
    E: INTERFACE=wwan0
    E: SUBSYSTEM=net
    E: USEC_INITIALIZED=174833330
    E: id=1-1.3
    

    rule: SUBSYSTEM=="usb", KERNEL=="*cdc-wdm*", ENV{id}="$id"

    # udevadm info --query=all --path=/devices/platform/atmel-ehci/usb1/1-1/1-1.3/1-
    1.3:1.5/usb/cdc-wdm0
    P: /devices/platform/atmel-ehci/usb1/1-1/1-1.3/1-1.3:1.5/usb/cdc-wdm0
    N: cdc-wdm0
    E: DEVNAME=/dev/cdc-wdm0
    E: DEVPATH=/devices/platform/atmel-ehci/usb1/1-1/1-1.3/1-1.3:1.5/usb/cdc-wdm0
    E: MAJOR=180
    E: MINOR=176
    E: SUBSYSTEM=usb
    E: USEC_INITIALIZED=174788259