diff options
author | Josh Boyer <jwboyer@redhat.com> | 2012-01-20 13:32:57 -0500 |
---|---|---|
committer | Josh Boyer <jwboyer@redhat.com> | 2012-01-20 13:32:57 -0500 |
commit | e8409b1dce1d927283cb4999d9902b8cda4f86fc (patch) | |
tree | aebdcb0443b56c5cee9135f08f5cf8b9678d76e6 /alps.patch | |
parent | 0a621ccdd414267ae3ff952951be5547f0512383 (diff) | |
download | kernel-e8409b1dce1d927283cb4999d9902b8cda4f86fc.tar.gz kernel-e8409b1dce1d927283cb4999d9902b8cda4f86fc.tar.xz kernel-e8409b1dce1d927283cb4999d9902b8cda4f86fc.zip |
Rebase to Linux 3.3-rc1
The utrace patch is left unapplied as it doesn't apply cleanly any longer
Diffstat (limited to 'alps.patch')
-rw-r--r-- | alps.patch | 1861 |
1 files changed, 0 insertions, 1861 deletions
diff --git a/alps.patch b/alps.patch deleted file mode 100644 index 331716d3b..000000000 --- a/alps.patch +++ /dev/null @@ -1,1861 +0,0 @@ -From d4b347b29b4d14647c7394f7167bf6785dc98e50 Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 7 Nov 2011 19:53:15 -0800 -Subject: [PATCH 1/6] Input: ALPS - move protocol information to Documentation - -In preparation for new protocol support, move the protocol -information currently documented in alps.c to -Documentation/input/alps.txt, where it can be expanded without -cluttering up the driver. - -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Acked-by: Chase Douglas <chase.douglas@canonical.com> -Signed-off-by: Dmitry Torokhov <dtor@mail.ru> ---- - Documentation/input/alps.txt | 75 ++++++++++++++++++++++++++++++++++++++++++ - drivers/input/mouse/alps.c | 37 +-------------------- - 2 files changed, 76 insertions(+), 36 deletions(-) - create mode 100644 Documentation/input/alps.txt - -diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt -new file mode 100644 -index 0000000..ab5478f ---- /dev/null -+++ b/Documentation/input/alps.txt -@@ -0,0 +1,75 @@ -+ALPS Touchpad Protocol -+---------------------- -+ -+Introduction -+------------ -+ -+Currently the ALPS touchpad driver supports two protocol versions in use by -+ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these -+differ only in the format of their event packets (in reality many features may -+be found on new protocol devices that aren't found on the old protocol -+devices, but these are handled transparently as feature differences rather -+than protocol differences). -+ -+Detection -+--------- -+ -+All ALPS touchpads should respond to the "E6 report" command sequence: -+E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or -+00-00-64. -+ -+If the E6 report is successful, the touchpad model is identified using the "E7 -+report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is -+matched against known models in the alps_model_data_array. -+ -+Packet Format -+------------- -+ -+In the following tables, the following notation us used. -+ -+ CAPITALS = stick, miniscules = touchpad -+ -+?'s can have different meanings on different models, such as wheel rotation, -+extra buttons, stick buttons on a dualpoint, etc. -+ -+PS/2 packet format -+------------------ -+ -+ byte 0: 0 0 YSGN XSGN 1 M R L -+ byte 1: X7 X6 X5 X4 X3 X2 X1 X0 -+ byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -+ -+Note that the device never signals overflow condition. -+ -+ALPS Absolute Mode - Old Format -+------------------------------- -+ -+ byte 0: 1 0 0 0 1 x9 x8 x7 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 ? ? l r ? fin ges -+ byte 3: 0 ? ? ? ? y9 y8 y7 -+ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+ALPS Absolute Mode - New Format -+------------------------------- -+ -+ byte 0: 1 ? ? ? 1 ? ? ? -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 x10 x9 x8 x7 ? fin ges -+ byte 3: 0 y9 y8 y7 1 M R L -+ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+Dualpoint device -- interleaved packet format -+--------------------------------------------- -+ -+ byte 0: 1 1 0 0 1 1 1 1 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 x10 x9 x8 x7 0 fin ges -+ byte 3: 0 0 YSGN XSGN 1 1 1 1 -+ byte 4: X7 X6 X5 X4 X3 X2 X1 X0 -+ byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -+ byte 6: 0 y9 y8 y7 1 m r l -+ byte 7: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 003587c..19d0943 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -67,42 +67,7 @@ static const struct alps_model_info alps_model_data[] = { - * isn't valid per PS/2 spec. - */ - --/* -- * PS/2 packet format -- * -- * byte 0: 0 0 YSGN XSGN 1 M R L -- * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 -- * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -- * -- * Note that the device never signals overflow condition. -- * -- * ALPS absolute Mode - new format -- * -- * byte 0: 1 ? ? ? 1 ? ? ? -- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -- * byte 2: 0 x10 x9 x8 x7 ? fin ges -- * byte 3: 0 y9 y8 y7 1 M R L -- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -- * -- * Dualpoint device -- interleaved packet format -- * -- * byte 0: 1 1 0 0 1 1 1 1 -- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -- * byte 2: 0 x10 x9 x8 x7 0 fin ges -- * byte 3: 0 0 YSGN XSGN 1 1 1 1 -- * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 -- * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -- * byte 6: 0 y9 y8 y7 1 m r l -- * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 -- * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -- * -- * CAPITALS = stick, miniscules = touchpad -- * -- * ?'s can have different meanings on different models, -- * such as wheel rotation, extra buttons, stick buttons -- * on a dualpoint, etc. -- */ -+/* Packet formats are described in Documentation/input/alps.txt */ - - static bool alps_is_valid_first_byte(const struct alps_model_info *model, - unsigned char data) --- -1.7.7.3 - - -From fa629ef5222193214da9a2b3c94369f79353bec9 Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 7 Nov 2011 19:53:24 -0800 -Subject: [PATCH 2/6] Input: ALPS - add protocol version field in - alps_model_info - -In preparation for adding support for more ALPS protocol versions, -add a field for the protocol version to the model info instead of -using a field in the flags. OLDPROTO and !OLDPROTO are now called -version 1 and version 2, repsectively. - -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Acked-by: Chase Douglas <chase.douglas@canonical.com> -Signed-off-by: Dmitry Torokhov <dtor@mail.ru> ---- - drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- - drivers/input/mouse/alps.h | 4 +++ - 2 files changed, 27 insertions(+), 24 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 19d0943..77b776d 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -23,7 +23,6 @@ - #include "psmouse.h" - #include "alps.h" - --#define ALPS_OLDPROTO 0x01 /* old style input */ - #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ - #define ALPS_PASS 0x04 /* device has a pass-through port */ - -@@ -35,30 +34,30 @@ - 6-byte ALPS packet */ - - static const struct alps_model_info alps_model_data[] = { -- { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ -- { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, -- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -- { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -- { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -- { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -- { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -- { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -- { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -- { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ -+ { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -+ { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -+ { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -+ { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -+ { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -+ { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -+ { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -+ { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -+ { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -+ { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -+ { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -+ { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ -- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, -+ { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, -- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -- { { 0x52, 0x01, 0x14 }, 0xff, 0xff, -- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -+ { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, -+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ - }; - - /* -@@ -112,7 +111,7 @@ static void alps_process_packet(struct psmouse *psmouse) - int x, y, z, ges, fin, left, right, middle; - int back = 0, forward = 0; - -- if (model->flags & ALPS_OLDPROTO) { -+ if (model->proto_version == ALPS_PROTO_V1) { - left = packet[2] & 0x10; - right = packet[2] & 0x08; - middle = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 904ed8b..4ce9bba 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -12,8 +12,12 @@ - #ifndef _ALPS_H - #define _ALPS_H - -+#define ALPS_PROTO_V1 0 -+#define ALPS_PROTO_V2 1 -+ - struct alps_model_info { - unsigned char signature[3]; -+ unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; - }; --- -1.7.7.3 - - -From b46615fe9215214ac00e26d35fc54dbe1c510803 Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 7 Nov 2011 19:53:30 -0800 -Subject: [PATCH 3/6] Input: ALPS - remove assumptions about packet size - -In preparation for version 4 protocol support, which has 8-byte -data packets, remove all hard-coded assumptions about packet size -and use psmouse->pktsize instead. - -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Acked-by: Chase Douglas <chase.douglas@canonical.com> -Signed-off-by: Dmitry Torokhov <dtor@mail.ru> ---- - drivers/input/mouse/alps.c | 10 +++++----- - 1 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 77b776d..44a0a71 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -308,7 +308,7 @@ static void alps_flush_packet(unsigned long data) - - serio_pause_rx(psmouse->ps2dev.serio); - -- if (psmouse->pktcnt == 6) { -+ if (psmouse->pktcnt == psmouse->pktsize) { - - /* - * We did not any more data in reasonable amount of time. -@@ -359,8 +359,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- /* Bytes 2 - 6 should have 0 in the highest bit */ -- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && -+ /* Bytes 2 - pktsize should have 0 in the highest bit */ -+ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, -@@ -368,7 +368,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- if (psmouse->pktcnt == 6) { -+ if (psmouse->pktcnt == psmouse->pktsize) { - alps_process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } -@@ -529,7 +529,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) - static int alps_poll(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- unsigned char buf[6]; -+ unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) --- -1.7.7.3 - - -From 25bded7cd60fa460e520e9f819bd06f4c5cb53f0 Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 7 Nov 2011 19:53:36 -0800 -Subject: [PATCH 4/6] Input: ALPS - add support for protocol versions 3 and 4 - -This patch adds support for two ALPS touchpad protocols not -supported currently by the driver, which I am arbitrarily naming -version 3 and version 4. Support is single-touch only at this time, -although both protocols are capable of limited multitouch support. - -Thanks to Andrew Skalski, who did the initial reverse-engineering -of the v3 protocol. - -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Acked-by: Chase Douglas <chase.douglas@canonical.com> -Signed-off-by: Dmitry Torokhov <dtor@mail.ru> ---- - drivers/input/mouse/alps.c | 791 +++++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/alps.h | 14 + - drivers/input/mouse/psmouse.h | 1 + - 3 files changed, 768 insertions(+), 38 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 44a0a71..a0248fd 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -23,6 +23,50 @@ - #include "psmouse.h" - #include "alps.h" - -+/* -+ * Definitions for ALPS version 3 and 4 command mode protocol -+ */ -+#define ALPS_CMD_NIBBLE_10 0x01f2 -+ -+static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -+ { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ -+ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -+ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ -+ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ -+ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ -+ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ -+ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ -+ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ -+ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ -+ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ -+ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ -+ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ -+ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ -+ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ -+ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ -+ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -+}; -+ -+static const struct alps_nibble_commands alps_v4_nibble_commands[] = { -+ { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ -+ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -+ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ -+ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ -+ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ -+ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ -+ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ -+ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ -+ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ -+ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ -+ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ -+ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ -+ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ -+ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ -+ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ -+ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -+}; -+ -+ - #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ - #define ALPS_PASS 0x04 /* device has a pass-through port */ - -@@ -34,30 +78,33 @@ - 6-byte ALPS packet */ - - static const struct alps_model_info alps_model_data[] = { -- { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -- { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -- { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -- { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -- { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -- { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -- { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -- { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -- { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -- { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -- { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -- { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ -+ { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -+ { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -+ { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -+ { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -+ { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -+ { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -+ { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -+ { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -+ { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -+ { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -+ { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -+ { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ -- { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, -+ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, -- { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -- { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, -- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -+ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, -+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -+ { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -+ { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - - /* -@@ -101,7 +148,7 @@ static void alps_report_buttons(struct psmouse *psmouse, - input_sync(dev2); - } - --static void alps_process_packet(struct psmouse *psmouse) -+static void alps_process_packet_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; -@@ -203,6 +250,224 @@ static void alps_process_packet(struct psmouse *psmouse) - input_sync(dev); - } - -+static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = priv->dev2; -+ int x, y, z, left, right, middle; -+ -+ /* Sanity check packet */ -+ if (!(packet[0] & 0x40)) { -+ psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); -+ return; -+ } -+ -+ /* -+ * There's a special packet that seems to indicate the end -+ * of a stream of trackstick data. Filter these out. -+ */ -+ if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) -+ return; -+ -+ x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); -+ y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); -+ z = (packet[4] & 0x7c) >> 2; -+ -+ /* -+ * The x and y values tend to be quite large, and when used -+ * alone the trackstick is difficult to use. Scale them down -+ * to compensate. -+ */ -+ x /= 8; -+ y /= 8; -+ -+ input_report_rel(dev, REL_X, x); -+ input_report_rel(dev, REL_Y, -y); -+ -+ /* -+ * Most ALPS models report the trackstick buttons in the touchpad -+ * packets, but a few report them here. No reliable way has been -+ * found to differentiate between the models upfront, so we enable -+ * the quirk in response to seeing a button press in the trackstick -+ * packet. -+ */ -+ left = packet[3] & 0x01; -+ right = packet[3] & 0x02; -+ middle = packet[3] & 0x04; -+ -+ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && -+ (left || right || middle)) -+ priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; -+ -+ if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ } -+ -+ input_sync(dev); -+ return; -+} -+ -+static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = psmouse->dev; -+ struct input_dev *dev2 = priv->dev2; -+ int x, y, z; -+ int left, right, middle; -+ -+ /* -+ * There's no single feature of touchpad position and bitmap -+ * packets that can be used to distinguish between them. We -+ * rely on the fact that a bitmap packet should always follow -+ * a position packet with bit 6 of packet[4] set. -+ */ -+ if (priv->multi_packet) { -+ priv->multi_packet = 0; -+ -+ /* -+ * Sometimes a position packet will indicate a multi-packet -+ * sequence, but then what follows is another position -+ * packet. Check for this, and when it happens process the -+ * position packet as usual. -+ */ -+ if (packet[0] & 0x40) { -+ /* -+ * Bitmap packets are not yet supported, so for now -+ * just ignore them. -+ */ -+ return; -+ } -+ } -+ -+ if (!priv->multi_packet && (packet[4] & 0x40)) -+ priv->multi_packet = 1; -+ else -+ priv->multi_packet = 0; -+ -+ left = packet[3] & 0x01; -+ right = packet[3] & 0x02; -+ middle = packet[3] & 0x04; -+ -+ x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | -+ ((packet[0] & 0x30) >> 4); -+ y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); -+ z = packet[5] & 0x7f; -+ -+ /* -+ * Sometimes the hardware sends a single packet with z = 0 -+ * in the middle of a stream. Real releases generate packets -+ * with x, y, and z all zero, so these seem to be flukes. -+ * Ignore them. -+ */ -+ if (x && y && !z) -+ return; -+ -+ if (z >= 64) -+ input_report_key(dev, BTN_TOUCH, 1); -+ else -+ 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); -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ -+ input_sync(dev); -+ -+ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -+ left = packet[3] & 0x10; -+ right = packet[3] & 0x20; -+ middle = packet[3] & 0x40; -+ -+ input_report_key(dev2, BTN_LEFT, left); -+ input_report_key(dev2, BTN_RIGHT, right); -+ input_report_key(dev2, BTN_MIDDLE, middle); -+ input_sync(dev2); -+ } -+} -+ -+static void alps_process_packet_v3(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * v3 protocol packets come in three types, two representing -+ * touchpad data and one representing trackstick data. -+ * Trackstick packets seem to be distinguished by always -+ * having 0x3f in the last byte. This value has never been -+ * observed in the last byte of either of the other types -+ * of packets. -+ */ -+ if (packet[5] == 0x3f) { -+ alps_process_trackstick_packet_v3(psmouse); -+ return; -+ } -+ -+ alps_process_touchpad_packet_v3(psmouse); -+} -+ -+static void alps_process_packet_v4(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = psmouse->dev; -+ int x, y, z; -+ int left, right; -+ -+ left = packet[4] & 0x01; -+ right = packet[4] & 0x02; -+ -+ x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | -+ ((packet[0] & 0x30) >> 4); -+ y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); -+ z = packet[5] & 0x7f; -+ -+ if (z >= 64) -+ input_report_key(dev, BTN_TOUCH, 1); -+ else -+ 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); -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ -+ input_sync(dev); -+} -+ -+static void alps_process_packet(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ const struct alps_model_info *model = priv->i; -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ alps_process_packet_v1_v2(psmouse); -+ break; -+ case ALPS_PROTO_V3: -+ alps_process_packet_v3(psmouse); -+ break; -+ case ALPS_PROTO_V4: -+ alps_process_packet_v4(psmouse); -+ break; -+ } -+} -+ - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -@@ -376,11 +641,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_GOOD_DATA; - } - -+static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ struct alps_data *priv = psmouse->private; -+ int command; -+ unsigned char *param; -+ unsigned char dummy[4]; -+ -+ BUG_ON(nibble > 0xf); -+ -+ command = priv->nibble_commands[nibble].command; -+ param = (command & 0x0f00) ? -+ dummy : (unsigned char *)&priv->nibble_commands[nibble].data; -+ -+ if (ps2_command(ps2dev, param, command)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ struct alps_data *priv = psmouse->private; -+ int i, nibble; -+ -+ if (ps2_command(ps2dev, NULL, priv->addr_command)) -+ return -1; -+ -+ for (i = 12; i >= 0; i -= 4) { -+ nibble = (addr >> i) & 0xf; -+ if (alps_command_mode_send_nibble(psmouse, nibble)) -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[4]; -+ -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return -1; -+ -+ /* -+ * The address being read is returned in the first two bytes -+ * of the result. Check that this address matches the expected -+ * address. -+ */ -+ if (addr != ((param[0] << 8) | param[1])) -+ return -1; -+ -+ return param[2]; -+} -+ -+static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -+{ -+ if (alps_command_mode_set_addr(psmouse, addr)) -+ return -1; -+ return __alps_command_mode_read_reg(psmouse, addr); -+} -+ -+static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) -+{ -+ if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) -+ return -1; -+ if (alps_command_mode_send_nibble(psmouse, value & 0xf)) -+ return -1; -+ return 0; -+} -+ -+static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, -+ u8 value) -+{ -+ if (alps_command_mode_set_addr(psmouse, addr)) -+ return -1; -+ return __alps_command_mode_write_reg(psmouse, value); -+} -+ -+static int alps_enter_command_mode(struct psmouse *psmouse, -+ unsigned char *resp) -+{ -+ unsigned char param[4]; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ psmouse_err(psmouse, "failed to enter command mode\n"); -+ return -1; -+ } -+ -+ if (param[0] != 0x88 && param[1] != 0x07) { -+ psmouse_dbg(psmouse, -+ "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); -+ return -1; -+ } -+ -+ if (resp) -+ *resp = param[2]; -+ return 0; -+} -+ -+static inline int alps_exit_command_mode(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) -+ return -1; -+ return 0; -+} -+ - static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; -+ const struct alps_model_info *model = NULL; - int i; - - /* -@@ -428,12 +809,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - *version = (param[0] << 8) | (param[1] << 4) | i; - } - -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) -+ 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; -+ sizeof(alps_model_data[i].signature))) { -+ model = alps_model_data + i; -+ break; -+ } -+ } - -- return NULL; -+ if (model && model->proto_version > ALPS_PROTO_V2) { -+ /* -+ * Need to check command mode response to identify -+ * model -+ */ -+ model = NULL; -+ if (alps_enter_command_mode(psmouse, param)) { -+ psmouse_warn(psmouse, -+ "touchpad failed to enter command mode\n"); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -+ alps_model_data[i].command_mode_resp == param[0]) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ alps_exit_command_mode(psmouse); -+ -+ if (!model) -+ psmouse_dbg(psmouse, -+ "Unknown command mode response %2.2x\n", -+ param[0]); -+ } -+ } -+ -+ return model; - } - - /* -@@ -441,7 +851,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * 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, bool enable) -+static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; -@@ -458,7 +868,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) - return 0; - } - --static int alps_absolute_mode(struct psmouse *psmouse) -+static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - -@@ -533,13 +943,13 @@ static int alps_poll(struct psmouse *psmouse) - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) -- alps_passthrough_mode(psmouse, true); -+ alps_passthrough_mode_v2(psmouse, true); - - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - - if (priv->i->flags & ALPS_PASS) -- alps_passthrough_mode(psmouse, false); -+ alps_passthrough_mode_v2(psmouse, false); - - if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) - return -1; -@@ -556,13 +966,13 @@ static int alps_poll(struct psmouse *psmouse) - return 0; - } - --static int alps_hw_init(struct psmouse *psmouse) -+static int alps_hw_init_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if ((model->flags & ALPS_PASS) && -- alps_passthrough_mode(psmouse, true)) { -+ alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } - -@@ -571,13 +981,13 @@ static int alps_hw_init(struct psmouse *psmouse) - return -1; - } - -- if (alps_absolute_mode(psmouse)) { -+ if (alps_absolute_mode_v1_v2(psmouse)) { - psmouse_err(psmouse, "Failed to enable absolute mode\n"); - return -1; - } - - if ((model->flags & ALPS_PASS) && -- alps_passthrough_mode(psmouse, false)) { -+ alps_passthrough_mode_v2(psmouse, false)) { - return -1; - } - -@@ -590,6 +1000,297 @@ static int alps_hw_init(struct psmouse *psmouse) - return 0; - } - -+/* -+ * Enable or disable passthrough mode to the trackstick. Must be in -+ * command mode when calling this function. -+ */ -+static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ if (reg_val == -1) -+ return -1; -+ -+ if (enable) -+ reg_val |= 0x01; -+ else -+ reg_val &= ~0x01; -+ -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+/* Must be in command mode when calling this function */ -+static int alps_absolute_mode_v3(struct psmouse *psmouse) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); -+ if (reg_val == -1) -+ return -1; -+ -+ reg_val |= 0x06; -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_hw_init_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val; -+ unsigned char param[4]; -+ -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error; -+ -+ /* Check for trackstick */ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ if (reg_val == -1) -+ goto error; -+ if (reg_val & 0x80) { -+ if (alps_passthrough_mode_v3(psmouse, true)) -+ goto error; -+ if (alps_exit_command_mode(psmouse)) -+ goto error; -+ -+ /* -+ * E7 report for the trackstick -+ * -+ * There have been reports of failures to seem to trace back -+ * to the above trackstick check failing. When these occur -+ * this E7 report fails, so when that happens we continue -+ * with the assumption that there isn't a trackstick after -+ * all. -+ */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ psmouse_warn(psmouse, "trackstick E7 report failed\n"); -+ } else { -+ psmouse_dbg(psmouse, -+ "trackstick E7 report: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); -+ -+ /* -+ * Not sure what this does, but it is absolutely -+ * essential. Without it, the touchpad does not -+ * work at all and the trackstick just emits normal -+ * PS/2 packets. -+ */ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ alps_command_mode_send_nibble(psmouse, 0x9) || -+ alps_command_mode_send_nibble(psmouse, 0x4)) { -+ psmouse_err(psmouse, -+ "Error sending magic E6 sequence\n"); -+ goto error_passthrough; -+ } -+ } -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error_passthrough; -+ if (alps_passthrough_mode_v3(psmouse, false)) -+ goto error; -+ } -+ -+ if (alps_absolute_mode_v3(psmouse)) { -+ psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ goto error; -+ } -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0006); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) -+ goto error; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0007); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, 0x04)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) -+ goto error; -+ if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) -+ goto error; -+ if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) -+ goto error; -+ -+ /* -+ * This ensures the trackstick packets are in the format -+ * supported by this driver. If bit 1 isn't set the packet -+ * format is different. -+ */ -+ if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ -+ /* Set rate and enable data reporting */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -+ psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ return -1; -+ } -+ -+ return 0; -+ -+error_passthrough: -+ /* Something failed while in passthrough mode, so try to get out */ -+ if (!alps_enter_command_mode(psmouse, NULL)) -+ alps_passthrough_mode_v3(psmouse, false); -+error: -+ /* -+ * Leaving the touchpad in command mode will essentially render -+ * it unusable until the machine reboots, so exit it here just -+ * to be safe -+ */ -+ alps_exit_command_mode(psmouse); -+ return -1; -+} -+ -+/* Must be in command mode when calling this function */ -+static int alps_absolute_mode_v4(struct psmouse *psmouse) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); -+ if (reg_val == -1) -+ return -1; -+ -+ reg_val |= 0x02; -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_hw_init_v4(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[4]; -+ -+ priv->nibble_commands = alps_v4_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_DISABLE; -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error; -+ -+ if (alps_absolute_mode_v4(psmouse)) { -+ psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ goto error; -+ } -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ -+ /* -+ * This sequence changes the output from a 9-byte to an -+ * 8-byte format. All the same data seems to be present, -+ * just in a more compact format. -+ */ -+ param[0] = 0xc8; -+ param[1] = 0x64; -+ param[2] = 0x50; -+ if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) -+ return -1; -+ -+ /* Set rate and enable data reporting */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -+ psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ return -1; -+ } -+ -+ return 0; -+ -+error: -+ /* -+ * Leaving the touchpad in command mode will essentially render -+ * it unusable until the machine reboots, so exit it here just -+ * to be safe -+ */ -+ alps_exit_command_mode(psmouse); -+ return -1; -+} -+ -+static int alps_hw_init(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ const struct alps_model_info *model = priv->i; -+ int ret = -1; -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ ret = alps_hw_init_v1_v2(psmouse); -+ break; -+ case ALPS_PROTO_V3: -+ ret = alps_hw_init_v3(psmouse); -+ break; -+ case ALPS_PROTO_V4: -+ ret = alps_hw_init_v4(psmouse); -+ break; -+ } -+ -+ return ret; -+} -+ - static int alps_reconnect(struct psmouse *psmouse) - { - const struct alps_model_info *model; -@@ -630,6 +1331,8 @@ int alps_init(struct psmouse *psmouse) - - psmouse->private = priv; - -+ psmouse_reset(psmouse); -+ - model = alps_get_model(psmouse, &version); - if (!model) - goto init_fail; -@@ -657,8 +1360,20 @@ int alps_init(struct psmouse *psmouse) - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); -- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+ break; -+ case ALPS_PROTO_V3: -+ case ALPS_PROTO_V4: -+ input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); -+ break; -+ } -+ - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - - if (model->flags & ALPS_WHEEL) { -@@ -701,7 +1416,7 @@ int alps_init(struct psmouse *psmouse) - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; -- psmouse->pktsize = 6; -+ psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 4ce9bba..62db7f4 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -14,22 +14,36 @@ - - #define ALPS_PROTO_V1 0 - #define ALPS_PROTO_V2 1 -+#define ALPS_PROTO_V3 2 -+#define ALPS_PROTO_V4 3 - - struct alps_model_info { - unsigned char signature[3]; -+ unsigned char command_mode_resp; /* v3/v4 only */ - unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; - }; - -+struct alps_nibble_commands { -+ int command; -+ unsigned char data; -+}; -+ - struct alps_data { - struct input_dev *dev2; /* Relative device */ - char phys[32]; /* Phys */ - const struct alps_model_info *i;/* Info */ -+ const struct alps_nibble_commands *nibble_commands; -+ int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ -+ int multi_packet; /* Multi-packet data in progress */ -+ u8 quirks; - struct timer_list timer; - }; - -+#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ -+ - #ifdef CONFIG_MOUSE_PS2_ALPS - int alps_detect(struct psmouse *psmouse, bool set_properties); - int alps_init(struct psmouse *psmouse); -diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h -index 9b84b0c..11a9c6c 100644 ---- a/drivers/input/mouse/psmouse.h -+++ b/drivers/input/mouse/psmouse.h -@@ -8,6 +8,7 @@ - #define PSMOUSE_CMD_SETSTREAM 0x00ea - #define PSMOUSE_CMD_SETPOLL 0x00f0 - #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ -+#define PSMOUSE_CMD_RESET_WRAP 0x00ec - #define PSMOUSE_CMD_GETID 0x02f2 - #define PSMOUSE_CMD_SETRATE 0x10f3 - #define PSMOUSE_CMD_ENABLE 0x00f4 --- -1.7.7.3 - - -From 01ce661fc83005947dc958a5739c153843af8a73 Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 7 Nov 2011 19:54:13 -0800 -Subject: [PATCH 5/6] Input: ALPS - add semi-MT support for v3 protocol - -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Acked-by: Chase Douglas <chase.douglas@canonical.com> -Signed-off-by: Dmitry Torokhov <dtor@mail.ru> ---- - drivers/input/mouse/alps.c | 233 ++++++++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/alps.h | 1 + - 2 files changed, 215 insertions(+), 19 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index a0248fd..bd87380 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -17,6 +17,7 @@ - - #include <linux/slab.h> - #include <linux/input.h> -+#include <linux/input/mt.h> - #include <linux/serio.h> - #include <linux/libps2.h> - -@@ -26,6 +27,12 @@ - /* - * Definitions for ALPS version 3 and 4 command mode protocol - */ -+#define ALPS_V3_X_MAX 2000 -+#define ALPS_V3_Y_MAX 1400 -+ -+#define ALPS_BITMAP_X_BITS 15 -+#define ALPS_BITMAP_Y_BITS 11 -+ - #define ALPS_CMD_NIBBLE_10 0x01f2 - - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -250,6 +257,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - input_sync(dev); - } - -+/* -+ * Process bitmap data from v3 and v4 protocols. Returns the number of -+ * fingers detected. A return value of 0 means at least one of the -+ * bitmaps was empty. -+ * -+ * The bitmaps don't have enough data to track fingers, so this function -+ * only generates points representing a bounding box of all contacts. -+ * These points are returned in x1, y1, x2, and y2 when the return value -+ * is greater than 0. -+ */ -+static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, -+ int *x1, int *y1, int *x2, int *y2) -+{ -+ struct alps_bitmap_point { -+ int start_bit; -+ int num_bits; -+ }; -+ -+ int fingers_x = 0, fingers_y = 0, fingers; -+ int i, bit, prev_bit; -+ struct alps_bitmap_point x_low = {0,}, x_high = {0,}; -+ struct alps_bitmap_point y_low = {0,}, y_high = {0,}; -+ struct alps_bitmap_point *point; -+ -+ if (!x_map || !y_map) -+ return 0; -+ -+ *x1 = *y1 = *x2 = *y2 = 0; -+ -+ prev_bit = 0; -+ point = &x_low; -+ for (i = 0; x_map != 0; i++, x_map >>= 1) { -+ bit = x_map & 1; -+ if (bit) { -+ if (!prev_bit) { -+ point->start_bit = i; -+ fingers_x++; -+ } -+ point->num_bits++; -+ } else { -+ if (prev_bit) -+ point = &x_high; -+ else -+ point->num_bits = 0; -+ } -+ prev_bit = bit; -+ } -+ -+ /* -+ * y bitmap is reversed for what we need (lower positions are in -+ * higher bits), so we process from the top end. -+ */ -+ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); -+ prev_bit = 0; -+ point = &y_low; -+ for (i = 0; y_map != 0; i++, y_map <<= 1) { -+ bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); -+ if (bit) { -+ if (!prev_bit) { -+ point->start_bit = i; -+ fingers_y++; -+ } -+ point->num_bits++; -+ } else { -+ if (prev_bit) -+ point = &y_high; -+ else -+ point->num_bits = 0; -+ } -+ prev_bit = bit; -+ } -+ -+ /* -+ * Fingers can overlap, so we use the maximum count of fingers -+ * on either axis as the finger count. -+ */ -+ fingers = max(fingers_x, fingers_y); -+ -+ /* -+ * If total fingers is > 1 but either axis reports only a single -+ * contact, we have overlapping or adjacent fingers. For the -+ * purposes of creating a bounding box, divide the single contact -+ * (roughly) equally between the two points. -+ */ -+ if (fingers > 1) { -+ if (fingers_x == 1) { -+ i = x_low.num_bits / 2; -+ x_low.num_bits = x_low.num_bits - i; -+ x_high.start_bit = x_low.start_bit + i; -+ x_high.num_bits = max(i, 1); -+ } else if (fingers_y == 1) { -+ i = y_low.num_bits / 2; -+ y_low.num_bits = y_low.num_bits - i; -+ y_high.start_bit = y_low.start_bit + i; -+ y_high.num_bits = max(i, 1); -+ } -+ } -+ -+ *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_X_BITS - 1)); -+ *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ -+ if (fingers > 1) { -+ *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_X_BITS - 1)); -+ *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ } -+ -+ return fingers; -+} -+ -+static void alps_set_slot(struct input_dev *dev, int slot, bool active, -+ int x, int y) -+{ -+ input_mt_slot(dev, slot); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); -+ if (active) { -+ input_report_abs(dev, ABS_MT_POSITION_X, x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, y); -+ } -+} -+ -+static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, -+ int x1, int y1, int x2, int y2) -+{ -+ alps_set_slot(dev, 0, num_fingers != 0, x1, y1); -+ alps_set_slot(dev, 1, num_fingers == 2, x2, y2); -+} -+ - static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -318,16 +456,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - struct input_dev *dev2 = priv->dev2; - int x, y, z; - int left, right, middle; -+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ int fingers = 0, bmap_fingers; -+ unsigned int x_bitmap, y_bitmap; - - /* -- * There's no single feature of touchpad position and bitmap -- * packets that can be used to distinguish between them. We -- * rely on the fact that a bitmap packet should always follow -- * a position packet with bit 6 of packet[4] set. -+ * There's no single feature of touchpad position and bitmap packets -+ * that can be used to distinguish between them. We rely on the fact -+ * that a bitmap packet should always follow a position packet with -+ * bit 6 of packet[4] set. - */ - if (priv->multi_packet) { -- priv->multi_packet = 0; -- - /* - * Sometimes a position packet will indicate a multi-packet - * sequence, but then what follows is another position -@@ -335,18 +474,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * position packet as usual. - */ - if (packet[0] & 0x40) { -+ fingers = (packet[5] & 0x3) + 1; -+ x_bitmap = ((packet[4] & 0x7e) << 8) | -+ ((packet[1] & 0x7f) << 2) | -+ ((packet[0] & 0x30) >> 4); -+ y_bitmap = ((packet[3] & 0x70) << 4) | -+ ((packet[2] & 0x7f) << 1) | -+ (packet[4] & 0x01); -+ -+ bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ &x1, &y1, &x2, &y2); -+ - /* -- * Bitmap packets are not yet supported, so for now -- * just ignore them. -+ * We shouldn't report more than one finger if -+ * we don't have two coordinates. - */ -- return; -+ if (fingers > 1 && bmap_fingers < 2) -+ fingers = bmap_fingers; -+ -+ /* Now process position packet */ -+ packet = priv->multi_data; -+ } else { -+ priv->multi_packet = 0; - } - } - -- if (!priv->multi_packet && (packet[4] & 0x40)) -+ /* -+ * Bit 6 of byte 0 is not usually set in position packets. The only -+ * times it seems to be set is in situations where the data is -+ * suspect anyway, e.g. a palm resting flat on the touchpad. Given -+ * this combined with the fact that this bit is useful for filtering -+ * out misidentified bitmap packets, we reject anything with this -+ * bit set. -+ */ -+ if (packet[0] & 0x40) -+ return; -+ -+ if (!priv->multi_packet && (packet[4] & 0x40)) { - priv->multi_packet = 1; -- else -- priv->multi_packet = 0; -+ memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); -+ return; -+ } -+ -+ priv->multi_packet = 0; - - left = packet[3] & 0x01; - right = packet[3] & 0x02; -@@ -366,22 +536,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - if (x && y && !z) - return; - -+ /* -+ * If we don't have MT data or the bitmaps were empty, we have -+ * to rely on ST data. -+ */ -+ if (!fingers) { -+ x1 = x; -+ y1 = y; -+ fingers = z > 0 ? 1 : 0; -+ } -+ - if (z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); - -+ alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); -+ input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); -+ -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ - 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); -- input_report_key(dev, BTN_LEFT, left); -- input_report_key(dev, BTN_RIGHT, right); -- input_report_key(dev, BTN_MIDDLE, middle); -- - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -@@ -1368,9 +1554,18 @@ int alps_init(struct psmouse *psmouse) - input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); - break; - case ALPS_PROTO_V3: -+ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -+ input_mt_init_slots(dev1, 2); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ -+ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -+ /* fall through */ - case ALPS_PROTO_V4: -- input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); -+ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); - break; - } - -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 62db7f4..a00a4ab 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -38,6 +38,7 @@ struct alps_data { - int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ - int multi_packet; /* Multi-packet data in progress */ -+ unsigned char multi_data[6]; /* Saved multi-packet data */ - u8 quirks; - struct timer_list timer; - }; --- -1.7.7.3 - - -From 7cf801cfc0774b777aa6861cf4a43a90b112b1ed Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 7 Nov 2011 19:54:35 -0800 -Subject: [PATCH 6/6] Input: ALPS - add documentation for protocol versions 3 - and 4 - -Also converts from using "old" and "new" to describe the already-known -protocols to using "version 1" and "version 2" to match the code. - -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Acked-by: Chase Douglas <chase.douglas@canonical.com> -Signed-off-by: Dmitry Torokhov <dtor@mail.ru> ---- - Documentation/input/alps.txt | 135 ++++++++++++++++++++++++++++++++++++++---- - 1 files changed, 124 insertions(+), 11 deletions(-) - -diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt -index ab5478f..f274c28 100644 ---- a/Documentation/input/alps.txt -+++ b/Documentation/input/alps.txt -@@ -4,12 +4,9 @@ ALPS Touchpad Protocol - Introduction - ------------ - --Currently the ALPS touchpad driver supports two protocol versions in use by --ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these --differ only in the format of their event packets (in reality many features may --be found on new protocol devices that aren't found on the old protocol --devices, but these are handled transparently as feature differences rather --than protocol differences). -+Currently the ALPS touchpad driver supports four protocol versions in use by -+ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various -+protocol versions is contained in the following sections. - - Detection - --------- -@@ -22,10 +19,37 @@ If the E6 report is successful, the touchpad model is identified using the "E7 - report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is - matched against known models in the alps_model_data_array. - -+With protocol versions 3 and 4, the E7 report model signature is always -+73-02-64. To differentiate between these versions, the response from the -+"Enter Command Mode" sequence must be inspected as described below. -+ -+Command Mode -+------------ -+ -+Protocol versions 3 and 4 have a command mode that is used to read and write -+one-byte device registers in a 16-bit address space. The command sequence -+EC-EC-EC-E9 places the device in command mode, and the device will respond -+with 88-07 followed by a third byte. This third byte can be used to determine -+whether the devices uses the version 3 or 4 protocol. -+ -+To exit command mode, PSMOUSE_CMD_SETSTREAM (EA) is sent to the touchpad. -+ -+While in command mode, register addresses can be set by first sending a -+specific command, either EC for v3 devices or F5 for v4 devices. Then the -+address is sent one nibble at a time, where each nibble is encoded as a -+command with optional data. This enoding differs slightly between the v3 and -+v4 protocols. -+ -+Once an address has been set, the addressed register can be read by sending -+PSMOUSE_CMD_GETINFO (E9). The first two bytes of the response contains the -+address of the register being read, and the third contains the value of the -+register. Registers are written by writing the value one nibble at a time -+using the same encoding used for addresses. -+ - Packet Format - ------------- - --In the following tables, the following notation us used. -+In the following tables, the following notation is used. - - CAPITALS = stick, miniscules = touchpad - -@@ -41,8 +65,8 @@ PS/2 packet format - - Note that the device never signals overflow condition. - --ALPS Absolute Mode - Old Format --------------------------------- -+ALPS Absolute Mode - Protocol Verion 1 -+-------------------------------------- - - byte 0: 1 0 0 0 1 x9 x8 x7 - byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -@@ -51,8 +75,8 @@ ALPS Absolute Mode - Old Format - byte 4: 0 y6 y5 y4 y3 y2 y1 y0 - byte 5: 0 z6 z5 z4 z3 z2 z1 z0 - --ALPS Absolute Mode - New Format --------------------------------- -+ALPS Absolute Mode - Protocol Version 2 -+--------------------------------------- - - byte 0: 1 ? ? ? 1 ? ? ? - byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -@@ -73,3 +97,92 @@ Dualpoint device -- interleaved packet format - byte 6: 0 y9 y8 y7 1 m r l - byte 7: 0 y6 y5 y4 y3 y2 y1 y0 - byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+ALPS Absolute Mode - Protocol Version 3 -+--------------------------------------- -+ -+ALPS protocol version 3 has three different packet formats. The first two are -+associated with touchpad events, and the third is associatd with trackstick -+events. -+ -+The first type is the touchpad position packet. -+ -+ byte 0: 1 ? x1 x0 1 1 1 1 -+ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 -+ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 -+ byte 3: 0 M R L 1 m r l -+ byte 4: 0 mt x3 x2 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+Note that for some devices the trackstick buttons are reported in this packet, -+and on others it is reported in the trackstick packets. -+ -+The second packet type contains bitmaps representing the x and y axes. In the -+bitmaps a given bit is set if there is a finger covering that position on the -+given axis. Thus the bitmap packet can be used for low-resolution multi-touch -+data, although finger tracking is not possible. This packet also encodes the -+number of contacts (f1 and f0 in the table below). -+ -+ byte 0: 1 1 x1 x0 1 1 1 1 -+ byte 1: 0 x8 x7 x6 x5 x4 x3 x2 -+ byte 2: 0 y7 y6 y5 y4 y3 y2 y1 -+ byte 3: 0 y10 y9 y8 1 1 1 1 -+ byte 4: 0 x14 x13 x12 x11 x10 x9 y0 -+ byte 5: 0 1 ? ? ? ? f1 f0 -+ -+This packet only appears after a position packet with the mt bit set, and -+ususally only appears when there are two or more contacts (although -+ocassionally it's seen with only a single contact). -+ -+The final v3 packet type is the trackstick packet. -+ -+ byte 0: 1 1 x7 y7 1 1 1 1 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 3: 0 1 0 0 1 0 0 0 -+ byte 4: 0 z4 z3 z2 z1 z0 ? ? -+ byte 5: 0 0 1 1 1 1 1 1 -+ -+ALPS Absolute Mode - Protocol Version 4 -+--------------------------------------- -+ -+Protocol version 4 has an 8-byte packet format. -+ -+ byte 0: 1 ? x1 x0 1 1 1 1 -+ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 -+ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 -+ byte 3: 0 1 x3 x2 y3 y2 y1 y0 -+ byte 4: 0 ? ? ? 1 ? r l -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ byte 6: bitmap data (described below) -+ byte 7: bitmap data (described below) -+ -+The last two bytes represent a partial bitmap packet, with 3 full packets -+required to construct a complete bitmap packet. Once assembled, the 6-byte -+bitmap packet has the following format: -+ -+ byte 0: 0 1 x7 x6 x5 x4 x3 x2 -+ byte 1: 0 x1 x0 y4 y3 y2 y1 y0 -+ byte 2: 0 0 ? x14 x13 x12 x11 x10 -+ byte 3: 0 x9 x8 y9 y8 y7 y6 y5 -+ byte 4: 0 0 0 0 0 0 0 0 -+ byte 5: 0 0 0 0 0 0 0 y10 -+ -+There are several things worth noting here. -+ -+ 1) In the bitmap data, bit 6 of byte 0 serves as a sync byte to -+ identify the first fragment of a bitmap packet. -+ -+ 2) The bitmaps represent the same data as in the v3 bitmap packets, although -+ the packet layout is different. -+ -+ 3) There doesn't seem to be a count of the contact points anywhere in the v4 -+ protocol packets. Deriving a count of contact points must be done by -+ analyzing the bitmaps. -+ -+ 4) There is a 3 to 1 ratio of position packets to bitmap packets. Therefore -+ MT position can only be updated for every third ST position update, and -+ the count of contact points can only be updated every third packet as -+ well. -+ -+So far no v4 devices with tracksticks have been encountered. --- -1.7.7.3 - |