diff --git a/configure.ac b/configure.ac index 44729a90..68e1d358 100644 --- a/configure.ac +++ b/configure.ac @@ -44,6 +44,7 @@ AC_CHECK_DECL(CLOCK_MONOTONIC,[], PKG_PROG_PKG_CONFIG() PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0]) PKG_CHECK_MODULES(LIBUDEV, [libudev]) +PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4]) if test "x$GCC" = "xyes"; then GCC_CFLAGS="-Wall -Wextra -Wno-unused-parameter -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden" @@ -64,20 +65,16 @@ AC_ARG_ENABLE(tests, [build_tests="$enableval"], [build_tests="auto"]) -PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4], [HAVE_LIBEVDEV="yes"], [HAVE_LIBEVDEV="no"]) PKG_CHECK_MODULES(CHECK, [check >= 0.9.9], [HAVE_CHECK="yes"], [HAVE_CHECK="no"]) if test "x$build_tests" = "xauto"; then - if test "x$HAVE_CHECK" = "xyes" -a "x$HAVE_LIBEVDEV" = "xyes"; then + if test "x$HAVE_CHECK" = "xyes"; then build_tests="yes" fi fi if test "x$build_tests" = "xyes" -a "x$HAVE_CHECK" = "xno"; then AC_MSG_ERROR([Cannot build tests, check is missing]) fi -if test "x$build_tests" = "xyes" -a "x$HAVE_LIBEVDEV" = "xno"; then - AC_MSG_ERROR([Cannot build tests, libevdev is missing]) -fi AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"]) diff --git a/src/Makefile.am b/src/Makefile.am index 6e27b3b4..f544ccd9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,9 +20,11 @@ libinput_la_SOURCES = \ libinput_la_LIBADD = $(MTDEV_LIBS) \ $(LIBUDEV_LIBS) \ + $(LIBEVDEV_LIBS) \ -lm libinput_la_CFLAGS = $(MTDEV_CFLAGS) \ $(LIBUDEV_CFLAGS) \ + $(LIBEVDEV_CFLAGS) \ $(GCC_CFLAGS) pkgconfigdir = $(libdir)/pkgconfig diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index d65ebb24..8185bf27 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -170,16 +170,16 @@ struct touchpad_dispatch { static enum touchpad_model get_touchpad_model(struct evdev_device *device) { - struct input_id id; + int vendor, product; unsigned int i; - if (ioctl(device->fd, EVIOCGID, &id) < 0) - return TOUCHPAD_MODEL_UNKNOWN; + vendor = libevdev_get_id_vendor(device->evdev); + product = libevdev_get_id_product(device->evdev); for (i = 0; i < ARRAY_LENGTH(touchpad_spec_table); i++) - if (touchpad_spec_table[i].vendor == id.vendor && + if (touchpad_spec_table[i].vendor == vendor && (!touchpad_spec_table[i].product || - touchpad_spec_table[i].product == id.product)) + touchpad_spec_table[i].product == product)) return touchpad_spec_table[i].model; return TOUCHPAD_MODEL_UNKNOWN; @@ -730,9 +730,7 @@ touchpad_init(struct touchpad_dispatch *touchpad, { struct motion_filter *accel; - unsigned long prop_bits[INPUT_PROP_MAX]; - struct input_absinfo absinfo; - unsigned long abs_bits[NBITS(ABS_MAX)]; + const struct input_absinfo *absinfo; bool has_buttonpad; @@ -746,16 +744,13 @@ touchpad_init(struct touchpad_dispatch *touchpad, /* Detect model */ touchpad->model = get_touchpad_model(device); - ioctl(device->fd, EVIOCGPROP(sizeof(prop_bits)), prop_bits); - has_buttonpad = TEST_BIT(prop_bits, INPUT_PROP_BUTTONPAD); + has_buttonpad = libevdev_has_property(device->evdev, INPUT_PROP_BUTTONPAD); /* Configure pressure */ - ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); - if (TEST_BIT(abs_bits, ABS_PRESSURE)) { - ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo); + if ((absinfo = libevdev_get_abs_info(device->evdev, ABS_PRESSURE))) { configure_touchpad_pressure(touchpad, - absinfo.minimum, - absinfo.maximum); + absinfo->minimum, + absinfo->maximum); } /* Configure acceleration factor */ diff --git a/src/evdev.c b/src/evdev.c index 37c366c7..7168bc08 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -29,8 +29,9 @@ #include #include #include -#include +#include #include +#include #include "libinput.h" #include "evdev.h" @@ -438,66 +439,89 @@ fallback_dispatch_create(void) return dispatch; } -static void -evdev_process_events(struct evdev_device *device, - struct input_event *ev, int count) +static inline void +evdev_process_event(struct evdev_device *device, struct input_event *e) { struct evdev_dispatch *dispatch = device->dispatch; - struct input_event *e, *end; - uint32_t time = 0; + uint32_t time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; - e = ev; - end = e + count; - for (e = ev; e < end; e++) { - time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; + dispatch->interface->process(dispatch, device, e, time); +} - dispatch->interface->process(dispatch, device, e, time); +static inline void +evdev_device_dispatch_one(struct evdev_device *device, + struct input_event *ev) +{ + if (!device->mtdev) { + evdev_process_event(device, ev); + } else { + mtdev_put_event(device->mtdev, ev); + if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) { + while (!mtdev_empty(device->mtdev)) { + struct input_event e; + mtdev_get_event(device->mtdev, &e); + evdev_process_event(device, &e); + } + } } } +static int +evdev_sync_device(struct evdev_device *device) +{ + struct input_event ev; + int rc; + + do { + rc = libevdev_next_event(device->evdev, + LIBEVDEV_READ_FLAG_SYNC, &ev); + if (rc < 0) + break; + evdev_device_dispatch_one(device, &ev); + } while (rc == LIBEVDEV_READ_STATUS_SYNC); + + return rc == -EAGAIN ? 0 : rc; +} + static void evdev_device_dispatch(void *data) { struct evdev_device *device = data; struct libinput *libinput = device->base.seat->libinput; - int fd = device->fd; - struct input_event ev[32]; - int len; + struct input_event ev; + int rc; /* If the compositor is repainting, this function is called only once * per frame and we have to process all the events available on the * fd, otherwise there will be input lag. */ do { - if (device->mtdev) - len = mtdev_get(device->mtdev, fd, ev, - ARRAY_LENGTH(ev)) * - sizeof (struct input_event); - else - len = read(fd, &ev, sizeof ev); + rc = libevdev_next_event(device->evdev, + LIBEVDEV_READ_FLAG_NORMAL, &ev); + if (rc == LIBEVDEV_READ_STATUS_SYNC) { + /* send one more sync event so we handle all + currently pending events before we sync up + to the current state */ + ev.code = SYN_REPORT; + evdev_device_dispatch_one(device, &ev); - if (len < 0 || len % sizeof ev[0] != 0) { - if (len < 0 && errno != EAGAIN && errno != EINTR) { - libinput_remove_source(libinput, - device->source); - device->source = NULL; - } - - return; + rc = evdev_sync_device(device); + if (rc == 0) + rc = LIBEVDEV_READ_STATUS_SUCCESS; + } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { + evdev_device_dispatch_one(device, &ev); } + } while (rc == LIBEVDEV_READ_STATUS_SUCCESS); - evdev_process_events(device, ev, len / sizeof ev[0]); - - } while (len > 0); + if (rc != -EAGAIN && rc != -EINTR) { + libinput_remove_source(libinput, device->source); + device->source = NULL; + } } static int evdev_configure_device(struct evdev_device *device) { - struct input_absinfo absinfo; - unsigned long ev_bits[NBITS(EV_MAX)]; - unsigned long abs_bits[NBITS(ABS_MAX)]; - unsigned long rel_bits[NBITS(REL_MAX)]; - unsigned long key_bits[NBITS(KEY_MAX)]; + const struct input_absinfo *absinfo; int has_abs, has_rel, has_mt; int has_button, has_keyboard, has_touch; unsigned int i; @@ -509,84 +533,71 @@ evdev_configure_device(struct evdev_device *device) has_keyboard = 0; has_touch = 0; - ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); - if (TEST_BIT(ev_bits, EV_ABS)) { - ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), - abs_bits); + if (libevdev_has_event_type(device->evdev, EV_ABS)) { - if (TEST_BIT(abs_bits, ABS_X)) { - ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); - device->abs.min_x = absinfo.minimum; - device->abs.max_x = absinfo.maximum; + if ((absinfo = libevdev_get_abs_info(device->evdev, ABS_X))) { + device->abs.min_x = absinfo->minimum; + device->abs.max_x = absinfo->maximum; has_abs = 1; } - if (TEST_BIT(abs_bits, ABS_Y)) { - ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); - device->abs.min_y = absinfo.minimum; - device->abs.max_y = absinfo.maximum; + if ((absinfo = libevdev_get_abs_info(device->evdev, ABS_Y))) { + device->abs.min_y = absinfo->minimum; + device->abs.max_y = absinfo->maximum; has_abs = 1; } /* We only handle the slotted Protocol B in weston. Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT require mtdev for conversion. */ - if (TEST_BIT(abs_bits, ABS_MT_POSITION_X) && - TEST_BIT(abs_bits, ABS_MT_POSITION_Y)) { - ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X), - &absinfo); - device->abs.min_x = absinfo.minimum; - device->abs.max_x = absinfo.maximum; - ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_Y), - &absinfo); - device->abs.min_y = absinfo.minimum; - device->abs.max_y = absinfo.maximum; + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_MT_POSITION_X) && + libevdev_has_event_code(device->evdev, EV_ABS, ABS_MT_POSITION_Y)) { + absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_POSITION_X); + device->abs.min_x = absinfo->minimum; + device->abs.max_x = absinfo->maximum; + absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_POSITION_Y); + device->abs.min_y = absinfo->minimum; + device->abs.max_y = absinfo->maximum; device->is_mt = 1; has_touch = 1; has_mt = 1; - if (!TEST_BIT(abs_bits, ABS_MT_SLOT)) { + if (!libevdev_has_event_code(device->evdev, EV_ABS, ABS_MT_SLOT)) { device->mtdev = mtdev_new_open(device->fd); if (!device->mtdev) return -1; device->mt.slot = device->mtdev->caps.slot.value; } else { - ioctl(device->fd, EVIOCGABS(ABS_MT_SLOT), - &absinfo); - device->mt.slot = absinfo.value; + device->mt.slot = libevdev_get_current_slot(device->evdev); } } } - if (TEST_BIT(ev_bits, EV_REL)) { - ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), - rel_bits); - if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y)) + if (libevdev_has_event_code(device->evdev, EV_REL, REL_X) || + libevdev_has_event_code(device->evdev, EV_REL, REL_Y)) has_rel = 1; - } - if (TEST_BIT(ev_bits, EV_KEY)) { - ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), - key_bits); - if (TEST_BIT(key_bits, BTN_TOOL_FINGER) && - !TEST_BIT(key_bits, BTN_TOOL_PEN) && + + if (libevdev_has_event_type(device->evdev, EV_KEY)) { + if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_FINGER) && + !libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_PEN) && (has_abs || has_mt)) { device->dispatch = evdev_touchpad_create(device); } for (i = KEY_ESC; i < KEY_MAX; i++) { if (i >= BTN_MISC && i < KEY_OK) continue; - if (TEST_BIT(key_bits, i)) { + if (libevdev_has_event_code(device->evdev, EV_KEY, i)) { has_keyboard = 1; break; } } - if (TEST_BIT(key_bits, BTN_TOUCH)) + if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOUCH)) has_touch = 1; for (i = BTN_MISC; i < BTN_JOYSTICK; i++) { - if (TEST_BIT(key_bits, i)) { + if (libevdev_has_event_code(device->evdev, EV_KEY, i)) { has_button = 1; break; } } } - if (TEST_BIT(ev_bits, EV_LED)) + if (libevdev_has_event_type(device->evdev, EV_LED)) has_keyboard = 1; if ((has_abs || has_rel) && has_button) @@ -606,7 +617,7 @@ evdev_device_create(struct libinput_seat *seat, { struct libinput *libinput = seat->libinput; struct evdev_device *device; - char devname[256] = "unknown"; + int rc; int fd; int unhandled_device = 0; @@ -626,6 +637,12 @@ evdev_device_create(struct libinput_seat *seat, libinput_device_init(&device->base, seat); + rc = libevdev_new_from_fd(fd, &device->evdev); + if (rc != 0) + return NULL; + + libevdev_set_clock_id(device->evdev, CLOCK_MONOTONIC); + device->seat_caps = 0; device->is_mt = 0; device->mtdev = NULL; @@ -637,10 +654,7 @@ evdev_device_create(struct libinput_seat *seat, device->dispatch = NULL; device->fd = fd; device->pending_event = EVDEV_NONE; - - ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); - devname[sizeof(devname) - 1] = '\0'; - device->devname = strdup(devname); + device->devname = libevdev_get_name(device->evdev); libinput_seat_ref(seat); @@ -745,8 +759,7 @@ evdev_device_destroy(struct evdev_device *device) dispatch->interface->destroy(dispatch); libinput_seat_unref(device->base.seat); - - free(device->devname); + libevdev_free(device->evdev); free(device->devnode); free(device->sysname); free(device); diff --git a/src/evdev.h b/src/evdev.h index 3c9f93a5..a9e27bfd 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -27,6 +27,7 @@ #include "config.h" #include +#include #include "libinput-private.h" @@ -55,10 +56,11 @@ struct evdev_device { struct libinput_source *source; struct evdev_dispatch *dispatch; + struct libevdev *evdev; char *output_name; char *devnode; char *sysname; - char *devname; + const char *devname; int fd; struct { int min_x, max_x, min_y, max_y; @@ -86,16 +88,6 @@ struct evdev_device { int is_mt; }; -/* copied from udev/extras/input_id/input_id.c */ -/* we must use this kernel-compatible implementation */ -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<> OFF(bit)) & 1) -/* end copied */ - #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1) struct evdev_dispatch;