Hi Peter, Neil,
I found on the net a possible way to detect ALPS driver so I made some changes
to your driver. Unfortunately I do not have ALPS touchpad so if anyone could
give it a spin I's appreciate it.
The patch is to be applied on top of my patches at:
http://www.geocities.com/dt_or/input/2_6_6-rc2/
--
Dmitry
===================================================================
[email protected], 2004-04-23 02:22:22-05:00, [email protected]
ALPS driver
Makefile | 2
alps.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
alps.h | 17 +++++
psmouse-base.c | 19 +++++
psmouse.h | 3
5 files changed, 224 insertions(+), 2 deletions(-)
===================================================================
diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
--- a/drivers/input/mouse/Makefile Fri Apr 23 02:24:19 2004
+++ b/drivers/input/mouse/Makefile Fri Apr 23 02:24:19 2004
@@ -15,4 +15,4 @@
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 alps.o logips2pp.o synaptics.o
diff -Nru a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/input/mouse/alps.c Fri Apr 23 02:24:19 2004
@@ -0,0 +1,185 @@
+/*
+ * ALPS touchpad PS/2 mouse driver
+ *
+ * Copyright (c) 2003 Neil Brown <[email protected]>
+ * Copyright (c) 2003 Peter Osterlund <[email protected]>
+ * Copyright (c) 2004 Dmitry Torokhov <[email protected]>
+ *
+ * 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 <linux/input.h>
+#include <linux/serio.h>
+
+#include "psmouse.h"
+#include "alps.h"
+
+/*
+ * 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 > 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);
+ }
+ input_report_abs(dev, ABS_PRESSURE, z);
+ input_report_key(dev, BTN_TOOL_FINGER, z > 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);
+}
+
+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_detect(struct psmouse *psmouse)
+{
+ unsigned char param[4];
+
+ /* First try "E6 report". ALPS should return 0x00 0x00 0x0a */
+ 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 0;
+
+ param[0] = param[1] = param[2] = 0xff;
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO))
+ return 0;
+
+ printk(KERN_INFO "alps.c: E6 report: %2.2x %2.2x %2.2x\n",
+ param[0], param[1], param[2]);
+
+ if (param[0] != 0x00 || param[1] != 0x00 || param[2] != 0x0a)
+ return 0;
+
+ /* 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 0;
+
+ param[0] = param[1] = param[2] = 0xff;
+ if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO))
+ return 0;
+
+ printk(KERN_INFO "alps.c: E7 report: %2.2x %2.2x %2.2x\n",
+ param[0], param[1], param[2]);
+
+ return param[0] != 0x33;
+}
+
+static void alps_disconnect(struct psmouse *psmouse)
+{
+ psmouse_reset(psmouse);
+}
+
+int alps_init(struct psmouse *psmouse)
+{
+ /* Try ALPS magic knock */
+ 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))
+ 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;
+
+ return 0;
+}
diff -Nru a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/input/mouse/alps.h Fri Apr 23 02:24:19 2004
@@ -0,0 +1,17 @@
+/*
+ * ALPS touchpad PS/2 mouse driver
+ *
+ * Copyright (c) 2003 Peter Osterlund <[email protected]>
+ *
+ * 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
+
+int alps_detect(struct psmouse *psmouse);
+int alps_init(struct psmouse *psmouse);
+
+#endif
diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c Fri Apr 23 02:24:19 2004
+++ b/drivers/input/mouse/psmouse-base.c Fri Apr 23 02:24:19 2004
@@ -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"
+#include "alps.h"
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
MODULE_DESCRIPTION("PS/2 mouse driver");
@@ -53,7 +55,7 @@
__obsolete_setup("psmouse_resetafter=");
__obsolete_setup("psmouse_rate=");
-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
@@ -440,6 +442,21 @@
* Make sure that touchpad is in relative mode, gestures (taps) are enabled
*/
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 (alps_detect(psmouse) == 0)
+ return PSMOUSE_ALPS;
}
if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
--- a/drivers/input/mouse/psmouse.h Fri Apr 23 02:24:19 2004
+++ b/drivers/input/mouse/psmouse.h Fri Apr 23 02:24:19 2004
@@ -2,6 +2,7 @@
#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
@@ -9,6 +10,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
@@ -72,6 +74,7 @@
#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);
On Fri, 23 Apr 2004, Dmitry Torokhov wrote:
> I found on the net a possible way to detect ALPS driver so I made some changes
> to your driver. Unfortunately I do not have ALPS touchpad so if anyone could
> give it a spin I's appreciate it.
> + /* 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 0;
> +
> + param[0] = param[1] = param[2] = 0xff;
> + if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO))
> + return 0;
> +
> + printk(KERN_INFO "alps.c: E7 report: %2.2x %2.2x %2.2x\n",
> + param[0], param[1], param[2]);
> +
> + return param[0] != 0x33;
Depending on ALPS version this request is also known to return one of
glidepats:
0x33,0x02,0x0a,
0x53,0x02,0x0a,
0x53,0x02,0x14,
0x63,0x02,0x0a,
0x63,0x02,0x14,
0x63,0x02,0x28,
0x63,0x02,0x3c,
0x63,0x02,0x50,
0x63,0x02,0x64,
0x73,0x02,0x0a,
glidepoints:
0x20,0x02,0x0e,
0x22,0x02,0x0a,
0x22,0x02,0x14,
Peter
--
E-Mail: [email protected]
Real name: Peter Berg Larsen
Where: Department of Computer Science, Copenhagen Uni., Denmark