Hi, On 09/03/2014 04:03 AM, Peter Hutterer wrote: > A device may disappear and a new device may re-appear with the same device > node while the original device is suspended. Prevent a device resume to open > the wrong device. > > In a path context, a changing syspath is the only indicator we get of the > device changing. > In a udev context, if the device was removed and libinput_dispatch() was > called, we can short-cut the syspath comparison by setting it to NULL. > > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
Looks good: Reviewed-by: Hans de Goede <hdego...@redhat.com> Regards, Hans > --- > src/evdev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- > src/evdev.h | 4 +++- > src/path.c | 9 ++++++--- > src/udev-seat.c | 4 +++- > 4 files changed, 59 insertions(+), 6 deletions(-) > > diff --git a/src/evdev.c b/src/evdev.c > index c9e9b2d..fad9fd9 100644 > --- a/src/evdev.c > +++ b/src/evdev.c > @@ -962,7 +962,8 @@ evdev_configure_device(struct evdev_device *device) > struct evdev_device * > evdev_device_create(struct libinput_seat *seat, > const char *devnode, > - const char *sysname) > + const char *sysname, > + const char *syspath) > { > struct libinput *libinput = seat->libinput; > struct evdev_device *device; > @@ -999,6 +1000,7 @@ evdev_device_create(struct libinput_seat *seat, > device->mtdev = NULL; > device->devnode = strdup(devnode); > device->sysname = strdup(sysname); > + device->syspath = strdup(syspath); > device->rel.dx = 0; > device->rel.dy = 0; > device->abs.seat_slot = -1; > @@ -1246,6 +1248,36 @@ evdev_device_suspend(struct evdev_device *device) > return 0; > } > > +static int > +evdev_device_compare_syspath(struct evdev_device *device, int fd) > +{ > + struct udev *udev = NULL; > + struct udev_device *udev_device = NULL; > + const char *syspath; > + struct stat st; > + int rc = 1; > + > + udev = udev_new(); > + if (!udev) > + goto out; > + > + if (fstat(fd, &st) < 0) > + goto out; > + > + udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); > + if (!device) > + goto out; > + > + syspath = udev_device_get_syspath(udev_device); > + rc = strcmp(syspath, device->syspath); > +out: > + if (udev_device) > + udev_device_unref(udev_device); > + if (udev) > + udev_unref(udev); > + return rc; > +} > + > int > evdev_device_resume(struct evdev_device *device) > { > @@ -1255,11 +1287,19 @@ evdev_device_resume(struct evdev_device *device) > if (device->fd != -1) > return 0; > > + if (device->syspath == NULL) > + return -ENODEV; > + > fd = open_restricted(libinput, device->devnode, O_RDWR | O_NONBLOCK); > > if (fd < 0) > return -errno; > > + if (evdev_device_compare_syspath(device, fd)) { > + close_restricted(libinput, fd); > + return -ENODEV; > + } > + > device->fd = fd; > device->source = > libinput_add_fd(libinput, fd, evdev_device_dispatch, device); > @@ -1276,6 +1316,11 @@ evdev_device_remove(struct evdev_device *device) > { > evdev_device_suspend(device); > > + /* A device may be removed while suspended. Free the syspath to > + * skip re-opening a different device with the same node */ > + free(device->syspath); > + device->syspath = NULL; > + > list_remove(&device->base.link); > > notify_removed_device(&device->base); > @@ -1297,5 +1342,6 @@ evdev_device_destroy(struct evdev_device *device) > free(device->mt.slots); > free(device->devnode); > free(device->sysname); > + free(device->syspath); > free(device); > } > diff --git a/src/evdev.h b/src/evdev.h > index 2af6828..bdd4a4e 100644 > --- a/src/evdev.h > +++ b/src/evdev.h > @@ -63,6 +63,7 @@ struct evdev_device { > char *output_name; > char *devnode; > char *sysname; > + char *syspath; > const char *devname; > int fd; > struct { > @@ -134,7 +135,8 @@ struct evdev_dispatch { > struct evdev_device * > evdev_device_create(struct libinput_seat *seat, > const char *devnode, > - const char *sysname); > + const char *sysname, > + const char *syspath); > > struct evdev_dispatch * > evdev_touchpad_create(struct evdev_device *device); > diff --git a/src/path.c b/src/path.c > index e9c0ee8..3752751 100644 > --- a/src/path.c > +++ b/src/path.c > @@ -112,6 +112,7 @@ path_seat_get_named(struct path_input *input, > static int > path_get_udev_properties(const char *path, > char **sysname, > + char **syspath, > char **seat_name, > char **seat_logical_name) > { > @@ -133,6 +134,7 @@ path_get_udev_properties(const char *path, > goto out; > > *sysname = strdup(udev_device_get_sysname(device)); > + *syspath = strdup(udev_device_get_syspath(device)); > > seat = udev_device_get_property_value(device, "ID_SEAT"); > *seat_name = strdup(seat ? seat : default_seat); > @@ -155,10 +157,10 @@ path_device_enable(struct path_input *input, const char > *devnode) > { > struct path_seat *seat; > struct evdev_device *device = NULL; > - char *sysname = NULL; > + char *sysname = NULL, *syspath = NULL; > char *seat_name = NULL, *seat_logical_name = NULL; > > - if (path_get_udev_properties(devnode, &sysname, > + if (path_get_udev_properties(devnode, &sysname, &syspath, > &seat_name, &seat_logical_name) == -1) { > log_info(&input->base, > "failed to obtain sysname for device '%s'.\n", > @@ -180,7 +182,7 @@ path_device_enable(struct path_input *input, const char > *devnode) > } > } > > - device = evdev_device_create(&seat->base, devnode, sysname); > + device = evdev_device_create(&seat->base, devnode, sysname, syspath); > libinput_seat_unref(&seat->base); > > if (device == EVDEV_UNHANDLED_DEVICE) { > @@ -198,6 +200,7 @@ path_device_enable(struct path_input *input, const char > *devnode) > > out: > free(sysname); > + free(syspath); > free(seat_name); > free(seat_logical_name); > > diff --git a/src/udev-seat.c b/src/udev-seat.c > index ccff35c..f2be66e 100644 > --- a/src/udev-seat.c > +++ b/src/udev-seat.c > @@ -47,6 +47,7 @@ device_added(struct udev_device *udev_device, struct > udev_input *input) > struct evdev_device *device; > const char *devnode; > const char *sysname; > + const char *syspath; > const char *device_seat, *seat_name, *output_name; > const char *calibration_values; > float calibration[6]; > @@ -61,6 +62,7 @@ device_added(struct udev_device *udev_device, struct > udev_input *input) > > devnode = udev_device_get_devnode(udev_device); > sysname = udev_device_get_sysname(udev_device); > + syspath = udev_device_get_syspath(udev_device); > > /* Search for matching logical seat */ > seat_name = udev_device_get_property_value(udev_device, "WL_SEAT"); > @@ -77,7 +79,7 @@ device_added(struct udev_device *udev_device, struct > udev_input *input) > return -1; > } > > - device = evdev_device_create(&seat->base, devnode, sysname); > + device = evdev_device_create(&seat->base, devnode, sysname, syspath); > libinput_seat_unref(&seat->base); > > if (device == EVDEV_UNHANDLED_DEVICE) { > _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel