#include "config.h"
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
-#include "compositor.h"
-#include "launcher-util.h"
#include "evdev.h"
#include "udev-seat.h"
static const char default_seat_name[] = "default";
static struct udev_seat *
-udev_seat_create(struct weston_compositor *c, const char *seat_name);
-static void
-udev_seat_destroy(struct udev_seat *seat);
+udev_seat_create(struct udev_input *input,
+ const char *device_seat,
+ const char *seat_name);
+static struct udev_seat *
+udev_seat_get_named(struct udev_input *input, const char *seat_name);
static int
device_added(struct udev_device *udev_device, struct udev_input *input)
{
- struct weston_compositor *c;
struct evdev_device *device;
- struct weston_output *output;
const char *devnode;
+ const char *sysname;
const char *device_seat, *seat_name, *output_name;
const char *calibration_values;
- int fd;
struct udev_seat *seat;
device_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
if (strcmp(device_seat, input->seat_id))
return 0;
- c = input->compositor;
devnode = udev_device_get_devnode(udev_device);
+ sysname = udev_device_get_sysname(udev_device);
/* Search for matching logical seat */
seat_name = udev_device_get_property_value(udev_device, "WL_SEAT");
if (!seat_name)
seat_name = default_seat_name;
- seat = udev_seat_get_named(c, seat_name);
-
- if (seat == NULL)
- return -1;
+ seat = udev_seat_get_named(input, seat_name);
- /* Use non-blocking mode so that we can loop on read on
- * evdev_device_data() until all events on the fd are
- * read. mtdev_get() also expects this. */
- fd = weston_launcher_open(c->launcher, devnode, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- weston_log("opening input device '%s' failed.\n", devnode);
- return 0;
+ if (seat)
+ libinput_seat_ref(&seat->base);
+ else {
+ seat = udev_seat_create(input, device_seat, seat_name);
+ if (!seat)
+ return -1;
}
- device = evdev_device_create(&seat->base, devnode, fd);
+ device = evdev_device_create(&seat->base, devnode, sysname);
+ libinput_seat_unref(&seat->base);
+
if (device == EVDEV_UNHANDLED_DEVICE) {
- close(fd);
- weston_log("not using input device '%s'.\n", devnode);
+ log_info(&input->base, "not using input device '%s'.\n", devnode);
return 0;
} else if (device == NULL) {
- close(fd);
- weston_log("failed to create input device '%s'.\n", devnode);
+ log_info(&input->base, "failed to create input device '%s'.\n", devnode);
return 0;
}
&device->abs.calibration[4],
&device->abs.calibration[5]) == 6) {
device->abs.apply_calibration = 1;
- weston_log ("Applying calibration: %f %f %f %f %f %f\n",
- device->abs.calibration[0],
- device->abs.calibration[1],
- device->abs.calibration[2],
- device->abs.calibration[3],
- device->abs.calibration[4],
- device->abs.calibration[5]);
+ log_info(&input->base,
+ "Applying calibration: %f %f %f %f %f %f\n",
+ device->abs.calibration[0],
+ device->abs.calibration[1],
+ device->abs.calibration[2],
+ device->abs.calibration[3],
+ device->abs.calibration[4],
+ device->abs.calibration[5]);
}
- wl_list_insert(seat->devices_list.prev, &device->link);
-
- if (seat->base.output && seat->base.pointer)
- weston_pointer_clamp(seat->base.pointer,
- &seat->base.pointer->x,
- &seat->base.pointer->y);
-
output_name = udev_device_get_property_value(udev_device, "WL_OUTPUT");
- if (output_name) {
- wl_list_for_each(output, &c->output_list, link)
- if (strcmp(output->name, output_name) == 0)
- device->output = output;
- }
-
- if (input->enabled == 1)
- weston_seat_repick(&seat->base);
+ if (output_name)
+ device->output_name = strdup(output_name);
return 0;
}
+static void
+device_removed(struct udev_device *udev_device, struct udev_input *input)
+{
+ const char *devnode;
+ struct evdev_device *device, *next;
+ struct udev_seat *seat;
+
+ devnode = udev_device_get_devnode(udev_device);
+ list_for_each(seat, &input->base.seat_list, base.link) {
+ list_for_each_safe(device, next,
+ &seat->base.devices_list, base.link) {
+ if (!strcmp(device->devnode, devnode)) {
+ log_info(&input->base,
+ "input device %s, %s removed\n",
+ device->devname, device->devnode);
+ evdev_device_remove(device);
+ break;
+ }
+ }
+ }
+}
+
static int
udev_input_add_devices(struct udev_input *input, struct udev *udev)
{
struct udev_list_entry *entry;
struct udev_device *device;
const char *path, *sysname;
- struct udev_seat *seat;
- int devices_found = 0;
e = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(e, "input");
}
udev_enumerate_unref(e);
- wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
- evdev_notify_keyboard_focus(&seat->base, &seat->devices_list);
-
- if (!wl_list_empty(&seat->devices_list))
- devices_found = 1;
- }
-
- if (devices_found == 0) {
- weston_log(
- "warning: no input devices on entering Weston. "
- "Possible causes:\n"
- "\t- no permissions to read /dev/input/event*\n"
- "\t- seats misconfigured "
- "(Weston backend option 'seat', "
- "udev device property ID_SEAT)\n");
- return -1;
- }
-
return 0;
}
-static int
-evdev_udev_handler(int fd, uint32_t mask, void *data)
+static void
+evdev_udev_handler(void *data)
{
struct udev_input *input = data;
struct udev_device *udev_device;
- struct evdev_device *device, *next;
const char *action;
- const char *devnode;
- struct udev_seat *seat;
udev_device = udev_monitor_receive_device(input->udev_monitor);
if (!udev_device)
- return 1;
+ return;
action = udev_device_get_action(udev_device);
if (!action)
if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0)
goto out;
- if (!strcmp(action, "add")) {
+ if (!strcmp(action, "add"))
device_added(udev_device, input);
- }
- else if (!strcmp(action, "remove")) {
- devnode = udev_device_get_devnode(udev_device);
- wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
- wl_list_for_each_safe(device, next, &seat->devices_list, link)
- if (!strcmp(device->devnode, devnode)) {
- weston_log("input device %s, %s removed\n",
- device->devname, device->devnode);
- evdev_device_destroy(device);
- break;
- }
- }
- }
+ else if (!strcmp(action, "remove"))
+ device_removed(udev_device, input);
out:
udev_device_unref(udev_device);
+}
- return 0;
+static void
+udev_input_remove_devices(struct udev_input *input)
+{
+ struct evdev_device *device, *next;
+ struct udev_seat *seat, *tmp;
+
+ list_for_each_safe(seat, tmp, &input->base.seat_list, base.link) {
+ libinput_seat_ref(&seat->base);
+ list_for_each_safe(device, next,
+ &seat->base.devices_list, base.link) {
+ evdev_device_remove(device);
+ }
+ libinput_seat_unref(&seat->base);
+ }
+}
+
+
+static void
+udev_input_disable(struct libinput *libinput)
+{
+ struct udev_input *input = (struct udev_input*)libinput;
+
+ if (!input->udev_monitor)
+ return;
+
+ udev_monitor_unref(input->udev_monitor);
+ input->udev_monitor = NULL;
+ libinput_remove_source(&input->base, input->udev_monitor_source);
+ input->udev_monitor_source = NULL;
+
+ udev_input_remove_devices(input);
}
-int
-udev_input_enable(struct udev_input *input, struct udev *udev)
+static int
+udev_input_enable(struct libinput *libinput)
{
- struct wl_event_loop *loop;
- struct weston_compositor *c = input->compositor;
+ struct udev_input *input = (struct udev_input*)libinput;
+ struct udev *udev = input->udev;
int fd;
+ if (input->udev_monitor)
+ return 0;
+
input->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
if (!input->udev_monitor) {
- weston_log("udev: failed to create the udev monitor\n");
+ log_info(libinput,
+ "udev: failed to create the udev monitor\n");
return -1;
}
"input", NULL);
if (udev_monitor_enable_receiving(input->udev_monitor)) {
- weston_log("udev: failed to bind the udev monitor\n");
+ log_info(libinput, "udev: failed to bind the udev monitor\n");
udev_monitor_unref(input->udev_monitor);
+ input->udev_monitor = NULL;
return -1;
}
- loop = wl_display_get_event_loop(c->wl_display);
fd = udev_monitor_get_fd(input->udev_monitor);
- input->udev_monitor_source =
- wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
- evdev_udev_handler, input);
+ input->udev_monitor_source = libinput_add_fd(&input->base,
+ fd,
+ evdev_udev_handler,
+ input);
if (!input->udev_monitor_source) {
udev_monitor_unref(input->udev_monitor);
+ input->udev_monitor = NULL;
return -1;
}
- if (udev_input_add_devices(input, udev) < 0)
+ if (udev_input_add_devices(input, udev) < 0) {
+ udev_input_disable(libinput);
return -1;
-
- input->enabled = 1;
+ }
return 0;
}
static void
-udev_input_remove_devices(struct udev_input *input)
+udev_input_destroy(struct libinput *input)
{
- struct evdev_device *device, *next;
- struct udev_seat *seat;
+ struct udev_input *udev_input = (struct udev_input*)input;
- wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
- wl_list_for_each_safe(device, next, &seat->devices_list, link)
- evdev_device_destroy(device);
+ if (input == NULL)
+ return;
- if (seat->base.keyboard)
- notify_keyboard_focus_out(&seat->base);
- }
+ udev_unref(udev_input->udev);
+ free(udev_input->seat_id);
}
-void
-udev_input_disable(struct udev_input *input)
+static void
+udev_seat_destroy(struct libinput_seat *seat)
{
- if (!input->udev_monitor)
- return;
-
- udev_monitor_unref(input->udev_monitor);
- input->udev_monitor = NULL;
- wl_event_source_remove(input->udev_monitor_source);
- input->udev_monitor_source = NULL;
-
- udev_input_remove_devices(input);
+ struct udev_seat *useat = (struct udev_seat*)seat;
+ free(useat);
}
-
-int
-udev_input_init(struct udev_input *input, struct weston_compositor *c, struct udev *udev,
- const char *seat_id)
+static struct udev_seat *
+udev_seat_create(struct udev_input *input,
+ const char *device_seat,
+ const char *seat_name)
{
- memset(input, 0, sizeof *input);
- input->seat_id = strdup(seat_id);
- input->compositor = c;
- if (udev_input_enable(input, udev) < 0)
- goto err;
+ struct udev_seat *seat;
- return 0;
+ seat = zalloc(sizeof *seat);
+ if (!seat)
+ return NULL;
- err:
- free(input->seat_id);
- return -1;
-}
+ libinput_seat_init(&seat->base, &input->base,
+ device_seat, seat_name,
+ udev_seat_destroy);
-void
-udev_input_destroy(struct udev_input *input)
-{
- struct udev_seat *seat, *next;
- udev_input_disable(input);
- wl_list_for_each_safe(seat, next, &input->compositor->seat_list, base.link)
- udev_seat_destroy(seat);
- free(input->seat_id);
+ return seat;
}
-static void
-drm_led_update(struct weston_seat *seat_base, enum weston_led leds)
+static struct udev_seat *
+udev_seat_get_named(struct udev_input *input, const char *seat_name)
{
- struct udev_seat *seat = (struct udev_seat *) seat_base;
- struct evdev_device *device;
+ struct udev_seat *seat;
- wl_list_for_each(device, &seat->devices_list, link)
- evdev_led_update(device, leds);
+ list_for_each(seat, &input->base.seat_list, base.link) {
+ if (strcmp(seat->base.logical_name, seat_name) == 0)
+ return seat;
+ }
+
+ return NULL;
}
-static struct udev_seat *
-udev_seat_create(struct weston_compositor *c, const char *seat_name)
+static const struct libinput_interface_backend interface_backend = {
+ .resume = udev_input_enable,
+ .suspend = udev_input_disable,
+ .destroy = udev_input_destroy,
+};
+
+LIBINPUT_EXPORT struct libinput *
+libinput_udev_create_context(const struct libinput_interface *interface,
+ void *user_data,
+ struct udev *udev)
{
- struct udev_seat *seat;
+ struct udev_input *input;
- seat = zalloc(sizeof *seat);
+ if (!interface || !udev)
+ return NULL;
- if (!seat)
+ input = zalloc(sizeof *input);
+ if (!input)
return NULL;
- weston_seat_init(&seat->base, c, seat_name);
- seat->base.led_update = drm_led_update;
- wl_list_init(&seat->devices_list);
- return seat;
-}
+ if (libinput_init(&input->base, interface,
+ &interface_backend, user_data) != 0) {
+ libinput_unref(&input->base);
+ free(input);
+ return NULL;
+ }
-static void
-udev_seat_destroy(struct udev_seat *seat)
-{
- weston_seat_release(&seat->base);
- free(seat);
+ input->udev = udev_ref(udev);
+
+ return &input->base;
}
-struct udev_seat *
-udev_seat_get_named(struct weston_compositor *c, const char *seat_name)
+LIBINPUT_EXPORT int
+libinput_udev_assign_seat(struct libinput *libinput,
+ const char *seat_id)
{
- struct udev_seat *seat;
+ struct udev_input *input = (struct udev_input*)libinput;
- wl_list_for_each(seat, &c->seat_list, base.link) {
- if (strcmp(seat->base.seat_name, seat_name) == 0)
- return seat;
+ if (!seat_id)
+ return -1;
+ if (input->seat_id != NULL)
+ return -1;
+
+ if (libinput->interface_backend != &interface_backend) {
+ log_bug_client(libinput, "Mismatching backends.\n");
+ return -1;
}
- seat = udev_seat_create(c, seat_name);
+ input->seat_id = strdup(seat_id);
- if (!seat)
- return NULL;
+ if (udev_input_enable(&input->base) < 0)
+ return -1;
- return seat;
+ return 0;
}