3

I'm attempting to write a udev rule for a usb device that eventually loads as an hid device. Here's the udevadm info for the device:

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/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3.3/1-1.2.3.3:1.0/0003:20CE:0023.0010/hidraw/hidraw15': KERNEL=="hidraw15" SUBSYSTEM=="hidraw" DRIVER=="" looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3.3/1-1.2.3.3:1.0/0003:20CE:0023.0010': KERNELS=="0003:20CE:0023.0010" SUBSYSTEMS=="hid" DRIVERS=="hid-generic" ATTRS{country}=="00" looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3.3/1-1.2.3.3:1.0': KERNELS=="1-1.2.3.3:1.0" SUBSYSTEMS=="usb" DRIVERS=="usbhid" ATTRS{authorized}=="1" ATTRS{bAlternateSetting}==" 0" ATTRS{bInterfaceClass}=="03" ATTRS{bInterfaceNumber}=="00" ATTRS{bInterfaceProtocol}=="00" ATTRS{bInterfaceSubClass}=="00" ATTRS{bNumEndpoints}=="02" ATTRS{supports_autosuspend}=="1" looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3.3': KERNELS=="1-1.2.3.3" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="64" ATTRS{bMaxPower}=="100mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="0100" ATTRS{bmAttributes}=="c0" ATTRS{busnum}=="1" ATTRS{configuration}=="" ATTRS{devnum}=="25" ATTRS{devpath}=="1.2.3.3" ATTRS{idProduct}=="0023" ATTRS{idVendor}=="20ce" ATTRS{ltm_capable}=="no" ATTRS{manufacturer}=="MCL" ATTRS{maxchild}=="0" ATTRS{product}=="Mini-Circuits" ATTRS{quirks}=="0x0" ATTRS{removable}=="unknown" ATTRS{speed}=="12" ATTRS{urbnum}=="12" ATTRS{version}==" 1.10" looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.3': KERNELS=="1-1.2.3" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="09" ATTRS{bDeviceProtocol}=="02" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="64" ATTRS{bMaxPower}=="100mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="9224" ATTRS{bmAttributes}=="e0" ATTRS{busnum}=="1" ATTRS{configuration}=="" ATTRS{devnum}=="6" ATTRS{devpath}=="1.2.3" ATTRS{idProduct}=="0610" ATTRS{idVendor}=="05e3" ATTRS{ltm_capable}=="no" ATTRS{manufacturer}=="GenesysLogic" ATTRS{maxchild}=="4" ATTRS{product}=="USB2.0 Hub" ATTRS{quirks}=="0x0" ATTRS{removable}=="fixed" ATTRS{speed}=="480" ATTRS{urbnum}=="70" ATTRS{version}==" 2.00" looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2': KERNELS=="1-1.2" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="09" ATTRS{bDeviceProtocol}=="02" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="64" ATTRS{bMaxPower}=="100mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="9224" ATTRS{bmAttributes}=="e0" ATTRS{busnum}=="1" ATTRS{configuration}=="" ATTRS{devnum}=="4" ATTRS{devpath}=="1.2" ATTRS{idProduct}=="0610" ATTRS{idVendor}=="05e3" ATTRS{ltm_capable}=="no" ATTRS{manufacturer}=="GenesysLogic" ATTRS{maxchild}=="4" ATTRS{product}=="USB2.0 Hub" ATTRS{quirks}=="0x0" ATTRS{removable}=="removable" ATTRS{speed}=="480" ATTRS{urbnum}=="80" ATTRS{version}==" 2.00" looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1': KERNELS=="1-1" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="09" ATTRS{bDeviceProtocol}=="02" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="64" ATTRS{bMaxPower}=="2mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="0200" ATTRS{bmAttributes}=="e0" ATTRS{busnum}=="1" ATTRS{configuration}=="" ATTRS{devnum}=="2" ATTRS{devpath}=="1" ATTRS{idProduct}=="9514" ATTRS{idVendor}=="0424" ATTRS{ltm_capable}=="no" ATTRS{maxchild}=="5" ATTRS{quirks}=="0x0" ATTRS{removable}=="unknown" ATTRS{speed}=="480" ATTRS{urbnum}=="55" ATTRS{version}==" 2.00" looking at parent device '/devices/platform/soc/3f980000.usb/usb1': KERNELS=="usb1" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{authorized_default}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="09" ATTRS{bDeviceProtocol}=="01" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="64" ATTRS{bMaxPower}=="0mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="0409" ATTRS{bmAttributes}=="e0" ATTRS{busnum}=="1" ATTRS{configuration}=="" ATTRS{devnum}=="1" ATTRS{devpath}=="0" ATTRS{idProduct}=="0002" ATTRS{idVendor}=="1d6b" ATTRS{interface_authorized_default}=="1" ATTRS{ltm_capable}=="no" ATTRS{manufacturer}=="Linux 4.9.60-1-ARCH dwc_otg_hcd" ATTRS{maxchild}=="1" ATTRS{product}=="DWC OTG Controller" ATTRS{quirks}=="0x0" ATTRS{removable}=="unknown" ATTRS{serial}=="3f980000.usb" ATTRS{speed}=="480" ATTRS{urbnum}=="26" ATTRS{version}==" 2.00" looking at parent device '/devices/platform/soc/3f980000.usb': KERNELS=="3f980000.usb" SUBSYSTEMS=="platform" DRIVERS=="dwc_otg" ATTRS{busconnected}=="Bus Connected = 0x1" ATTRS{buspower}=="Bus Power = 0x1" ATTRS{bussuspend}=="Bus Suspend = 0x0" ATTRS{devspeed}=="Device Speed = 0x0" ATTRS{driver_override}=="(null)" ATTRS{enumspeed}=="Device Enumeration Speed = 0x1" ATTRS{fr_interval}=="Frame Interval = 0x1d4b" ATTRS{ggpio}=="GGPIO = 0x00000000" ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306" ATTRS{gotgctl}=="GOTGCTL = 0x001c0001" ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000" ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306" ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a" ATTRS{guid}=="GUID = 0x2708a000" ATTRS{gusbcfg}=="GUSBCFG = 0x20001700" ATTRS{hcd_frrem}=="HCD Dump Frame Remaining" ATTRS{hcddump}=="HCD Dump" ATTRS{hnp}=="HstNegScs = 0x0" ATTRS{hnpcapable}=="HNPCapable = 0x1" ATTRS{hprt0}=="HPRT0 = 0x00001405" ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406" ATTRS{hsic_connect}=="HSIC Connect = 0x1" ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0" ATTRS{mode}=="Mode = 0x1" ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0" ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 1330 msecs (133 jiffies)" ATTRS{regdump}=="Register Dump" ATTRS{regoffset}=="0xffffffff" ATTRS{regvalue}=="invalid offset" ATTRS{rem_wakeup_pwrdn}=="" ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0" ATTRS{spramdump}=="SPRAM Dump" ATTRS{srp}=="SesReqScs = 0x1" ATTRS{srpcapable}=="SRPCapable = 0x1" ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 330 msecs (33 jiffies)" looking at parent device '/devices/platform/soc': KERNELS=="soc" SUBSYSTEMS=="platform" DRIVERS=="" ATTRS{driver_override}=="(null)" looking at parent device '/devices/platform': KERNELS=="platform" SUBSYSTEMS=="" DRIVERS=="" 

