From: Peter Hutterer Date: Tue, 10 Dec 2013 03:20:36 +0000 (+1000) Subject: Add libinput_create_from_path X-Git-Tag: 0.1.0~92 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=069fc60b8ba8a0f95cecf5f6abe46cf936326688;p=platform%2Fupstream%2Flibinput.git Add libinput_create_from_path Hooking libinput up to udev isn't always possible, especially if libinput were to be used in the X server which already has the udev handling built-in. Add an option to create a context from a path. Signed-off-by: Peter Hutterer --- diff --git a/src/Makefile.am b/src/Makefile.am index d3dc3575..6e27b3b4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,8 @@ libinput_la_SOURCES = \ evdev-touchpad.c \ filter.c \ filter.h \ + path.h \ + path.c \ udev-seat.c \ udev-seat.h diff --git a/src/libinput.h b/src/libinput.h index 0d03073d..d1c6746a 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -447,6 +447,25 @@ libinput_create_from_udev(const struct libinput_interface *interface, void *user_data, struct udev *udev, const char *seat_id); +/** + * @ingroup base + * + * Create a new libinput context from the given path. This context + * represents one single device only, it will not respond to new devices + * being added and reading from the device after it was removed will fail. + * + * @param interface The callback interface + * @param user_data Caller-specific data passed to the various callback + * interfaces. + * @param path Path to an input device + * + * @return An initialized libinput context, ready to handle events or NULL on + * error. + */ +struct libinput * +libinput_create_from_path(const struct libinput_interface *interface, + void *user_data, + const char *path); /** * @ingroup base diff --git a/src/path.c b/src/path.c new file mode 100644 index 00000000..cafe1fe8 --- /dev/null +++ b/src/path.c @@ -0,0 +1,199 @@ +/* + * Copyright © 2013 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include + +#include "path.h" +#include "evdev.h" + +int path_input_process_event(struct libinput_event); +static void path_seat_destroy(struct libinput_seat *seat); + +static void +path_input_disable(struct libinput *libinput) +{ + struct path_input *input = (struct path_input*)libinput; + struct evdev_device *device = input->device; + struct path_seat *seat, *tmp; + + if (device) { + close_restricted(libinput, device->fd); + evdev_device_remove(device); + input->device = NULL; + } + + /* should only be one seat anyway */ + list_for_each_safe(seat, tmp, &libinput->seat_list, base.link) { + notify_removed_seat(&seat->base); + list_remove(&seat->base.link); + list_init(&seat->base.link); + libinput_seat_unref(&seat->base); + } +} + +static void +path_seat_destroy(struct libinput_seat *seat) +{ + struct path_seat *pseat = (struct path_seat*)seat; + free(pseat); +} + +static struct path_seat* +path_seat_create(struct path_input *input) +{ + struct path_seat *seat; + + seat = zalloc(sizeof(*seat)); + if (!seat) + return NULL; + + seat->name = "default"; + + libinput_seat_init(&seat->base, &input->base, seat->name, path_seat_destroy); + list_insert(&input->base.seat_list, &seat->base.link); + notify_added_seat(&seat->base); + + return seat; +} + +static char * +path_get_sysname(const char *path) +{ + struct udev *udev = NULL; + struct udev_device *device = NULL; + struct stat st; + char *syspath = NULL; + + udev = udev_new(); + if (!udev) + goto out; + + if (stat(path, &st) < 0) + goto out; + + device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); + if (!device) + goto out; + + syspath = strdup(udev_device_get_syspath(device)); +out: + if (device) + udev_device_unref(device); + if (udev) + udev_unref(udev); + return syspath; +} + +static int +path_input_enable(struct libinput *libinput) +{ + struct path_input *input = (struct path_input*)libinput; + struct path_seat *seat; + struct evdev_device *device; + const char *devnode = input->path; + char *syspath; + int fd; + + if (input->device) + return 0; + + fd = open_restricted(libinput, input->path, O_RDWR|O_NONBLOCK); + if (fd < 0) { + log_info("opening input device '%s' failed.\n", devnode); + return -1; + } + + syspath = path_get_sysname(devnode); + if (!syspath) { + close_restricted(libinput, fd); + log_info("failed to obtain syspath for device '%s'.\n", devnode); + return -1; + } + + seat = path_seat_create(input); + + device = evdev_device_create(&seat->base, devnode, syspath, fd); + free(syspath); + + if (device == EVDEV_UNHANDLED_DEVICE) { + close_restricted(libinput, fd); + log_info("not using input device '%s'.\n", devnode); + libinput_seat_unref(&seat->base); + return -1; + } else if (device == NULL) { + close_restricted(libinput, fd); + log_info("failed to create input device '%s'.\n", devnode); + libinput_seat_unref(&seat->base); + return -1; + } + + input->device = device; + + return 0; +} + +static void +path_input_destroy(struct libinput *input) +{ + struct path_input *path_input = (struct path_input*)input; + free(path_input->path); +} + +static const struct libinput_interface_backend interface_backend = { + .resume = path_input_enable, + .suspend = path_input_disable, + .destroy = path_input_destroy, +}; + +LIBINPUT_EXPORT struct libinput * +libinput_create_from_path(const struct libinput_interface *interface, + void *user_data, + const char *path) +{ + struct path_input *input; + + if (!interface || !path) + return NULL; + + input = zalloc(sizeof *input); + if (!input) + return NULL; + + if (libinput_init(&input->base, interface, + &interface_backend, user_data) != 0) { + free(input); + return NULL; + } + + input->path = strdup(path); + + if (path_input_enable(&input->base) < 0) { + libinput_destroy(&input->base); + return NULL; + } + + return &input->base; +} diff --git a/src/path.h b/src/path.h new file mode 100644 index 00000000..72cc5472 --- /dev/null +++ b/src/path.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2013 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _PATH_H_ +#define _PATH_H_ + +#include "config.h" +#include "libinput-private.h" + +struct path_input { + struct libinput base; + char *path; + struct evdev_device *device; +}; + +struct path_seat { + struct libinput_seat base; + const char *name; +}; + +int path_input_process_event(struct libinput_event); + +#endif