linuxkeyboardusbhidtelephony

Are there standardised key codes for "answer" and/or "hangup" like a multimedia keyboard might have?


I'm messing about, writing some code that simulates keyboard/input device events to automate various things under linux.

I've been using /usr/include/linux/input-event-codes.h as a bit of a reference for what key-codes are available. Within that header, it mentions that some of the content is based on a USB standard:

/*
 * Keys and buttons
 *
 * Most of the keys/buttons are modeled after USB HUT 1.12
 * (see http://www.usb.org/developers/hidpage).
 * Abbreviations in the comments:
 * AC - Application Control
 * AL - Application Launch Button
 * SC - System Control
 */

I assume it's referring to an old version of this HID User Table doc...

For example Volume up/down:

Consumer Page (0x0C)
Usage ID: E9 = Volume increment
Usage ID: EA = Volume decrement

So the USB scan codes of 0x0C00E9 and 0x0C00EA somehow map through to the key codes from the header:

#define KEY_VOLUMEDOWN          114
#define KEY_VOLUMEUP            115

Which I confirmed on my keyboard with evtest:

Testing ... (interrupt to exit)
Event: time 1670822773.520848, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1670822773.520848, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1
Event: time 1670822773.520848, -------------- SYN_REPORT ------------
Event: time 1670822773.521763, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1670822773.521763, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 0
Event: time 1670822773.521763, -------------- SYN_REPORT ------------
Event: time 1670822775.779771, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1670822775.779771, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1670822775.779771, -------------- SYN_REPORT ------------
Event: time 1670822775.780761, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1670822775.780761, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1670822775.780761, -------------- SYN_REPORT ------------

My question is, where is that mapping defined (udev? kernel usb driver?), because if I find other functions in the USB standard, I'd like to see if and what key code they map to. The volume example was straightforward to figure out based on the names and the fact I could test with a physical device, but others won't be.

Specifically I want to start with scan code 0x0b0026 (Telephony Device - Drop), which I would call hangup, because I can't find a key code for that.

My search engine results fail to find much, but like always, I'm sure I'm just searching the wrong terms.


Solution

  • Looks like scan code to key code mapping is a combination of kernel driver and udev.

    The default mapping looks to be done in the kernel driver: see here for the example volume up/down in the hid-input driver:

    case 0x0e9: map_key_clear(KEY_VOLUMEUP);    break;
    case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);  break;
    

    After that, there's a whole bunch of extra mapping and/or remapping done by udev hwdb. See the Arch wiki for a good write-up of that here.

    So that means the final mapping is by no means 'standard'. There could be a whole range of mappings for a single USB HID usage table function, depending on the driver and the hardware id. For example, you might have two different vendor USB keyboard that both have a volume button that both send the same scan code, but they could produce two different key codes. Or you could load a different driver for the same keyboard and get another key code.

    Now, for the specific question of a key code for a hang-up button (scan code 0x0b0026, Telephony Device - Drop): There's no default mapping in the hid-input driver:

    case HID_UP_TELEPHONY:
            switch (usage->hid & HID_USAGE) {
            case 0x2f: map_key_clear(KEY_MICMUTE);      break;
            case 0xb0: map_key_clear(KEY_NUMERIC_0);    break;
            case 0xb1: map_key_clear(KEY_NUMERIC_1);    break;
            case 0xb2: map_key_clear(KEY_NUMERIC_2);    break;
            case 0xb3: map_key_clear(KEY_NUMERIC_3);    break;
            case 0xb4: map_key_clear(KEY_NUMERIC_4);    break;
            case 0xb5: map_key_clear(KEY_NUMERIC_5);    break;
            case 0xb6: map_key_clear(KEY_NUMERIC_6);    break;
            case 0xb7: map_key_clear(KEY_NUMERIC_7);    break;
            case 0xb8: map_key_clear(KEY_NUMERIC_8);    break;
            case 0xb9: map_key_clear(KEY_NUMERIC_9);    break;
            case 0xba: map_key_clear(KEY_NUMERIC_STAR); break;
            case 0xbb: map_key_clear(KEY_NUMERIC_POUND);    break;
            case 0xbc: map_key_clear(KEY_NUMERIC_A);    break;
            case 0xbd: map_key_clear(KEY_NUMERIC_B);    break;
            case 0xbe: map_key_clear(KEY_NUMERIC_C);    break;
            case 0xbf: map_key_clear(KEY_NUMERIC_D);    break;
            default: goto ignore;
            }
            break;
    

    And there's no udev hwdb mappings I can find:

    me@computer:/usr/lib/udev/hwdb.d$ grep -n -e "[bB]0026" ./*
    me@computer:/usr/lib/udev/hwdb.d$ 
    

    at least on ubuntu 20.04.

    So in summary No there is not a an even somewhat standardised key code for a hang-up button.