Udev Rules

From Leo's Notes
Last edited on 1 September 2019, at 06:21.

udev is a device manager for the Linux kernel and handles device nodes in /dev. Rules can be defined which governs how these device nodes are created and what attributes are set.

Creating New udev rules[edit | edit source]

Place new rules in /etc/udev/rules.d. The filename should be numbered.

If you are attempting to write a rule for a specific device, you should plug the device to your computer now and determine what the device path is. You must then list out all the udev properties of the device using the udevadm command.

To see attributes of a device, run: udevadm info --attribute-walk --name=/dev/ttyUSB0

For example, to create a udev rule for a USB Webcam at /etc/video0:

# udevadm info -a -p `udevadm info -q path -n /dev/video0`

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/bcm2708_usb/usb1/1-1/1-1.3/1-1.3:1.0/video4linux/video0':
    KERNEL=="video0"
    SUBSYSTEM=="video4linux"
    DRIVER==""
    ATTR{debug}=="0"
    ATTR{index}=="0"

  looking at parent device '/devices/platform/bcm2708_usb/usb1/1-1/1-1.3/1-1.3:1.0':
    KERNELS=="1-1.3:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="uvcvideo"
    ATTRS{bInterfaceClass}=="0e"
    ATTRS{iad_bFunctionClass}=="0e"
    ATTRS{iad_bFirstInterface}=="00"
    ATTRS{bInterfaceSubClass}=="01"
    ATTRS{bInterfaceProtocol}=="00"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{iad_bFunctionSubClass}=="03"
    ATTRS{iad_bFunctionProtocol}=="00"
    ATTRS{supports_autosuspend}=="1"
    ATTRS{iad_bInterfaceCount}=="02"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceNumber}=="00"

  looking at parent device '/devices/platform/bcm2708_usb/usb1/1-1/1-1.3':
    KERNELS=="1-1.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="02"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{devpath}=="1.3"
    ATTRS{idVendor}=="045e"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 4"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="6"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="500mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0100"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="38"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Microsoft"
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="0761"
    ATTRS{bDeviceClass}=="ef"

  looking at parent device '/devices/platform/bcm2708_usb/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{devpath}=="1"
    ATTRS{idVendor}=="0424"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="2"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="2mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="3"
    ATTRS{bcdDevice}=="0200"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="80"
    ATTRS{ltm_capable}=="no"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="9512"
    ATTRS{bDeviceClass}=="09"

  looking at parent device '/devices/platform/bcm2708_usb/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{devpath}=="0"
    ATTRS{idVendor}=="1d6b"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{authorized_default}=="1"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="1"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="0mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="1"
    ATTRS{bcdDevice}=="0318"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="bcm2708_usb"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="26"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 3.18.9-3-ARCH dwc_otg_hcd"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="0002"
    ATTRS{bDeviceClass}=="09"
    ATTRS{product}=="DWC OTG Controller"

  looking at parent device '/devices/platform/bcm2708_usb':
    KERNELS=="bcm2708_usb"
    SUBSYSTEMS=="platform"
    DRIVERS=="dwc_otg"
    ATTRS{hnp}=="HstNegScs = 0x0"
    ATTRS{srp}=="SesReqScs = 0x1"
    ATTRS{regvalue}=="invalid offset"
    ATTRS{hsic_connect}=="HSIC Connect = 0x1"
    ATTRS{guid}=="GUID = 0x2708a000"
    ATTRS{mode}=="Mode = 0x1"
    ATTRS{srpcapable}=="SRPCapable = 0x1"
    ATTRS{regdump}=="Register Dump"
    ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
    ATTRS{ggpio}=="GGPIO = 0x00000000"
    ATTRS{hprt0}=="HPRT0 = 0x00001005"
    ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 670 msecs (67 jiffies)"
    ATTRS{driver_override}=="(null)"
    ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
    ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
    ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
    ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
    ATTRS{busconnected}=="Bus Connected = 0x1"
    ATTRS{hcddump}=="HCD Dump"
    ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
    ATTRS{spramdump}=="SPRAM Dump"
    ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
    ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
    ATTRS{gusbcfg}=="GUSBCFG = 0x00001700"
    ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
    ATTRS{devspeed}=="Device Speed = 0x0"
    ATTRS{fr_interval}=="Frame Interval = 0x1d4c"
    ATTRS{rem_wakeup_pwrdn}==""
    ATTRS{bussuspend}=="Bus Suspend = 0x0"
    ATTRS{buspower}=="Bus Power = 0x1"
    ATTRS{hnpcapable}=="HNPCapable = 0x1"
    ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 1510 msecs (151 jiffies)"
    ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
    ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
    ATTRS{regoffset}=="0xffffffff"

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

In the udev rules file, match all attributes that uniquely identify the device you're targetting. In the example above, using the SUBSYSTEM, ATTRS{idVendor}, and ATTRS{idProduct} would be sufficient. Eg:

SUBSYSTEM=="video4linux", ATTRS{idVendor}=="045e"

In the second half of the line, you may define values for this device. If the webcam needs to be world read and writable, assign 0666 to MODE like so:

SUBSYSTEM=="video4linux", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="0761", MODE="0666"

Restart the udev daemon and check the logs for any errors. If the rules are correct, replugging the device should have have the affects defined in the rules.

See Also[edit | edit source]