Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

im trying to load a new keyboard layout when I plug in a usb keyboard but my udev rule isnt working.

SUBSYSTEM=="input", ATTR{idVendor}=="062a", ATTR{idProduct}=="0201", GOTO="usb_xmodmap_auto"

LABEL="usb_xmodmap_auto"
ACTION=="add", RUN+="/usr/bin/xmodmap ~/.usbXmodmap"
ACTION=="remove", RUN+="/usr/bin/xmodmap ~/.pndXmodmap"

I have reloaded the rules using:

>sudo udevadm control --reload-rules

and by restarting the system but when I plug in the usb keyboard the orginal xmodmap is still loaded and thus the keyboard layout is wrong, but if i run the command in the terminal

>/usr/bin/xmodmap ~/.usbXmodmap
or
>/usr/bin/xmodmap ~/.pndXmodmap

they work just fine.

hope soneone can help.

Edit:

just to help more I ran some udevadm tests:

>udevadm test --action=add /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10

outputs:

run_command: calling: test
udevadm_test: version 151
This program is for debugging only, it does not run any program,
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

[...]
parse_file: reading '/etc/udev/rules.d/usb-keyboard.rules' as rules file
udev_rules_new: rules use 100572 bytes tokens (8381 * 12 bytes), 21523 bytes buffer
udev_rules_new: temporary index used 35380 bytes (1769 * 20 bytes)
udev_device_new_from_syspath: device 0x3b4d8 has devpath '/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10'
udev_rules_apply_to_event: RUN '/sbin/modprobe -b $env{MODALIAS}' /etc/udev/rules.d/80-drivers.rules:5
udev_rules_apply_to_event: RUN 'socket:@/org/freedesktop/hal/udev_event' /etc/udev/rules.d/90-hal.rules:2
udev_rules_apply_to_event: RUN '/sbin/modprobe $env{MODALIAS}' /etc/udev/rules.d/local.rules:31
udev_rules_apply_to_event: RUN 'socket:/org/kernel/udev/monitor' /etc/udev/rules.d/run.rules:2
udev_rules_apply_to_event: RUN '/usr/bin/xmodmap ~/.usbXmodmap' /etc/udev/rules.d/usb-keyboard.rules:4
udevadm_test: UDEV_LOG=6
udevadm_test: DEVPATH=/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10
udevadm_test: PRODUCT=3/62a/201/110
udevadm_test: NAME="USB-compliant keyboard"
udevadm_test: PHYS="usb-ehci-omap.0-2.3/input1"
udevadm_test: UNIQ=""
udevadm_test: EV==1f
udevadm_test: KEY==837fff 2c3027 bf004444 0 0 1fe3 c04 a27c000 267bfa d941dfed 9e0000 0 0 0
udevadm_test: REL==143
udevadm_test: ABS==1 0
udevadm_test: MSC==10
udevadm_test: MODALIAS=input:b0003v062Ap0201e0110-e0,1,2,3,4,k71,72,73,74,77,80,82,83,85,86,87,88,89,8A,8B,8C,8E,8F,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B1,B2,B5,CE,CF,D0,D1,D2,D5,D9,DB,E2,EA,EB,100,101,105,106,107,108,109,10A,10B,10C,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,r0,1,6,8,a20,m4,lsfw
udevadm_test: ACTION=add
udevadm_test: SUBSYSTEM=input
udevadm_test: run: '/sbin/modprobe -b input:b0003v062Ap0201e0110-e0,1,2,3,4,k71,72,73,74,77,80,82,83,85,86,87,88,89,8A,8B,8C,8E,8F,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B1,B2,B5,CE,CF,D0,D1,D2,D5,D9,DB,E2,EA,EB,100,101,105,106,107,108,109,10A,10B,10C,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,r0,1,6,8,a20,m4,lsfw'
udevadm_test: run: 'socket:@/org/freedesktop/hal/udev_event'
udevadm_test: run: '/sbin/modprobe input:b0003v062Ap0201e0110-e0,1,2,3,4,k71,72,73,74,77,80,82,83,85,86,87,88,89,8A,8B,8C,8E,8F,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B1,B2,B5,CE,CF,D0,D1,D2,D5,D9,DB,E2,EA,EB,100,101,105,106,107,108,109,10A,10B,10C,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,r0,1,6,8,a20,m4,lsfw'
udevadm_test: run: 'socket:/org/kernel/udev/monitor'
udevadm_test: run: '/usr/bin/xmodmap ~/.usbXmodmap'

and

>udevadm test --action=remove /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10

outputs:

run_command: calling: test
udevadm_test: version 151
This program is for debugging only, it does not run any program,
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

