I'm running Ubuntu 9.10 (Karmic Koala) on a laptop and would like NumLock to automatically toggle depending on whether my USB keyboard is plugged in (numlock on) or unplugged (numlock off).
To accomplish this, I first installed the "numlockx" package. numlockx on
and numlockx off
works fine.
To hook into the device system, I thought I'd use udev. I have looked at other questions on StackOverflow and read "Writing udev rules". But I'm having trouble getting the udev rule to work.
First, here's an example of the dmesg
output:
[20906.985102] usb 3-2: new low speed USB device using uhci_hcd and address 6 [20907.166403] usb 3-2: configuration #1 chosen from 1 choice [20907.192904] input: Microsoft Natural® Ergonomic Keyboard 4000 as /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/input/input20 [20907.193100] microsoft 0003:045E:00DB.000B: input,hidraw1: USB HID v1.11 Keyboard [Microsoft Natural® Ergonomic Keyboard 4000] on usb-0000:00:1a.0-2/input0 [20907.217810] input: Microsoft Natural® Ergonomic Keyboard 4000 as /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21 [20907.217979] microsoft 0003:045E:00DB.000C: input,hidraw2: USB HID v1.11 Device [Microsoft Natural® Ergonomic Keyboard 4000] on usb-0000:00:1a.0-2/input1
I used udevadm info
to gather the device info:
> udevadm info -a -p /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21 looking at device '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21': KERNEL=="input21" SUBSYSTEM=="input" DRIVER=="" ATTR{phys}=="usb-0000:00:1a.0-2/input1" ATTR{uniq}=="" ATTR{modalias}=="input:b0003v045Ep00DBe0111-e0,1,2,3,4,14,k71,72,73,74,75,77,79,7A,7B,7C,7D,7E,7F,80,81,82,83,84,85,86,87,88,89,8A,8B,8C,8E,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B0,B1,B2,B3,B4,B5,B6,B8,B9,BA,BB,BC,BD,BE,BF,C0,C1,C2,CE,CF,D0,D1,D2,D5,D9,DB,DF,E2,E7,E8,E9,EA,EB,F0,100,162,166,16A,16E,178,179,17A,17B,17C,17D,17F,180,181,182,185,18C,18D,192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA,1AB,1AC,1AD,1AE,1B0,1B1,1B7,r6,a20,m4,lsfw" looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1': KERNELS=="3-2:1.1" SUBSYSTEMS=="usb" DRIVERS=="usbhid" ATTRS{bInterfaceNumber}=="01" ATTRS{bAlternateSetting}==" 0" ATTRS{bNumEndpoints}=="01" ATTRS{bInterfaceClass}=="03" ATTRS{bInterfaceSubClass}=="00" ATTRS{bInterfaceProtocol}=="00" ATTRS{modalias}=="usb:v045Ep00DBd0173dc00dsc00dp00ic03isc00ip00" ATTRS{supports_autosuspend}=="1" looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb3/3-2': KERNELS=="3-2" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{configuration}=="" ATTRS{bNumInterfaces}==" 2" ATTRS{bConfigurationValue}=="1" ATTRS{bmAttributes}=="a0" ATTRS{bMaxPower}=="100mA" ATTRS{urbnum}=="532" ATTRS{idVendor}=="045e" ATTRS{idProduct}=="00db" ATTRS{bcdDevice}=="0173" ATTRS{bDeviceClass}=="00" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{bNumConfigurations}=="1" ATTRS{bMaxPacketSize0}=="8" ATTRS{speed}=="1.5" ATTRS{busnum}=="3" ATTRS{devnum}=="6" ATTRS{version}==" 2.00" ATTRS{maxchild}=="0" ATTRS{quirks}=="0x0" ATTRS{authorized}=="1" ATTRS{manufacturer}=="Microsoft" looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb3': KERNELS=="usb3" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{configuration}=="" ATTRS{bNumInterfaces}==" 1" ATTRS{bConfigurationValue}=="1" ATTRS{bmAttributes}=="e0" ATTRS{bMaxPower}==" 0mA" ATTRS{urbnum}=="127" ATTRS{idVendor}=="1d6b" ATTRS{idProduct}=="0001" ATTRS{bcdDevice}=="0206" ATTRS{bDeviceClass}=="09" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{bNumConfigurations}=="1" ATTRS{bMaxPacketSize0}=="64" ATTRS{speed}=="12" ATTRS{busnum}=="3" ATTRS{devnum}=="1" ATTRS{version}==" 1.10" ATTRS{maxchild}=="2" ATTRS{quirks}=="0x0" ATTRS{authorized}=="1" ATTRS{manufacturer}=="Linux 2.6.31-16-generic uhci_hcd" ATTRS{product}=="UHCI Host Controller" ATTRS{serial}=="0000:00:1a.0" ATTRS{authorized_default}=="1" looking at parent device '/devices/pci0000:00/0000:00:1a.0': KERNELS=="0000:00:1a.0" SUBSYSTEMS=="pci" DRIVERS=="uhci_hcd" ATTRS{vendor}=="0x8086" ATTRS{device}=="0x2937" ATTRS{subsystem_vendor}=="0x1558" ATTRS{subsystem_device}=="0x0860" ATTRS{class}=="0x0c0300" ATTRS{irq}=="16" ATTRS{local_cpus}=="ff" ATTRS{local_cpulist}=="0-7" ATTRS{modalias}=="pci:v00008086d00002937sv00001558sd00000860bc0Csc03i00" ATTRS{broken_parity_status}=="0" ATTRS{msi_bus}=="" looking at parent device '/devices/pci0000:00': KERNELS=="pci0000:00" SUBSYSTEMS=="" DRIVERS==""
So I created a file called /etc/udev/rules.d/usb-keyboard.rules
:
# Turn on NumLock when keyboard is plugged in. ACTION=="add", ATTRS{manufacturer}=="Microsoft", SUBSYSTEM=="input", RUN+="/usr/bin/numlockx on" # Turn off NumLock when keyboard is unplugged. ACTION=="remove", ATTRS{manufacturer}=="Microsoft", SUBSYSTEM=="input", RUN+="/usr/bin/numlockx off"
I have used udevadm test
to verify that the rules are correct:
> udevadm test --action=add /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21 run_command: calling: test udevadm_test: version 147 [...] parse_file: reading '/etc/udev/rules.d/usb-keyboard.rules' as rules file udev_rules_new: rules use 180864 bytes tokens (15072 * 12 bytes), 31614 bytes buffer udev_rules_new: temporary index used 49760 bytes (2488 * 20 bytes) udev_device_new_from_syspath: device 0x28d7d80 has devpath '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21' udev_rules_apply_to_event: RUN '/sbin/modprobe -b $env{MODALIAS}' /lib/udev/rules.d/80-drivers.rules:5 udev_rules_apply_to_event: RUN 'socket:@/org/freedesktop/hal/udev_event' /lib/udev/rules.d/90-hal.rules:2 udev_device_new_from_syspath: device 0x28d8560 has devpath '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1' udev_device_new_from_syspath: device 0x28d8708 has devpath '/devices/pci0000:00/0000:00:1a.0/usb3/3-2' udev_rules_apply_to_event: RUN '/usr/bin/numlockx on' /etc/udev/rules.d/usb-keyboard.rules:7 udevadm_test: UDEV_LOG=6 udevadm_test: DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21 udevadm_test: PRODUCT=3/45e/db/111 udevadm_test: NAME="Microsoft Natural® Ergonomic Keyboard 4000" udevadm_test: PHYS="usb-0000:00:1a.0-2/input1" udevadm_test: UNIQ="" udevadm_test: EV==10001f udevadm_test: KEY==837fff 2c3027 bf004444 0 0 1 10f84 8a27c007 ff7f7bfa d9415fff febeffdf ffefffff ffffffff fffffffe udevadm_test: REL==40 udevadm_test: ABS==1 0 udevadm_test: MSC==10 udevadm_test: MODALIAS=input:b0003v045Ep00DBe0111-e0,1,2,3,4,14,k71,72,73,74,75,77,79,7A,7B,7C,7D,7E,7F,80,81,82,83,84,85,86,87,88,89,8A,8B,8C,8E,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B0,B1,B2,B3,B4,B5,B6,B8,B9,BA,BB,BC,BD,BE,BF,C0,C1,C2,CE,CF,D0,D1,D2,D5,D9,DB,DF,E2,E7,E8,E9,EA,EB,F0,100,162,166,16A,16E,178,179,17A,17B,17C,17D,17F,180,181,182,185,18C,18D,192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA,1AB,1AC,1AD,1AE,1B0,1B1,1B7,r6,a20,m4,lsfw udevadm_test: ACTION=add udevadm_test: SUBSYSTEM=input udevadm_test: run: '/sbin/modprobe -b input:b0003v045Ep00DBe0111-e0,1,2,3,4,14,k71,72,73,74,75,77,79,7A,7B,7C,7D,7E,7F,80,81,82,83,84,85,86,87,88,89,8A,8B,8C,8E,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B0,B1,B2,B3,B4,B5,B6,B8,B9,BA,BB,BC,BD,BE,BF,C0,C1,C2,CE,CF,D0,D1,D2,D5,D9,DB,DF,E2,E7,E8,E9,EA,EB,F0,100,162,166,16A,16E,178,179,17A,17B,17C,17D,17F,180,181,182,185,18C,18D,192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA,1AB,1AC,1AD,1AE,1B0,1B1,1B7,r6,a20,m4,lsfw' udevadm_test: run: 'socket:@/org/freedesktop/hal/udev_event' udevadm_test: run: '/usr/bin/numlockx on'
And here's the "remove" test:
> udevadm test --action=remove /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21 run_command: calling: test udevadm_test: version 147 [...] parse_file: reading '/etc/udev/rules.d/usb-keyboard.rules' as rules file udev_rules_new: rules use 180864 bytes tokens (15072 * 12 bytes), 31614 bytes buffer udev_rules_new: temporary index used 49760 bytes (2488 * 20 bytes) udev_device_new_from_syspath: device 0xd2fd80 has devpath '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21' udev_rules_apply_to_event: RUN 'socket:@/org/freedesktop/hal/udev_event' /lib/udev/rules.d/90-hal.rules:2 udev_device_new_from_syspath: device 0xd2fff8 has devpath '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1' udev_device_new_from_syspath: device 0xd30690 has devpath '/devices/pci0000:00/0000:00:1a.0/usb3/3-2' udev_rules_apply_to_event: RUN '/usr/bin/numlockx off' /etc/udev/rules.d/usb-keyboard.rules:10 udevadm_test: UDEV_LOG=6 udevadm_test: DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1/input/input21 udevadm_test: PRODUCT=3/45e/db/111 udevadm_test: NAME="Microsoft Natural® Ergonomic Keyboard 4000" udevadm_test: PHYS="usb-0000:00:1a.0-2/input1" udevadm_test: UNIQ="" udevadm_test: EV==10001f udevadm_test: KEY==837fff 2c3027 bf004444 0 0 1 10f84 8a27c007 ff7f7bfa d9415fff febeffdf ffefffff ffffffff fffffffe udevadm_test: REL==40 udevadm_test: ABS==1 0 udevadm_test: MSC==10 udevadm_test: MODALIAS=input:b0003v045Ep00DBe0111-e0,1,2,3,4,14,k71,72,73,74,75,77,79,7A,7B,7C,7D,7E,7F,80,81,82,83,84,85,86,87,88,89,8A,8B,8C,8E,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B0,B1,B2,B3,B4,B5,B6,B8,B9,BA,BB,BC,BD,BE,BF,C0,C1,C2,CE,CF,D0,D1,D2,D5,D9,DB,DF,E2,E7,E8,E9,EA,EB,F0,100,162,166,16A,16E,178,179,17A,17B,17C,17D,17F,180,181,182,185,18C,18D,192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA,1AB,1AC,1AD,1AE,1B0,1B1,1B7,r6,a20,m4,lsfw udevadm_test: ACTION=remove udevadm_test: SUBSYSTEM=input udevadm_test: run: 'socket:@/org/freedesktop/hal/udev_event' udevadm_test: run: '/usr/bin/numlockx off'
The problem is that when the keyboard is plugged in or unplugged, the NumLock status doesn't change. I have tried restarting the udev service, with no luck. Are my udev rules wrong? Am I going about this the wrong way?