Input devices (whether physically present, or emulated) may produce any "kind" of input.
In other words there is no clear distinction between a keyboard and a mouse, other than the data they (i.e., their drivers) write to their corresponding /dev/input/eventX
file (where X is an integer).
That can be problematic sometimes, for example if a program in userspace consumes input data from a device and expects that data to only contain certain keycodes, event types, etc.
Another example could be a video game which displays different sprites/text when a gamepad is used instead of a keyboard, like key/button prompts in a tutorial or a settings menu.
Luckily, most devices only write a strict set of event types and codes to their eventX file, because well, most hardware is only a keyboard, or mouse, or gamepad, or touchscreen, etc. and not a wild combination.
The kernel calls these the input device's capabilities, as documented here.
As stated in the kernel documentation, each eventX device has a "capabilities" subdirectory at this path: /sys/class/input/eventX/device/capabilities
(where X is an integer).
The file structure and format is unfortunately not documented, however I have conducted some experiments and believe that I've cracked the case.
First of all, the subdirectory always contains 9 files. Each of these files contains information about what kind of events or event codes the device is able to send. Please refer to the previously linked page in the kernel documentation to find out more about each type of event, and their associated event codes.
abs
-> Absolute Values (ABS_<...>)ev
-> All possible Event Types (EV_<...>)ff
-> Force Feedback (FF_<...>)key
-> Keycodes (KEY_<...>)led
-> Light Emitting Diodes (LED_<...>)msc
-> Miscellaneous (MSC_<...>)rel
-> Relative Values (REL_<...>)snd
-> Sound (SND_<...>)sw
-> Binary Switches (SW_<...>)
All of the files contain ASCII encoded characters, so make sure you decode the data correctly when reading it (especially relevant for programmers). The ASCII characters exclusively consist of hex characters (0-9, a-f), spaces, and LF (linefeed). As you can probably guess, the hex characters represent the main "payload" of the capabilities, so to speak. However, their spacing is equally as important. The following rules describe the text format accurately:
- All text is evaluated from right to left. Keep that in mind for the rest of the rules!
- LF (linefeed) characters should be ignored completely, including the terminology of these rules. For example, two hex characters separated by LF are still considered "consecutive" and "contiguous".
- Hex characters appear in contiguous groups that are no longer than 16 characters. The groups are divided by a single space character (no sequential spaces).
- There are no space characters at the beginning or end of the text.
Examples of possible text:
402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
120013
0
1f0000 0 0 0 0
The hexadecimal characters found in the formatted text cannot be directly translated into binary. Instead, use the following algorithm (# marks comments):
# ordered collection of individual bits (0 or 1)
binary = empty
# integer counter
i = 0
# iterate over ASCII text, in reverse
for each character "c" in reversed-text:
if c is LF:
# ignore linefeed
continue
else if c is space:
# hex groups which are less than 16 characters long omit false bits,
# so they have to be added back manually
append (4 * (16 - i)) false bits to binary
i = 0
else:
# -> must be hex character
# only 4 bits should be appended, in reverse order
bits = hex_to_reversed_binary(c)
append bits to binary
i = i + 1
The text examples from the previous section would be decoded into this:
011111111111111111111111111111111111111111111111111111111111111111111111111111111111011111111111111110111111111111111111011111111000000000001011000000000001111100011110000011000000000111000000000000000000000000000000010000000010
110010000000000001001000
0000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111000
Each bit is a boolean flag that, when set, indicates that the input device is capable of generating an event of a specific type or with a specific code. The position of each bit corresponds with the value of the respective macro in input-event-codes.h.
To check whether a device is capable of sending any key or button events (keyboard, mouse, gamepad, ...), follow these steps:
- Decode the file
/sys/class/input/eventX/device/capabilities/ev
(where X is an integer) to binary, as described in the previous sections. - Read the bit at zero-based index EV_KEY (check the linked header for reference).
- If the bit is set (i.e., is 1), the device may send events of type EV_KEY.
- If the bit is not set (i.e., is 0) or the index is out of range, the device will never send events of type EV_KEY.
To check whether a device is capable of sending the key code corresponding to "A" (most keyboards):
- Decode the file
/sys/class/input/eventX/device/capabilities/key
(where X is an integer) to binary, as described in the previous sections. - Read the bit at zero-based index KEY_A (check the linked header for reference).
- If the bit is set (i.e., is 1), the device may send events with keycode KEY_A.
- If the bit is not set (i.e., is 0) or the index is out of range, the device will never send events with keycode KEY_A.
Obviously, if a device is not capable of sending EV_KEY events, it will also never send event code KEY_A.
You can now (hopefully) decode evdev device capabilities! If you have any remarks or questions, feel free to leave a comment.
This document was created by Trice Helix for the Public Domain.