[...]
parse_file: reading '/etc/udev/rules.d/usb-keyboard.rules' as rules file
udev_rules_new: rules use 100572 bytes tokens (8381 * 12 bytes), 21523 bytes buffer
udev_rules_new: temporary index used 35380 bytes (1769 * 20 bytes)
udev_device_new_from_syspath: device 0x3b4d8 has devpath '/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10'
udev_rules_apply_to_event: RUN 'socket:@/org/freedesktop/hal/udev_event' /etc/udev/rules.d/90-hal.rules:2
udev_rules_apply_to_event: RUN 'socket:/org/kernel/udev/monitor' /etc/udev/rules.d/run.rules:2
udev_rules_apply_to_event: RUN '/usr/bin/xmodmap ~/.pndXmodmap' /etc/udev/rules.d/usb-keyboard.rules:5
udevadm_test: UDEV_LOG=6
udevadm_test: DEVPATH=/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10
udevadm_test: PRODUCT=3/62a/201/110
udevadm_test: NAME="USB-compliant keyboard"
udevadm_test: PHYS="usb-ehci-omap.0-2.3/input1"
udevadm_test: UNIQ=""
udevadm_test: EV==1f
udevadm_test: KEY==837fff 2c3027 bf004444 0 0 1fe3 c04 a27c000 267bfa d941dfed 9e0000 0 0 0
udevadm_test: REL==143
udevadm_test: ABS==1 0
udevadm_test: MSC==10
udevadm_test: MODALIAS=input:b0003v062Ap0201e0110-e0,1,2,3,4,k71,72,73,74,77,80,82,83,85,86,87,88,89,8A,8B,8C,8E,8F,90,96,98,9B,9C,9E,9F,A1,A3,A4,A5,A6,A7,A8,A9,AB,AC,AD,AE,B1,B2,B5,CE,CF,D0,D1,D2,D5,D9,DB,E2,EA,EB,100,101,105,106,107,108,109,10A,10B,10C,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,r0,1,6,8,a20,m4,lsfw
udevadm_test: ACTION=remove
udevadm_test: SUBSYSTEM=input
udevadm_test: run: 'socket:@/org/freedesktop/hal/udev_event'
udevadm_test: run: 'socket:/org/kernel/udev/monitor'
udevadm_test: run: '/usr/bin/xmodmap ~/.pndXmodmap'

which seems to show it should work, but it doesnt hope this helps get an answer.

share|improve this question
    
related. –  user250846 Oct 5 '13 at 15:16
add comment

5 Answers 5

up vote 8 down vote accepted

I found a way to work around this, though its a little hacky.

I got to the same exact point today in trying to set up two keyboards with udev, setxkbmap, and xinput --list and for them to work with usb hotplugging. I am swapping keys around, not changing the layout, but its all the same, once you've identified your keyboard on a hotplug and can conditonally call setxkbmap, then you should be able to set the language of only the keyboard you've specified. The list of keyboard layouts can be found here ls -l /usr/share/kbd/keymaps/i386/ and you can find your device name to gre on with xinput -list.

  1. You'll want to replace rizumu with your username, as I found it wasn't possible a way to do this without being explicit.
  2. Make sure you grep on the your keyboard name.
  3. Use lsusb to discover the Hardware ID that you need to set in the udev rule. My das keyboard looks like this Bus 002 Device 009: ID 04d9:2013 Holtek Semiconductor, Inc.

I first set up the udev rule to autodetct the keyboard is by creating a udev rule:

In the file /etc/udev/rules.d/00-usb-keyboards.rules:

ACTION=="add", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="2013", RUN+="/home/rizumu/bin/kbd_udev", OWNER="rizumu"

I have two files ~/bin/kbd and ~/bin/kbd_udev. Make sure they have the right permissions chmod 755 ~/bin/kbd*

The ~/bin/kbd_udev script contains:

#!/bin/bash
/home/rizumu/bin/kbd &

And you'll notice that all it does is call ~/bin/kbd in the background, so that udev can complete its process and activate the keyboard. Inside the ~/bin/kbd script we sleep for a second, because we need to wait until the keyboard is activated so we can get the device id using xinput. To achive this I've set some variables and exported them so xinput setxkbmap can do thier work: DISPLAY, XAUTHORITY, HOME, and one daskb_id for the id of my daskeyboard:

#!/bin/bash
sleep 1
DISPLAY=":0.0"
HOME=/home/rizumu/
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME
daskb_id=`xinput -list | grep -i 'daskeyboard' | grep -o id=[0-9]. | grep -o [0-9]. | head -1`

