You are not logged in.
I'm trying to persistently switch the caps lock key and escape key. I can do this temporarily with the following:
setxkbmap -option caps:escape
If I then unplug and plug my keyboard back in the setting reverts to the default. To fix this, I'm trying to write a udev rule that will run the above command when I plug in a keyboard. Here's the udev rule I have:
SUBSYSTEM=="input", ATTRS{interface}=="Keyboard", ACTION=="add", RUN+="/bin/su khouli -c /home/khouli/kbd_setup.sh"
And here's kbd_setup.sh. It also writes a file to confirm that it's working, "it_works.txt", and also sets the repeat rate for keys with xset:
#!/usr/bin/env bash
(
sleep 5
DISPLAY=:0.0 setxkbmap -option caps:escape
xset r rate 200 30
echo hi there > /home/khouli/it_works.txt
) &
This is based on the suggestions here:
https://pbrisbin.com/posts/disable_all_the_caps/
When a keyboard is plugged in, it_works.txt is created, confirming that the rule is being matched. Strangely, even though the sleep is running in a subprocess in the background, I do my terminal does sleep for several seconds. The xset command does work. The setxkmap command has no effect.
How can I persistently switch the caps lock key and escape key?
Offline
RUN+= with `sleep` will fail because it blocks (see man udev). Write a service file and use SYSTEMD_WANTS instead, see man systemd.device.
Offline
I now have this udev rule:
SUBSYSTEM=="input", ATTRS{interface}=="Keyboard", ACTION=="add", ENV{SYSTEMD_WANTS}=="keyboard.service"
This systemd service, /usr/lib/systemd/system/keyboard.service:
[Unit]
Description=Set keyboard repeat rate and switch CapsLocka and Escape
[Service]
ExecStart=/home/khouli/scripts/keyboard_setup.sh
And this script, /home/khouli/scripts/keyboard_setup.sh
#!/usr/bin/env bash
DISPLAY=:0.0 setxkbmap -option caps:escape
xset r rate 200 30
echo hi there > /home/khouli/it_works.txt
This doesn't work. The it_works.txt test file isn't created. What should I change or how can I debug this?
If I unplug and replug my keyboard the last few journalctl entries are:
Mar 20 01:36:23 shodan kernel: usb 1-10: USB disconnect, device number 21
Mar 20 01:36:23 shodan systemd-udevd[234]: error opening USB device 'descriptors' file
Mar 20 01:36:26 shodan kernel: usb 1-10: new full-speed USB device number 22 using xhci_hcd
Mar 20 01:36:26 shodan kernel: usb 1-10: ep 0x81 - rounding interval to 64 microframes, ep desc says 80 microframes
Mar 20 01:36:26 shodan kernel: input: Topre Corporation Realforce 87 as /devices/pci0000:00/0000:00:14.0/usb1/1-10/1-10:1.0/0003:0853:0111.0015/input/input38
Mar 20 01:36:26 shodan kernel: hid-generic 0003:0853:0111.0015: input,hidraw2: USB HID v1.11 Keyboard [Topre Corporation Realforce 87] on usb-0000:00:14.0-10/input0
The udevd error appears to be an unsolved bug.
https://bbs.archlinux.org/viewtopic.php?id=190953
Running
systemctl start keyboard.service
will create the file it_works.txt but doesn't swap caps lock and escape.
Last edited by khouli (2015-03-20 06:03:12)
Offline
What does `systemctl status keyboard.service` show?
Offline
`systemctl status keyboard.service`
$ systemctl status keyboard.service
● keyboard.service - Set keyboard repeat rate and switch CapsLocka and Escape
Loaded: loaded (/usr/lib/systemd/system/keyboard.service; static; vendor preset: disabled)
Active: inactive (dead)
Mar 20 02:05:20 shodan keyboard_setup.sh[9067]: No protocol specified
Mar 20 02:05:20 shodan keyboard_setup.sh[9067]: Cannot open display ":0.0"
Mar 20 02:05:20 shodan keyboard_setup.sh[9067]: No protocol specified
Mar 20 02:05:20 shodan keyboard_setup.sh[9067]: xset: unable to open display ":0.0"
If I comment out the xset line in the script for now then the errors are:
Mar 20 02:08:57 shodan keyboard_setup.sh[9358]: No protocol specified
Mar 20 02:08:57 shodan keyboard_setup.sh[9358]: Cannot open display ":0.0"
Offline
Based on this:
http://unix.stackexchange.com/questions … rvice-file
I changed the systemd service file to:
[Unit]
Description=Set keyboard repeat rate and switch CapsLocka and Escape
[Service]
User=khouli
Environment=DISPLAY=:0
ExecStart=/home/khouli/scripts/keyboard_setup.sh
It now works when run as `systemctl start keyboard.service` but still doesn't work when unplugging and replugging.
Offline
You might need a connection to the dbus session for that to work...
I do something similar on one of my boxes:
if [[ $? -eq 0 ]]; then
pids=$(pgrep dwm)
for p in $pids; do
dbus=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$p/environ \
| sed 's/DBUS_SESSION_BUS_ADDRESS=//')
user=$(grep -z USER /proc/$p/environ | sed 's/USER=//')
dply=$(grep -z DISPLAY /proc/$p/environ | sed 's/DISPLAY=//')
title="Sync Complete"
body="Music transferred to Apollo…"
sudo -u $user sh -c "DBUS_SESSION_BUS_ADDRESS=\"$dbus\" DISPLAY=\"$dply\" \
/usr/bin/notify-send -t 3000 -i \"$title\" \"$body\""
done
fi
Offline
Maybe this is relevant.
$ systemctl status systemd-udevd
● systemd-udevd.service - udev Kernel Device Manager
Loaded: loaded (/usr/lib/systemd/system/systemd-udevd.service; static; vendor preset: disabled)
Active: active (running) since Thu 2015-03-19 23:18:01 EDT; 3h 9min ago
Docs: man:systemd-udevd.service(8)
man:udev(7)
Main PID: 234 (systemd-udevd)
CGroup: /system.slice/systemd-udevd.service
└─234 /usr/lib/systemd/systemd-udevd
Mar 20 02:22:07 shodan systemd-udevd[234]: error opening USB device 'descriptors' file
Mar 20 02:24:29 shodan systemd-udevd[234]: error opening USB device 'descriptors' file
Offline