Random Wisdom

Tag: udev

Fine grained system control with custom udev rules

by on Feb.16, 2012, under Hardware, How To ..., Linux

When a new hardware device is plugged into a Linux system, udev handles the creation of device nodes and symbolic links under ‘/dev’. Certain aspects of this process, such as initial file permissions, can be controlled using custom udev rules placed in the appropriate configuration file directory (e.g. ‘/etc/udev/rules.d/’). Recently, I found myself looking into custom udev rules for two reasons: setting the default device permissions on a USB scanner and setting a unique name for an external disk.

udev rules always start with directives that tell udev how to match a device of interest. E.g.

ACTION=="add", KERNEL=="sg[0-9]*", BUS=="scsi", SYSFS{type}=="8", \
        SYMLINK+="changer changer-%k", MODE="0660", GROUP="disk"

In this particular example, if the keys ACTION, KERNEL, BUS and SYSFS{type} for the new device match the given values, then the values specified for SYMLINK, MODE and GROUP are applied to each of those attributes when creating the device node. A list of the valid test and assignment operators for udev rules can be found in the man page for udev.

The key/value pairs necessary to match a given device can be discovered by using the ‘udevadm‘ tool. For a USB device, ‘lsusb‘ can be used first to determine the generic device node after plugging in the hardware:

[root@localhost ~]# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 003: ID 0644:0200 TEAC Corp. All-In-One Multi-Card Reader CA200/B/S
Bus 004 Device 003: ID 04b8:010f Seiko Epson Corp. Perfection 1250
Bus 002 Device 003: ID 0665:5161 Cypress Semiconductor USB to Serial
Bus 001 Device 007: ID 0bc2:5071 Seagate RSS LLC 

In this list, ‘Bus 004 Device 003: ID 04b8:010f Seiko Epson Corp. Perfection 1250‘ is the scanner and it is at device node ‘/dev/bus/usb/004/003’. Armed with that information, it is now possible to use ‘udevadm’ to get the key/value pairs:

[root@localhost ~]# udevadm info --attribute-walk --path \
                    $(udevadm info --query path --name /dev/bus/usb/004/003)

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/pci0000:00/0000:00:1d.2/usb4/4-2':
    KERNEL=="4-2"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{configuration}==""
    ATTR{bNumInterfaces}==" 1"
    ATTR{bConfigurationValue}=="1"
    ATTR{bmAttributes}=="c0"
    ATTR{bMaxPower}=="  2mA"
    ATTR{urbnum}=="282"
    ATTR{idVendor}=="04b8"
    ATTR{idProduct}=="010f"
    ATTR{bcdDevice}=="0100"
    ATTR{bDeviceClass}=="ff"
    ATTR{bDeviceSubClass}=="00"
    ATTR{bDeviceProtocol}=="ff"
    ATTR{bNumConfigurations}=="1"
    ATTR{bMaxPacketSize0}=="8"
    ATTR{speed}=="12"
    ATTR{busnum}=="4"
    ATTR{devnum}=="3"
    ATTR{version}==" 1.10"
    ATTR{maxchild}=="0"
    ATTR{quirks}=="0x0"
    ATTR{authorized}=="1"
    ATTR{manufacturer}=="EPSON"
    ATTR{product}=="EPSON Scanner 010F"

  looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4':
    KERNELS=="usb4"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ...
    ...
    [output trimmed]

Using this information from ‘udevadm‘ the following rule was created:

[root@localhost ~]# cat /etc/udev/rules.d/60-scanner.rules 
# UDEV rules for Epson scanner

ACTION!="add", GOTO="epson_rules_end"
SUBSYSTEM!="usb", GOTO="epson_rules_end"

SUBSYSTEM=="usb", DRIVER=="usb", ATTR{idVendor}=="04b8", ATTR{idProduct}=="010f", \
 MODE="0666", SYMLINK+="scanner" LABEL="epson_rules_end"

LABEL="epson_rules_end"

