Bug 199143

Summary: USB KEYBOARD doesn't produce modified keycodes set by ioctl(fd,KDSETKEYCODE,...)
Product: Drivers Reporter: gumix (m.sokalski)
Component: Input DevicesAssignee: drivers_input-devices
Status: RESOLVED INVALID    
Severity: normal CC: dmitry.torokhov, m.sokalski
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 4.15.9 Subsystem:
Regression: No Bisected commit-id:

Description gumix 2018-03-19 18:06:48 UTC
My program attempts to modify scan-code to key-code mapping tables using  ioctl(fd,KDSETKEYCODE,...).

In all cases it returns 0 (ok), ioctl(fd,KDGETKEYCODE,...) confirms mapping is set to desired value. 

Now, my program is listening to key events in K_MEDIUMRAW mode set by ioctl(fd, KDSKBMODE,K_MEDIUMRAW).

- It works perfectly with PS/2 keyboards, I receive modified keycodes. 

- But using USB keyboard, it keeps sending unmodified keycodes.

I've tried different distributions: Fedora27 (4.15.9), Arch (4.13.11), Debian (4.9.0) - all the same. 

My intuition says the problem is somewhere in the hid-input handler.
I'd be happy to provide any additional information if needed.
Comment 1 gumix 2018-03-19 18:28:43 UTC
Adding how to easily reproduce the problem:

# mapping TAB scancode (hex 0x0F) to ENTER keycode (dec 28)
sudo setkeycodes 0F 28

Now pressing TAB key on PS/2 keyboard makes new lines (Enter), USB keyboards keep Tabs.
Comment 2 Dmitry Torokhov 2018-03-20 17:44:43 UTC
There is no such thing as "scancode" for USB keyboards, they use "usage codes" and they are different from PS/2 scancodes. The usage code for TAB key on USB keyboards is 0x7002b:

Event: time 1521567515.603992, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7002b
Event: time 1521567515.603992, type 1 (EV_KEY), code 15 (KEY_TAB), value 1

I would not recommend using setkeycodes in environments where there are multiple keyboards. From drivers/tty/vt/keyboard.c:

/*
 * Translation of scancodes to keycodes. We set them on only the first
 * keyboard in the list that accepts the scancode and keycode.
 * Explanation for not choosing the first attached keyboard anymore:
 *  USB keyboards for example have two event devices: one for all "normal"
 *  keys and one for extra function keys (like "volume up", "make coffee",
 *  etc.). So this means that scancodes for the extra function keys won't
 *  be valid for the first event device, but will be for the second.
 */

But it all breaks down anyway when you throw in other devices into mix. If you need remapping, please use evdev interface with EVIOCSKEYCODE_V2 ioctl.

Neither of this has anything to do with K_MEDIUMRAW. Why do you even need this?
Comment 3 gumix 2018-03-20 18:43:16 UTC
First of all, thank you Dmitry, for such great explanations.

I tried to use KDSETKEYCODE as a hack onto midnight commander. 
I use K_MEDIUMRAW to be able to intercept key presses & releases in console application, but when I start my app from MC, and I press TAB key (scancode/keycode = 0x0F), MC thinks I presses Ctrl+0 (ascii 0x0F) so it gets on top of my application. What the unfortunate coincidence of codes. So I used KDSETKEYCODE to remap TAB scan-code onto some unused key-code, with success, but only on PS/2 keyboard. I was wondering why It doesn't do its job with USB keyboard but couldn't find any clue. 

Now everything's clear. Thanks you so much, and my apologies for adding yet another unwanted not-a-bbug report. Hopefully somebody else with similar misunderstandings as mine will find it useful.
Comment 4 gumix 2018-03-20 21:32:50 UTC
Adding reference to some nice tool which proves it indeed works:

sudo ./keytable -k 0x7002b=28 --device /dev/input/event8

https://github.com/stefansaraev/keytable