How do I correct this mismapped stylus button?
I'm running Kubuntu 15.10 on an HP Spectre x360, which has a non-Wacom active digitizer built into the display. I'm using a two-button stylus with this, but the second button doesn't work. I couldn't get xinput
to show any state change when the button is pressed; it seems X can't see it at all. evtest
does see an event, but it reports the button as BTN_TOOL_RUBBER
instead of the appropriate BTN_STYLUS2
:
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x4f3 product 0x2073 version 0x110
Input device name: "ELAN Touchscreen Pen"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 256 (BTN_0)
Event code 320 (BTN_TOOL_PEN)
Event code 321 (BTN_TOOL_RUBBER)
Event code 330 (BTN_TOUCH)
Event code 331 (BTN_STYLUS)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 23080
Min 0
Max 32256
Resolution 110
Event code 1 (ABS_Y)
Value 10408
Min 0
Max 17920
Resolution 108
Event code 24 (ABS_PRESSURE)
Value 0
Min 0
Max 255
Event type 4 (EV_MSC)
Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)
Event: time 1453608432.242049, type 1 (EV_KEY), code 321 (BTN_TOOL_RUBBER), value 1
Event: time 1453608432.242049, -------------- SYN_REPORT ------------
The stylus has no eraser tip. input-kbd
gives me the scancodes and shows the same issue:
/dev/input/event8
bustype : BUS_USB
vendor : 0x4f3
product : 0x2073
version : 272
name : "ELAN Touchscreen Pen"
phys : "usb-0000:00:14.0-4/input0"
uniq : ""
bits ev : EV_SYN EV_KEY EV_ABS EV_MSC
map: 15 keys, size: 294/320
0xd0032 = 320 # BTN_TOOL_PEN
0xd0042 = 330 # BTN_TOUCH
0xd0044 = 331 # BTN_STYLUS
0xd003c = 321 # BTN_TOOL_RUBBER
0xd0045 = 256 # BTN_0
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
0xd0042 = 330 # BTN_TOUCH
Trying to use input-kbd
to assign a new map gives a "scancode out of range" error. The straightforward setkeycodes d003c 332
also does not work (USB keyboard bug).
Update: I've tried fixing this through udev by adding a custom hwdb file to /etc/udev/hwdb.d, but it doesn't seem to be having any effect.
$ cat /etc/udev/hwdb.d/61-touchscreen-quirks.hwdb
evdev:input:b0003v04f3p2073e0110* # Matches ELAN Touchscreen devices
KEYBOARD_KEY_d003c=14c # Reassigns scancode from BTN_TOOL_RUBBER to BTN_STYLUS2
$ sudo udevadm --debug hwdb --update
calling: hwdb
reading file '/lib/udev/hwdb.d/20-OUI.hwdb'
reading file '/lib/udev/hwdb.d/20-acpi-vendor.hwdb'
reading file '/lib/udev/hwdb.d/20-bluetooth-vendor-product.hwdb'
reading file '/lib/udev/hwdb.d/20-libgphoto2-6.hwdb'
reading file '/lib/udev/hwdb.d/20-net-ifname.hwdb'
reading file '/lib/udev/hwdb.d/20-pci-classes.hwdb'
reading file '/lib/udev/hwdb.d/20-pci-vendor-model.hwdb'
reading file '/lib/udev/hwdb.d/20-sdio-classes.hwdb'
reading file '/lib/udev/hwdb.d/20-sdio-vendor-model.hwdb'
reading file '/lib/udev/hwdb.d/20-usb-classes.hwdb'
reading file '/lib/udev/hwdb.d/20-usb-media-players.hwdb'
reading file '/lib/udev/hwdb.d/20-usb-vendor-model.hwdb'
reading file '/lib/udev/hwdb.d/60-evdev.hwdb'
reading file '/lib/udev/hwdb.d/60-keyboard.hwdb'
reading file '/etc/udev/hwdb.d/61-touchscreen-quirks.hwdb'
reading file '/lib/udev/hwdb.d/69-libmtp.hwdb'
reading file '/lib/udev/hwdb.d/70-mouse.hwdb'
reading file '/lib/udev/hwdb.d/70-pointingstick.hwdb'
=== trie in-memory ===
nodes: 3899920 bytes ( 97498)
children arrays: 1559952 bytes ( 97497)
values arrays: 1241904 bytes ( 77619)
strings: 1721567 bytes
strings incoming: 4005992 bytes ( 240722)
strings dedup'ed: 2347672 bytes ( 177476)
=== trie on-disk ===
size: 6863455 bytes
header: 80 bytes
nodes: 2339952 bytes ( 97498)
child pointers: 1559952 bytes ( 97497)
value pointers: 1241904 bytes ( 77619)
string store: 1721567 bytes
strings start: 5141888
$ sudo udevadm -d control --reload
calling: control
$ sudo udevadm -d trigger /dev/input/event*
calling: trigger
$ sudo udevadm info -q all -p /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:04F3:2073.0004/input/input9
P: /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:04F3:2073.0004/input/input9
E: ABS=1000003
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:04F3:2073.0004/input/input9
E: EV=1b
E: ID_BUS=usb
E: ID_FOR_SEAT=input-pci-0000_00_14_0-usb-0_4_1_0
E: ID_INPUT=1
E: ID_INPUT_TABLET=1
E: ID_MODEL=Touchscreen
E: ID_MODEL_ENC=Touchscreen
E: ID_MODEL_ID=2073
E: ID_PATH=pci-0000:00:14.0-usb-0:4:1.0
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_4_1_0
E: ID_REVISION=5107
E: ID_SERIAL=ELAN_Touchscreen
E: ID_TYPE=hid
E: ID_USB_DRIVER=usbhid
E: ID_USB_INTERFACES=:030000:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=ELAN
E: ID_VENDOR_ENC=ELAN
E: ID_VENDOR_ID=04f3
E: KEY=c03 1 0 0 0 0
E: MODALIAS=input:b0003v04F3p2073e0110-e0,1,3,4,k100,140,141,14A,14B,ra0,1,18,m4,lsfw
E: MSC=10
E: NAME="ELAN Touchscreen Pen"
E: PHYS="usb-0000:00:14.0-4/input0"
E: PRODUCT=3/4f3/2073/110
E: PROP=0
E: SUBSYSTEM=input
E: TAGS=:seat:
E: UNIQ=""
E: USEC_INITIALIZED=4595650
What did I do wrong here, or alternatively, what is a better way of doing this?
Solution 1:
I was finally able to remap the scancode to BTN_STYLUS2
using ir-keytable
. The command was:
sudo ir-keytable --device /dev/input/event8 --set-key 0xd003c=BTN_STYLUS2
HOWEVER, while I could see that the scancode had been successfully rebound, the button remained dead. evtest
no longer reported any event when the button was pressed.
Before this, there was no MSC_SCAN
event reported by evtest
when that button was pressed, though there were scancodes reported for the other button and also the pen touch. This didn't strike me as more than an odd quirk at the time, but now it seems like the button really does generate no scancode. How did evtest
report a keycode event at all, then? Beats me, and at this point I'm chalking it up to a kernel bug.
In the end, I just kludged together a bash script to watch evtest
for BTN_TOOL_RUBBER
events and simulate a right-click with xdotool
:
#!/bin/bash
# Find the input device number.
devicename="ELAN Touchscreen Pen"
numevents=$(ls /dev/input | grep -c event*)
for ((devnr=0;devnr<$numevents;devnr++)); do
input-kbd $devnr | grep -q "$devicename"
if [[ $? == 0 ]]; then
break
fi
done
# Listen for BTN_TOOL_RUBBER events.
evtest /dev/input/event$devnr | while read line; do
for value in {0..1}; do
echo $line | grep -q "type 1 (EV_KEY), code 321 (BTN_TOOL_RUBBER), value $value"
if [[ $? == 0 ]]; then
case $value in
0) xdotool mouseup 3 ;;
1) xdotool mousedown 3 ;;
esac
fi
done
done
This gives me essentially the basic functionality I wanted anyways. It's not perfect: the mouseup event only happens once the pen leaves proximity, not when the button is released (this is when the BTN_TOOL_RUBBER
key-up event is reported in evtest
), but it works well enough that I'm not going to try debugging the kernel.