mirror of
https://github.com/X11Libre/xf86-input-synaptics.git
synced 2026-04-14 11:54:16 +00:00
* 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:
58
README.alps
58
README.alps
@@ -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"
|
||||
|
||||
|
||||
|
||||
510
alps.patch
510
alps.patch
@@ -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);
|
||||
_
|
||||
|
||||
Reference in New Issue
Block a user