touchpad: move the pressure range to a hwdb entry
authorPeter Hutterer <peter.hutterer@who-t.net>
Wed, 19 Apr 2017 03:45:34 +0000 (13:45 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Wed, 26 Apr 2017 02:38:15 +0000 (12:38 +1000)
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev-mt-touchpad.c
src/libinput-util.c
src/libinput-util.h
test/test-misc.c
udev/90-libinput-model-quirks.hwdb
udev/parse_hwdb.py

index eb950a2c06bcade4c18954a85761540de41dbfc4..99963e6038529c86a3dc74a60d60e0878d2b559d 100644 (file)
@@ -2372,8 +2372,9 @@ tp_init_pressure(struct tp_dispatch *tp,
                 struct evdev_device *device)
 {
        const struct input_absinfo *abs;
-       unsigned int range;
        unsigned int code = ABS_PRESSURE;
+       const char *prop;
+       int hi, lo;
 
        if (tp->has_mt)
                code = ABS_MT_PRESSURE;
@@ -2383,25 +2384,44 @@ tp_init_pressure(struct tp_dispatch *tp,
                return;
        }
 
-       tp->pressure.use_pressure = true;
-
        abs = libevdev_get_abs_info(device->evdev, code);
        assert(abs);
 
-       range = abs->maximum - abs->minimum;
+       prop = udev_device_get_property_value(device->udev_device,
+                                             "LIBINPUT_ATTR_PRESSURE_RANGE");
+       if (prop) {
+               if (!parse_pressure_range_property(prop, &hi, &lo)) {
+                       evdev_log_bug_client(device,
+                                    "discarding invalid pressure range '%s'\n",
+                                    prop);
+                       return;
+               }
 
-       if (device->model_flags & EVDEV_MODEL_ELANTECH_TOUCHPAD) {
-               tp->pressure.high = 24;
-               tp->pressure.low = 10;
-       } else if (device->model_flags & EVDEV_MODEL_CYAPA) {
-               tp->pressure.high = 10;
-               tp->pressure.low = 8;
+               if (hi == 0 && lo == 0) {
+                       evdev_log_info(device,
+                              "pressure-based touch detection disabled\n");
+                       return;
+               }
        } else {
+               unsigned int range = abs->maximum - abs->minimum;
+
                /* Approximately the synaptics defaults */
-               tp->pressure.high = abs->minimum + 0.12 * range;
-               tp->pressure.low = abs->minimum + 0.10 * range;
+               hi = abs->minimum + 0.12 * range;
+               lo = abs->minimum + 0.10 * range;
+       }
+
+       if (hi > abs->maximum || hi < abs->minimum ||
+           lo > abs->maximum || lo < abs->minimum) {
+               evdev_log_bug_libinput(device,
+                              "discarding out-of-bounds pressure range %d:%d\n",
+                              hi, lo);
+               return;
        }
 
+       tp->pressure.use_pressure = true;
+       tp->pressure.high = hi;
+       tp->pressure.low = lo;
+
        evdev_log_debug(device,
                        "using pressure-based touch detection\n");
 }
index 351bbe4abb8093d388e3de48e74eb6aafd0be096..38594fa4fab25795a890d2ca184e5818c77fd95c 100644 (file)
@@ -359,6 +359,42 @@ parse_tpkbcombo_layout_poperty(const char *prop,
        return false;
 }
 
+/**
+ * Parses a string of the format "a:b" where both a and b must be integer
+ * numbers and a > b. Also allowed is the special string vaule "none" which
+ * amounts to unsetting the property.
+ *
+ * @param prop The value of the property
+ * @param hi Set to the first digit or 0 in case of 'none'
+ * @param lo Set to the second digit or 0 in case of 'none'
+ * @return true on success, false otherwise
+ */
+bool
+parse_pressure_range_property(const char *prop, int *hi, int *lo)
+{
+       int first, second;
+
+       if (!prop)
+               return false;
+
+       if (streq(prop, "none")) {
+               *hi = 0;
+               *lo = 0;
+               return true;
+       }
+
+       if (sscanf(prop, "%d:%d", &first, &second) != 2)
+               return false;
+
+       if (second >= first)
+               return false;
+
+       *hi = first;
+       *lo = second;
+
+       return true;
+}
+
 /**
  * Return the next word in a string pointed to by state before the first
  * separator character. Call repeatedly to tokenize a whole string.
index 3fe0a029b6825ceafa9b107ae7648d94b9c3ea08..4e97e0114bbb6e390c70419c81d7359bd48da64a 100644 (file)
@@ -393,6 +393,7 @@ int parse_mouse_wheel_click_count_property(const char *prop);
 double parse_trackpoint_accel_property(const char *prop);
 bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
 bool parse_calibration_property(const char *prop, float calibration[6]);
+bool parse_pressure_range_property(const char *prop, int *hi, int *lo);
 
 enum tpkbcombo_layout {
        TPKBCOMBO_LAYOUT_UNKNOWN,
index 3f4b2290e9339ceef5321f56b82f4d484ffdaca3..5101dcffa5ee45ce32383d1296c40b247a25b430 100644 (file)
@@ -1001,6 +1001,48 @@ START_TEST(calibration_prop_parser)
 }
 END_TEST
 
+struct parser_test_pressure_range {
+       char *tag;
+       bool success;
+       int hi, lo;
+};
+
+START_TEST(pressure_range_prop_parser)
+{
+       struct parser_test_pressure_range tests[] = {
+               { "10:8", true, 10, 8 },
+               { "100:-1", true, 100, -1 },
+               { "-203813:-502023", true, -203813, -502023 },
+               { "238492:28210", true, 238492, 28210 },
+               { "none", true, 0, 0 },
+               { "0:0", false, 0, 0 },
+               { "", false, 0, 0 },
+               { "abcd", false, 0, 0 },
+               { "10:30:10", false, 0, 0 },
+               { NULL, false, 0, 0 }
+       };
+       int i;
+       int hi, lo;
+       bool success;
+
+       for (i = 0; tests[i].tag != NULL; i++) {
+               hi = lo = 0xad;
+               success = parse_pressure_range_property(tests[i].tag, &hi, &lo);
+               ck_assert(success == tests[i].success);
+               if (success) {
+                       ck_assert_int_eq(hi, tests[i].hi);
+                       ck_assert_int_eq(lo, tests[i].lo);
+               } else {
+                       ck_assert_int_eq(hi, 0xad);
+                       ck_assert_int_eq(lo, 0xad);
+               }
+       }
+
+       success = parse_pressure_range_property(NULL, NULL, NULL);
+       ck_assert(success == false);
+}
+END_TEST
+
 START_TEST(time_conversion)
 {
        ck_assert_int_eq(us(10), 10);
@@ -1275,6 +1317,7 @@ litest_setup_tests_misc(void)
        litest_add_no_device("misc:parser", dimension_prop_parser);
        litest_add_no_device("misc:parser", reliability_prop_parser);
        litest_add_no_device("misc:parser", calibration_prop_parser);
+       litest_add_no_device("misc:parser", pressure_range_prop_parser);
        litest_add_no_device("misc:parser", safe_atoi_test);
        litest_add_no_device("misc:parser", safe_atod_test);
        litest_add_no_device("misc:parser", strsplit_test);
index 5370e36f206850b32e611ef474d9b74d62dab790..3ae7a4970e46d1d8b2cb82148bf653b1761da41d 100644 (file)
@@ -88,6 +88,7 @@ libinput:name:* Touchpad:dmi:*svnDellInc.:*
 ##########################################
 libinput:name:*ETPS/2 Elantech Touchpad*:dmi:*
  LIBINPUT_ATTR_RESOLUTION_HINT=31x31
+ LIBINPUT_ATTR_PRESSURE_RANGE=24:10
  LIBINPUT_MODEL_ELANTECH_TOUCHPAD=1
 
 ##########################################
@@ -114,6 +115,7 @@ libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus*
 
 libinput:name:Cypress APA Trackpad ?cyapa?:dmi:*
  LIBINPUT_MODEL_CYAPA=1
+ LIBINPUT_ATTR_PRESSURE_RANGE=10:8
 
 ##########################################
 # HP
index 2a342bf1b7abb693aff3c1e3541f11fa8b59e20c..97f04f4f78b1456caf248ecfe7d677e6effb414f 100755 (executable)
@@ -112,7 +112,13 @@ def property_grammar():
                          Suppress('=') -
                          tpkbcombo_tags('VALUE')]
 
-    grammar = Or(model_props + size_props + reliability + tpkbcombo)
+    pressure_range = INTEGER('X') + Suppress(':') + INTEGER('Y')
+    pressure_prop = [ Literal('LIBINPUT_ATTR_PRESSURE_RANGE')('NAME') -
+                      Suppress('=') -
+                      Group(pressure_range('SETTINGS*')) ]
+
+    grammar = Or(model_props + size_props + reliability + tpkbcombo +
+                 pressure_prop)
 
     return grammar