The rule I'm attempting to create should filter by any usb device by idVendor and idProduct, then symlink the hidraw device to attenuators/%s{devpath}. The devpath is an attribute of the usb parent and not the hidraw device itself though.

This rule seems to match and symlink the correct usb device correctly, but I need them to link to the hidraw device:

SUBSYSTEM=="usb", ATTRS{idVendor}=="20ce", ATTR{idProduct}=="0023", SYMLINK+="attenuators/%s{devpath}" 

Here are my attempts at a solution, none of which seem to work:

1:

SUBSYSTEM=="usb", ATTRS{idVendor}=="20ce", ATTR{idProduct}=="0023", ENV{IS_ATTENUATOR}="t", ENV{DEV_PATH}="%s{devpath}" SUBSYSTEM=="hidraw", ENV{IS_ATTENUATOR}=="t", SYMLINK+="attenuators/%E{DEV_PATH}" 

2:

SUBSYSTEM=="usb", ATTRS{idVendor}=="20ce", ATTR{idProduct}=="0023", ENV{IS_ATTENUATOR}="t", ENV{DEV_PATH}="%s{devpath}" ENV{IS_ATTENUATOR}!="t", GOTO="attenuator_end" SUBSYSTEM=="hidraw", SYMLINK+="attenuators/%E{DEV_PATH}" LABEL="attenuator_end" 

3, attempting to just reference parent attributes:

SUBSYSTEM=="hidraw", ATTR{idVendor}=="20ce", ATTR{idProduct}=="0023", SYMLINK+="attenuators/%s{devpath}" 

Along with several tests, few of which seem to even link a device. I feel like there is some fundamental understanding that I'm missing here. Any help would be appreciated!

2 Answers 2

3

I think your main problem was that you tried to use %s{devpath} instead of simply using $devpath.

So something like this should work:

SUBSYSTEM=="usb", ATTRS{idVendor}=="20ce", ATTRS{idProduct}=="0023", SYMLINK+="attenuators/$devpath" 

Watch out for ATTRS instead of ATTR (notice the S at the end, you mixed up these multiple times) because you are filtering on some parent node. See Difference between ATTRS and ATTR in udev rules?

1

Although it may not be the easiest or most elegant solution, I ended up writing a python script to recursively move up a directory from the DEVPATH of the hidraw device until it found a file named 'devpath' (holding the bus/port path of the physcial usb port). Once that's found, it checks the idVendor and idProduct against (hardcoded for now) the correct values and prints the devpath of the device if correct.

My rules ended up like this:

SUBSYSTEM=="hidraw", PROGRAM="/path/to/script.py", SYMLINK+="attenuators/%c" 

And the script looks like this:

#!/usr/bin/env python3 import os, sys path = '/sys' + os.environ["DEVPATH"] while path != '/': if 'devpath' in os.listdir(path): with open(path + '/idVendor') as f: vendor = f.readline().rstrip() with open(path + '/idProduct') as f: product = f.readline().rstrip() if vendor != '20ce' or product != '0023': sys.exit(1) with open(path + '/devpath') as f: print(f.readline().rstrip()) sys.exit(0) else: path = os.path.dirname(path) 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.