switch: only sync the initial state if we know the state is reliable

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@who-t.net>
This commit is contained in:
Peter Hutterer 2017-01-25 13:24:31 +10:00
parent 3f5e9cb636
commit 5f2402a41a
5 changed files with 105 additions and 4 deletions

View file

@ -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));

View file

@ -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.

View file

@ -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)
{

View file

@ -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\"";

View file

@ -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);