touchpad: Use remove callback to unlink event listener and stop timers

We use 2 mechanisms to unregister the trackpoint event listener depending on
device removal order.

1) We have a device_removed callback, if the trackpoint gets removed before
the touchpad, this gets called, sees the device being removed is the trackpoint
and unregisters the listener

2) If the touchpad gets removed first, then in tp_destroy we unregister the
listener

2) May be delayed beyond the destruction of the trackpoint itself if the
libinput user has a reference to the libinput_device for the touchpad.
When this happens the trackpoint still has an eventlistener at destroy time
and an assert triggers.

To fix this we must do 2) at the same time as we do 1), so at remove time.

While working on this I noticed that the touchpad code was also cancelling
timers at destroy time rather then remove time, which means that they may
expire between remove and destroy time, and cause events to be emitted from
a removed device, so this commit moves the cancelling of the timers to the
remove callback as well.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Hans de Goede 2014-12-05 12:50:39 +01:00
parent 4a971a69cf
commit 36017fbd3c
5 changed files with 22 additions and 14 deletions

View file

@ -603,7 +603,7 @@ tp_init_buttons(struct tp_dispatch *tp,
}
void
tp_destroy_buttons(struct tp_dispatch *tp)
tp_remove_buttons(struct tp_dispatch *tp)
{
struct tp_touch *t;

View file

@ -271,7 +271,7 @@ tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device)
}
void
tp_destroy_edge_scroll(struct tp_dispatch *tp)
tp_remove_edge_scroll(struct tp_dispatch *tp)
{
struct tp_touch *t;

View file

@ -720,7 +720,7 @@ tp_init_tap(struct tp_dispatch *tp)
}
void
tp_destroy_tap(struct tp_dispatch *tp)
tp_remove_tap(struct tp_dispatch *tp)
{
libinput_timer_cancel(&tp->tap.timer);
}

View file

@ -512,9 +512,9 @@ tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
}
static void
tp_destroy_scroll(struct tp_dispatch *tp)
tp_remove_scroll(struct tp_dispatch *tp)
{
tp_destroy_edge_scroll(tp);
tp_remove_edge_scroll(tp);
}
static void
@ -668,7 +668,7 @@ tp_process(struct evdev_dispatch *dispatch,
}
static void
tp_destroy_sendevents(struct tp_dispatch *tp)
tp_remove_sendevents(struct tp_dispatch *tp)
{
libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
@ -677,16 +677,24 @@ tp_destroy_sendevents(struct tp_dispatch *tp)
&tp->sendevents.trackpoint_listener);
}
static void
tp_remove(struct evdev_dispatch *dispatch)
{
struct tp_dispatch *tp =
(struct tp_dispatch*)dispatch;
tp_remove_tap(tp);
tp_remove_buttons(tp);
tp_remove_sendevents(tp);
tp_remove_scroll(tp);
}
static void
tp_destroy(struct evdev_dispatch *dispatch)
{
struct tp_dispatch *tp =
(struct tp_dispatch*)dispatch;
tp_destroy_tap(tp);
tp_destroy_buttons(tp);
tp_destroy_sendevents(tp);
tp_destroy_scroll(tp);
free(tp->touches);
free(tp);
@ -858,7 +866,7 @@ tp_tag_device(struct evdev_device *device,
static struct evdev_dispatch_interface tp_interface = {
tp_process,
NULL, /* remove */
tp_remove,
tp_destroy,
tp_device_added,
tp_device_removed,

View file

@ -287,7 +287,7 @@ int
tp_init_tap(struct tp_dispatch *tp);
void
tp_destroy_tap(struct tp_dispatch *tp);
tp_remove_tap(struct tp_dispatch *tp);
int
tp_init_buttons(struct tp_dispatch *tp, struct evdev_device *device);
@ -298,7 +298,7 @@ tp_init_softbuttons(struct tp_dispatch *tp,
double topbutton_size_mult);
void
tp_destroy_buttons(struct tp_dispatch *tp);
tp_remove_buttons(struct tp_dispatch *tp);
int
tp_process_button(struct tp_dispatch *tp,
@ -338,7 +338,7 @@ int
tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device);
void
tp_destroy_edge_scroll(struct tp_dispatch *tp);
tp_remove_edge_scroll(struct tp_dispatch *tp);
void
tp_edge_scroll_handle_state(struct tp_dispatch *tp, uint64_t time);