[PATCH 8/9] evdev: add hotplug support
Kristian Høgsberg
krh at bitplanet.net
Mon Oct 24 08:21:10 PDT 2011
On Mon, Oct 24, 2011 at 10:42 AM, Tiago Vignatti
<tiago.vignatti at intel.com> wrote:
> Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
Very nice, we just need to make sure we filter hotplugged devices for
the seat number as we do in the initial device discovery.
Kristian
> ---
> compositor/evdev.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 106 insertions(+), 6 deletions(-)
>
> diff --git a/compositor/evdev.c b/compositor/evdev.c
> index b81e513..18ebe04 100644
> --- a/compositor/evdev.c
> +++ b/compositor/evdev.c
> @@ -34,6 +34,8 @@
>
> struct evdev_input {
> struct wlsc_input_device base;
> + struct wl_list devices_list;
> + struct udev_monitor *udev_monitor;
> };
>
> /* Event queue used to defer keyboard/button events until EV_SYN time. */
> @@ -49,6 +51,7 @@ struct evdev_event_queue {
>
> struct evdev_input_device {
> struct evdev_input *master;
> + struct wl_list link;
> struct wl_event_source *source;
> struct wlsc_output *output;
> int fd;
> @@ -62,6 +65,7 @@ struct evdev_input_device {
>
> int is_touchpad, old_x_value, old_y_value, reset_x_value, reset_y_value;
> uint32_t time;
> + char *devnode;
>
> /* Event queue used to defer keyboard/button events until EV_SYN time */
> int num_queue;
> @@ -384,8 +388,11 @@ evdev_input_device_data(int fd, uint32_t mask, void *data)
> {
> len = read(fd, &ev, sizeof(ev));
> if (len <= 0) {
> - /* FIXME: handle error... reopen device? */
> - fprintf(stderr, "input read error %s", strerror(errno));
> + if (errno == ENODEV)
> + close(device->fd);
> + else
> + fprintf(stderr, "input read error %s\n",
> + strerror(errno));
> break;
> }
> /* The kernel promises that we always only read a complete
> @@ -473,6 +480,7 @@ evdev_input_device_create(struct evdev_input *master,
> device->dx = 0;
> device->dy = 0;
> device->num_queue = 0;
> + device->devnode = strdup(path);
>
> ec = (struct wlsc_compositor *) master->base.input_device.compositor;
> device->output =
> @@ -483,6 +491,7 @@ evdev_input_device_create(struct evdev_input *master,
>
> device->fd = open(path, O_RDONLY);
> if (device->fd < 0) {
> + free(device->devnode);
> free(device);
> fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
> return NULL;
> @@ -490,6 +499,7 @@ evdev_input_device_create(struct evdev_input *master,
>
> if (evdev_configure_device(device) == -1) {
> close(device->fd);
> + free(device->devnode);
> free(device);
> return NULL;
> }
> @@ -500,15 +510,101 @@ evdev_input_device_create(struct evdev_input *master,
> evdev_input_device_data, device);
> if (device->source == NULL) {
> close(device->fd);
> + free(device->devnode);
> free(device);
> return NULL;
> }
>
> + wl_list_insert(master->devices_list.prev, &device->link);
> return device;
> }
>
> +static void
> +device_added(struct udev_device *udev_device, struct evdev_input *master)
> +{
> + struct wlsc_compositor *c =
> + (struct wlsc_compositor *) master->base.input_device.compositor;
> +
> + const char *devnode = udev_device_get_devnode(udev_device);
> +
> + if (evdev_input_device_create(master, c->wl_display, devnode))
> + fprintf(stderr, "evdev input device: added: %s\n", devnode);
> +}
> +
> +static void
> +device_removed(struct udev_device *udev_device, struct evdev_input *master)
> +{
> + const char *devnode = udev_device_get_devnode(udev_device);
> + struct evdev_input_device *device, *next;
> +
> + wl_list_for_each_safe(device, next, &master->devices_list, link) {
> + if (!strcmp(device->devnode, devnode)) {
> + wl_event_source_remove(device->source);
> + wl_list_remove(&device->link);
> + close(device->fd);
> + free(device->devnode);
> + free(device);
> + break;
> + }
> + }
> + fprintf(stderr, "evdev input device: removed: %s\n", devnode);
> +}
> +
> static const char default_seat[] = "seat0";
>
> +static int
> +evdev_udev_handler(int fd, uint32_t mask, void *data)
> +{
> + struct evdev_input *master = data;
> + struct udev_device *udev_device;
> + const char *action;
> +
> + udev_device = udev_monitor_receive_device(master->udev_monitor);
> + if (!udev_device)
> + return 1;
> +
> + action = udev_device_get_action(udev_device);
> + if (action) {
> + if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0)
> + return 0;
> +
> + if (!strcmp(action, "add")) {
> + device_added(udev_device, master);
> + }
> + else if (!strcmp(action, "remove"))
> + device_removed(udev_device, master);
> + }
> + udev_device_unref(udev_device);
> +
> + return 0;
> +}
> +
> +static int
> +evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master)
> +{
> + struct wl_event_loop *loop;
> + struct wlsc_compositor *c =
> + (struct wlsc_compositor *) master->base.input_device.compositor;
> +
> + master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
> + if (!master->udev_monitor)
> + return 0;
> +
> + udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor,
> + "input", NULL);
> +
> + if (udev_monitor_enable_receiving(master->udev_monitor)) {
> + fprintf(stderr, "udev: failed to bind the udev monitor\n");
> + return 0;
> + }
> +
> + loop = wl_display_get_event_loop(c->wl_display);
> + wl_event_loop_add_fd(loop, udev_monitor_get_fd(master->udev_monitor),
> + WL_EVENT_READABLE, evdev_udev_handler, master);
> +
> + return 1;
> +}
> +
> void
> evdev_input_add_devices(struct wlsc_compositor *c,
> struct udev *udev, const char *seat)
> @@ -527,6 +623,12 @@ evdev_input_add_devices(struct wlsc_compositor *c,
> memset(input, 0, sizeof *input);
> wlsc_input_device_init(&input->base, c);
>
> + wl_list_init(&input->devices_list);
> + if (!evdev_config_udev_monitor(udev, input)) {
> + free(input);
> + return;
> + }
> +
> e = udev_enumerate_new(udev);
> udev_enumerate_add_match_subsystem(e, "input");
> udev_enumerate_scan_devices(e);
> @@ -542,10 +644,8 @@ evdev_input_add_devices(struct wlsc_compositor *c,
> if (!device_seat)
> device_seat = default_seat;
>
> - if (strcmp(device_seat, seat) == 0) {
> - evdev_input_device_create(input, c->wl_display,
> - udev_device_get_devnode(device));
> - }
> + if (strcmp(device_seat, seat) == 0)
> + device_added(device, input);
>
> udev_device_unref(device);
> }
> --
> 1.7.5.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
More information about the wayland-devel
mailing list