From a7e4cbc212be85950f942830aebfb017f43b2504 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 15 Nov 2022 13:53:43 +1000 Subject: [PATCH] quirks: allow overriding of AttrEventCode and AttrInputProp This switches the quirk from AttrEventCodeEnable/Disable to just AttrEventCode with a +/- prefix for each entry. This switches the quirk from AttrInputPropEnable/Disable to just AttrInputProp with a +/- prefix for each entry. Previously, both event codes and input props would only apply the last-matching section entry for a device. Furthermore, an earlier Disable entry would take precedence over a later Enable entry. For example, a set of sections with these lines *should* enable left, right and middle: [first] AttrEventCodeEnable=BTN_LEFT;BTN_RIGHT;BTN_MIDDLE [second] AttrEventCodeDisable=BTN_RIGHT [third] AttrEventCodeEnable=BTN_LEFT;BTN_RIGHT; Alas: the first line was effectively ignored (quirks only returned the last-matching one, i.e. the one from "third"). And due to implementation details in evdev.c, the Disable attribute was processed after Enable, i.e. the device was enabled for left + right and then disabled for right. As a result, the device only had BTN_LEFT enabled. Fix this by changing the attribute to carry both enable/disable information and merging the commands together. Internally, all quirks matching a device are simply ref'd into an array in the struct quirks. The applied value is simply the last entry in the array corresponding to our quirk. For AttrEventCode and AttrInputProp instead do this: - switch them to a tuple with the code as first entry and a boolean enable/disable as second entry - if the struct quirk already has an entry for either, append the more recent one to the existing entry (instead of creating a new entry in the array). This way we have all entries that match and in-order of precedence - i.e. we can process them left-to-right to end up with the right state. Fixes: https://gitlab.freedesktop.org/libinput/libinput/-/issues/821 Signed-off-by: Peter Hutterer --- doc/user/clickpad-with-right-button.rst | 2 +- doc/user/device-quirks.rst | 17 ++-- doc/user/incorrectly-enabled-hires.rst | 2 +- quirks/30-vendor-aiptek.quirks | 2 +- quirks/30-vendor-kensington.quirks | 2 +- quirks/30-vendor-logitech.quirks | 2 +- quirks/30-vendor-madcatz.quirks | 4 +- quirks/30-vendor-synaptics.quirks | 2 +- quirks/30-vendor-wacom.quirks | 4 +- quirks/50-framework.quirks | 2 +- quirks/50-system-apple.quirks | 2 +- quirks/50-system-asus.quirks | 2 +- quirks/50-system-chuwi.quirks | 4 +- quirks/50-system-cyborg.quirks | 2 +- quirks/50-system-dell.quirks | 2 +- quirks/50-system-gpd.quirks | 2 +- quirks/50-system-hp.quirks | 6 +- quirks/50-system-huawei.quirks | 2 +- quirks/50-system-lenovo.quirks | 12 +-- quirks/50-system-starlabs.quirks | 4 +- src/evdev.c | 93 ++++++++----------- src/quirks.c | 105 ++++++++++++++++----- src/quirks.h | 7 +- src/util-prop-parsers.c | 43 +++++++-- src/util-prop-parsers.h | 7 +- test/litest-device-keyboard-quirked.c | 34 ++++++- test/test-device.c | 28 +++++- test/test-utils.c | 118 ++++++++++++------------ tools/shared.c | 31 ++++--- 29 files changed, 332 insertions(+), 211 deletions(-) diff --git a/doc/user/clickpad-with-right-button.rst b/doc/user/clickpad-with-right-button.rst index b874b2ed..76c1ca54 100644 --- a/doc/user/clickpad-with-right-button.rst +++ b/doc/user/clickpad-with-right-button.rst @@ -30,7 +30,7 @@ MyVendor OEM:: MatchName=Foo Bar Touchpad MatchUdevtype=touchpad MatchDMIModAlias=dmi:*svnMyVendor:pnMyModel:* - AttrEventCodeDisable=BTN_RIGHT + AttrEventCode=-BTN_RIGHT The name of the device can be obtained using :ref:`libinput record `, the modalias match is a shell-style glob against the value of ``/sys/class/dmi/id/modalias``. diff --git a/doc/user/device-quirks.rst b/doc/user/device-quirks.rst index 7c220282..d7461b08 100644 --- a/doc/user/device-quirks.rst +++ b/doc/user/device-quirks.rst @@ -174,19 +174,14 @@ AttrTPKComboLayout=below Indicates the position of the touchpad on an external touchpad+keyboard combination device. This is a string enum. Don't specify it unless the touchpad is below. -AttrEventCodeDisable=EV_ABS;BTN_STYLUS;EV_KEY:0x123; - Disables the evdev event type/code tuples on the device. Entries may be +AttrEventCode=+EV_ABS;-BTN_STYLUS;+EV_KEY:0x123; + Enables or disables the evdev event type/code tuples on the device. The prefix + for each entry is either '+' (enable) or '-' (disable). Entries may be a named event type, or a named event code, or a named event type with a hexadecimal event code, separated by a single colon. -AttrEventCodeEnable=EV_ABS;BTN_STYLUS;EV_KEY:0x123; - Enables the evdev event type/code tuples on the device. Entries may be - a named event type, or a named event code, or a named event type with a - hexadecimal event code, separated by a single colon. -AttrInputPropDisable=INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER; - Disables the evdev input property on the device. Entries may be - a named input property or the hexadecimal value of that property. -AttrInputPropEnable=INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER; - Enables the evdev input property on the device. Entries may be +AttrInputProp=+INPUT_PROP_BUTTONPAD;-INPUT_PROP_POINTER; + Enables or disables the evdev input property on the device. The prefix + for each entry is either '+' (enable) or '-' (disable). Entries may be a named input property or the hexadecimal value of that property. AttrPointingStickIntegration=internal|external Indicates the integration of the pointing stick. This is a string enum. diff --git a/doc/user/incorrectly-enabled-hires.rst b/doc/user/incorrectly-enabled-hires.rst index 7dffca79..4273db21 100644 --- a/doc/user/incorrectly-enabled-hires.rst +++ b/doc/user/incorrectly-enabled-hires.rst @@ -57,6 +57,6 @@ events are sent: :: The issue can be fixed by adding a quirk to unset the ``REL_WHEEL_HI_RES`` and ``REL_HWHEEL_HI_RES`` event codes: :: - AttrEventCodeDisable=REL_WHEEL_HI_RES;REL_HWHEEL_HI_RES; + AttrEventCode=-REL_WHEEL_HI_RES;-REL_HWHEEL_HI_RES; Please see :ref:`device-quirks` for details. diff --git a/quirks/30-vendor-aiptek.quirks b/quirks/30-vendor-aiptek.quirks index 3efddb63..70bed023 100644 --- a/quirks/30-vendor-aiptek.quirks +++ b/quirks/30-vendor-aiptek.quirks @@ -4,7 +4,7 @@ MatchUdevType=tablet MatchBus=usb MatchVendor=0x08CA -AttrEventCodeDisable=ABS_TILT_X;ABS_TILT_Y; +AttrEventCode=-ABS_TILT_X;-ABS_TILT_Y; [Aiptek 8000U pressure threshold] MatchUdevType=tablet diff --git a/quirks/30-vendor-kensington.quirks b/quirks/30-vendor-kensington.quirks index f4d83a09..e77204b6 100644 --- a/quirks/30-vendor-kensington.quirks +++ b/quirks/30-vendor-kensington.quirks @@ -4,4 +4,4 @@ MatchBus=usb MatchVendor=0x047D MatchProduct=0x2048 ModelTrackball=1 -AttrEventCodeDisable=BTN_MIDDLE +AttrEventCode=-BTN_MIDDLE diff --git a/quirks/30-vendor-logitech.quirks b/quirks/30-vendor-logitech.quirks index c2b327d4..4a4fe859 100644 --- a/quirks/30-vendor-logitech.quirks +++ b/quirks/30-vendor-logitech.quirks @@ -10,7 +10,7 @@ MatchUdevType=mouse MatchBus=usb MatchVendor=0x46D MatchProduct=0xC408 -AttrEventCodeDisable=BTN_MIDDLE +AttrEventCode=-BTN_MIDDLE [Logitech K400] MatchUdevType=mouse diff --git a/quirks/30-vendor-madcatz.quirks b/quirks/30-vendor-madcatz.quirks index 57934c03..3cfb27ce 100644 --- a/quirks/30-vendor-madcatz.quirks +++ b/quirks/30-vendor-madcatz.quirks @@ -21,7 +21,7 @@ MatchBus=usb MatchVendor=0x0738 MatchProduct=0x1703 # EV_KEY 0x115, 0x116, 0x117 -AttrEventCodeDisable=EV_KEY:0x115;EV_KEY:0x116;EV_KEY:0x117 +AttrEventCode=-EV_KEY:0x115;-EV_KEY:0x116;-EV_KEY:0x117 # Like the Madcatz RAT3, but with different codes: # event8 POINTER_BUTTON +0.488s ??? (280) pressed, seat count: 1 @@ -37,4 +37,4 @@ MatchBus=usb MatchVendor=0x0738 MatchProduct=0x1708 # EV_KEY 0x118, 0x119, 0x11A -AttrEventCodeDisable=EV_KEY:0x118;EV_KEY:0x119;EV_KEY:0x11A +AttrEventCode=-EV_KEY:0x118;-EV_KEY:0x119;-EV_KEY:0x11A diff --git a/quirks/30-vendor-synaptics.quirks b/quirks/30-vendor-synaptics.quirks index 26f4373a..315ab41e 100644 --- a/quirks/30-vendor-synaptics.quirks +++ b/quirks/30-vendor-synaptics.quirks @@ -16,4 +16,4 @@ ModelSynapticsSerialTouchpad=1 [Synaptics 0911:5288 Touchpad] MatchUdevType=touchpad MatchName=* 0911:5288 Touchpad -AttrEventCodeDisable=BTN_RIGHT +AttrEventCode=-BTN_RIGHT diff --git a/quirks/30-vendor-wacom.quirks b/quirks/30-vendor-wacom.quirks index 685c007d..d9733aea 100644 --- a/quirks/30-vendor-wacom.quirks +++ b/quirks/30-vendor-wacom.quirks @@ -18,11 +18,11 @@ MatchUdevType=tablet MatchBus=usb MatchVendor=0x56A MatchProduct=0x4200 -AttrEventCodeDisable=ABS_TILT_X;ABS_TILT_Y; +AttrEventCode=-ABS_TILT_X;-ABS_TILT_Y; [Wacom ISDV4 524c Pen] MatchUdevType=tablet MatchBus=usb MatchVendor=0x2D1F MatchProduct=0x524C -AttrEventCodeDisable=ABS_TILT_X;ABS_TILT_Y; +AttrEventCode=-ABS_TILT_X;-ABS_TILT_Y; diff --git a/quirks/50-framework.quirks b/quirks/50-framework.quirks index aa9523f8..d42fe370 100644 --- a/quirks/50-framework.quirks +++ b/quirks/50-framework.quirks @@ -2,4 +2,4 @@ MatchName=PIXA3854:00 093A:0274 Touchpad MatchUdevType=touchpad MatchDMIModalias=dmi:*svnFramework:pnLaptop* -AttrEventCodeDisable=BTN_RIGHT +AttrEventCode=-BTN_RIGHT diff --git a/quirks/50-system-apple.quirks b/quirks/50-system-apple.quirks index a6d6eea9..a9a09423 100644 --- a/quirks/50-system-apple.quirks +++ b/quirks/50-system-apple.quirks @@ -41,7 +41,7 @@ MatchUdevType=mouse MatchBus=bluetooth MatchVendor=0x05AC MatchProduct=0x030D -AttrEventCodeDisable=EV_ABS +AttrEventCode=-EV_ABS # The External Apple "Magic" trackpads, both the 1st and 2nd generations, have # pretty good built-in spurious touch filtering in the device firmware. Using diff --git a/quirks/50-system-asus.quirks b/quirks/50-system-asus.quirks index 623fc724..d5b79754 100644 --- a/quirks/50-system-asus.quirks +++ b/quirks/50-system-asus.quirks @@ -16,7 +16,7 @@ AttrPressureRange=24:10 [Asus UX302LA] MatchName=*ETPS/2 Elantech Touchpad* MatchDMIModalias=dmi:*svnASUSTeKCOMPUTERINC.:pnUX302LA:* -AttrEventCodeDisable=ABS_MT_PRESSURE;ABS_PRESSURE; +AttrEventCode=-ABS_MT_PRESSURE;-ABS_PRESSURE; # Asus VivoBook Flip 14 TP412UA tablet switch seems misbehaving, always # indicating tablet position diff --git a/quirks/50-system-chuwi.quirks b/quirks/50-system-chuwi.quirks index f93a53d5..ac90037a 100644 --- a/quirks/50-system-chuwi.quirks +++ b/quirks/50-system-chuwi.quirks @@ -1,9 +1,9 @@ [Chuwi Gemibook] MatchName=HTIX5288:00 093A:1336 Touchpad MatchUdevType=touchpad -AttrEventCodeDisable=BTN_RIGHT +AttrEventCode=-BTN_RIGHT [Chuwi AeroBook Plus] MatchName=SYNA3602:01 093A:1336 Touchpad MatchUdevType=touchpad -AttrEventCodeDisable=BTN_RIGHT +AttrEventCode=-BTN_RIGHT diff --git a/quirks/50-system-cyborg.quirks b/quirks/50-system-cyborg.quirks index 6a21f646..7dec2352 100644 --- a/quirks/50-system-cyborg.quirks +++ b/quirks/50-system-cyborg.quirks @@ -28,4 +28,4 @@ MatchBus=usb MatchVendor=0x06A3 MatchProduct=0x0CD5 # EV_KEY 0x118, 0x119, 0x11a -AttrEventCodeDisable=EV_KEY:0x118;EV_KEY:0x119;EV_KEY:0x11a +AttrEventCode=-EV_KEY:0x118;-EV_KEY:0x119;-EV_KEY:0x11a diff --git a/quirks/50-system-dell.quirks b/quirks/50-system-dell.quirks index 9bc3e357..7abb6ce9 100644 --- a/quirks/50-system-dell.quirks +++ b/quirks/50-system-dell.quirks @@ -98,7 +98,7 @@ AttrTrackpointMultiplier=0.3 MatchBus=i2c MatchUdevType=touchpad MatchDMIModalias=dmi:*svnDellInc.:pnPrecision7?50* -AttrInputPropDisable=INPUT_PROP_BUTTONPAD +AttrInputProp=-INPUT_PROP_BUTTONPAD # The touch device has the same vid/pid as the totem, the MatchName # directive is required here diff --git a/quirks/50-system-gpd.quirks b/quirks/50-system-gpd.quirks index 6f8b2c76..bdfeae95 100644 --- a/quirks/50-system-gpd.quirks +++ b/quirks/50-system-gpd.quirks @@ -2,4 +2,4 @@ MatchName=HTIX5288:00 093A:0255 Touchpad MatchUdevType=touchpad MatchDMIModalias=dmi:*svnGPD:*pnG1619-* -AttrEventCodeDisable=BTN_RIGHT +AttrEventCode=-BTN_RIGHT diff --git a/quirks/50-system-hp.quirks b/quirks/50-system-hp.quirks index 9ab0a22f..03901d85 100644 --- a/quirks/50-system-hp.quirks +++ b/quirks/50-system-hp.quirks @@ -5,14 +5,14 @@ [HP Compaq 6910p] MatchName=*SynPS/2 Synaptics TouchPad MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPCompaq6910p* -AttrEventCodeDisable=BTN_TOOL_DOUBLETAP;BTN_TOOL_TRIPLETAP; +AttrEventCode=-BTN_TOOL_DOUBLETAP;-BTN_TOOL_TRIPLETAP; # Claims to have double/tripletap but doesn't actually send it # https://bugzilla.redhat.com/show_bug.cgi?id=1351285 and [HP Compaq 8510w] MatchName=*SynPS/2 Synaptics TouchPad MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPCompaq8510w* -AttrEventCodeDisable=BTN_TOOL_DOUBLETAP;BTN_TOOL_TRIPLETAP; +AttrEventCode=-BTN_TOOL_DOUBLETAP;-BTN_TOOL_TRIPLETAP; [HP Pavilion dmi4] MatchName=*SynPS/2 Synaptics TouchPad @@ -24,7 +24,7 @@ ModelHPPavilionDM4Touchpad=1 [HP Stream 11] MatchName=SYN1EDE:00 06CB:7442* MatchDMIModalias=dmi:*svnHewlett-Packard:pnHPStreamNotebookPC11* -AttrInputPropEnable=INPUT_PROP_BUTTONPAD +AttrInputProp=+INPUT_PROP_BUTTONPAD # The HP stream x360's embedded-controller filters out events form its builtin # keyboard when in tablet-mode itself; and it has a capacitive home-button diff --git a/quirks/50-system-huawei.quirks b/quirks/50-system-huawei.quirks index 43ccb075..c25379a6 100644 --- a/quirks/50-system-huawei.quirks +++ b/quirks/50-system-huawei.quirks @@ -4,4 +4,4 @@ MatchName=ELAN2604:00 04F3:3114 Touchpad MatchUdevType=touchpad MatchDMIModalias=dmi:*svnHUAWEI:*pvrM1010* -AttrEventCodeDisable=BTN_RIGHT +AttrEventCode=-BTN_RIGHT diff --git a/quirks/50-system-lenovo.quirks b/quirks/50-system-lenovo.quirks index 3526e6c4..ade45883 100644 --- a/quirks/50-system-lenovo.quirks +++ b/quirks/50-system-lenovo.quirks @@ -41,14 +41,14 @@ AttrTrackpointMultiplier=0.4 [Lenovo T480s Touchpad] MatchName=Elan Touchpad MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT480s* -AttrInputPropEnable=INPUT_PROP_BUTTONPAD +AttrInputProp=+INPUT_PROP_BUTTONPAD # Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see # https://gitlab.freedesktop.org/libinput/libinput/issues/177 [Lenovo T490s Touchpad] MatchName=Elan Touchpad MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT490s* -AttrInputPropEnable=INPUT_PROP_BUTTONPAD +AttrInputProp=+INPUT_PROP_BUTTONPAD [Lenovo T490s Trackpoint] MatchName=*TPPS/2 IBM TrackPoint @@ -60,7 +60,7 @@ AttrTrackpointMultiplier=0.4 [Lenovo L380 Touchpad] MatchName=Elan Touchpad MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadL380* -AttrInputPropEnable=INPUT_PROP_BUTTONPAD +AttrInputProp=+INPUT_PROP_BUTTONPAD [Lenovo X200 Trackpoint] MatchName=*TPPS/2 IBM TrackPoint @@ -147,7 +147,7 @@ AttrTrackpointMultiplier=1.25 MatchBus=i2c MatchVendor=0x06CB MatchProduct=0xCE37 -AttrEventCodeDisable=ABS_MT_PRESSURE;ABS_PRESSURE; +AttrEventCode=-ABS_MT_PRESSURE;-ABS_PRESSURE; [Lenovo Yoga C930 Tablet] MatchBus=i2c @@ -160,7 +160,7 @@ AttrTabletSmoothing=1 [Lenovo Carbon X1 6th gen] MatchName=Synaptics TM3288-011 MatchDMIModalias=dmi:*svnLENOVO:*pvrThinkPadX1Carbon6th:* -AttrEventCodeDisable=ABS_MT_TOOL_TYPE +AttrEventCode=-ABS_MT_TOOL_TYPE ModelLenovoX1Gen6Touchpad=1 [Lenovo X41 Tablet] @@ -272,7 +272,7 @@ AttrKeyboardIntegration=internal MatchBus=i2c MatchVendor=0x27C6 MatchProduct=0x01E8 -AttrEventCodeDisable=ABS_MT_PRESSURE;ABS_PRESSURE; +AttrEventCode=-ABS_MT_PRESSURE;-ABS_PRESSURE; # Duet 7i tablet switch activated by folding keyboard cover, or removing it. # We must not disable volume rocker 'keyboard'. diff --git a/quirks/50-system-starlabs.quirks b/quirks/50-system-starlabs.quirks index 9864d85b..794f4173 100644 --- a/quirks/50-system-starlabs.quirks +++ b/quirks/50-system-starlabs.quirks @@ -2,5 +2,5 @@ MatchName=*Touchpad MatchUdevType=touchpad MatchDMIModalias=dmi:*svnStarLabs:* -AttrEventCodeDisable=BTN_RIGHT -AttrInputPropEnable=INPUT_PROP_BUTTONPAD +AttrEventCode=-BTN_RIGHT +AttrInputProp=+INPUT_PROP_BUTTONPAD diff --git a/src/evdev.c b/src/evdev.c index 2c4d4726..c20d2749 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2231,8 +2231,6 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) struct quirks_context *quirks; struct quirks *q; const struct quirk_tuples *t; - const uint32_t *props = NULL; - size_t nprops = 0; char *prop; /* Touchpad claims to have 4 slots but only ever sends 2 @@ -2251,7 +2249,7 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) libevdev_disable_event_code(device->evdev, EV_MSC, MSC_TIMESTAMP); } - if (quirks_get_tuples(q, QUIRK_ATTR_EVENT_CODE_ENABLE, &t)) { + if (quirks_get_tuples(q, QUIRK_ATTR_EVENT_CODE, &t)) { for (size_t i = 0; i < t->ntuples; i++) { const struct input_absinfo absinfo = { .minimum = 0, @@ -2260,16 +2258,27 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) int type = t->tuples[i].first; int code = t->tuples[i].second; + bool enable = t->tuples[i].third; - if (code == EVENT_CODE_UNDEFINED) - libevdev_enable_event_type(device->evdev, type); - else - libevdev_enable_event_code(device->evdev, - type, - code, - type == EV_ABS ? &absinfo : NULL); + if (code == EVENT_CODE_UNDEFINED) { + if (enable) + libevdev_enable_event_type(device->evdev, type); + else + libevdev_disable_event_type(device->evdev, type); + } else { + if (enable) + libevdev_enable_event_code(device->evdev, + type, + code, + type == EV_ABS ? &absinfo : NULL); + else + libevdev_disable_event_code(device->evdev, + type, + code); + } evdev_log_debug(device, - "quirks: enabling %s %s (%#x %#x)\n", + "quirks: %s %s %s (%#x %#x)\n", + enable ? "enabling" : "disabling", libevdev_event_type_get_name(type), libevdev_event_code_get_name(type, code), type, @@ -2277,58 +2286,28 @@ evdev_pre_configure_model_quirks(struct evdev_device *device) } } - if (quirks_get_tuples(q, QUIRK_ATTR_EVENT_CODE_DISABLE, &t)) { - for (size_t i = 0; i < t->ntuples; i++) { - int type = t->tuples[i].first; - int code = t->tuples[i].second; + if (quirks_get_tuples(q, QUIRK_ATTR_INPUT_PROP, &t)) { + for (size_t idx = 0; idx < t->ntuples; idx++) { + unsigned int p = t->tuples[idx].first; + bool enable = t->tuples[idx].second; - if (code == EVENT_CODE_UNDEFINED) - libevdev_disable_event_type(device->evdev, - type); - else - libevdev_disable_event_code(device->evdev, - type, - code); - evdev_log_debug(device, - "quirks: disabling %s %s (%#x %#x)\n", - libevdev_event_type_get_name(type), - libevdev_event_code_get_name(type, code), - type, - code); - } - } - - if (quirks_get_uint32_array(q, - QUIRK_ATTR_INPUT_PROP_ENABLE, - &props, - &nprops)) { - for (size_t idx = 0; idx < nprops; idx++) { - unsigned int p = props[idx]; - libevdev_enable_property(device->evdev, p); - evdev_log_debug(device, - "quirks: enabling %s (%#x)\n", - libevdev_property_get_name(p), - p); - } - } - - if (quirks_get_uint32_array(q, - QUIRK_ATTR_INPUT_PROP_DISABLE, - &props, - &nprops)) { + if (enable) { + libevdev_enable_property(device->evdev, p); + } + else { #if HAVE_LIBEVDEV_DISABLE_PROPERTY - for (size_t idx = 0; idx < nprops; idx++) { - unsigned int p = props[idx]; - libevdev_disable_property(device->evdev, p); + libevdev_disable_property(device->evdev, p); +#else + evdev_log_error(device, + "quirks: a quirk for this device requires newer libevdev than installed\n"); +#endif + } evdev_log_debug(device, - "quirks: disabling %s (%#x)\n", + "quirks: %s %s (%#x)\n", + enable ? "enabling" : "disabling", libevdev_property_get_name(p), p); } -#else - evdev_log_error(device, - "quirks: a quirk for this device requires newer libevdev than installed\n"); -#endif } quirks_unref(q); diff --git a/src/quirks.c b/src/quirks.c index 932706f3..0e3006b5 100644 --- a/src/quirks.c +++ b/src/quirks.c @@ -175,6 +175,10 @@ struct quirks { /* These are not ref'd, just a collection of pointers */ struct property **properties; size_t nproperties; + + /* Special properties for AttrEventCode and AttrInputCode, these are + * owned by us, not the section */ + struct list floating_properties; }; /** @@ -282,10 +286,8 @@ quirk_get_name(enum quirk q) case QUIRK_ATTR_TABLET_SMOOTHING: return "AttrTabletSmoothing"; case QUIRK_ATTR_THUMB_SIZE_THRESHOLD: return "AttrThumbSizeThreshold"; case QUIRK_ATTR_MSC_TIMESTAMP: return "AttrMscTimestamp"; - case QUIRK_ATTR_EVENT_CODE_DISABLE: return "AttrEventCodeDisable"; - case QUIRK_ATTR_EVENT_CODE_ENABLE: return "AttrEventCodeEnable"; - case QUIRK_ATTR_INPUT_PROP_DISABLE: return "AttrInputPropDisable"; - case QUIRK_ATTR_INPUT_PROP_ENABLE: return "AttrInputPropEnable"; + case QUIRK_ATTR_EVENT_CODE: return "AttrEventCode"; + case QUIRK_ATTR_INPUT_PROP: return "AttrInputProp"; default: abort(); } @@ -817,14 +819,11 @@ parse_attr(struct quirks_context *ctx, p->type = PT_STRING; p->value.s = safe_strdup(value); rc = true; - } else if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_DISABLE)) || - streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_ENABLE))) { + } else if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE))) { struct input_event events[32]; size_t nevents = ARRAY_LENGTH(events); - if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_DISABLE))) - p->id = QUIRK_ATTR_EVENT_CODE_DISABLE; - else - p->id = QUIRK_ATTR_EVENT_CODE_ENABLE; + + p->id = QUIRK_ATTR_EVENT_CODE; if (!parse_evcode_property(value, events, &nevents) || nevents == 0) @@ -833,27 +832,29 @@ parse_attr(struct quirks_context *ctx, for (size_t i = 0; i < nevents; i++) { p->value.tuples.tuples[i].first = events[i].type; p->value.tuples.tuples[i].second = events[i].code; + p->value.tuples.tuples[i].third = events[i].value; } p->value.tuples.ntuples = nevents; p->type = PT_TUPLES; rc = true; - } else if (streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP_DISABLE)) || - streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP_ENABLE))) { - unsigned int props[INPUT_PROP_CNT]; + } else if (streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP))) { + struct input_prop props[INPUT_PROP_CNT]; size_t nprops = ARRAY_LENGTH(props); - if (streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP_DISABLE))) - p->id = QUIRK_ATTR_INPUT_PROP_DISABLE; - else - p->id = QUIRK_ATTR_INPUT_PROP_ENABLE; + + p->id = QUIRK_ATTR_INPUT_PROP; if (!parse_input_prop_property(value, props, &nprops) || nprops == 0) goto out; - memcpy(p->value.array.data.u, props, nprops * sizeof(unsigned int)); - p->value.array.nelements = nprops; - p->type = PT_UINT_ARRAY; + for (size_t i = 0; i < nprops; i++) { + p->value.tuples.tuples[i].first = props[i].prop; + p->value.tuples.tuples[i].second = props[i].enabled; + } + + p->value.tuples.ntuples = nprops; + p->type = PT_TUPLES; rc = true; } else { @@ -1201,6 +1202,7 @@ quirks_new(void) q->refcount = 1; q->nproperties = 0; list_init(&q->link); + list_init(&q->floating_properties); return q; } @@ -1219,6 +1221,13 @@ quirks_unref(struct quirks *q) property_unref(q->properties[i]); } + /* Floating properties are owned by our quirks context, need to be + * cleaned up here */ + struct property *p; + list_for_each_safe(p, &q->floating_properties, link) { + property_cleanup(p); + } + list_remove(&q->link); free(q->properties); free(q); @@ -1378,6 +1387,41 @@ match_free(struct match *m) free(m); } +static void +quirk_merge_event_codes(struct quirks_context *ctx, + struct quirks *q, + const struct property *property) +{ + for (size_t i = 0; i < q->nproperties; i++) { + struct property *p = q->properties[i]; + + if (p->id != property->id) + continue; + + /* We have a duplicated property, merge in with ours */ + size_t offset = p->value.tuples.ntuples; + size_t max = ARRAY_LENGTH(p->value.tuples.tuples); + for (size_t j = 0; j < property->value.tuples.ntuples; j++) { + if (offset + j >= max) + break; + p->value.tuples.tuples[offset + j] = property->value.tuples.tuples[j]; + p->value.tuples.ntuples++; + } + return; + } + + /* First time we add AttrEventCode: create a new property. + * Unlike the other properties, this one isn't part of a section, it belongs + * to the quirks */ + struct property *newprop = property_new(); + newprop->id = property->id; + newprop->type = property->type; + newprop->value.tuples = property->value.tuples; + /* Caller responsible for pre-allocating space */ + q->properties[q->nproperties++] = property_ref(newprop); + list_append(&q->floating_properties, &newprop->link); +} + static void quirk_apply_section(struct quirks_context *ctx, struct quirks *q, @@ -1401,7 +1445,26 @@ quirk_apply_section(struct quirks_context *ctx, qlog_debug(ctx, "property added: %s from %s\n", quirk_get_name(p->id), s->name); - q->properties[q->nproperties++] = property_ref(p); + /* All quirks but AttrEventCode and AttrInputProp + * simply overwrite each other, so we can just append the + * matching property and, later when checking the quirk, pick + * the last one in the array. + * + * The event codes/input props are special because they're lists + * that may *partially* override each other, e.g. a section may + * enable BTN_LEFT and BTN_RIGHT but a later section may disable + * only BTN_RIGHT. This should result in BTN_LEFT force-enabled + * and BTN_RIGHT force-disabled. + * + * To hack around this, those are the only ones where only ever + * have one struct property in the list (not owned by a section) + * and we simply merge any extra sections onto that. + */ + if (p->id == QUIRK_ATTR_EVENT_CODE || + p->id == QUIRK_ATTR_INPUT_PROP) + quirk_merge_event_codes(ctx, q, p); + else + q->properties[q->nproperties++] = property_ref(p); } } diff --git a/src/quirks.h b/src/quirks.h index 8f1aae91..bd96c3af 100644 --- a/src/quirks.h +++ b/src/quirks.h @@ -54,6 +54,7 @@ struct quirk_tuples { struct { int first; int second; + int third; } tuples[32]; size_t ntuples; }; @@ -104,10 +105,8 @@ enum quirk { QUIRK_ATTR_TABLET_SMOOTHING, QUIRK_ATTR_THUMB_SIZE_THRESHOLD, QUIRK_ATTR_MSC_TIMESTAMP, - QUIRK_ATTR_EVENT_CODE_DISABLE, - QUIRK_ATTR_EVENT_CODE_ENABLE, - QUIRK_ATTR_INPUT_PROP_DISABLE, - QUIRK_ATTR_INPUT_PROP_ENABLE, + QUIRK_ATTR_EVENT_CODE, + QUIRK_ATTR_INPUT_PROP, _QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */ }; diff --git a/src/util-prop-parsers.c b/src/util-prop-parsers.c index a03fbdd5..47ba3b51 100644 --- a/src/util-prop-parsers.c +++ b/src/util-prop-parsers.c @@ -347,10 +347,10 @@ parse_evcode_string(const char *s, int *type_out, int *code_out) } /** - * Parses a string of the format "EV_ABS;KEY_A;BTN_TOOL_DOUBLETAP;ABS_X;" - * where each element must be a named event type OR a named event code OR a - * tuple in the form of EV_KEY:0x123, i.e. a named event type followed by a - * hex event code. + * Parses a string of the format "+EV_ABS;+KEY_A;-BTN_TOOL_DOUBLETAP;-ABS_X;" + * where each element must be + or - (enable/disable) followed by a named event + * type OR a named event code OR a tuple in the form of EV_KEY:0x123, i.e. a + * named event type followed by a hex event code. * * events must point to an existing array of size nevents. * nevents specifies the size of the array in events and returns the number @@ -361,7 +361,8 @@ parse_evcode_string(const char *s, int *type_out, int *code_out) * other fields undefined. Where only the event type is specified, the code * is set to EVENT_CODE_UNDEFINED. * - * On success, events contains nevents events. + * On success, events contains nevents events with each event's value set to 1 + * or 0 depending on the + or - prefix. */ bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents) @@ -380,6 +381,16 @@ parse_evcode_property(const char *prop, struct input_event *events, size_t *neve ncodes = min(*nevents, ncodes); for (size_t idx = 0; strv[idx]; idx++) { char *s = strv[idx]; + bool enable; + + switch (*s) { + case '+': enable = true; break; + case '-': enable = false; break; + default: + goto out; + } + + s++; int type, code; @@ -399,6 +410,7 @@ parse_evcode_property(const char *prop, struct input_event *events, size_t *neve evs[idx].type = type; evs[idx].code = code; + evs[idx].value = enable; } memcpy(events, evs, ncodes * sizeof *events); @@ -411,9 +423,9 @@ out: } /** - * Parses a string of the format "INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER;0x123;" + * Parses a string of the format "+INPUT_PROP_BUTTONPAD;-INPUT_PROP_POINTER;+0x123;" * where each element must be a named input prop OR a hexcode in the form - * 0x1234 + * 0x1234. The prefix for each element must be either '+' (enable) or '-' (disable). * * props must point to an existing array of size nprops. * nprops specifies the size of the array in props and returns the number @@ -423,10 +435,10 @@ out: * On success, props contains nprops elements. */ bool -parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops) +parse_input_prop_property(const char *prop, struct input_prop *props_out, size_t *nprops) { bool rc = false; - unsigned int props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */ + struct input_prop props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */ size_t count; char **strv = strv_from_string(prop, ";", &count); @@ -437,6 +449,16 @@ parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *npr for (size_t idx = 0; strv[idx]; idx++) { char *s = strv[idx]; unsigned int prop; + bool enable; + + switch (*s) { + case '+': enable = true; break; + case '-': enable = false; break; + default: + goto out; + } + + s++; if (safe_atou_base(s, &prop, 16)) { if (prop > INPUT_PROP_MAX) @@ -447,7 +469,8 @@ parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *npr goto out; prop = (unsigned int)val; } - props[idx] = prop; + props[idx].prop = prop; + props[idx].enabled = enable; } memcpy(props_out, props, count * sizeof *props); diff --git a/src/util-prop-parsers.h b/src/util-prop-parsers.h index 71789141..81b20490 100644 --- a/src/util-prop-parsers.h +++ b/src/util-prop-parsers.h @@ -30,6 +30,11 @@ #include #include +struct input_prop { + unsigned int prop; + bool enabled; +}; + int parse_mouse_dpi_property(const char *prop); int parse_mouse_wheel_click_angle_property(const char *prop); int parse_mouse_wheel_click_count_property(const char *prop); @@ -39,7 +44,7 @@ bool parse_range_property(const char *prop, int *hi, int *lo); bool parse_boolean_property(const char *prop, bool *b); #define EVENT_CODE_UNDEFINED 0xffff bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents); -bool parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops); +bool parse_input_prop_property(const char *prop, struct input_prop *props_out, size_t *nprops); enum tpkbcombo_layout { TPKBCOMBO_LAYOUT_UNKNOWN, diff --git a/test/litest-device-keyboard-quirked.c b/test/litest-device-keyboard-quirked.c index 53161fa4..914238a9 100644 --- a/test/litest-device-keyboard-quirked.c +++ b/test/litest-device-keyboard-quirked.c @@ -199,22 +199,46 @@ static int events[] = { }; static const char quirk_file[] = -"[litest Quirked Keyboard enable rel]\n" +"[litest Quirked Keyboard enable buttons]\n" "MatchName=litest Quirked Keyboard\n" -"AttrEventCodeEnable=BTN_RIGHT;EV_KEY:0x110\n" /* BTN_LEFT */ +"AttrEventCode=+BTN_RIGHT;+BTN_MIDDLE;+EV_KEY:0x110\n" /* BTN_LEFT */ +"\n" +"[litest Quirked Keyboard disable buttons]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrEventCode=-BTN_MIDDLE;-BTN_RIGHT\n" +"\n" +"[litest Quirked Keyboard re-enable buttons]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrEventCode=+BTN_RIGHT\n" "\n" "[litest Quirked keyboard disable F1-F3]\n" "MatchName=litest Quirked Keyboard\n" -"AttrEventCodeDisable=KEY_F1;EV_KEY:0x3c;KEY_F3\n" +"AttrEventCode=-KEY_F1;-EV_KEY:0x3c;-KEY_F3\n" #if HAVE_LIBEVDEV_DISABLE_PROPERTY "\n" "[litest Quirked keyboard enable buttonpad]\n" "MatchName=litest Quirked Keyboard\n" -"AttrInputPropEnable=INPUT_PROP_BUTTONPAD\n" +"AttrInputProp=+INPUT_PROP_BUTTONPAD\n" "\n" "[litest Quirked keyboard disable pointingstick]\n" "MatchName=litest Quirked Keyboard\n" -"AttrInputPropDisable=INPUT_PROP_POINTING_STICK\n" +"AttrInputProp=-INPUT_PROP_POINTING_STICK\n" +"\n" +"[litest Quirked keyboard enable direct]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrInputProp=+INPUT_PROP_DIRECT\n" +"\n" +"[litest Quirked keyboard disable direct]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrInputProp=-INPUT_PROP_DIRECT\n" +"\n" +"[litest Quirked keyboard disable semi-mt]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrInputProp=-INPUT_PROP_SEMI_MT\n" +"\n" +"[litest Quirked keyboard enable semi-mt]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrInputProp=+INPUT_PROP_SEMI_MT\n" #endif ; diff --git a/test/test-device.c b/test/test-device.c index 3b153436..f7895b28 100644 --- a/test/test-device.c +++ b/test/test-device.c @@ -1477,7 +1477,11 @@ START_TEST(device_quirks) enable_btn_left = false; #if HAVE_LIBEVDEV_DISABLE_PROPERTY bool disable_pointingstick = false, - enable_buttonpad = false; + enable_buttonpad = false, + enable_direct = false, + disable_direct = false, + enable_semi_mt = false, + disable_semi_mt = false; #endif li = litest_create_context(); @@ -1490,6 +1494,8 @@ START_TEST(device_quirks) BTN_LEFT)); ck_assert(libinput_device_pointer_has_button(dev->libinput_device, BTN_RIGHT)); + ck_assert(!libinput_device_pointer_has_button(device, + BTN_MIDDLE)); ck_assert(!libinput_device_keyboard_has_key(dev->libinput_device, KEY_F1)); ck_assert(!libinput_device_keyboard_has_key(dev->libinput_device, @@ -1510,6 +1516,22 @@ START_TEST(device_quirks) enable_buttonpad = true; if (strstr(*message, "disabling INPUT_PROP_POINTING_STICK")) disable_pointingstick = true; + if (strstr(*message, "enabling INPUT_PROP_DIRECT")) { + ck_assert(!disable_direct); + enable_direct = true; + } + if (strstr(*message, "disabling INPUT_PROP_DIRECT")) { + ck_assert(enable_direct); + disable_direct = true; + } + if (strstr(*message, "enabling INPUT_PROP_SEMI_MT")) { + ck_assert(disable_semi_mt); + enable_semi_mt = true; + } + if (strstr(*message, "disabling INPUT_PROP_SEMI_MT")) { + ck_assert(!enable_semi_mt); + disable_semi_mt = true; + } #endif free(*message); message++; @@ -1520,6 +1542,10 @@ START_TEST(device_quirks) #if HAVE_LIBEVDEV_DISABLE_PROPERTY ck_assert(enable_buttonpad); ck_assert(disable_pointingstick); + ck_assert(enable_direct); + ck_assert(disable_direct); + ck_assert(enable_semi_mt); + ck_assert(disable_semi_mt); #endif litest_disable_log_handler(li); diff --git a/test/test-utils.c b/test/test-utils.c index ab3158a9..a5248147 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -560,47 +560,50 @@ START_TEST(evcode_prop_parser) struct parser_test_tuple { const char *prop; bool success; - size_t ntuples; - int tuples[20]; + size_t nevents; + struct input_event events[20]; } tests[] = { - { "EV_KEY", true, 1, {EV_KEY, 0xffff} }, - { "EV_ABS;", true, 1, {EV_ABS, 0xffff} }, - { "ABS_X;", true, 1, {EV_ABS, ABS_X} }, - { "SW_TABLET_MODE;", true, 1, {EV_SW, SW_TABLET_MODE} }, - { "EV_SW", true, 1, {EV_SW, 0xffff} }, - { "ABS_Y", true, 1, {EV_ABS, ABS_Y} }, - { "EV_ABS:0x00", true, 1, {EV_ABS, ABS_X} }, - { "EV_ABS:01", true, 1, {EV_ABS, ABS_Y} }, - { "ABS_TILT_X;ABS_TILT_Y;", true, 2, - { EV_ABS, ABS_TILT_X, - EV_ABS, ABS_TILT_Y} }, - { "BTN_TOOL_DOUBLETAP;EV_KEY;KEY_A", true, 3, - { EV_KEY, BTN_TOOL_DOUBLETAP, - EV_KEY, 0xffff, - EV_KEY, KEY_A } }, - { "REL_Y;ABS_Z;BTN_STYLUS", true, 3, - { EV_REL, REL_Y, - EV_ABS, ABS_Z, - EV_KEY, BTN_STYLUS } }, - { "REL_Y;EV_KEY:0x123;BTN_STYLUS", true, 3, - { EV_REL, REL_Y, - EV_KEY, 0x123, - EV_KEY, BTN_STYLUS } }, + { "+EV_KEY", true, 1, {{ .type = EV_KEY, .code = 0xffff, .value = 1 }} }, + { "-EV_ABS;", true, 1, {{ .type = EV_ABS, .code = 0xffff, .value = 0 }} }, + { "+ABS_X;", true, 1, {{ .type = EV_ABS, .code = ABS_X, .value = 1 }} }, + { "-SW_TABLET_MODE;", true, 1, {{ .type = EV_SW, .code = SW_TABLET_MODE, .value = 0 }} }, + { "+EV_SW", true, 1, {{ .type = EV_SW, .code = 0xffff, .value = 1 }} }, + { "-ABS_Y", true, 1, {{ .type = EV_ABS, .code = ABS_Y, .value = 0 }} }, + { "+EV_ABS:0x00", true, 1, {{ .type = EV_ABS, .code = ABS_X, .value = 1 }} }, + { "-EV_ABS:01", true, 1, {{ .type = EV_ABS, .code = ABS_Y, .value = 0 }} }, + { "+ABS_TILT_X;-ABS_TILT_Y;", true, 2, + {{ .type = EV_ABS, .code = ABS_TILT_X, .value = 1 }, + { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0}} }, + { "+BTN_TOOL_DOUBLETAP;+EV_KEY;-KEY_A", true, 3, + {{ .type = EV_KEY, .code = BTN_TOOL_DOUBLETAP, .value = 1 } , + { .type = EV_KEY, .code = 0xffff, .value = 1 }, + { .type = EV_KEY, .code = KEY_A, .value = 0 }} }, + { "+REL_Y;-ABS_Z;+BTN_STYLUS", true, 3, + {{ .type = EV_REL, .code = REL_Y, .value = 1}, + { .type = EV_ABS, .code = ABS_Z, .value = 0}, + { .type = EV_KEY, .code = BTN_STYLUS, .value = 1 }} }, + { "-REL_Y;+EV_KEY:0x123;-BTN_STYLUS", true, 3, + {{ .type = EV_REL, .code = REL_Y, .value = 0 }, + { .type = EV_KEY, .code = 0x123, .value = 1 }, + { .type = EV_KEY, .code = BTN_STYLUS, .value = 0 }} }, { .prop = "", .success = false }, - { .prop = "EV_FOO", .success = false }, - { .prop = "EV_KEY;EV_FOO", .success = false }, - { .prop = "BTN_STYLUS;EV_FOO", .success = false }, - { .prop = "BTN_UNKNOWN", .success = false }, - { .prop = "BTN_UNKNOWN;EV_KEY", .success = false }, - { .prop = "PR_UNKNOWN", .success = false }, - { .prop = "BTN_STYLUS;PR_UNKNOWN;ABS_X", .success = false }, - { .prop = "EV_REL:0xffff", .success = false }, - { .prop = "EV_REL:0x123.", .success = false }, - { .prop = "EV_REL:ffff", .success = false }, - { .prop = "EV_REL:blah", .success = false }, - { .prop = "KEY_A:0x11", .success = false }, - { .prop = "EV_KEY:0x11 ", .success = false }, - { .prop = "EV_KEY:0x11not", .success = false }, + { .prop = "+", .success = false }, + { .prop = "-", .success = false }, + { .prop = "!", .success = false }, + { .prop = "+EV_FOO", .success = false }, + { .prop = "+EV_KEY;-EV_FOO", .success = false }, + { .prop = "+BTN_STYLUS;-EV_FOO", .success = false }, + { .prop = "-BTN_UNKNOWN", .success = false }, + { .prop = "+BTN_UNKNOWN;+EV_KEY", .success = false }, + { .prop = "-PR_UNKNOWN", .success = false }, + { .prop = "-BTN_STYLUS;+PR_UNKNOWN;-ABS_X", .success = false }, + { .prop = "-EV_REL:0xffff", .success = false }, + { .prop = "-EV_REL:0x123.", .success = false }, + { .prop = "-EV_REL:ffff", .success = false }, + { .prop = "-EV_REL:blah", .success = false }, + { .prop = "+KEY_A:0x11", .success = false }, + { .prop = "+EV_KEY:0x11 ", .success = false }, + { .prop = "+EV_KEY:0x11not", .success = false }, { .prop = "none", .success = false }, { .prop = NULL }, }; @@ -617,14 +620,14 @@ START_TEST(evcode_prop_parser) if (!success) continue; - ck_assert_int_eq(nevents, t->ntuples); + ck_assert_int_eq(nevents, t->nevents); for (size_t j = 0; j < nevents; j++) { - int type, code; - - type = events[j].type; - code = events[j].code; - ck_assert_int_eq(t->tuples[j * 2], type); - ck_assert_int_eq(t->tuples[j * 2 + 1], code); + unsigned int type = events[j].type; + unsigned int code = events[j].code; + int value = events[j].value; + ck_assert_int_eq(t->events[j].type, type); + ck_assert_int_eq(t->events[j].code, code); + ck_assert_int_eq(t->events[j].value, value); } } } @@ -636,16 +639,16 @@ START_TEST(input_prop_parser) const char *prop; bool success; size_t nvals; - uint32_t values[20]; + struct input_prop values[20]; } tests[] = { - { "INPUT_PROP_BUTTONPAD", true, 1, {INPUT_PROP_BUTTONPAD}}, - { "INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER", true, 2, - { INPUT_PROP_BUTTONPAD, - INPUT_PROP_POINTER }}, - { "INPUT_PROP_BUTTONPAD;0x00;0x03", true, 3, - { INPUT_PROP_BUTTONPAD, - INPUT_PROP_POINTER, - INPUT_PROP_SEMI_MT }}, + { "+INPUT_PROP_BUTTONPAD", true, 1, {{ INPUT_PROP_BUTTONPAD, true }}}, + { "+INPUT_PROP_BUTTONPAD;-INPUT_PROP_POINTER", true, 2, + { { INPUT_PROP_BUTTONPAD, true }, + { INPUT_PROP_POINTER, false }}}, + { "+INPUT_PROP_BUTTONPAD;-0x00;+0x03", true, 3, + { { INPUT_PROP_BUTTONPAD, true }, + { INPUT_PROP_POINTER, false }, + { INPUT_PROP_SEMI_MT, true }}}, { .prop = "", .success = false }, { .prop = "0xff", .success = false }, { .prop = "INPUT_PROP", .success = false }, @@ -659,7 +662,7 @@ START_TEST(input_prop_parser) for (int i = 0; tests[i].prop; i++) { bool success; - uint32_t props[32]; + struct input_prop props[32]; size_t nprops = ARRAY_LENGTH(props); t = &tests[i]; @@ -670,7 +673,8 @@ START_TEST(input_prop_parser) ck_assert_int_eq(nprops, t->nvals); for (size_t j = 0; j < t->nvals; j++) { - ck_assert_int_eq(t->values[j], props[j]); + ck_assert_int_eq(t->values[j].prop, props[j].prop); + ck_assert_int_eq(t->values[j].enabled, props[j].enabled); } } } diff --git a/tools/shared.c b/tools/shared.c index 8dc3b607..d7791838 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -632,11 +632,13 @@ sprintf_event_codes(char *buf, size_t sz, struct quirks *quirks, enum quirk q) off += printed; for (size_t i = 0; off < sz && i < t->ntuples; i++) { - const char *name = libevdev_event_code_get_name( - t->tuples[i].first, - t->tuples[i].second); + unsigned int type = t->tuples[i].first; + unsigned int code = t->tuples[i].second; + bool enable = t->tuples[i].third; - printed = snprintf(buf + off, sz - off, "%s;", name); + const char *name = libevdev_event_code_get_name(type, code); + + printed = snprintf(buf + off, sz - off, "%c%s;", enable ? '+' : '-', name); assert(printed != -1); off += printed; } @@ -645,21 +647,24 @@ sprintf_event_codes(char *buf, size_t sz, struct quirks *quirks, enum quirk q) static void sprintf_input_props(char *buf, size_t sz, struct quirks *quirks, enum quirk q) { - const uint32_t *properties; - size_t nprops = 0; + const struct quirk_tuples *t; size_t off = 0; int printed; const char *name; - quirks_get_uint32_array(quirks, q, &properties, &nprops); + quirks_get_tuples(quirks, q, &t); name = quirk_get_name(q); printed = snprintf(buf, sz, "%s=", name); assert(printed != -1); off += printed; - for (size_t i = 0; off < sz && i < nprops; i++) { - const char *name = libevdev_property_get_name(properties[i]); - printed = snprintf(buf + off, sz - off, "%s;", name); + for (size_t i = 0; off < sz && i < t->ntuples; i++) { + unsigned int prop = t->tuples[i].first; + bool enable = t->tuples[i].second; + + const char *name = libevdev_property_get_name(prop); + + printed = snprintf(buf + off, sz - off, "%c%s;", enable ? '+' : '-', name); assert(printed != -1); off += printed; } @@ -747,13 +752,11 @@ tools_list_device_quirks(struct quirks_context *ctx, snprintf(buf, sizeof(buf), "%s=%d", name, b); callback(userdata, buf); break; - case QUIRK_ATTR_EVENT_CODE_DISABLE: - case QUIRK_ATTR_EVENT_CODE_ENABLE: + case QUIRK_ATTR_EVENT_CODE: sprintf_event_codes(buf, sizeof(buf), quirks, q); callback(userdata, buf); break; - case QUIRK_ATTR_INPUT_PROP_DISABLE: - case QUIRK_ATTR_INPUT_PROP_ENABLE: + case QUIRK_ATTR_INPUT_PROP: sprintf_input_props(buf, sizeof(buf), quirks, q); callback(userdata, buf); break;