diff options
Diffstat (limited to 'src/evdev.c')
-rw-r--r-- | src/evdev.c | 471 |
1 files changed, 208 insertions, 263 deletions
diff --git a/src/evdev.c b/src/evdev.c index bafe81f..d14d08f 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,8 +748,12 @@ EvdevProcessTouch(InputInfoPtr pInfo) static int num_slots(EvdevPtr pEvdev) { - int value = pEvdev->absinfo[ABS_MT_SLOT].maximum - - pEvdev->absinfo[ABS_MT_SLOT].minimum + 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; @@ -772,7 +762,7 @@ num_slots(EvdevPtr pEvdev) static int last_mt_vals_slot(EvdevPtr pEvdev) { - int value = pEvdev->cur_slot - pEvdev->absinfo[ABS_MT_SLOT].minimum; + int value = pEvdev->cur_slot; return value < num_slots(pEvdev) ? value : -1; } @@ -783,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) { @@ -1089,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; @@ -1099,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 @@ -1267,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 */ @@ -1277,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; @@ -1295,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; @@ -1323,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 @@ -1356,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) { @@ -1364,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", @@ -1372,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, @@ -1401,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; @@ -1427,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 @@ -1456,8 +1450,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes) num_touches = pEvdev->mtdev->caps.slot.maximum - pEvdev->mtdev->caps.slot.minimum + 1; } else - num_touches = pEvdev->absinfo[ABS_MT_SLOT].maximum - - pEvdev->absinfo[ABS_MT_SLOT].minimum + 1; + num_touches = num_slots(pEvdev); if (!InitTouchClassDeviceStruct(device, num_touches, mode, num_mt_axes_total)) { @@ -1466,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], @@ -1481,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; @@ -1511,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) @@ -1523,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); } @@ -1539,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, @@ -1552,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, @@ -1565,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, @@ -1587,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); @@ -1636,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) @@ -1676,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 @@ -1684,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); @@ -2013,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; - } /** @@ -2105,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; @@ -2132,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); } } @@ -2160,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. @@ -2195,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) @@ -2203,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) { @@ -2215,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) @@ -2239,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"); @@ -2252,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; } @@ -2260,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; } @@ -2278,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 { @@ -2290,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; @@ -2304,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 { @@ -2314,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; @@ -2323,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); } @@ -2334,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; @@ -2379,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; @@ -2442,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; } @@ -2462,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"); @@ -2530,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. */ @@ -2585,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. @@ -2627,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; @@ -2648,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"); @@ -2811,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); @@ -2851,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) |