* Better default parameters for alps touchpads.

* Added Dmitry's updated alps patch that can do hardware auto-detection
  and also disables hardware tapping.
This commit is contained in:
Peter Osterlund
2004-07-23 12:21:11 +02:00
parent f40f0e40ce
commit 7ff083e441
2 changed files with 387 additions and 181 deletions

View File

@@ -1,61 +1,41 @@
It is possible to use the driver with an ALPS Glidepoint device, but
you probably have to change some parameter values. One user reported
success with the following settings:
It is possible to use this driver with an ALPS Glidepoint device. If
you use a 2.6 linux kernel, you need to apply the ALPS kernel patch
in the alps.patch file.
LeftEdge = 60
RightEdge = 830
TopEdge = 70
BottomEdge = 650
FingerLow = 25
FingerHigh = 30
MaxTapTime = 180
MaxTapMove = 110
EmulateMidButtonTime = 75
VertScrollDelta = 50
HorizScrollDelta = 50
MinSpeed = 0.2
MaxSpeed = 0.5
AccelFactor = 0.01
EdgeMotionSpeed = 40
UpDownScrolling = 1
TouchpadOff = 0
If you use a 2.6 linux kernel, you need to apply the ALPS kernel patch
in the alps.patch file. Note also that the auto-dev protocol option
doesn't work for ALPS devices, so you have to use the "event" protocol
instead and set the device option to the correct event device. (Look
for a mouse device in /proc/bus/input/devices and see which event
device it is connected to.) Here is an example InputDevice section for
the XF86Config file.
Since ALPS touchpads don't have the same resolution as Synaptics
touchpads, you probably have to change some parameter values. Here is
an example InputDevice section for the X configuration file.
Section "InputDevice"
Driver "synaptics"
Identifier "Mouse[1]"
Option "Device" "/dev/input/event1"
Option "Protocol" "event"
Option "LeftEdge" "60"
Option "Device" "/dev/psaux"
Option "Protocol" "auto-dev"
Option "LeftEdge" "120"
Option "RightEdge" "830"
Option "TopEdge" "70"
Option "TopEdge" "120"
Option "BottomEdge" "650"
Option "FingerLow" "25"
Option "FingerHigh" "30"
Option "FingerLow" "14"
Option "FingerHigh" "15"
Option "MaxTapTime" "180"
Option "MaxTapMove" "110"
Option "EmulateMidButtonTime" "75"
Option "VertScrollDelta" "50"
Option "HorizScrollDelta" "50"
Option "VertScrollDelta" "20"
Option "HorizScrollDelta" "20"
Option "MinSpeed" "0.2"
Option "MaxSpeed" "0.5"
Option "AccelFactor" "0.01"
Option "EdgeMotionSpeed" "40"
Option "EdgeMotionMinSpeed" "15"
Option "EdgeMotionMaxSpeed" "15"
Option "UpDownScrolling" "1"
Option "TouchpadOff" "0"
Option "CircularScrolling" "1"
Option "CircScrollDelta" "0.1"
Option "CircScrollTrigger" "2"
EndSection
If you use a 2.4 linux kernel, you don't need to patch the kernel, but
you should instead set "Device" and "Protocol" like this:
Option "Device" "/dev/psaux"
Option "Protocol" "alps"

View File

