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;