Using xkbcomp for a specific device
Darren Hart
darren at dvhart.com
Sun Sep 16 13:41:02 PDT 2012
I'm looking to modify the keysyms of a remote that presents as a usbhid device.
I also have an HP wireless keyboard and mouse combination device that I do not
wish to modify. I'm trying to accomplish this with a combination of setxkbmap
and xkbcomp, using the "-i device_id" to xkbcomp to modify the keymap of only
the remote. The problem: both devices get remapped.
The following describes my system and the exact steps I've taken to try and
remap the remote.
$ xinput --list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ HOLTEK id=10 [slave pointer (2)]
⎜ ↳ HP HP Wireless Mini Keyboard id=11 [slave pointer (2)]
⎜ ↳ HP HP Wireless Mini Keyboard id=12 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Video Bus id=7 [slave keyboard (3)]
↳ Power Button id=8 [slave keyboard (3)]
↳ HOLTEK id=9 [slave keyboard (3)]
In the list above, the HOLTEK is the remote (it sends both keyboard and mouse
events). Yes it's horrible, but it's what I have and I'd like to make it work. The
two entries for the HP Wireless Mini Keyboard correspond to the single USB
receiver for the keyboard and mouse.
$ lsusb
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 1241:e000 Belkin <----- This is the remote
Bus 002 Device 004: ID 03f0:a107 Hewlett-Packard <----- This is the HP keyboard/mouse
$ lsusb -t
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/2p, 480M
|__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/8p, 480M
|__ Port 5: Dev 4, If 0, Class=HID, Driver=usbhid, 12M <----- HP keyboard/mouse
|__ Port 5: Dev 4, If 1, Class=HID, Driver=usbhid, 12M <----- HP keyboard/mouse
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/2p, 480M
|__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/6p, 480M
|__ Port 3: Dev 3, If 0, Class=HID, Driver=usbhid, 1.5M <----- Remote
|__ Port 3: Dev 3, If 1, Class=HID, Driver=usbhid, 1.5M <----- Remote
dmesg reports each as USB input devices using the usbhid driver:
$ dmesg | egrep "(HOLTEK|HP Wireless)"
[ 3.966054] input: HOLTEK as /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.0/input/input2
[ 3.966267] hid-generic 0003:1241:E000.0001: input,hidraw0: USB HID v1.10 Keyboard [HOLTEK] on usb-0000:00:1a.0-1.3/input0
[ 3.966405] input: HOLTEK as /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.1/input/input3
[ 3.966480] hid-generic 0003:1241:E000.0002: input,hiddev0,hidraw1: USB HID v1.10 Mouse [HOLTEK] on usb-0000:00:1a.0-1.3/input1
[ 3.966605] input: HP HP Wireless Mini Keyboard as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5/2-1.5:1.0/input/input4
[ 3.966649] hid-generic 0003:03F0:A107.0003: input,hidraw2: USB HID v1.11 Keyboard [HP HP Wireless Mini Keyboard] on usb-0000:00:1d.0-1.5/input0
[ 3.966752] input: HP HP Wireless Mini Keyboard as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5/2-1.5:1.1/input/input5
[ 3.966833] hid-generic 0003:03F0:A107.0004: input,hidraw3: USB HID v1.11 Mouse [HP HP Wireless Mini Keyboard] on usb-0000:00:1d.0-1.5/input1
The remote sends ctrl+p and ctrl+shift+p for pause and play. MythTV doesn't
distinguish between the two, so I want to change the shifted P to another key,
such as XF86AudioPlay. I'd also like to change the Backspace to Esc on the remote.
I can make this work with the following script which I lifted from the MythTV
wiki, and then modified:
#!/bin/sh
set -x
remote_id=$(xinput list | sed -n 's/.*HOLTEK.*id=\([0-9]*\).*keyboard.*/\1/p')
[ "$remote_id" ] || exit
mkdir -p /tmp/xkb/symbols
cat >/tmp/xkb/symbols/custom <<\EOF
xkb_symbols "remote" {
key <AD10> { [ p, XF86AudioPlay ] };
key <BKSP> { [ Escape, Escape ] };
};
EOF
setxkbmap -device $remote_id -print | sed 's/\(xkb_symbols.*\)"/\1+custom(remote)"/' | xkbcomp -I/tmp/xkb -i $remote_id -synch - $DISPLAY 2>/dev/null
Once run, the HP keyboard p and backspace keys continue to work. But once I run xev
and press the play button, both the remote and the HP keyboard have been remapped.
shift+p sends XF86AudioPlay and Backspace sends Esc on both devices. I checked that
my version of xkbcomp contains the per-device patch by downloading the sources and
checking the contents of xkbcomp.c:
$ grep -B 3 device_id x11-xkb-utils-7.6+4/xkbcomp/xkbcomp.c
static char *preErrorMsg = NULL;
static char *postErrorMsg = NULL;
static char *errorPrefix = NULL;
static unsigned int device_id = XkbUseCoreKbd;
--
if (warningLevel > 0)
WARN("No device ID specified\n");
}
device_id = atoi(argv[i]);
--
ok = False;
break;
}
result.xkb->device_spec = device_id;
--
ERROR1("Cannot read XKM file \"%s\"\n", inputFile);
ok = False;
}
result.xkb->device_spec = device_id;
--
{
bzero((char *) &result, sizeof(result));
result.type = XkmKeymapFile;
result.xkb = XkbGetMap(inDpy, XkbAllMapComponentsMask, device_id);
I also confirmed that if I send a bad device_id, the script displays X11 out of range
errors, with the value to the operation being the hex value of the bogus device_id.
No error is reported when I pass "9" (the device_id for the HOLTEK keyboard xinput
assigns to the remote). If I use the HP Wireless xinput device IDs, the remapping does
not take place.
I can reset the devices to their original state using:
$ setxkbmap -print | xkbcomp - $DISPLAY 2>/dev/null
If I try to use "-i 11" or "-i 12" to reset just the HP Wireless keyboard, the change doesn't take effect.
I am running on a 32 bit installation of Ubuntu 12.04 (Mythbuntu specifically). I've
tried this in the XFCE desktop as well as with a .xinitrc with only an xterm running
with the same results.
Am I on the right track? Or is there another method I should be considering?
Can anyone point to why xkbcomp appears to be sending the device_id, yet both
the remote and the keyboard are being remapped?
Thanks in advance!
--
Darren Hart
More information about the xorg
mailing list