diff --git a/meson.build b/meson.build index 4f08d25c..0119c02c 100644 --- a/meson.build +++ b/meson.build @@ -339,7 +339,7 @@ src_libquirks = [ 'src/builddir.h', ] -deps_libquirks = [dep_udev, dep_libwacom, dep_libinput_util] +deps_libquirks = [dep_udev, dep_libwacom, dep_libinput_util, dep_libevdev] libquirks = static_library('quirks', src_libquirks, dependencies : deps_libquirks, include_directories : includes_include) @@ -375,6 +375,8 @@ src_libinput = src_libfilter + [ 'src/evdev-tablet-pad.c', 'src/evdev-tablet-pad.h', 'src/evdev-tablet-pad-leds.c', + 'src/evdev-type.c', + 'src/evdev-type.h', 'src/netlink-seat.c', 'src/netlink-seat.h', 'src/path-seat.c', diff --git a/src/evdev-mt-touchpad-thumb.c b/src/evdev-mt-touchpad-thumb.c index ceb123ef..9ea06467 100644 --- a/src/evdev-mt-touchpad-thumb.c +++ b/src/evdev-mt-touchpad-thumb.c @@ -418,7 +418,11 @@ tp_init_thumb(struct tp_dispatch *tp) tp->thumb.lower_thumb_line = edges.y; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_MT_PRESSURE)) { if (quirks_get_uint32(q, diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 5ff90027..1319f074 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -3219,7 +3219,11 @@ tp_is_tpkb_combo_below(struct evdev_device *device) int rc = false; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q) return false; @@ -3301,7 +3305,11 @@ tp_read_palm_pressure_prop(struct tp_dispatch *tp, struct quirks *q; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q) return threshold; @@ -3337,7 +3345,11 @@ tp_init_palmdetect_size(struct tp_dispatch *tp, uint32_t threshold; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q) return; @@ -3531,7 +3543,11 @@ tp_init_pressure(struct tp_dispatch *tp, assert(abs); quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (q && quirks_get_range(q, QUIRK_ATTR_PRESSURE_RANGE, &r)) { hi = r.upper; lo = r.lower; @@ -3587,7 +3603,11 @@ tp_init_touch_size(struct tp_dispatch *tp, } quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (q && quirks_get_range(q, QUIRK_ATTR_TOUCH_SIZE_RANGE, &r)) { hi = r.upper; lo = r.lower; diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 3b77b47c..5fb23f32 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1089,7 +1089,11 @@ tool_set_pressure_thresholds(struct tablet_dispatch *tablet, goto out; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif tool->pressure.offset = pressure->minimum; @@ -2400,7 +2404,11 @@ tablet_init_smoothing(struct evdev_device *device, bool use_smoothing = true; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif /* By default, always enable smoothing except on AES devices. * AttrTabletSmoothing can override this, if necessary. diff --git a/src/evdev-type.c b/src/evdev-type.c new file mode 100644 index 00000000..43e1918e --- /dev/null +++ b/src/evdev-type.c @@ -0,0 +1,80 @@ +#include +#include + +#include "evdev-type.h" +#include "linux/input.h" + +uint32_t get_input_type(struct libevdev *evdev) +{ + uint32_t type = 0; + unsigned long bit; + + if (libevdev_has_property(evdev, INPUT_PROP_POINTING_STICK)) { + type |= EVDEV_TYPE_POINTING_STICK; + } + + if (libevdev_has_property(evdev, INPUT_PROP_ACCELEROMETER)) { + type |= EVDEV_TYPE_ACCELEROMETER; + } + + if (libevdev_has_event_type(evdev, EV_SW)) { + type |= EVDEV_TYPE_SWITCH; + } + + if (libevdev_has_event_type(evdev, EV_REL)) { + if (libevdev_has_event_code(evdev, EV_REL, REL_Y) && + libevdev_has_event_code(evdev, EV_REL, REL_X) && + libevdev_has_event_code(evdev, EV_KEY, BTN_MOUSE)) { + type |= EVDEV_TYPE_MOUSE; + } + } + else if (libevdev_has_event_type(evdev, EV_ABS)) { + if (libevdev_has_event_code(evdev, EV_KEY, BTN_SELECT) || + libevdev_has_event_code(evdev, EV_KEY, BTN_TR) || + libevdev_has_event_code(evdev, EV_KEY, BTN_START) || + libevdev_has_event_code(evdev, EV_KEY, BTN_TL)) { + if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH)) { + type |= EVDEV_TYPE_TOUCHSCREEN; + } + else { + type |= EVDEV_TYPE_JOYSTICK; + } + } + else if (libevdev_has_event_code(evdev, EV_ABS, ABS_Y) && + libevdev_has_event_code(evdev, EV_ABS, ABS_X)) { + if (libevdev_has_event_code(evdev, EV_ABS, ABS_Z) && + !libevdev_has_event_type(evdev, EV_KEY)) { + type |= EVDEV_TYPE_ACCELEROMETER; + } + else if (libevdev_has_event_code(evdev, EV_KEY, BTN_STYLUS) || + libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN)) { + type |= EVDEV_TYPE_TABLET; + } + else if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH)) { + if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER)) { + type |= EVDEV_TYPE_TOUCHPAD; + } + else { + type |= EVDEV_TYPE_TOUCHSCREEN; + } + } + else if (libevdev_has_event_code(evdev, EV_KEY, BTN_MOUSE)) { + type |= EVDEV_TYPE_MOUSE; + } + } + } + + for (bit = KEY_ESC; bit < BTN_MISC; bit++) { + if (libevdev_has_event_code(evdev, EV_KEY, bit)) { + type |= EVDEV_TYPE_KEY; + + if (libevdev_has_event_code(evdev, EV_KEY, KEY_ENTER)) { + type |= EVDEV_TYPE_KEYBOARD; + } + + break; + } + } + + return type ? type : EVDEV_TYPE_UNKNOWN; +} diff --git a/src/evdev-type.h b/src/evdev-type.h new file mode 100644 index 00000000..78d9bd0d --- /dev/null +++ b/src/evdev-type.h @@ -0,0 +1,18 @@ +#include +#include + +enum { + EVDEV_TYPE_UNKNOWN = 1 << 0, + EVDEV_TYPE_MOUSE = 1 << 1, + EVDEV_TYPE_TABLET = 1 << 2, + EVDEV_TYPE_TOUCHPAD = 1 << 3, + EVDEV_TYPE_KEYBOARD = 1 << 4, + EVDEV_TYPE_JOYSTICK = 1 << 5, + EVDEV_TYPE_TOUCHSCREEN = 1 << 6, + EVDEV_TYPE_SWITCH = 1 << 7, + EVDEV_TYPE_ACCELEROMETER = 1 << 8, + EVDEV_TYPE_POINTING_STICK = 1 << 9, + EVDEV_TYPE_KEY = 1 << 10, +}; + +uint32_t get_input_type(struct libevdev *evdev); diff --git a/src/evdev.c b/src/evdev.c index 64bc3d6d..49babd43 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -48,6 +48,7 @@ #include "libinput-private.h" #include "quirks.h" #include "util-input-event.h" +#include "evdev-type.h" #if HAVE_LIBWACOM #include @@ -98,6 +99,24 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = { {"ID_INPUT_TRACKBALL", EVDEV_UDEV_TAG_TRACKBALL}, {"ID_INPUT_SWITCH", EVDEV_UDEV_TAG_SWITCH}, }; +#else +static const struct { + uint32_t name; + enum evdev_device_udev_tags tag; +} evdev_udev_tag_matches[] = { + {EVDEV_TYPE_KEYBOARD, EVDEV_UDEV_TAG_KEYBOARD}, + {EVDEV_TYPE_KEY, EVDEV_UDEV_TAG_KEYBOARD}, + {EVDEV_TYPE_MOUSE, EVDEV_UDEV_TAG_MOUSE}, + {EVDEV_TYPE_TOUCHPAD, EVDEV_UDEV_TAG_TOUCHPAD}, + {EVDEV_TYPE_TOUCHSCREEN, EVDEV_UDEV_TAG_TOUCHSCREEN}, + {EVDEV_TYPE_TABLET, EVDEV_UDEV_TAG_TABLET}, + // {EVDEV_TYPE_TABLET_PAD, EVDEV_UDEV_TAG_TABLET_PAD}, + {EVDEV_TYPE_JOYSTICK, EVDEV_UDEV_TAG_JOYSTICK}, + {EVDEV_TYPE_ACCELEROMETER, EVDEV_UDEV_TAG_ACCELEROMETER}, + {EVDEV_TYPE_POINTING_STICK, EVDEV_UDEV_TAG_POINTINGSTICK}, + // {EVDEV_TYPE_TRACKBALL, EVDEV_UDEV_TAG_TRACKBALL}, + {EVDEV_TYPE_SWITCH, EVDEV_UDEV_TAG_SWITCH}, +}; #endif static inline bool @@ -510,7 +529,11 @@ evdev_tag_trackpoint(struct evdev_device *device, device->tags |= EVDEV_TAG_TRACKPOINT; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (q && quirks_get_string(q, QUIRK_ATTR_TRACKPOINT_INTEGRATION, &prop)) { if (streq(prop, "internal")) { /* noop, this is the default anyway */ @@ -562,7 +585,11 @@ evdev_tag_keyboard(struct evdev_device *device, } quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (q && quirks_get_string(q, QUIRK_ATTR_KEYBOARD_INTEGRATION, &prop)) { if (streq(prop, "internal")) { evdev_tag_keyboard_internal(device); @@ -994,7 +1021,11 @@ evdev_read_switch_reliability_prop(struct evdev_device *device) char *prop; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q || !quirks_get_string(q, QUIRK_ATTR_LID_SWITCH_RELIABILITY, &prop)) { r = RELIABILITY_UNKNOWN; } else if (!parse_switch_reliability_property(prop, &r)) { @@ -1408,7 +1439,11 @@ evdev_get_trackpoint_multiplier(struct evdev_device *device) return 1.0; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (q) { quirks_get_double(q, QUIRK_ATTR_TRACKPOINT_MULTIPLIER, &multiplier); quirks_unref(q); @@ -1437,7 +1472,11 @@ evdev_need_velocity_averaging(struct evdev_device *device) bool use_velocity_averaging = false; /* default off unless we have quirk */ quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (q) { quirks_get_bool(q, QUIRK_ATTR_USE_VELOCITY_AVERAGING, @@ -1509,7 +1548,11 @@ evdev_read_model_flags(struct evdev_device *device) struct quirks *q; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif while (q && m->quirk) { bool is_set; @@ -1576,7 +1619,11 @@ evdev_read_attr_res_prop(struct evdev_device *device, bool rc = false; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q) return false; @@ -1602,7 +1649,11 @@ evdev_read_attr_size_prop(struct evdev_device *device, bool rc = false; quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q) return false; @@ -1688,26 +1739,11 @@ evdev_device_get_udev_tags(struct evdev_device *device, return 0; if (major(st.st_rdev) == INPUT_MAJOR) tags |= EVDEV_UDEV_TAG_INPUT; - if (libevdev_has_event_code(evdev, EV_KEY, KEY_ENTER) || - libevdev_has_event_code(evdev, EV_KEY, KEY_VOLUMEUP) || - libevdev_has_event_code(evdev, EV_KEY, KEY_POWER)) - tags |= EVDEV_UDEV_TAG_KEYBOARD; - if (libevdev_has_event_code(evdev, EV_REL, REL_X) && - libevdev_has_event_code(evdev, EV_REL, REL_Y) && - libevdev_has_event_code(evdev, EV_KEY, BTN_MOUSE)) - tags |= EVDEV_UDEV_TAG_MOUSE; - if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) && - libevdev_has_event_code(evdev, EV_ABS, ABS_Y)) { - if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) && - !libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN) && - !libevdev_has_property(evdev, INPUT_PROP_DIRECT)) { - tags |= EVDEV_UDEV_TAG_TOUCHPAD; - } else if (libevdev_has_event_code(evdev, EV_KEY, BTN_MOUSE)) { - tags |= EVDEV_UDEV_TAG_MOUSE; - } else if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH) || - libevdev_has_property(evdev, INPUT_PROP_DIRECT)) { - tags |= EVDEV_UDEV_TAG_TOUCHSCREEN; - } + + uint32_t evdev_type = get_input_type(evdev); + for (size_t i = 0; i < ARRAY_LENGTH(evdev_udev_tag_matches); i++) { + if (evdev_type & evdev_udev_tag_matches[i].name) + tags |= evdev_udev_tag_matches[i].tag; } #endif @@ -2199,7 +2235,11 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) * unnecessary wakeups but on some devices we need to watch it for * pointer jumps */ quirks = evdev_libinput_context(device)->quirks; +#if HAVE_UDEV q = quirks_fetch_for_device(quirks, device->udev_device); +#else + q = quirks_fetch_for_evdev(quirks, device->evdev); +#endif if (!q || !quirks_get_string(q, QUIRK_ATTR_MSC_TIMESTAMP, &prop) || !streq(prop, "watch")) { diff --git a/src/quirks.c b/src/quirks.c index fe2cebba..4eb36e43 100644 --- a/src/quirks.c +++ b/src/quirks.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef __FreeBSD__ #include #endif @@ -46,6 +47,7 @@ #include "libinput-util.h" #include "quirks.h" +#include "evdev-type.h" /* Custom logging so we can have detailed output for the tool but minimal * logging for libinput itself. */ @@ -1187,7 +1189,6 @@ quirks_context_unref(struct quirks_context *ctx) return NULL; } -#if HAVE_UDEV static struct quirks * quirks_new(void) { @@ -1200,7 +1201,6 @@ quirks_new(void) return q; } -#endif struct quirks * quirks_unref(struct quirks *q) @@ -1247,8 +1247,10 @@ udev_prop(struct udev_device *device, const char *prop) static inline void match_fill_name(struct match *m, - struct udev_device *device) + struct udev_device *device, + struct libevdev *evdev) { +#if HAVE_UDEV const char *str = udev_prop(device, "NAME"); size_t slen; @@ -1264,17 +1266,22 @@ match_fill_name(struct match *m, if (slen > 1 && m->name[slen - 1] == '"') m->name[slen - 1] = '\0'; +#else + m->name = safe_strdup(libevdev_get_name(evdev)); +#endif m->bits |= M_NAME; } static inline void match_fill_bus_vid_pid(struct match *m, - struct udev_device *device) + struct udev_device *device, + struct libevdev *evdev) { const char *str; unsigned int product, vendor, bus, version; +#if HAVE_UDEV str = udev_prop(device, "PRODUCT"); if (!str) return; @@ -1284,6 +1291,12 @@ match_fill_bus_vid_pid(struct match *m, if (sscanf(str, "%x/%x/%x/%x", &bus, &vendor, &product, &version) != 4) return; +#else + bus = libevdev_get_id_bustype(evdev); + product = libevdev_get_id_product(evdev); + vendor = libevdev_get_id_vendor(evdev); + version = libevdev_get_id_version(evdev); +#endif m->product = product; m->vendor = vendor; m->version = version; @@ -1320,8 +1333,10 @@ match_fill_bus_vid_pid(struct match *m, static inline void match_fill_udev_type(struct match *m, - struct udev_device *device) + struct udev_device *device, + struct libevdev *evdev) { +#if HAVE_UDEV struct ut_map { const char *prop; enum udev_type flag; @@ -1341,6 +1356,28 @@ match_fill_udev_type(struct match *m, if (udev_prop(device, map->prop)) m->udev_type |= map->flag; } +#else + struct ut_map { + uint32_t prop; + enum udev_type flag; + } mappings[] = { + { EVDEV_TYPE_MOUSE, UDEV_MOUSE }, + { EVDEV_TYPE_POINTING_STICK, UDEV_POINTINGSTICK }, + { EVDEV_TYPE_TOUCHPAD, UDEV_TOUCHPAD }, + { EVDEV_TYPE_TABLET, UDEV_TABLET }, + // { EVDEV_TYPE_TABLET_PAD, UDEV_TABLET_PAD }, + { EVDEV_TYPE_JOYSTICK, UDEV_JOYSTICK }, + { EVDEV_TYPE_KEYBOARD, UDEV_KEYBOARD }, + { EVDEV_TYPE_KEY, UDEV_KEYBOARD }, + }; + struct ut_map *map; + + uint32_t type = get_input_type(evdev); + ARRAY_FOR_EACH(mappings, map) { + if (type & map->prop) + m->udev_type |= map->flag; + } +#endif m->bits |= M_UDEV_TYPE; } @@ -1358,17 +1395,16 @@ match_fill_dmi_dt(struct match *m, char *dmi, char *dt) } } -#if HAVE_UDEV static struct match * -match_new(struct udev_device *device, +match_new(struct udev_device *device, struct libevdev *evdev, char *dmi, char *dt) { struct match *m = zalloc(sizeof *m); - match_fill_name(m, device); - match_fill_bus_vid_pid(m, device); + match_fill_name(m, device, evdev); + match_fill_bus_vid_pid(m, device, evdev); match_fill_dmi_dt(m, dmi, dt); - match_fill_udev_type(m, device); + match_fill_udev_type(m, device, evdev); return m; } @@ -1484,7 +1520,6 @@ quirk_match_section(struct quirks_context *ctx, return true; } -#endif struct quirks * quirks_fetch_for_device(struct quirks_context *ctx, @@ -1503,7 +1538,7 @@ quirks_fetch_for_device(struct quirks_context *ctx, q = quirks_new(); - m = match_new(udev_device, ctx->dmi, ctx->dt); + m = match_new(udev_device, NULL, ctx->dmi, ctx->dt); list_for_each(s, &ctx->sections, link) { quirk_match_section(ctx, q, s, m, udev_device); @@ -1524,6 +1559,36 @@ quirks_fetch_for_device(struct quirks_context *ctx, #endif } +struct quirks * +quirks_fetch_for_evdev(struct quirks_context *ctx, + struct libevdev *evdev) +{ + struct quirks *q = NULL; + struct section *s; + struct match *m; + + if (!ctx) + return NULL; + + q = quirks_new(); + + m = match_new(NULL, evdev, ctx->dmi, ctx->dt); + + list_for_each(s, &ctx->sections, link) { + quirk_match_section(ctx, q, s, m, NULL); + } + + match_free(m); + + if (q->nproperties == 0) { + quirks_unref(q); + return NULL; + } + + list_insert(&ctx->quirks, &q->link); + + return q; +} static inline struct property * quirk_find_prop(struct quirks *q, enum quirk which) diff --git a/src/quirks.h b/src/quirks.h index 94b6eed0..85c47c04 100644 --- a/src/quirks.h +++ b/src/quirks.h @@ -27,6 +27,7 @@ #include #include +#include #include "libinput.h" @@ -193,6 +194,10 @@ struct quirks * quirks_fetch_for_device(struct quirks_context *ctx, struct udev_device *device); +struct quirks * +quirks_fetch_for_evdev(struct quirks_context *ctx, + struct libevdev *evdev); + /** * Reduce the refcount by one. When the refcount reaches zero, the * associated struct is released.