summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2008-10-28 17:10:45 +1030
committerPeter Hutterer <peter.hutterer@redhat.com>2008-10-28 17:26:20 +1030
commit2acbd6e67c859290a37cf3134b120c5ca7577268 (patch)
tree2a112e91e867bebd74776f1bfa20930826f2344f
parent934bc0012f948c52aadc8eda912f7728fb7394a2 (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.c77
-rw-r--r--src/synapticsstr.h1
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
@@ -79,3 +79,5 @@ 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)];
@@ -91,16 +93,20 @@ event_query_is_touchpad(int fd)
- 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 */
@@ -116,3 +122,4 @@ event_query_axis_ranges(LocalDevicePtr local)
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];
@@ -121,3 +128,3 @@ event_query_axis_ranges(LocalDevicePtr local)
SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_X), &abs));
- if (rc == 0)
+ if (rc >= 0)
{
@@ -132,3 +139,3 @@ event_query_axis_ranges(LocalDevicePtr local)
SYSCALL(rc = ioctl(local->fd, EVIOCGABS(ABS_Y), &abs));
- if (rc == 0)
+ if (rc >= 0)
{
@@ -142,13 +149,27 @@ event_query_axis_ranges(LocalDevicePtr local)
- 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)
{
@@ -160,3 +181,3 @@ event_query_axis_ranges(LocalDevicePtr local)
- 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)
@@ -164,11 +185,11 @@ event_query_axis_ranges(LocalDevicePtr local)
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");
@@ -231,2 +252,4 @@ EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
struct SynapticsHwState *hw = &(comm->hwState);
+ SynapticsPrivate *priv = (SynapticsPrivate *)local->private;
+ SynapticsSHM *para = priv->synpara;
@@ -306,2 +329,6 @@ EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
break;
+ case BTN_TOUCH:
+ if (!priv->has_pressure)
+ hw->z = v ? para->finger_high + 1 : 0;
+ break;
}
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index cc0a29f..688167c 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -147,2 +147,3 @@ typedef struct _SynapticsPrivateRec
Bool has_triple; /* triple click detected for this device */
+ Bool has_pressure; /* device reports pressure */
} SynapticsPrivate;