How to set up Ubuntu to automatically turn NumLock on when an external keyboard is attached and off when it is not?

Having NumLock on is convenient when using a full-sized external keyboard (having a keypad) and very inconvenient when using laptop's built-in keyboard (which places digits instead of letters on the keyboard's right sid unless Fn is pressed).

So I have to turn NumLock on every time I attach an external keyboard (or boot with it attached) and off every time I detach an external keyboard (or boot with it detached). And I do this frequently because I prefer using a full-sized external keyboard, but have not enough (only 3) USB ports to plug-in it alongside with a mouse, a 3G modem and an external hard/flash drive.

Can I automate this? Seems a very formaliseable, logically simple task: if there is an USB keyboard attached (some device in /dev present?) - NumLock is on, if not - NumLock is off. My laptop's built-in keyboard is PS/2-attached, external is USB.

Maybe I should code it myself, but where to put it in this case?

I use Ubuntu 10.10.


First off, install numlockx (click here to install numlockx). Basically this allows you to write scripts to set the state of Num Lock - see the numlockx man page for details.

Next we need to start delving into the fun of udev rules. First we need to find out how the keyboard is identified. You can do this by

ls /dev/input/by-id/

This should give you some human readable file names (that are soft links to the not particularly readable true name). My keyboard was

/dev/input/by-id/usb-KINESIS_FREESTYLE_KB700_KB700_Kinesis_Freestyle-event-kbd

So then we need to find out all the info about the keyboard. I did

udevadm info -a -p $(udevadm info -q path -n /dev/input/by-id/usb-KINESIS_FREESTYLE_KB700_KB700_Kinesis_Freestyle-event-kbd)

But insert your own path there of course. You'll get a lot of info, but you want to look at the first block that names the keyboard and has SUBSYSTEMS=="usb". (Rather than the USB controller or whatever). In my case that was:

  looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2.3':
    KERNELS=="3-2.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 2"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bMaxPower}==" 50mA"
    ATTRS{urbnum}=="6284"
    ATTRS{idVendor}=="058f"
    ATTRS{idProduct}=="9410"
    ATTRS{bcdDevice}=="0122"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{speed}=="1.5"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="3"
    ATTRS{devpath}=="2.3"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="KINESIS FREESTYLE KB700"
    ATTRS{product}=="KB700 Kinesis Freestyle"

So now we have enough information to write some rules. Use your favourite editor to create /etc/udev/rules.d/10-local.rules and put in:

BUS=="usb",ATTRS{product}=="KB700 Kinesis Freestyle",ACTION=="add",RUN+="/usr/bin/numlockx on"
BUS=="usb",ATTRS{product}=="KB700 Kinesis Freestyle",ACTION=="remove",RUN+="/usr/bin/numlockx off"

Again, put the name of your keyboard in here, and the ATTRS if it is different. Then it should work :)

Note I haven't been able to test this, though I have run all the commands up until creating the rules file. And the sources in case you need to do some more investigation are:

  • http://ubuntuforums.org/showthread.php?t=168221
  • http://reactivated.net/writing_udev_rules.html#external-run

If you are using Gnome3 shell.

Install numlockx

then launch Startup application preferences gnome-session-properties

Image (new users can't post images :))

Click Add

Write anything into name field and into command field copy this:numlockx on

Image