@@ -1,145 +1,117 @@
Hi,
Vojtech Pavlik <vojtech@suse.cz> writes:
I lifted some code off tpconfig and merged it with Peter's/Neil's ALPS driver.
The driver will try to auto-detect presence of an ALPS touchpad by issuing
E6/E7 requests and matching responses with known ALPS signatures. It will
also try disabling hardware tapping so taps could be controlled by either
userspace drivers (X/GPM) or future version of mousedev (2.6.8 I hope will
have it).
> 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 ...
Please give it a try.
--
Dmitry
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 | 137 ++++++++++++++++++++++++
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, 164 insertions(+), 1 deletion(-)
linux-petero/drivers/input/mouse/alps.c | 359 ++++++++++++++++++++++++
linux-petero/drivers/input/mouse/alps.h | 17 +
linux-petero/drivers/input/mouse/psmouse-base.c | 24 +
linux-petero/drivers/input/mouse/psmouse.h | 4
5 files changed, 404 insertions(+), 2 deletions(-)
diff -puN drivers/input/mouse/Makefile~alps drivers/input/mouse/Makefile
--- linux/drivers/input/mouse/Makefile~alps 2004-06-08 23:17:59.940957256 +0200
+++ linux-petero/drivers/input/mouse/Makefile 2004-06-08 23:17:59.963953760 +0200
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
--- linux/drivers/input/mouse/Makefile~alps 2004-07-21 17:24:22.499256904 +0200
+++ linux-petero/drivers/input/mouse/Makefile 2004-07-21 17:24:22.504256144 +0200
@@ -14,4 +14,4 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
-psmouse-objs := psmouse-base.o logips2pp.o synaptics.o
+psmouse-objs := psmouse-base.o logips2pp.o alps.o synaptics.o
+psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o
diff -puN /dev/null drivers/input/mouse/alps.c
--- /dev/null 2004-02-23 22:02:56.000000000 +0100
+++ linux-petero/drivers/input/mouse/alps.c 2004-06-08 23:17:59.963953760 +0200
@@ -0,0 +1,137 @@
+++ linux-petero/drivers/input/mouse/alps.c 2004-07-21 17:24:22.504256144 +0200
@@ -0,0 +1,359 @@
+/*
+ * ALPS touchpad PS/2 mouse driver
+ *
+ * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
+ * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
+ *
+ * ALPS detection, tap switching and status querying info is taken from
+ * tpconfig utility (by C. Scott Ananian and Bruce Kall).
+ *
+ * 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"
+#include "alps.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;
+#define DEBUG
+#ifdef DEBUG
+#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+ set_bit(axis, dev->absbit);
+}
+#define ALPS_MODEL_GLIDEPOINT 1
+#define ALPS_MODEL_DUALPOINT 2
+
+/*
+ * 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);
+ }
+}
+struct alps_model_info {
+ unsigned char signature[3];
+ unsigned char model;
+} alps_model_data[] = {
+ { { 0x33, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x53, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x53, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x63, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x63, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x73, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x73, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x63, 0x02, 0x28 }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x63, 0x02, 0x3c }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x63, 0x02, 0x50 }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x63, 0x02, 0x64 }, ALPS_MODEL_GLIDEPOINT },
+ { { 0x20, 0x02, 0x0e }, ALPS_MODEL_DUALPOINT },
+ { { 0x22, 0x02, 0x0a }, ALPS_MODEL_DUALPOINT },
+ { { 0x22, 0x02, 0x14 }, ALPS_MODEL_DUALPOINT },
+};
+
+/*
+ * 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
+ * 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)
+static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
+{
+ unsigned char *packet = psmouse->packet;
+ struct input_dev *dev = &psmouse->dev;
@@ -152,6 +124,9 @@ diff -puN /dev/null drivers/input/mouse/alps.c
+ y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4));
+ z = packet[5];
+
+ if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
+ if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
+
+ if (z > 0) {
+ input_report_abs(dev, ABS_X, x);
+ input_report_abs(dev, ABS_Y, y);
@@ -159,9 +134,6 @@ diff -puN /dev/null drivers/input/mouse/alps.c
+ 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;
@@ -189,27 +161,242 @@ diff -puN /dev/null drivers/input/mouse/alps.c
+ input_sync(dev);
+}
+
+int ALPS_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t 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
+ */
+ /* ALPS absolute mode packets start with 0b11111mrl */
+ if ((psmouse->packet[0] & 0xf8) != 0xf8)
+ return -1;
+ return PSMOUSE_BAD_DATA;
+
+ /* Bytes 2 - 6 should have 0 in the highest bit */
+ if (psmouse->pktcnt > 1 && psmouse->pktcnt <= 6 &&
+ (psmouse->packet[psmouse->pktcnt] & 0x80))
+ return PSMOUSE_BAD_DATA;
+
+ if (psmouse->pktcnt == 6) {
+ ALPS_process_packet(psmouse, regs);
+ psmouse->pktcnt = 0;
+ alps_process_packet(psmouse, regs);
+ return PSMOUSE_FULL_PACKET;
+ }
+
+ return PSMOUSE_GOOD_DATA;
+}
+
+int alps_get_model(struct psmouse *psmouse)
+{
+ unsigned char param[4];
+ int i;
+
+ /*
+ * First try "E6 report".
+ * ALPS should return 0x00,0x00,0x0a or 0x00,0x00,0x64
+ */
+ param[0] = 0;
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11))
+ return -1;
+
+ param[0] = param[1] = param[2] = 0xff;
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO))
+ return -1;
+
+ dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+
+ if (param[0] != 0x00 || param[1] != 0x00 || (param[2] != 0x0a && param[2] != 0x64))
+ return -1;
+
+ /* Now try "E7 report". ALPS should return 0x33 in byte 1 */
+ param[0] = 0;
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE21) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE21) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE21))
+ return -1;
+
+ param[0] = param[1] = param[2] = 0xff;
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO))
+ return -1;
+
+ dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+
+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++)
+ if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature)))
+ return alps_model_data[i].model;
+
+ return -1;
+}
+
+static int alps_absolute_mode(struct psmouse *psmouse)
+{
+ /* Try ALPS magic knock - 4 disable before enable */
+ if (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) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
+ return -1;
+
+ /*
+ * Switch mouse to poll (remote) mode so motion data will not
+ * get in our way
+ */
+ return psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETPOLL);
+}
+
+static int alps_get_status(struct psmouse *psmouse, char *param)
+{
+ /* Get status: 0xF5 0xF5 0xF5 0xE9 */
+ if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) ||
+ psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO))
+ return -1;
+
+ dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+
+ return 0;
+}
+
+/*
+ * For DualPint devices select the device that should respond to
+ * subsequent commands. It looks like glidepad is behind stickpointer,
+ * I'd thought it would be other way around...
+ */
+static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
+{
+ unsigned char param[3];
+ int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
+
+ if (psmouse_command(psmouse, NULL, cmd) ||
+ psmouse_command(psmouse, NULL, cmd) ||
+ psmouse_command(psmouse, NULL, cmd) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE))
+ return -1;
+
+ /* we may get 3 more bytes, just ignore them */
+ psmouse_command(psmouse, param, 0x0300);
+
+ return 0;
+}
+
+/*
+ * Turn touchpad tappinig on or off. The sequence are:
+ * 0xE9 0xF5 0xF5 0xF3 0x0A to enable,
+ * 0xE9 0xF5 0xF5 0xE8 0x00 to disable.
+ * My guess that 0xE9 (GetInfo) is here as a sync point.
+ * For models that also have stickpointer (DualPoints) its tapping
+ * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but
+ * we don't fiddle with it.
+ */
+static int alps_tap_mode(struct psmouse *psmouse, int model, int enable)
+{
+ int rc = 0;
+ int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES;
+ unsigned char tap_arg = enable ? 0x0A : 0x00;
+ unsigned char param[4];
+
+ if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 1))
+ return -1;
+
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) ||
+ psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) ||
+ psmouse_command(psmouse, &tap_arg, cmd))
+ rc = -1;
+
+ if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 0))
+ return -1;
+
+ if (alps_get_status(psmouse, param))
+ return -1;
+
+
+ return rc;
+}
+
+static int alps_reconnect(struct psmouse *psmouse)
+{
+ int model;
+ unsigned char param[4];
+
+ if ((model = alps_get_model(psmouse)) < 0)
+ return -1;
+
+ if (alps_get_status(psmouse, param))
+ return -1;
+
+ if ((model == ALPS_MODEL_DUALPOINT ? param[2] : param[0]) & 0x04)
+ alps_tap_mode(psmouse, model, 0);
+
+ if (alps_absolute_mode(psmouse)) {
+ printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void alps_disconnect(struct psmouse *psmouse)
+{
+ psmouse_reset(psmouse);
+}
+
+int alps_init(struct psmouse *psmouse)
+{
+ unsigned char param[4];
+ int model;
+
+ if ((model = alps_get_model(psmouse)) < 0)
+ return -1;
+
+ if (alps_get_status(psmouse, param)) {
+ printk(KERN_ERR "alps.c: touchpad status report request failed\n");
+ return -1;
+ }
+
+ printk(KERN_INFO "ALPS Touchpad (%s) detected\n",
+ model == ALPS_MODEL_GLIDEPOINT ? "Glidepoint" : "Dualpoint");
+
+ if ((model == ALPS_MODEL_DUALPOINT ? param[2] : param[0]) & 0x04) {
+ printk(KERN_INFO " Disabling hardware tapping\n");
+ if (alps_tap_mode(psmouse, model, 0))
+ printk(KERN_WARNING "alps.c: Failed to disable hardware tapping\n");
+ }
+
+ if (alps_absolute_mode(psmouse)) {
+ printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
+ return -1;
+ }
+
+ psmouse->dev.evbit[LONG(EV_REL)] &= ~BIT(EV_REL);
+ psmouse->dev.relbit[LONG(REL_X)] &= ~BIT(REL_X);
+ psmouse->dev.relbit[LONG(REL_X)] &= ~BIT(REL_X);
+
+ psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
+ input_set_abs_params(&psmouse->dev, ABS_X, 0, 0, 0, 0);
+ input_set_abs_params(&psmouse->dev, ABS_Y, 0, 0, 0, 0);
+ input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
+
+ psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+ psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
+ psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
+ psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+
+ psmouse->protocol_handler = alps_process_byte;
+ psmouse->disconnect = alps_disconnect;
+ psmouse->reconnect = alps_reconnect;
+
+ return 0;
+}
+
+int alps_detect(struct psmouse *psmouse)
+{
+ return alps_get_model(psmouse) < 0 ? 0 : 1;
+}
+
diff -puN /dev/null drivers/input/mouse/alps.h
--- /dev/null 2004-02-23 22:02:56.000000000 +0100
+++ linux-petero/drivers/input/mouse/alps.h 2004-06-08 23:17:59.963953760 +0200
+++ linux-petero/drivers/input/mouse/alps.h 2004-07-21 17:24:22.504256144 +0200
@@ -0,0 +1,17 @@
+/*
+ * ALPS touchpad PS/2 mouse driver
@@ -223,15 +410,23 @@ diff -puN /dev/null drivers/input/mouse/alps.h
+
+#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);
+
+int alps_detect(struct psmouse *psmouse);
+int alps_init(struct psmouse *psmouse);
+
+#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-06-08 23:17:59.943956800 +0200
+++ linux-petero/drivers/input/mouse/psmouse-base.c 2004-06-08 23:27:27.101735712 +0200
@@ -21,6 +21,7 @@
--- linux/drivers/input/mouse/psmouse-base.c~alps 2004-07-21 17:24:22.500256752 +0200
+++ linux-petero/drivers/input/mouse/psmouse-base.c 2004-07-21 17:24:22.505255992 +0200
@@ -2,6 +2,7 @@
* PS/2 mouse driver
*
* Copyright (c) 1999-2002 Vojtech Pavlik
+ * Copyright (c) 2003-2004 Dmitry Torokhov
*/
/*
@@ -21,6 +22,7 @@
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
@@ -239,31 +434,55 @@ diff -puN drivers/input/mouse/psmouse-base.c~alps drivers/input/mouse/psmouse-ba
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("PS/2 mouse driver");
@@ -203,6 +204,10 @@ static irqreturn_t psmouse_interrupt(str
}
}
@@ -53,7 +55,7 @@ __obsolete_setup("psmouse_smartscroll=")
__obsolete_setup("psmouse_resetafter=");
__obsolete_setup("psmouse_rate=");
+ if ((psmouse_max_proto > PSMOUSE_PS2) &&
+ !ALPS_process_byte(psmouse, regs))
+ goto out;
+
rc = psmouse->protocol_handler(psmouse, regs);
switch (rc) {
@@ -595,6 +600,9 @@ static void psmouse_initialize(struct ps
*/
psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
+
+ if (psmouse_max_proto > PSMOUSE_PS2)
+ ALPS_initialize(psmouse);
}
-static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
+static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" };
/*
* psmouse_process_byte() analyzes the PS/2 data stream and reports
@@ -442,6 +444,26 @@ static int psmouse_extensions(struct psm
synaptics_reset(psmouse);
}
+/*
+ * Try ALPS TouchPad
+ */
+ if (max_proto > PSMOUSE_PS2 && alps_detect(psmouse)) {
+
+ if (set_properties) {
+ psmouse->vendor = "ALPS";
+ psmouse->name = "TouchPad";
+ }
+
+ if (max_proto > PSMOUSE_IMEX)
+ if (!set_properties || alps_init(psmouse) == 0)
+ return PSMOUSE_ALPS;
+
+/*
+ * Don't try anything fancy, just basic Intellimouse/Explorer protocols
+ */
+ max_proto = PSMOUSE_IMEX;
+ }
+
if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
if (set_properties) {
diff -puN drivers/input/mouse/psmouse.h~alps drivers/input/mouse/psmouse.h
--- linux/drivers/input/mouse/psmouse.h~alps 2004-06-08 23:17:59.944956648 +0200
+++ linux-petero/drivers/input/mouse/psmouse.h 2004-06-08 23:17:59.965953456 +0200
@@ -9,6 +9,7 @@
--- linux/drivers/input/mouse/psmouse.h~alps 2004-07-21 17:24:22.501256600 +0200
+++ linux-petero/drivers/input/mouse/psmouse.h 2004-07-21 17:24:22.505255992 +0200
@@ -2,13 +2,16 @@
#define _PSMOUSE_H
#define PSMOUSE_CMD_SETSCALE11 0x00e6
+#define PSMOUSE_CMD_SETSCALE21 0x00e7
#define PSMOUSE_CMD_SETRES 0x10e8
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
+#define PSMOUSE_CMD_SETPOLL 0x00f0
#define PSMOUSE_CMD_POLL 0x03eb
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
@@ -271,5 +490,12 @@ diff -puN drivers/input/mouse/psmouse.h~alps drivers/input/mouse/psmouse.h
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_BAT 0x02ff
@@ -72,6 +75,7 @@ struct psmouse {
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
#define PSMOUSE_SYNAPTICS 7
+#define PSMOUSE_ALPS 8
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
_