summaryrefslogtreecommitdiff
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2008-10-28 06:40:45 (GMT)
committer Peter Hutterer <peter.hutterer@redhat.com>2008-10-28 06:56:20 (GMT)
commit2acbd6e67c859290a37cf3134b120c5ca7577268 (patch) (side-by-side diff)
tree2a112e91e867bebd74776f1bfa20930826f2344f
parent934bc0012f948c52aadc8eda912f7728fb7394a2 (diff)
downloadxf86-input-synaptics-2acbd6e67c859290a37cf3134b120c5ca7577268.zip
xf86-input-synaptics-2acbd6e67c859290a37cf3134b120c5ca7577268.tar.gz
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>
Diffstat (more/less context) (ignore whitespace changes)
-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
@@ -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_ */