summaryrefslogtreecommitdiff
path: root/src/udev-seat.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2013-12-23 14:10:56 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2014-01-10 11:08:21 +1000
commit6fcaf7699c3b5ee1bc0a8199044a8989b2c6145f (patch)
tree8fd1a30faf471c54e85e975756820dff5a27fb9c /src/udev-seat.c
parent1ee5b28c6e207d168b230f8287721d5b19c8a804 (diff)
downloadlibinput-6fcaf7699c3b5ee1bc0a8199044a8989b2c6145f.tar.gz
udev: Refcount the seat for each device
Use the seat's internal refcounting to up the reference each time we have a device using it. This fixes the issue with seats being created but never actually removed by anything. udev_seat_get_named() will now return a seat with refcount 1 for a newly created seat, or just up the refcount for the seat if it already exists. This requires that the ADDED_SEAT and REMOVED_SEAT events up the refcount of the seat as well: a device may be removed before the event is processed, without the refcount the seat would be destroyed (if it's the last device on the seat). Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'src/udev-seat.c')
-rw-r--r--src/udev-seat.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/src/udev-seat.c b/src/udev-seat.c
index a78be437..08e7ada7 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -68,8 +68,13 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
seat = udev_seat_get_named(input, seat_name);
- if (seat == NULL)
- return -1;
+ if (seat)
+ libinput_seat_ref(&seat->base);
+ else {
+ seat = udev_seat_create(input, seat_name);
+ if (!seat)
+ return -1;
+ }
/* Use non-blocking mode so that we can loop on read on
* evdev_device_data() until all events on the fd are
@@ -77,18 +82,18 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
if (fd < 0) {
log_info("opening input device '%s' failed (%s).\n", devnode, strerror(-fd));
- return 0;
+ goto error;
}
device = evdev_device_create(&seat->base, devnode, sysname, fd);
if (device == EVDEV_UNHANDLED_DEVICE) {
close_restricted(libinput, fd);
log_info("not using input device '%s'.\n", devnode);
- return 0;
+ goto error;
} else if (device == NULL) {
close_restricted(libinput, fd);
log_info("failed to create input device '%s'.\n", devnode);
- return 0;
+ goto error;
}
calibration_values =
@@ -118,6 +123,10 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
device->output_name = strdup(output_name);
return 0;
+error:
+ if (seat)
+ libinput_seat_unref(&seat->base);
+ return 0;
}
static int
@@ -189,6 +198,7 @@ evdev_udev_handler(void *data)
device->devname, device->devnode);
close_restricted(libinput, device->fd);
evdev_device_remove(device);
+ libinput_seat_unref(&seat->base);
break;
}
}
@@ -202,13 +212,14 @@ static void
udev_input_remove_devices(struct udev_input *input)
{
struct evdev_device *device, *next;
- struct udev_seat *seat;
+ struct udev_seat *seat, *tmp;
- list_for_each(seat, &input->base.seat_list, base.link) {
+ list_for_each_safe(seat, tmp, &input->base.seat_list, base.link) {
list_for_each_safe(device, next,
&seat->base.devices_list, base.link) {
close_restricted(&input->base, device->fd);
evdev_device_remove(device);
+ libinput_seat_unref(&seat->base);
}
}
}
@@ -278,16 +289,12 @@ udev_input_enable(struct libinput *libinput)
static void
udev_input_destroy(struct libinput *input)
{
- struct libinput_seat *seat, *next;
struct udev_input *udev_input = (struct udev_input*)input;
if (input == NULL)
return;
udev_input_disable(input);
- list_for_each_safe(seat, next, &input->seat_list, link) {
- libinput_seat_unref(seat);
- }
udev_unref(udev_input->udev);
free(udev_input->seat_id);
}
@@ -325,12 +332,7 @@ udev_seat_get_named(struct udev_input *input, const char *seat_name)
return seat;
}
- seat = udev_seat_create(input, seat_name);
-
- if (!seat)
- return NULL;
-
- return seat;
+ return NULL;
}
static const struct libinput_interface_backend interface_backend = {