xset r rate 200 30
setxkbmap -layout colemak
setxkbmap -option ctrl:nocaps
if [ "${daskb_id}" ]; then
    setxkbmap -device "${daskb_id}" -option altwin:swap_lalt_lwin
fi
share|improve this answer
    
Thanks for the writeup! This worked great on Arch. –  denaje Mar 29 '13 at 7:28
    
Thanks a lot for helping me answer my own question is AskUbuntu: askubuntu.com/questions/337411/… –  Sadi Sep 22 '13 at 16:34
    
And I wonder if you can also help me add a notification message at the end of this script (e.g. notify-send "USB Keyboard is plugged in and ready for use now." -i gtk-dialog-info -t 1000 -u normal). As I don't know much about scripting, I tried inserting it before or after "fi" but in both cases the notification message kept on appearing over and over again :-( –  Sadi Sep 22 '13 at 16:42
    
Why setting OWNER for this device? –  Limbo Peng Jun 27 at 4:01
add comment

If you're running GNOME then you'll need to disable its keyboard management plugin so that it doesn't override your layout changes.

gconftool-2 --toggle /apps/gnome_settings_daemon/plugins/keyboard/active

Run the same command again to enable it as desired.

share|improve this answer
    
im running angstrom. will this work? –  milkshake Feb 23 '11 at 2:06
    
Are you using GNOME on Ångström? –  Ignacio Vazquez-Abrams Feb 23 '11 at 2:18
    
nope im using xfce 4.6.1 –  milkshake Feb 23 '11 at 2:40
1  
In my Ubuntu 13.04, this is in dconf under /org/gnome/settings-daemon/plugins/keyboard/active. –  nh2 Aug 16 '13 at 14:06
    
And the command for Ubuntu 13.04 is: gsettings set org.gnome.settings-daemon.plugins.keyboard active false –  Sadi Sep 22 '13 at 16:33
add comment

It does not work because udev and xmodmap don't have access to your X11 display. In fact, udev doesn't even know if there are active X11 displays.

  • Note: displays, plural. It can't use "the" X11 display because there can be more than one. For example, if you use "fast user switching".
share|improve this answer
    
so How could I make this work? –  milkshake Feb 23 '11 at 13:27
    
anyone know how I can fix this? –  milkshake Feb 23 '11 at 15:27
1  
I've gotten udev to call setxkbmap. The udev rule calls a script which backgrounds another script (so udev can complete). The second script pauses for a second, sets up the expected X11 variables, and triggers setxkbmap. See my answer to the main question for more details. –  rizumu Oct 25 '11 at 18:41
    
@rizumu: Ahh, good luck getting that to work with GDM though. –  grawity Oct 25 '11 at 19:41
add comment

To answer your question about accessing the running display, you can export the appropriate DISPLAY variable in the script, assuming that permissions for the display are correctly set. (man xset for display permissions.)

In many usual cases you can simply export DISPLAY=:0 for the command, as that's the first display on a single user system. It's probably easiest to run a script rather than xmodmap directly, as this will allow you to have more control over environment variables and the rest. (So replace "/usr/bin/xmodmap ~/.usbXmodmap" in your rule with "/usr/local/bin/keyboard_plug.sh" and put the appropriate commands in that script along with the DISPLAY variable.)

As noted above, though, if you assume DISPLAY=:0 then you might run into problems later on if you have multiple users or displays. You can write scripts to detect the appropriate display, but in that case you're on your own (as far as this answer is concerned). :)

share|improve this answer
add comment

What about X.Org configuration? From Gentoo Wiki: X.Org/Input_drivers - udev:

Example: If you have a Logitech Access keyboard for the French part of Switzerland, you can use the following:

File: /etc/X11/xorg.conf.d/10-keyboard.conf

Section "InputClass"
    Identifier             "evdev keyboard catchall"
    MatchIsKeyboard        "on"
    MatchDevicePath        "/dev/input/event*"
    Driver                 "evdev"
    Option                 "XkbModel" "logiaccess"
    Option                 "XkbLayout" "ch"
    Option                 "XkbVariant" "fr"
EndSection

For an in-depth explanation, read:

man xorg.conf

and:

man evdev

ArchWiki demonstrates using the same syntax in xorg.conf but notes that "nowadays you should create a separate config file, like /etc/X11/xorg.conf.d/90-keyboard-layouts.conf". I use Arch and configured my own USB keyboard in the existing /etc/X11/xorg.conf.d/vim 10-evdev.conf Worked for me.

@rizomu: Nice job hacking together a temporary kludge and sharing.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.