This rule instructs udev to create an additional device node at ‘/dev/scanner’ and set the access permissions to ‘rw-rw-rw-‘. After saving the rules file, it is necessary to apply the changes using:

[root@localhost ~]# udevadm trigger

Useful resources: “Writing udev rules“, udev and udevadm man pages.

1 Comment :, , , more...

Turn on 800DPI mode for the Logitech MX-510 Mouse

by on Aug.27, 2005, under Hardware, How To ..., Linux, Software

5 easy steps:

1. Get and install the Logitech Applet from here or directly from here

2. Install the poper udev rules:
Create a file logitech-mice.rules under /etc/udev/rules.d/ with the following contents:

[darkknight@darkworld rules.d]$ cat logitech-mice.rules
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c00e", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c00f", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c012", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c024", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c01b", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c025", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c01d", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"
BUS="usb", SYSFS{idVendor}="046d", SYSFS{idProduct}="c031", PROGRAM="/usr/local/bin/logitech_applet -e -s 800"

Change the file permissions:

[darkknight@darkworld rules.d]$ sudo chown root.root logitech-mice.rules
[darkknight@darkworld rules.d]$ sudo chmod 644 logitech-mice.rules && ls -l
total 24
-rw-r--r--  1 root root  146 Apr 13 20:30 10-wacom.rules
-rw-r--r--  1 root root 7406 May 21 05:45 50-udev.rules
-rw-r--r--  1 root root  888 Sep  6 23:12 logitech-mice.rules

3. Modify /etc/X11/xorg.conf as follows to support the thumb buttons:

Section "InputDevice"
    Identifier  "Mouse0"
    Driver      "mouse"
    Option      "Protocol" "ExplorerPS/2"
    Option      "Device" "/dev/input/mice"
    Option      "ZAxisMapping" "6 7"
    Option      "Buttons" "7"
    Option      "Emulate3Buttons" "no"
EndSection

4. Create a script xmouse.sh under /etc/X11/xinit/xinitrc.d with the following contents:

[darkknight@darkworld xinitrc.d]$ cat xmouse.sh
#!/bin/bash

/usr/X11R6/bin/xmodmap -e "pointer = 1 2 3 6 7 4 5"

This ensures that the scrolling funtion is correctly assigned to the wheel and not to the thumb buttons.

Make sure that the file permissions are correct:

[darkknight@darkworld xinitrc.d]$ sudo chmod 755 xmouse.sh && ls -l
total 16
-rwxr-xr-x  1 root root 1579 Apr 11 13:43 xinput.sh
-rwxr-xr-x  1 root root   81 Sep  2 17:36 xmbind.sh
-rwxr-xr-x  1 root root   66 Sep  6 23:41 xmouse.sh

5. Reboot (Or simply unplug/re-plug mouse and restart X)

Happy surfing! Got the udev rules from the Ubuntu Forum (modified the PROGRAM line to use logitech_applet instead of lmctl).

Edit [July 30, 2007]: It has been a while since the steps above were posted. The syntax of UDEV rules have changed much since then. The updated rule is (for my MX-510):

$ cat /etc/udev/rules.d/60-logitech-mouse.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c01d", RUN+="/usr/local/bin/logitech_applet -e -s 800"

Device details necessary for writing UDEV rules can be discovered using (substitute /dev/input/mouse1 with path to device of interest):

# udevinfo -a -p $(udevinfo -q path -n /dev/input/mouse1)

Update [19th Nov. 2009]: On Fedora 12 (X.Org X Server 1.7.1), the configuration needed to get the thumb buttons working is:

Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "mouse"
        Option      "Protocol" "ExplorerPS/2"
        Option      "Device" "/dev/input/mice"
        Option      "Emulate3Buttons" "no"
        Option      "Buttons" "9"
        Option      "ZAxisMapping" "4 5"
EndSection

It seems that it is no longer necessary to remap the buttons using xmouse.sh.

Leave a Comment :, , more...