mirror of
https://github.com/X11Libre/xf86-input-synaptics.git
synced 2026-04-14 11:54:16 +00:00
283 lines
9.7 KiB
Diff
283 lines
9.7 KiB
Diff
|
|
Vojtech Pavlik <vojtech@suse.cz> writes:
|
|
|
|
> On Sun, Oct 05, 2003 at 06:55:31PM +0200, Peter Osterlund wrote:
|
|
>
|
|
> > I have updated your patch for kernel 2.6.0-test6-bk6 and made it
|
|
> > report events compatible with the synaptics touchpad kernel driver.
|
|
> > This should make it possible to use an ALPS device with the XFree86
|
|
> > synaptics driver:
|
|
> >
|
|
> > http://w1.894.telia.com/~u89404340/touchpad/index.html
|
|
> >
|
|
> > Using this driver will give you edge scrolling and similar things.
|
|
> >
|
|
> > I don't have an ALPS GlidePoint so I haven't been able to test this
|
|
> > patch at all. Test reports are appreciated. You probably need to
|
|
> > change a few parameters in the X configuration, like edge parameters
|
|
> > and finger pressure thresholds. Also note that the auto detection will
|
|
> > not work with an ALPS device, so you have to use Protocol="event" and
|
|
> > Device="/dev/input/eventN" for some value of N.
|
|
>
|
|
> Very nice. Could you also make it a separate file? I think it's enough
|
|
> code to make that worth it ...
|
|
|
|
Here is a new patch that moves the ALPS code to a separate file. The
|
|
logic in ALPS_process_packet() has also gone through a few iterations
|
|
with Johan Braennlund as a tester, so that it actually even works now,
|
|
at least with his touchpad.
|
|
|
|
Note though that the potential problems mentioned by Neil Brown in his
|
|
initial announcement have not been dealt with:
|
|
|
|
It appears (but see 1) that it is not possible to reliably detect
|
|
an ALPS device.
|
|
...
|
|
So the current code always sends the ALPS set-absolute-mode
|
|
sequence (4 disables before the enable) unless a
|
|
non-3-byte-protocol device was detected.
|
|
|
|
There are two consequences of always assuming an ALPS that may not
|
|
be good.
|
|
1) The mouse always claims to generate various ABS events even
|
|
when there might not be any ABS-generating device behind the
|
|
mouse.
|
|
2) The driver could misinterpret a normal mouse event that
|
|
overflowed in the negative direction for both X and Y as part
|
|
of an ALPS absolute event. This is because ALPS absolute
|
|
events are detected by checking if the top 5 bits of the first
|
|
byte are all one. I doubt this is a real problem as double
|
|
overflows are very unlikely (aren't they?)
|
|
|
|
|
|
linux-petero/drivers/input/mouse/Makefile | 2
|
|
linux-petero/drivers/input/mouse/alps.c | 144 ++++++++++++++++++++++++
|
|
linux-petero/drivers/input/mouse/alps.h | 17 ++
|
|
linux-petero/drivers/input/mouse/psmouse-base.c | 8 +
|
|
linux-petero/drivers/input/mouse/psmouse.h | 1
|
|
5 files changed, 171 insertions(+), 1 deletion(-)
|
|
|
|
diff -puN drivers/input/mouse/Makefile~alps drivers/input/mouse/Makefile
|
|
--- linux/drivers/input/mouse/Makefile~alps 2004-02-22 08:29:18.000000000 +0100
|
|
+++ linux-petero/drivers/input/mouse/Makefile 2004-02-22 08:29:18.000000000 +0100
|
|
@@ -14,4 +14,4 @@ obj-$(CONFIG_MOUSE_PC9800) += 98busmouse
|
|
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
|
|
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
|
|
|
|
-psmouse-objs := psmouse-base.o logips2pp.o synaptics.o
|
|
+psmouse-objs := psmouse-base.o logips2pp.o alps.o synaptics.o
|
|
diff -puN drivers/input/mouse/alps.c~alps drivers/input/mouse/alps.c
|
|
--- linux/drivers/input/mouse/alps.c~alps 2004-02-22 08:29:18.000000000 +0100
|
|
+++ linux-petero/drivers/input/mouse/alps.c 2004-02-28 20:42:41.000000000 +0100
|
|
@@ -0,0 +1,144 @@
|
|
+/*
|
|
+ * ALPS touchpad PS/2 mouse driver
|
|
+ *
|
|
+ * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
|
|
+ * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 as published by
|
|
+ * the Free Software Foundation.
|
|
+ */
|
|
+
|
|
+#include "alps.h"
|
|
+#include <linux/input.h>
|
|
+#include <linux/serio.h>
|
|
+#include "psmouse.h"
|
|
+
|
|
+static inline void set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
|
|
+{
|
|
+ dev->absmin[axis] = min;
|
|
+ dev->absmax[axis] = max;
|
|
+ dev->absfuzz[axis] = fuzz;
|
|
+ dev->absflat[axis] = flat;
|
|
+
|
|
+ set_bit(axis, dev->absbit);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * If it is a 3-byte setting and we are allowed to use extensions,
|
|
+ * then it could be an ALPS Glidepoint, so send the init sequence just
|
|
+ * incase. i.e. 4 consecutive "disable"s before the "enable"
|
|
+ */
|
|
+
|
|
+void ALPS_initialize(struct psmouse *psmouse)
|
|
+{
|
|
+ if (psmouse->type < PSMOUSE_GENPS) {
|
|
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE);
|
|
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE);
|
|
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE);
|
|
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE);
|
|
+
|
|
+ set_bit(BTN_TOUCH, psmouse->dev.keybit);
|
|
+ set_bit(BTN_BACK, psmouse->dev.keybit);
|
|
+ set_bit(BTN_FORWARD, psmouse->dev.keybit);
|
|
+ set_bit(BTN_TOOL_FINGER, psmouse->dev.keybit);
|
|
+ set_bit(EV_ABS, psmouse->dev.evbit);
|
|
+ set_abs_params(&psmouse->dev, ABS_X, 0, 0, 0, 0);
|
|
+ set_abs_params(&psmouse->dev, ABS_Y, 0, 0, 0, 0);
|
|
+ set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * ALPS abolute Mode
|
|
+ * byte 0: 1 1 1 1 1 mid0 rig0 lef0
|
|
+ * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
|
|
+ * byte 2: 0 x10 x9 x8 x7 up1 fin ges
|
|
+ * byte 3: 0 y9 y8 y7 1 mid1 rig1 lef1
|
|
+ * byte 4: 0 y6 y5 y4 y3 y2 y1 y0
|
|
+ * byte 5: 0 z6 z5 z4 z3 z2 z1 z0
|
|
+ *
|
|
+ * On a dualpoint, {mid,rig,lef}0 are the stick, 1 are the pad.
|
|
+ * We just 'or' them together for now.
|
|
+ *
|
|
+ * We used to send 'ges'tures as BTN_TOUCH but this made it impossible
|
|
+ * to disable tap events in the synaptics driver since the driver
|
|
+ * was unable to distinguish a gesture tap from an actual button click.
|
|
+ * A tap gesture now creates an emulated touch that the synaptics
|
|
+ * driver can interpret as a tap event, if MaxTapTime=0 and
|
|
+ * MaxTapMove=0 then the driver will ignore taps.
|
|
+ *
|
|
+ * The touchpad on an 'Acer Aspire' has 4 buttons:
|
|
+ * left,right,up,down.
|
|
+ * This device always sets {mid,rig,lef}0 to 1 and
|
|
+ * reflects left,right,down,up in lef1,rig1,mid1,up1.
|
|
+ */
|
|
+
|
|
+static void ALPS_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
|
|
+{
|
|
+ unsigned char *packet = psmouse->packet;
|
|
+ struct input_dev *dev = &psmouse->dev;
|
|
+ int x, y, z;
|
|
+ int left = 0, right = 0, middle = 0;
|
|
+
|
|
+ input_regs(dev, regs);
|
|
+
|
|
+ x = (packet[1] & 0x7f) | ((packet[2] & 0x78)<<(7-3));
|
|
+ y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4));
|
|
+ z = packet[5];
|
|
+
|
|
+ if (z > 0) {
|
|
+ input_report_abs(dev, ABS_X, x);
|
|
+ input_report_abs(dev, ABS_Y, y);
|
|
+ }
|
|
+ input_report_abs(dev, ABS_PRESSURE, z);
|
|
+ input_report_key(dev, BTN_TOOL_FINGER, z > 0);
|
|
+
|
|
+ if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
|
|
+ if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
|
|
+
|
|
+ left |= (packet[2] ) & 1;
|
|
+ left |= (packet[3] ) & 1;
|
|
+ right |= (packet[3] >> 1) & 1;
|
|
+ if (packet[0] == 0xff) {
|
|
+ int back = (packet[3] >> 2) & 1;
|
|
+ int forward = (packet[2] >> 2) & 1;
|
|
+ if (back && forward) {
|
|
+ middle = 1;
|
|
+ back = 0;
|
|
+ forward = 0;
|
|
+ }
|
|
+ input_report_key(dev, BTN_BACK, back);
|
|
+ input_report_key(dev, BTN_FORWARD, forward);
|
|
+ } else {
|
|
+ left |= (packet[0] ) & 1;
|
|
+ right |= (packet[0] >> 1) & 1;
|
|
+ middle |= (packet[0] >> 2) & 1;
|
|
+ middle |= (packet[3] >> 2) & 1;
|
|
+ }
|
|
+
|
|
+ input_report_key(dev, BTN_LEFT, left);
|
|
+ input_report_key(dev, BTN_RIGHT, right);
|
|
+ input_report_key(dev, BTN_MIDDLE, middle);
|
|
+
|
|
+ input_sync(dev);
|
|
+}
|
|
+
|
|
+int ALPS_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
|
|
+{
|
|
+ if (psmouse->type >= PSMOUSE_GENPS)
|
|
+ return -1;
|
|
+
|
|
+ /* ALPS absolute mode packets start with 0b11111mrl
|
|
+ * Normal mouse packets are extremely unlikely to overflow both
|
|
+ * x and y
|
|
+ */
|
|
+ if ((psmouse->packet[0] & 0xf8) != 0xf8)
|
|
+ return -1;
|
|
+
|
|
+ if (psmouse->pktcnt == 6) {
|
|
+ ALPS_process_packet(psmouse, regs);
|
|
+ psmouse->pktcnt = 0;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
diff -puN drivers/input/mouse/alps.h~alps drivers/input/mouse/alps.h
|
|
--- linux/drivers/input/mouse/alps.h~alps 2004-02-22 08:29:18.000000000 +0100
|
|
+++ linux-petero/drivers/input/mouse/alps.h 2004-02-22 08:29:18.000000000 +0100
|
|
@@ -0,0 +1,17 @@
|
|
+/*
|
|
+ * ALPS touchpad PS/2 mouse driver
|
|
+ *
|
|
+ * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 as published by
|
|
+ * the Free Software Foundation.
|
|
+ */
|
|
+
|
|
+#ifndef _ALPS_H
|
|
+#define _ALPS_H
|
|
+struct psmouse;
|
|
+struct pt_regs;
|
|
+void ALPS_initialize(struct psmouse *psmouse);
|
|
+int ALPS_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
|
|
+#endif
|
|
diff -puN drivers/input/mouse/psmouse-base.c~alps drivers/input/mouse/psmouse-base.c
|
|
--- linux/drivers/input/mouse/psmouse-base.c~alps 2004-02-22 08:29:18.000000000 +0100
|
|
+++ linux-petero/drivers/input/mouse/psmouse-base.c 2004-02-22 08:29:18.000000000 +0100
|
|
@@ -21,6 +21,7 @@
|
|
#include "psmouse.h"
|
|
#include "synaptics.h"
|
|
#include "logips2pp.h"
|
|
+#include "alps.h"
|
|
|
|
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
|
|
MODULE_DESCRIPTION("PS/2 mouse driver");
|
|
@@ -196,6 +197,10 @@ static irqreturn_t psmouse_interrupt(str
|
|
goto out;
|
|
}
|
|
|
|
+ if ((psmouse_max_proto > PSMOUSE_PS2) &&
|
|
+ !ALPS_process_byte(psmouse, regs))
|
|
+ goto out;
|
|
+
|
|
if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
|
|
psmouse_process_packet(psmouse, regs);
|
|
psmouse->pktcnt = 0;
|
|
@@ -513,6 +518,9 @@ static void psmouse_initialize(struct ps
|
|
*/
|
|
|
|
psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
|
|
+
|
|
+ if (psmouse_max_proto > PSMOUSE_PS2)
|
|
+ ALPS_initialize(psmouse);
|
|
}
|
|
|
|
/*
|
|
diff -puN drivers/input/mouse/psmouse.h~alps drivers/input/mouse/psmouse.h
|
|
--- linux/drivers/input/mouse/psmouse.h~alps 2004-02-22 08:29:18.000000000 +0100
|
|
+++ linux-petero/drivers/input/mouse/psmouse.h 2004-02-22 08:29:18.000000000 +0100
|
|
@@ -9,6 +9,7 @@
|
|
#define PSMOUSE_CMD_GETID 0x02f2
|
|
#define PSMOUSE_CMD_SETRATE 0x10f3
|
|
#define PSMOUSE_CMD_ENABLE 0x00f4
|
|
+#define PSMOUSE_CMD_DISABLE 0x00f5
|
|
#define PSMOUSE_CMD_RESET_DIS 0x00f6
|
|
#define PSMOUSE_CMD_RESET_BAT 0x02ff
|
|
|
|
|
|
_
|