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 <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2013-12-10 13:20:36 +10:00
parent 3cf9cd9c86
commit 069fc60b8b
4 changed files with 262 additions and 0 deletions

View file

@ -13,6 +13,8 @@ libinput_la_SOURCES = \
evdev-touchpad.c \
filter.c \
filter.h \
path.h \
path.c \
udev-seat.c \
udev-seat.h

View file

@ -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

199
src/path.c Normal file
View file

@ -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 <fcntl.h>
#include <string.h>
#include <libudev.h>
#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;
}

42
src/path.h Normal file
View file

@ -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