diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-05-29 07:17:41 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-10-04 16:19:19 +1000 |
commit | 164c62a97591d4c9b649460e7442977ea82ac02b (patch) | |
tree | 0c29a85f315718831a63f656600ff6dbfd73542c | |
parent | 43e270fb7a10da20ab89dd699839c1cb6df119b4 (diff) |
Use libevdev as backend
Removes the need to ioctl manually and check bits, with all the dangers that
come with that. libevdev is much better prepared for invalid values, OOB
checks, etc.
Plus, we get almost free SYN_DROPPED handling as well which we didn't have
before.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/apple.c | 3 | ||||
-rw-r--r-- | src/evdev.c | 465 | ||||
-rw-r--r-- | src/evdev.h | 12 |
5 files changed, 214 insertions, 271 deletions
diff --git a/configure.ac b/configure.ac index b8a9c41..2953d15 100644 --- a/configure.ac +++ b/configure.ac @@ -48,6 +48,7 @@ PKG_CHECK_MODULES(XORG, [xorg-server >= 1.10] xproto inputproto) PKG_CHECK_MODULES(UDEV, libudev) PKG_CHECK_MODULES(XI22, [inputproto >= 2.1.99.3] [xorg-server >= 1.11.99.901], HAVE_XI22="yes", HAVE_XI22="no") +PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4]) if test "x$HAVE_XI22" = xyes; then # Obtain compiler/linker options for mtdev diff --git a/src/Makefile.am b/src/Makefile.am index da76540..5e0c3b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,11 +26,11 @@ # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS) -AM_CPPFLAGS =-I$(top_srcdir)/include +AM_CPPFLAGS =-I$(top_srcdir)/include $(LIBEVDEV_CFLAGS) @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version -@DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS) $(UDEV_LIBS) +@DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS) $(UDEV_LIBS) $(LIBEVDEV_LIBS) @DRIVER_NAME@_drv_ladir = @inputdir@ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \ diff --git a/src/apple.c b/src/apple.c index 8e00a84..71f1dc3 100644 --- a/src/apple.c +++ b/src/apple.c @@ -303,7 +303,8 @@ EvdevAppleInitProperty(DeviceIntPtr dev) enum fkeymode fkeymode; if (!product_check(apple_keyboard_table, - pEvdev->id_vendor, pEvdev->id_product)) + libevdev_get_id_vendor(pEvdev->dev), + libevdev_get_id_product(pEvdev->dev))) return; fkeymode = get_fnmode(); diff --git a/src/evdev.c b/src/evdev.c index 209ea7e..dbc5eb4 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -178,23 +178,6 @@ static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode) return Success; } -static size_t EvdevCountBits(unsigned long *array, size_t nlongs) -{ - unsigned int i; - size_t count = 0; - - for (i = 0; i < nlongs; i++) { - unsigned long x = array[i]; - - while (x > 0) - { - count += (x & 0x1); - x >>= 1; - } - } - return count; -} - static inline int EvdevBitIsSet(const unsigned long *array, int bit) { return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS))); @@ -433,13 +416,16 @@ EvdevSwapAbsValuators(EvdevPtr pEvdev, ValuatorMask *mask) for(i = 0; i <= 1; i++) { if (valuator_mask_isset(mask, i)) { + const struct input_absinfo *abs1 = + libevdev_get_abs_info(pEvdev->dev, i); + const struct input_absinfo *abs2 = + libevdev_get_abs_info(pEvdev->dev, 1 - i); + swapped_isset[1 - i] = 1; swapped_values[1 - i] = xf86ScaleAxis(valuator_mask_get(mask, i), - pEvdev->absinfo[1 - i].maximum, - pEvdev->absinfo[1 - i].minimum, - pEvdev->absinfo[i].maximum, - pEvdev->absinfo[i].minimum); + abs2->maximum, abs2->minimum, + abs1->maximum, abs1->minimum); } } @@ -457,6 +443,7 @@ EvdevApplyCalibration(EvdevPtr pEvdev, ValuatorMask *mask) int i; for (i = 0; i <= 1; i++) { + const struct input_absinfo *abs; int val; int calib_min; int calib_max; @@ -465,6 +452,7 @@ EvdevApplyCalibration(EvdevPtr pEvdev, ValuatorMask *mask) continue; val = valuator_mask_get(mask, i); + abs = libevdev_get_abs_info(pEvdev->dev, i); if (i == 0) { calib_min = pEvdev->calibration.min_x; @@ -475,13 +463,11 @@ EvdevApplyCalibration(EvdevPtr pEvdev, ValuatorMask *mask) } if (pEvdev->flags & EVDEV_CALIBRATED) - val = xf86ScaleAxis(val, pEvdev->absinfo[i].maximum, - pEvdev->absinfo[i].minimum, calib_max, - calib_min); + val = xf86ScaleAxis(val, abs->maximum, abs->minimum, + calib_max, calib_min); if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y)) - val = (pEvdev->absinfo[i].maximum - val + - pEvdev->absinfo[i].minimum); + val = (abs->maximum - val + abs->minimum); valuator_mask_set(mask, i, val); } @@ -762,7 +748,12 @@ EvdevProcessTouch(InputInfoPtr pInfo) static int num_slots(EvdevPtr pEvdev) { - int value = pEvdev->absinfo[ABS_MT_SLOT].maximum + 1; + int value; + + if (pEvdev->mtdev) + value = pEvdev->mtdev->caps.slot.maximum + 1; + else + value = libevdev_get_num_slots(pEvdev->dev); /* If we don't know how many slots there are, assume at least 10 */ return value > 1 ? value : 10; @@ -782,7 +773,8 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevPtr pEvdev = pInfo->private; int map; - if (!pEvdev->mtdev && !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_SLOT)) + if (!pEvdev->mtdev && + !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT)) return; if (ev->code == ABS_MT_SLOT) { @@ -1088,7 +1080,7 @@ EvdevFreeMasks(EvdevPtr pEvdev) valuator_mask_free(&pEvdev->mt_mask); if (pEvdev->last_mt_vals) { - for (i = 0; i < num_slots(pEvdev); i++) + for (i = 0; i < libevdev_get_num_slots(pEvdev->dev); i++) valuator_mask_free(&pEvdev->last_mt_vals[i]); free(pEvdev->last_mt_vals); pEvdev->last_mt_vals = NULL; @@ -1098,68 +1090,60 @@ EvdevFreeMasks(EvdevPtr pEvdev) #endif } +#ifdef MULTITOUCH static void -EvdevProcessAllEvents(InputInfoPtr pInfo, struct input_event *ev, int nevents, size_t max_events) +EvdevHandleMTDevEvent(InputInfoPtr pInfo, struct input_event *ev) { EvdevPtr pEvdev = pInfo->private; - int i, more_events_left = 0; - do { -#ifdef MULTITOUCH - if (pEvdev->mtdev) { - int nmtevents = 0; - for (i = 0; i < nevents; i++) - mtdev_put_event(pEvdev->mtdev, &ev[i]); - - while (!mtdev_empty(pEvdev->mtdev) && nmtevents < max_events) - mtdev_get_event(pEvdev->mtdev, &ev[nmtevents++]); - - /* mtdev may have converted to more events than we have space for */ - more_events_left = nmtevents >= max_events && !mtdev_empty(pEvdev->mtdev); - nevents = nmtevents; + mtdev_put_event(pEvdev->mtdev, ev); + if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) { + while (!mtdev_empty(pEvdev->mtdev)) { + struct input_event e; + mtdev_get_event(pEvdev->mtdev, &e); + EvdevProcessEvent(pInfo, &e); } -#endif - - for (i = 0; i < nevents; i++) - EvdevProcessEvent(pInfo, &ev[i]); - - nevents = 0; - } while(more_events_left); + } } - -/* just a magic number to reduce the number of reads */ -#define NUM_EVENTS 16 +#endif static void EvdevReadInput(InputInfoPtr pInfo) { - struct input_event ev[NUM_EVENTS]; - int len = sizeof(ev); - - while (len == sizeof(ev)) - { - len = read(pInfo->fd, &ev, sizeof(ev)); + int rc = 0; + EvdevPtr pEvdev = pInfo->private; + struct input_event ev; - if (len <= 0) - { - if (errno == ENODEV) /* May happen after resume */ + do { + rc = libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); + if (rc < 0) { + if (rc == -ENODEV) /* May happen after resume */ xf86RemoveEnabledDevice(pInfo); - else if (errno != EAGAIN) + else if (rc != -EAGAIN) LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error: %s\n", pInfo->name, - strerror(errno)); + strerror(-rc)); break; + } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { +#ifdef MULTITOUCH + if (pEvdev->mtdev) + EvdevHandleMTDevEvent(pInfo, &ev); + else +#endif + EvdevProcessEvent(pInfo, &ev); } - - /* The kernel promises that we always only read a complete - * event, so len != sizeof ev is an error. */ - if (len % sizeof(ev[0])) { - LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno)); - break; + else { /* SYN_DROPPED */ + rc = libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_SYNC, &ev); + while (rc == LIBEVDEV_READ_STATUS_SYNC) { +#ifdef MULTITOUCH + if (pEvdev->mtdev) + EvdevHandleMTDevEvent(pInfo, &ev); + else +#endif + EvdevProcessEvent(pInfo, &ev); + rc = libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_SYNC, &ev); + } } - - EvdevProcessAllEvents(pInfo, ev, len/sizeof(ev[0]), NUM_EVENTS); - - } + } while (rc == LIBEVDEV_READ_STATUS_SUCCESS); } static void @@ -1266,7 +1250,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) { InputInfoPtr pInfo; EvdevPtr pEvdev; - int num_axes, axis, i = 0; + int num_axes = 0, axis, i = 0; int num_mt_axes = 0, /* number of MT-only axes */ num_mt_axes_total = 0; /* total number of MT axes, including double-counted ones, excluding blacklisted */ @@ -1276,17 +1260,20 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) pInfo = device->public.devicePrivate; pEvdev = pInfo->private; - if (!EvdevBitIsSet(pEvdev->bitmask, EV_ABS)) + if (!libevdev_has_event_type(pEvdev->dev, EV_ABS)) goto out; - num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX)); + for (i = 0; i < ABS_MAX; i++) + if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) + num_axes++; + if (num_axes < 1) goto out; #ifdef MULTITOUCH for (axis = ABS_MT_SLOT; axis < ABS_MAX; axis++) { - if (EvdevBitIsSet(pEvdev->abs_bitmask, axis)) + if (libevdev_has_event_code(pEvdev->dev, EV_ABS, axis)) { int j; Bool skip = FALSE; @@ -1294,7 +1281,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) for (j = 0; j < ArrayLength(mt_axis_mappings); j++) { if (mt_axis_mappings[j].mt_code == axis && - EvdevBitIsSet(pEvdev->abs_bitmask, mt_axis_mappings[j].code)) + libevdev_has_event_code(pEvdev->dev, EV_ABS, mt_axis_mappings[j].code)) { mt_axis_mappings[j].needs_mapping = TRUE; skip = TRUE; @@ -1322,13 +1309,13 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) #endif #ifdef HAVE_SMOOTH_SCROLLING - if (want_scroll_axes && EvdevBitIsSet(pEvdev->bitmask, EV_REL)) + if (want_scroll_axes && libevdev_has_event_type(pEvdev->dev, EV_REL)) { - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL)) num_axes++; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL)) num_axes++; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL)) num_axes++; } #endif @@ -1355,6 +1342,14 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) } #ifdef MULTITOUCH if (num_mt_axes_total > 0) { + int num_slots = 0; + + if (pEvdev->mtdev) { + num_slots = pEvdev->mtdev->caps.slot.maximum - + pEvdev->mtdev->caps.slot.minimum + 1; + } else + num_slots = libevdev_get_num_slots(pEvdev->dev); + pEvdev->num_mt_vals = num_mt_axes_total; pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total); if (!pEvdev->mt_mask) { @@ -1363,7 +1358,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) goto out; } - pEvdev->last_mt_vals = calloc(num_slots(pEvdev), sizeof(ValuatorMask *)); + pEvdev->last_mt_vals = calloc(num_slots, sizeof(ValuatorMask *)); if (!pEvdev->last_mt_vals) { xf86IDrvMsg(pInfo, X_ERROR, "%s: failed to allocate MT last values mask array.\n", @@ -1371,7 +1366,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) goto out; } - for (i = 0; i < num_slots(pEvdev); i++) { + for (i = 0; i < num_slots; i++) { pEvdev->last_mt_vals[i] = valuator_mask_new(num_mt_axes_total); if (!pEvdev->last_mt_vals[i]) { xf86IDrvMsg(pInfo, X_ERROR, @@ -1400,7 +1395,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) int j; #endif pEvdev->abs_axis_map[axis] = -1; - if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) || + if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, axis) || is_blacklisted_axis(axis)) continue; @@ -1426,11 +1421,11 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) { mapping++; /* continue from abs axis mapping */ - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL)) pEvdev->rel_axis_map[REL_HWHEEL] = mapping++; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL)) pEvdev->rel_axis_map[REL_DIAL] = mapping++; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL)) pEvdev->rel_axis_map[REL_WHEEL] = mapping++; } #endif @@ -1464,10 +1459,10 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) goto out; } - for (i = 0; i < num_slots(pEvdev); i++) { + for (i = 0; i < num_touches; i++) { for (axis = ABS_MT_TOUCH_MAJOR; axis < ABS_MAX; axis++) { if (pEvdev->abs_axis_map[axis] >= 0) { - int val = pEvdev->mtdev ? 0 : pEvdev->absinfo[axis].value; + int val = pEvdev->mtdev ? 0 : libevdev_get_current_slot(pEvdev->dev); /* XXX: read initial values from mtdev when it adds support * for doing so. */ valuator_mask_set(pEvdev->last_mt_vals[i], @@ -1479,28 +1474,30 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) #endif for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) { + const struct input_absinfo *abs; int axnum = pEvdev->abs_axis_map[axis]; int resolution = 0; if (axnum == -1) continue; + abs = libevdev_get_abs_info(pEvdev->dev, axis); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30) /* Kernel provides units/mm, X wants units/m */ - if (pEvdev->absinfo[axis].resolution) - resolution = pEvdev->absinfo[axis].resolution * 1000; + resolution = abs->resolution * 1000; #endif xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], - pEvdev->absinfo[axis].minimum, - pEvdev->absinfo[axis].maximum, + abs->minimum, + abs->maximum, resolution, 0, resolution, Absolute); xf86InitValuatorDefaults(device, axnum); } #ifdef MULTITOUCH for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) { + const struct input_absinfo *abs; int axnum = pEvdev->abs_axis_map[axis]; int resolution = 0; int j; @@ -1509,6 +1506,8 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) if (axnum < 0) continue; + abs = libevdev_get_abs_info(pEvdev->dev, axis); + for (j = 0; j < ArrayLength(mt_axis_mappings); j++) if (mt_axis_mappings[j].mt_code == axis && mt_axis_mappings[j].needs_mapping) @@ -1521,13 +1520,12 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) if (skip) continue; - if (pEvdev->absinfo[axis].resolution) - resolution = pEvdev->absinfo[axis].resolution * 1000; + resolution = abs->resolution * 1000; xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], - pEvdev->absinfo[axis].minimum, - pEvdev->absinfo[axis].maximum, + abs->minimum, + abs->maximum, resolution, 0, resolution, Absolute); } @@ -1537,7 +1535,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) if (want_scroll_axes) { int idx; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL)) { idx = REL_WHEEL; xf86InitValuatorAxisStruct(device, @@ -1550,7 +1548,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) SCROLL_FLAG_PREFERRED); } - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL)) { idx = REL_HWHEEL; xf86InitValuatorAxisStruct(device, @@ -1563,7 +1561,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) SCROLL_FLAG_NONE); } - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL)) { idx = REL_DIAL; xf86InitValuatorAxisStruct(device, @@ -1585,7 +1583,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) if (!pEvdev->use_proximity) break; - if (EvdevBitIsSet(pEvdev->key_bitmask, proximity_bits[i])) + if (libevdev_has_event_code(pEvdev->dev, EV_KEY, proximity_bits[i])) { InitProximityClassDeviceStruct(device); pEvdev->prox = valuator_mask_new(num_axes); @@ -1634,27 +1632,29 @@ EvdevAddRelValuatorClass(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; - int num_axes, axis, i = 0; + int num_axes = 0, axis, map, i = 0; Atom *atoms; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; - if (!EvdevBitIsSet(pEvdev->bitmask, EV_REL)) + if (!libevdev_has_event_type(pEvdev->dev, EV_REL)) goto out; - num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX)); + for (i = 0; i < REL_MAX; i++) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, i)) + num_axes++; if (num_axes < 1) goto out; #ifndef HAVE_SMOOTH_SCROLLING /* Wheels are special, we post them as button events. So let's ignore them * in the axes list too */ - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL)) num_axes--; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL)) num_axes--; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL)) num_axes--; if (num_axes <= 0) @@ -1674,7 +1674,7 @@ EvdevAddRelValuatorClass(DeviceIntPtr device) } atoms = malloc(pEvdev->num_vals * sizeof(Atom)); - for (axis = REL_X; i < MAX_VALUATORS && axis <= REL_MAX; axis++) + for (axis = REL_X, map = 0; map < MAX_VALUATORS && axis <= REL_MAX; axis++) { pEvdev->rel_axis_map[axis] = -1; #ifndef HAVE_SMOOTH_SCROLLING @@ -1682,10 +1682,10 @@ EvdevAddRelValuatorClass(DeviceIntPtr device) if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL) continue; #endif - if (!EvdevBitIsSet(pEvdev->rel_bitmask, axis)) + if (!libevdev_has_event_code(pEvdev->dev, EV_REL, axis)) continue; - pEvdev->rel_axis_map[axis] = i; - i++; + pEvdev->rel_axis_map[axis] = map; + map++; } EvdevInitAxesLabels(pEvdev, Relative, pEvdev->num_vals, atoms); @@ -2011,83 +2011,21 @@ static int EvdevCache(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; - int i, len; - struct input_id id; - - unsigned long bitmask[NLONGS(EV_CNT)] = {0}; - unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0}; - unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0}; - unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0}; - - - if (ioctl(pInfo->fd, EVIOCGID, &id) < 0) - { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGID failed: %s\n", strerror(errno)); - goto error; - } - - pEvdev->id_vendor = id.vendor; - pEvdev->id_product = id.product; - - len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT for bitmask failed: %s\n", - strerror(errno)); - goto error; - } - - memcpy(pEvdev->bitmask, bitmask, len); - - len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT for EV_REL failed: %s\n", - strerror(errno)); - goto error; - } - - memcpy(pEvdev->rel_bitmask, rel_bitmask, len); - - len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT for EV_ABS failed: %s\n", - strerror(errno)); - goto error; - } - - memcpy(pEvdev->abs_bitmask, abs_bitmask, len); + int i; /* * Do not try to validate absinfo data since it is not expected * to be static, always refresh it in evdev structure. */ for (i = ABS_X; i <= ABS_MAX; i++) { - if (EvdevBitIsSet(abs_bitmask, i)) { - len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdev->absinfo[i]); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGABSi(%d) failed: %s\n", - i, strerror(errno)); - goto error; - } + if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) { + const struct input_absinfo *abs = libevdev_get_abs_info(pEvdev->dev, i); xf86IDrvMsgVerb(pInfo, X_PROBED, 6, "absolute axis %#x [%d..%d]\n", - i, pEvdev->absinfo[i].maximum, pEvdev->absinfo[i].minimum); + i, abs->minimum, abs->maximum); } } - len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT for EV_KEY failed: %s\n", - strerror(errno)); - goto error; - } - - /* Copy the data so we have reasonably up-to-date info */ - memcpy(pEvdev->key_bitmask, key_bitmask, len); - return Success; - -error: - return !Success; - } /** @@ -2103,13 +2041,14 @@ EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab) if (pEvdev->grabDevice) { - if (grab && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) { + int rc; + if (grab && (rc = libevdev_grab(pEvdev->dev, LIBEVDEV_GRAB)) < 0) { xf86IDrvMsg(pInfo, X_WARNING, "Grab failed (%s)\n", - strerror(errno)); + strerror(-rc)); return FALSE; - } else if (ungrab && ioctl(pInfo->fd, EVIOCGRAB, (void *)0)) + } else if (ungrab && (rc = libevdev_grab(pEvdev->dev, LIBEVDEV_UNGRAB)) < 0) xf86IDrvMsg(pInfo, X_WARNING, "Release failed (%s)\n", - strerror(errno)); + strerror(-rc)); } return TRUE; @@ -2130,20 +2069,21 @@ EvdevForceXY(InputInfoPtr pInfo, int mode) if (mode == Relative) { - EvdevSetBit(pEvdev->rel_bitmask, REL_X); - EvdevSetBit(pEvdev->rel_bitmask, REL_Y); + libevdev_enable_event_code(pEvdev->dev, EV_REL, REL_X, NULL); + libevdev_enable_event_code(pEvdev->dev, EV_REL, REL_Y, NULL); } else if (mode == Absolute) { - EvdevSetBit(pEvdev->abs_bitmask, ABS_X); - EvdevSetBit(pEvdev->abs_bitmask, ABS_Y); - pEvdev->absinfo[ABS_X].minimum = 0; - pEvdev->absinfo[ABS_X].maximum = 1000; - pEvdev->absinfo[ABS_X].value = 0; - pEvdev->absinfo[ABS_X].resolution = 0; - pEvdev->absinfo[ABS_Y].minimum = 0; - pEvdev->absinfo[ABS_Y].maximum = 1000; - pEvdev->absinfo[ABS_Y].value = 0; - pEvdev->absinfo[ABS_Y].resolution = 0; + struct input_absinfo abs; + + abs.minimum = 0; + abs.maximum = 1000; + abs.value = 0; + abs.fuzz = 0; + abs.flat = 0; + abs.resolution = 0; + + libevdev_enable_event_code(pEvdev->dev, EV_ABS, ABS_X, &abs); + libevdev_enable_event_code(pEvdev->dev, EV_ABS, ABS_Y, &abs); } } @@ -2158,7 +2098,8 @@ EvdevProbe(InputInfoPtr pInfo) int rc = 1; xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n", - pEvdev->id_vendor, pEvdev->id_product); + libevdev_get_id_vendor(pEvdev->dev), + libevdev_get_id_product(pEvdev->dev)); /* Trinary state for ignoring axes: - unset: do the normal thing. @@ -2193,7 +2134,7 @@ EvdevProbe(InputInfoPtr pInfo) for (i = BTN_MISC; i < BTN_JOYSTICK; i++) { int mapping = 0; - if (EvdevBitIsSet(pEvdev->key_bitmask, i)) + if (libevdev_has_event_code(pEvdev->dev, EV_KEY, i)) { mapping = EvdevUtilButtonEventToButtonNumber(pEvdev, i); if (mapping > num_buttons) @@ -2201,9 +2142,9 @@ EvdevProbe(InputInfoPtr pInfo) } } - has_lmr = EvdevBitIsSet(pEvdev->key_bitmask, BTN_LEFT) || - EvdevBitIsSet(pEvdev->key_bitmask, BTN_MIDDLE) || - EvdevBitIsSet(pEvdev->key_bitmask, BTN_RIGHT); + has_lmr = libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_LEFT) || + libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_MIDDLE) || + libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_RIGHT); if (num_buttons) { @@ -2213,16 +2154,16 @@ EvdevProbe(InputInfoPtr pInfo) } for (i = 0; i < REL_MAX; i++) { - if (EvdevBitIsSet(pEvdev->rel_bitmask, i)) { + if (libevdev_has_event_code(pEvdev->dev, EV_REL, i)) { has_rel_axes = TRUE; break; } } if (has_rel_axes) { - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL) || - EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL) || - EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) { + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL) || + libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL) || + libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL)) { xf86IDrvMsg(pInfo, X_PROBED, "Found scroll wheel(s)\n"); has_scroll = TRUE; if (!num_buttons) @@ -2237,11 +2178,11 @@ EvdevProbe(InputInfoPtr pInfo) xf86IDrvMsg(pInfo, X_PROBED, "Found relative axes\n"); pEvdev->flags |= EVDEV_RELATIVE_EVENTS; - if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) && - EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) { + if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_X) && + libevdev_has_event_code(pEvdev->dev, EV_REL, REL_Y)) { xf86IDrvMsg(pInfo, X_PROBED, "Found x and y relative axes\n"); - } else if (!EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) || - !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y)) + } else if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_X) || + !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_Y)) EvdevForceXY(pInfo, Relative); } else { xf86IDrvMsg(pInfo, X_INFO, "Relative axes present but ignored.\n"); @@ -2250,7 +2191,7 @@ EvdevProbe(InputInfoPtr pInfo) } for (i = 0; i < ABS_MAX; i++) { - if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) { + if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) { has_abs_axes = TRUE; break; } @@ -2258,7 +2199,7 @@ EvdevProbe(InputInfoPtr pInfo) #ifdef MULTITOUCH for (i = ABS_MT_SLOT; i < ABS_MAX; i++) { - if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) { + if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) { has_mt = TRUE; break; } @@ -2276,7 +2217,7 @@ EvdevProbe(InputInfoPtr pInfo) if (has_mt) { xf86IDrvMsg(pInfo, X_PROBED, "Found absolute multitouch axes\n"); if (num_buttons == 0) { - if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_JOYSTICK)) { + if (libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_JOYSTICK)) { xf86IDrvMsg(pInfo, X_INFO, "Device is a Joystick with MT without buttons. Ignoring it.\n"); goto out; } else { @@ -2288,12 +2229,12 @@ EvdevProbe(InputInfoPtr pInfo) } } - if ((EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) && - EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))) { + if ((libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_X) && + libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_Y))) { xf86IDrvMsg(pInfo, X_PROBED, "Found x and y absolute axes\n"); - if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOOL_PEN) || - EvdevBitIsSet(pEvdev->key_bitmask, BTN_STYLUS) || - EvdevBitIsSet(pEvdev->key_bitmask, BTN_STYLUS2)) + if (libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOOL_PEN) || + libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_STYLUS) || + libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_STYLUS2)) { xf86IDrvMsg(pInfo, X_PROBED, "Found absolute tablet.\n"); pEvdev->flags |= EVDEV_TABLET; @@ -2302,9 +2243,9 @@ EvdevProbe(InputInfoPtr pInfo) pEvdev->num_buttons = 7; /* LMR + scroll wheels */ pEvdev->flags |= EVDEV_BUTTON_EVENTS; } - } else if (EvdevBitIsSet(pEvdev->abs_bitmask, ABS_PRESSURE) || - EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOUCH)) { - if (has_lmr || EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOOL_FINGER)) { + } else if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_PRESSURE) || + libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOUCH)) { + if (has_lmr || libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOOL_FINGER)) { xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchpad.\n"); pEvdev->flags |= EVDEV_TOUCHPAD; } else { @@ -2312,8 +2253,8 @@ EvdevProbe(InputInfoPtr pInfo) pEvdev->flags |= EVDEV_TOUCHSCREEN; pEvdev->flags |= EVDEV_BUTTON_EVENTS; } - } else if (!(EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) && - EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) && has_lmr) { + } else if (!(libevdev_has_event_code(pEvdev->dev, EV_REL, REL_X) && + libevdev_has_event_code(pEvdev->dev, EV_REL, REL_Y)) && has_lmr) { /* some touchscreens use BTN_LEFT rather than BTN_TOUCH */ xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n"); pEvdev->flags |= EVDEV_TOUCHSCREEN; @@ -2321,8 +2262,8 @@ EvdevProbe(InputInfoPtr pInfo) } } else { #ifdef MULTITOUCH - if (!EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_POSITION_X) || - !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_POSITION_Y)) + if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_X) || + !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_Y)) #endif EvdevForceXY(pInfo, Absolute); } @@ -2332,7 +2273,7 @@ EvdevProbe(InputInfoPtr pInfo) } for (i = 0; i < BTN_MISC; i++) { - if (EvdevBitIsSet(pEvdev->key_bitmask, i)) { + if (libevdev_has_event_code(pEvdev->dev, EV_KEY, i)) { xf86IDrvMsg(pInfo, X_PROBED, "Found keys\n"); pEvdev->flags |= EVDEV_KEYBOARD_EVENTS; has_keys = TRUE; @@ -2377,8 +2318,8 @@ EvdevProbe(InputInfoPtr pInfo) xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchscreen\n"); pInfo->type_name = XI_TOUCHSCREEN; } else { - if (!EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) || - !EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) + if (!libevdev_has_event_code(pEvdev->dev, EV_REL, REL_X) || + !libevdev_has_event_code(pEvdev->dev, EV_REL, REL_Y)) EvdevForceXY(pInfo, Relative); xf86IDrvMsg(pInfo, X_INFO, "Configuring as mouse\n"); pInfo->type_name = XI_MOUSE; @@ -2440,18 +2381,12 @@ static Bool EvdevOpenMTDev(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; - unsigned long bitmask[NLONGS(EV_CNT)] = {0}; - unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0}; - int len; if (pEvdev->mtdev) { pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value; return TRUE; - } else if (EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_SLOT)) { - struct input_absinfo abs; - len = ioctl(pInfo->fd, EVIOCGABS(ABS_MT_SLOT), &abs); - if (len != -1) - pEvdev->cur_slot = abs.value; + } else if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT)) { + pEvdev->cur_slot = libevdev_get_current_slot(pEvdev->dev); return TRUE; } @@ -2460,30 +2395,15 @@ EvdevOpenMTDev(InputInfoPtr pInfo) return FALSE; } - /* Use ioctl here, this may be called before EvdevCache */ - len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT for bitmask in %s failed: %s\n", - __func__, strerror(errno)); - return FALSE; - } - - if (!EvdevBitIsSet(bitmask, EV_ABS)) + if (!libevdev_has_event_type(pEvdev->dev, EV_ABS)) return TRUE; - len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask); - if (len < 0) { - xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT for EV_ABS in %s failed: %s\n", - __func__, strerror(errno)); - return FALSE; - } - /* don't need mtdev for protocol B devices */ - if (EvdevBitIsSet(abs_bitmask, ABS_MT_SLOT)) + if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT)) return TRUE; - if (!EvdevBitIsSet(abs_bitmask, ABS_MT_POSITION_X) || - !EvdevBitIsSet(abs_bitmask, ABS_MT_POSITION_Y)) + if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_X) || + !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_Y)) return TRUE; xf86IDrvMsg(pInfo, X_INFO, "Using mtdev for this device\n"); @@ -2528,6 +2448,23 @@ EvdevOpenDevice(InputInfoPtr pInfo) xf86IDrvMsg(pInfo, X_ERROR, "Unable to open evdev device \"%s\".\n", device); return BadValue; } + + if (libevdev_get_fd(pEvdev->dev) != -1) { + struct input_event ev; + + libevdev_change_fd(pEvdev->dev, pInfo->fd); + /* re-sync libevdev's view of the device, but + we don't care about the actual events here */ + libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev); + while (libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_SYNC, &ev) == LIBEVDEV_READ_STATUS_SYNC) + ; + } else { + int rc = libevdev_set_fd(pEvdev->dev, pInfo->fd); + if (rc < 0) { + xf86IDrvMsg(pInfo, X_ERROR, "Unable to query fd: %s\n", strerror(-rc)); + return BadValue; + } + } } /* Check major/minor of device node to avoid adding duplicate devices. */ @@ -2583,18 +2520,27 @@ EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) free(pEvdev->type_name); pEvdev->type_name = NULL; + + libevdev_free(pEvdev->dev); } xf86DeleteInput(pInfo, flags); } static EvdevPtr -EvdevAlloc(void) +EvdevAlloc(InputInfoPtr pInfo) { int i; EvdevPtr pEvdev = calloc(sizeof(EvdevRec), 1); if (!pEvdev) return NULL; + + pEvdev->dev = libevdev_new(); + if (!pEvdev->dev) { + free(pEvdev); + return NULL; + } + /* * We initialize pEvdev->in_proximity to 1 so that device that doesn't use * proximity will still report events. @@ -2625,7 +2571,7 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) EvdevPtr pEvdev; int rc = BadAlloc; - if (!(pEvdev = EvdevAlloc())) + if (!(pEvdev = EvdevAlloc(pInfo))) goto error; pInfo->private = pEvdev; @@ -2646,6 +2592,7 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) /* If grabDevice is set, ungrab immediately since we only want to grab * between DEVICE_ON and DEVICE_OFF. If we never get DEVICE_ON, don't * hold a grab. */ + if (!EvdevGrabDevice(pInfo, 1, 1)) { xf86IDrvMsg(pInfo, X_WARNING, "Device may already be configured.\n"); @@ -2809,7 +2756,7 @@ static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms) for (button = BTN_MISC; button < BTN_JOYSTICK; button++) { - if (EvdevBitIsSet(pEvdev->key_bitmask, button)) + if (libevdev_has_event_code(pEvdev->dev, EV_KEY, button)) { int group = (button % 0x100)/16; int idx = button - ((button/16) * 16); @@ -2849,8 +2796,8 @@ EvdevInitProperty(DeviceIntPtr dev) CARD32 product[2]; prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID, strlen(XI_PROP_PRODUCT_ID), TRUE); - product[0] = pEvdev->id_vendor; - product[1] = pEvdev->id_product; + product[0] = libevdev_get_id_vendor(pEvdev->dev); + product[1] = libevdev_get_id_product(pEvdev->dev); rc = XIChangeDeviceProperty(dev, prop_product_id, XA_INTEGER, 32, PropModeReplace, 2, product, FALSE); if (rc != Success) diff --git a/src/evdev.h b/src/evdev.h index 4742b43..563d108 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -47,6 +47,8 @@ #include <mtdev.h> #endif +#include <libevdev/libevdev.h> + #ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */ #define EV_CNT (EV_MAX+1) #endif @@ -150,8 +152,7 @@ typedef struct { } EventQueueRec, *EventQueuePtr; typedef struct { - unsigned short id_vendor; - unsigned short id_product; + struct libevdev *dev; char *device; int grabDevice; /* grab the event device? */ @@ -234,13 +235,6 @@ typedef struct { int reopen_left; /* number of attempts left to re-open the device */ OsTimerPtr reopen_timer; - /* Cached info from device. */ - unsigned long bitmask[NLONGS(EV_CNT)]; - unsigned long key_bitmask[NLONGS(KEY_CNT)]; - unsigned long rel_bitmask[NLONGS(REL_CNT)]; - unsigned long abs_bitmask[NLONGS(ABS_CNT)]; - struct input_absinfo absinfo[ABS_CNT]; - /* minor/major number */ dev_t min_maj; |