diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-10-28 17:10:45 +1030 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@redhat.com> | 2008-10-28 17:26:20 +1030 |
commit | 2acbd6e67c859290a37cf3134b120c5ca7577268 (patch) | |
tree | 2a112e91e867bebd74776f1bfa20930826f2344f | |
parent | 934bc0012f948c52aadc8eda912f7728fb7394a2 (diff) |
Add support for touchpads (such as Elantech) that do not report pressure
Change the driver to react to BTN_TOUCH if device does not report
ABS_PRESSURE since there are touchpads (such as Elantech) that do not
support pressure reading but otherwise are perfectly useable in absolute
mode.
Also fix error checking of ioctl calls (positive return value is not an
error, only negative is).
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
-rw-r--r-- | src/eventcomm.c | 77 | ||||
-rw-r--r-- | src/synapticsstr.h | 1 |
2 files changed, 53 insertions, 25 deletions
diff --git a/src/eventcomm.c b/src/eventcomm.c index b2d0891..620f2f3 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -77,7 +77,9 @@ static Bool event_query_is_touchpad(int fd) { int ret; - unsigned long evbits[NBITS(KEY_MAX)]; + unsigned long evbits[NBITS(EV_MAX)]; + unsigned long absbits[NBITS(ABS_MAX)]; + unsigned long keybits[NBITS(KEY_MAX)]; /* Check for ABS_X, ABS_Y, ABS_PRESSURE and BTN_TOOL_FINGER */ @@ -89,20 +91,24 @@ event_query_is_touchpad(int fd) !TEST_BIT(EV_KEY, evbits)) return FALSE; - SYSCALL(ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evbits)), evbits)); + SYSCALL(ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits)); if (ret < 0) return FALSE; - if (!TEST_BIT(ABS_X, evbits) || - !TEST_BIT(ABS_Y, evbits) || - !TEST_BIT(ABS_PRESSURE, evbits)) + if (!TEST_BIT(ABS_X, absbits) || + !TEST_BIT(ABS_Y, absbits)) return FALSE; - SYSCALL(ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evbits)), evbits)); + SYSCALL(ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits)); if (ret < 0) return FALSE; - if (!TEST_BIT(BTN_TOOL_FINGER, evbits)) + + /* we expect touchpad either report raw pressure or touches */ + if (!TEST_BIT(ABS_PRESSURE, absbits) && !TEST_BIT(BTN_TOUCH, keybits)) + return FALSE; + /* all Synaptics-like touchpad report BTN_TOOL_FINGER */ + if (!TEST_BIT(BTN_TOOL_FINGER, keybits)) return FALSE; - if (TEST_BIT(BTN_TOOL_PEN, evbits)) + if (TEST_BIT(BTN_TOOL_PEN, keybits)) return FALSE; /* Don't match wacom tablets */ return TRUE; @@ -114,12 +120,13 @@ event_query_axis_ranges(LocalDevicePtr local) { SynapticsPrivate *priv = (SynapticsPrivate *)local->private; struct input_absinfo abs; - unsigned long evbits[NBITS(KEY_MAX)]; + unsigned long absbits[NBITS(ABS_MAX)]; + unsigned long keybits[NBITS(KEY_MAX)]; char buf[256]; int rc; SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_X), &abs)); - if (rc == 0) + if (rc >= 0) { xf86Msg(X_INFO, "%s: x-axis range %d - %d\n", local->name, abs.minimum, abs.maximum); @@ -130,7 +137,7 @@ event_query_axis_ranges(LocalDevicePtr local) strerror(errno)); SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_Y), &abs)); - if (rc == 0) + if (rc >= 0) { xf86Msg(X_INFO, "%s: y-axis range %d - %d\n", local->name, abs.minimum, abs.maximum); @@ -140,17 +147,31 @@ event_query_axis_ranges(LocalDevicePtr local) xf86Msg(X_ERROR, "%s: failed to query axis range (%s)\n", local->name, strerror(errno)); - SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_PRESSURE), &abs)); - if (rc == 0) + priv->has_pressure = FALSE; + SYSCALL(rc = ioctl(local->fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits)); + if (rc >= 0) + priv->has_pressure = TEST_BIT(ABS_PRESSURE, absbits); + else + xf86Msg(X_ERROR, "%s: failed to query ABS bits (%s)\n", local->name, + strerror(errno)); + + if (priv->has_pressure) { - xf86Msg(X_INFO, "%s: pressure range %d - %d\n", local->name, - abs.minimum, abs.maximum); - priv->minp = abs.minimum; - priv->maxp = abs.maximum; - } + SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_PRESSURE), &abs)); + if (rc >= 0) + { + xf86Msg(X_INFO, "%s: pressure range %d - %d\n", local->name, + abs.minimum, abs.maximum); + priv->minp = abs.minimum; + priv->maxp = abs.maximum; + } + } else + xf86Msg(X_INFO, + "%s: device does not report pressure, will use touch data.\n", + local->name); SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_TOOL_WIDTH), &abs)); - if (rc == 0) + if (rc >= 0) { xf86Msg(X_INFO, "%s: finger width range %d - %d\n", local->name, abs.minimum, abs.maximum); @@ -158,19 +179,19 @@ event_query_axis_ranges(LocalDevicePtr local) priv->maxw = abs.maximum; } - SYSCALL(rc = ioctl(local->fd, EVIOCGBIT(EV_KEY, sizeof(evbits)), evbits)); + SYSCALL(rc = ioctl(local->fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits)); if (rc >= 0) { buf[0] = 0; - if ((priv->has_left = TEST_BIT(BTN_LEFT, evbits))) + if ((priv->has_left = TEST_BIT(BTN_LEFT, keybits))) strcat(buf, " left"); - if ((priv->has_right = TEST_BIT(BTN_RIGHT, evbits))) + if ((priv->has_right = TEST_BIT(BTN_RIGHT, keybits))) strcat(buf, " right"); - if ((priv->has_middle = TEST_BIT(BTN_MIDDLE, evbits))) + if ((priv->has_middle = TEST_BIT(BTN_MIDDLE, keybits))) strcat(buf, " middle"); - if ((priv->has_double = TEST_BIT(BTN_TOOL_DOUBLETAP, evbits))) + if ((priv->has_double = TEST_BIT(BTN_TOOL_DOUBLETAP, keybits))) strcat(buf, " double"); - if ((priv->has_triple = TEST_BIT(BTN_TOOL_TRIPLETAP, evbits))) + if ((priv->has_triple = TEST_BIT(BTN_TOOL_TRIPLETAP, keybits))) strcat(buf, " triple"); xf86Msg(X_INFO, "%s: buttons:%s\n", local->name, buf); } @@ -229,6 +250,8 @@ EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw, struct input_event ev; Bool v; struct SynapticsHwState *hw = &(comm->hwState); + SynapticsPrivate *priv = (SynapticsPrivate *)local->private; + SynapticsSHM *para = priv->synpara; while (SynapticsReadEvent(comm, &ev)) { switch (ev.type) { @@ -304,6 +327,10 @@ EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw, case BTN_B: hw->guest_right = v; break; + case BTN_TOUCH: + if (!priv->has_pressure) + hw->z = v ? para->finger_high + 1 : 0; + break; } break; case EV_ABS: diff --git a/src/synapticsstr.h b/src/synapticsstr.h index cc0a29f..688167c 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -145,6 +145,7 @@ typedef struct _SynapticsPrivateRec Bool has_middle; /* middle button detected for this device */ Bool has_double; /* double click detected for this device */ Bool has_triple; /* triple click detected for this device */ + Bool has_pressure; /* device reports pressure */ } SynapticsPrivate; #endif /* _SYNAPTICSSTR_H_ */ |