}
}
+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)
{
struct lid_switch_dispatch *dispatch =
(struct lid_switch_dispatch*)evdev_dispatch;
struct libevdev *evdev = device->evdev;
+ bool is_closed = false;
+
+ /* 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 = libevdev_get_event_value(evdev,
- EV_SW,
- SW_LID);
+ dispatch->lid_is_closed = is_closed;
if (dispatch->lid_is_closed) {
uint64_t time;
time = libinput_now(evdev_libinput_context(device));
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.
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)
{
"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\"";
}
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);
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);