[PATCH libinput 10/14] switch: only sync the initial state if we know the state is reliable

Peter Hutterer peter.hutterer at who-t.net
Wed Jan 25 23:44:20 UTC 2017


This changes the default behavior to "disable the touchpad on the first lid
close event", thus filtering any laptops where the switch state is buggy and
always in "on" state. Devices where we know the lid switch state is
reliable can be marked as such.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev.c                     | 40 +++++++++++++++++++++++++++++++++++++---
 src/libinput-util.c             | 17 +++++++++++++++++
 src/libinput-util.h             |  9 +++++++++
 test/litest-device-lid-switch.c |  3 ++-
 test/test-misc.c                | 40 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 50c8abd..f15b8ac 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1356,6 +1356,25 @@ lid_switch_process(struct evdev_dispatch *evdev_dispatch,
 	}
 }
 
+static inline enum switch_reliability
+evdev_read_switch_reliability_prop(struct evdev_device *device)
+{
+	const char *prop;
+	enum switch_reliability r;
+
+	prop = udev_device_get_property_value(device->udev_device,
+					      "LIBINPUT_ATTR_LID_SWITCH_RELIABILITY");
+	if (!parse_switch_reliability_property(prop, &r)) {
+		log_error(evdev_libinput_context(device),
+			  "%s: switch reliability set to unknown value '%s'\n",
+			  device->devname,
+			  prop);
+		r =  RELIABILITY_UNKNOWN;
+	}
+
+	return r;
+}
+
 static void
 lid_switch_destroy(struct evdev_dispatch *evdev_dispatch)
 {
@@ -1372,10 +1391,25 @@ lid_switch_sync_initial_state(struct evdev_device *device,
 	struct lid_switch_dispatch *dispatch =
 		(struct lid_switch_dispatch*)evdev_dispatch;
 	struct libevdev *evdev = device->evdev;
+	bool is_closed = false;
 
-	dispatch->lid_is_closed = libevdev_get_event_value(evdev,
-							   EV_SW,
-							   SW_LID);
+	/* For the initial state sync, we depend on whether the lid switch
+	 * is reliable. If we know it's reliable, we sync as expected.
+	 * If we're not sure, we ignore the initial state and only sync on
+	 * the first future lid close event. Laptops with a broken switch
+	 * that always have the switch in 'on' state thus don't mess up our
+	 * touchpad.
+	 */
+	switch(evdev_read_switch_reliability_prop(device)) {
+	case RELIABILITY_UNKNOWN:
+		is_closed = false;
+		break;
+	case RELIABILITY_RELIABLE:
+		is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID);
+		break;
+	}
+
+	dispatch->lid_is_closed = is_closed;
 	if (dispatch->lid_is_closed) {
 		uint64_t time;
 		time = libinput_now(evdev_libinput_context(device));
diff --git a/src/libinput-util.c b/src/libinput-util.c
index 40e1e6e..f5d0aa7 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -278,6 +278,23 @@ parse_dimension_property(const char *prop, size_t *w, size_t *h)
 	return true;
 }
 
+bool
+parse_switch_reliability_property(const char *prop,
+				  enum switch_reliability *reliability)
+{
+	if (!prop) {
+		*reliability = RELIABILITY_UNKNOWN;
+		return true;
+	}
+
+	if (streq(prop, "reliable"))
+		*reliability = RELIABILITY_RELIABLE;
+	else
+		return false;
+
+	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.
diff --git a/src/libinput-util.h b/src/libinput-util.h
index ba09ab6..ce3a5ac 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -377,6 +377,15 @@ 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);
 
+enum switch_reliability {
+	RELIABILITY_UNKNOWN,
+	RELIABILITY_RELIABLE,
+};
+
+bool
+parse_switch_reliability_property(const char *prop,
+				  enum switch_reliability *reliability);
+
 static inline uint64_t
 us(uint64_t us)
 {
diff --git a/test/litest-device-lid-switch.c b/test/litest-device-lid-switch.c
index 823a5c9..b96592d 100644
--- a/test/litest-device-lid-switch.c
+++ b/test/litest-device-lid-switch.c
@@ -49,7 +49,8 @@ static const char udev_rule[] =
 "KERNEL!=\"event*\", GOTO=\"switch_end\"\n"
 "\n"
 "ATTRS{name}==\"litest Lid Switch*\",\\\n"
-"    ENV{ID_INPUT_SWITCH}=\"1\"\n"
+"    ENV{ID_INPUT_SWITCH}=\"1\",\\\n"
+"    ENV{LIBINPUT_ATTR_LID_SWITCH_RELIABILITY}=\"reliable\"\n"
 "\n"
 "LABEL=\"switch_end\"";
 
diff --git a/test/test-misc.c b/test/test-misc.c
index 9517042..36cabdc 100644
--- a/test/test-misc.c
+++ b/test/test-misc.c
@@ -908,6 +908,45 @@ START_TEST(dimension_prop_parser)
 }
 END_TEST
 
+struct parser_test_reliability {
+	char *tag;
+	bool success;
+	enum switch_reliability reliability;
+};
+
+START_TEST(reliability_prop_parser)
+{
+	struct parser_test_reliability tests[] = {
+		{ "reliable", true, RELIABILITY_RELIABLE },
+		{ "unreliable", false, 0 },
+		{ "", false, 0 },
+		{ "0", false, 0 },
+		{ "1", false, 0 },
+		{ NULL, false, 0, }
+	};
+	enum switch_reliability r;
+	bool success;
+	int i;
+
+	for (i = 0; tests[i].tag != NULL; i++) {
+		r = 0xaf;
+		success = parse_switch_reliability_property(tests[i].tag, &r);
+		ck_assert(success == tests[i].success);
+		if (success)
+			ck_assert_int_eq(r, tests[i].reliability);
+		else
+			ck_assert_int_eq(r, 0xaf);
+	}
+
+	success = parse_switch_reliability_property(NULL, &r);
+	ck_assert(success == true);
+	ck_assert_int_eq(r, RELIABILITY_UNKNOWN);
+
+	success = parse_switch_reliability_property("foo", NULL);
+	ck_assert(success == false);
+}
+END_TEST
+
 START_TEST(time_conversion)
 {
 	ck_assert_int_eq(us(10), 10);
@@ -1180,6 +1219,7 @@ litest_setup_tests_misc(void)
 	litest_add_no_device("misc:parser", wheel_click_count_parser);
 	litest_add_no_device("misc:parser", trackpoint_accel_parser);
 	litest_add_no_device("misc:parser", dimension_prop_parser);
+	litest_add_no_device("misc:parser", reliability_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);
-- 
2.9.3



More information about the wayland-devel mailing list