Fix udev not detecting ID_INPUT_KEY devices when udev is not running https://bugzilla.libsdl.org/show_bug.cgi?id=5308 The udev code labels devices that are found by this code with ID_INPUT_KEY which in turn gets used by SDL to label the devices as SDL_UDEV_DEVICE_KEYBOARD. This was missing for the code path when udev is not running and as such devices such as the power button of a phone was not detected as keyboard input and no devices were emitted.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
diff --git a/src/core/linux/SDL_evdev_capabilities.c b/src/core/linux/SDL_evdev_capabilities.c
index 12185fe..92f247e 100644
--- a/src/core/linux/SDL_evdev_capabilities.c
+++ b/src/core/linux/SDL_evdev_capabilities.c
@@ -24,12 +24,34 @@
#if HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)
+/* missing defines in older Linux kernel headers */
+#ifndef BTN_TRIGGER_HAPPY
+#define BTN_TRIGGER_HAPPY 0x2c0
+#endif
+#ifndef BTN_DPAD_UP
+#define BTN_DPAD_UP 0x220
+#endif
+#ifndef KEY_ALS_TOGGLE
+#define KEY_ALS_TOGGLE 0x230
+#endif
+
extern int
SDL_EVDEV_GuessDeviceClass(unsigned long bitmask_ev[NBITS(EV_MAX)],
unsigned long bitmask_abs[NBITS(ABS_MAX)],
unsigned long bitmask_key[NBITS(KEY_MAX)],
unsigned long bitmask_rel[NBITS(REL_MAX)])
{
+ struct range {
+ unsigned start;
+ unsigned end;
+ };
+
+ /* key code ranges above BTN_MISC (start is inclusive, stop is exclusive)*/
+ static const struct range high_key_blocks[] = {
+ { KEY_OK, BTN_DPAD_UP },
+ { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY }
+ };
+
int devclass = 0;
unsigned long keyboard_mask;
@@ -86,6 +108,31 @@ SDL_EVDEV_GuessDeviceClass(unsigned long bitmask_ev[NBITS(EV_MAX)],
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
}
+ if (test_bit(EV_KEY, bitmask_ev)) {
+ unsigned i;
+ unsigned long found = 0;
+
+ for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) {
+ found |= bitmask_key[i];
+ }
+ /* If there are no keys in the lower block, check the higher blocks */
+ if (!found) {
+ unsigned block;
+ for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) {
+ for (i = high_key_blocks[block].start; i < high_key_blocks[block].end; ++i) {
+ if (test_bit(i, bitmask_key)) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (found > 0) {
+ devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEY */
+ }
+ }
+
/* the first 32 bits are ESC, numbers, and Q to D; if we have any of
* those, consider it a keyboard device; do not test KEY_RESERVED, though */
keyboard_mask = 0xFFFFFFFE;