diff options
author | Peter Osterlund <petero2@telia.com> | 2004-07-23 12:21:11 +0200 |
---|---|---|
committer | Peter Osterlund <petero2@telia.com> | 2006-04-09 04:02:35 +0200 |
commit | 7ff083e441ec925ca0d138c5ec2a53e8a6435d99 (patch) | |
tree | 0f098f381f5c11ac6c9c048abc5de2900ce76a4f | |
parent | f40f0e40ce01415baff8f86a8038ad8b6d02a118 (diff) |
* Better default parameters for alps touchpads.
* Added Dmitry's updated alps patch that can do hardware auto-detection
and also disables hardware tapping.
-rw-r--r-- | README.alps | 58 | ||||
-rw-r--r-- | alps.patch | 502 |
2 files changed, 383 insertions, 177 deletions
diff --git a/README.alps b/README.alps index 99ee0d8..55317e6 100644 --- a/README.alps +++ b/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" @@ -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" + -+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; ++#include "psmouse.h" ++#include "alps.h" + -+ set_bit(axis, dev->absbit); -+} ++#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 + -+/* -+ * 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" -+ */ ++#define ALPS_MODEL_GLIDEPOINT 1 ++#define ALPS_MODEL_DUALPOINT 2 + -+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) ++{ ++ /* ALPS absolute mode packets start with 0b11111mrl */ ++ if ((psmouse->packet[0] & 0xf8) != 0xf8) ++ 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); ++ return PSMOUSE_FULL_PACKET; ++ } ++ ++ return PSMOUSE_GOOD_DATA; ++} ++ ++int alps_get_model(struct psmouse *psmouse) +{ -+ if (psmouse->type >= PSMOUSE_GENPS) ++ 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; + -+ /* ALPS absolute mode packets start with 0b11111mrl -+ * Normal mouse packets are extremely unlikely to overflow both -+ * x and y ++ 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 + */ -+ if ((psmouse->packet[0] & 0xf8) != 0xf8) ++ 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; + -+ if (psmouse->pktcnt == 6) { -+ ALPS_process_packet(psmouse, regs); -+ psmouse->pktcnt = 0; ++ 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); +-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" }; - switch (rc) { -@@ -595,6 +600,9 @@ static void psmouse_initialize(struct ps - */ + /* + * psmouse_process_byte() analyzes the PS/2 data stream and reports +@@ -442,6 +444,26 @@ static int psmouse_extensions(struct psm + synaptics_reset(psmouse); + } - psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM); ++/* ++ * 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; + -+ if (psmouse_max_proto > PSMOUSE_PS2) -+ ALPS_initialize(psmouse); - } ++/* ++ * 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); _ |