Patchwork [2/3] Input: ALPS - Add code to support "Rushmore" touchpads

login
register
mail settings
Submitter Kevin Cernekee
Date Jan. 20, 2013, 9:31 a.m.
Message ID <092b691c8e994d31cb235fd7c45afee4@localhost>
Download mbox | patch
Permalink /patch/2007961/
State New, archived
Headers show

Comments

Kevin Cernekee - Jan. 20, 2013, 9:31 a.m.
These touchpads mostly speak the V3 protocol, but they use a different
method for detection.  The manufacturer's driver follows a sequence that
looks something like:

  Send E7 query and look for an exact match: 73 03 50 ("Dolphin")
  If no match, send EC query and look for 88 {07,08} xx ("Pinnacle")
  If no match, send E7 query and look for 73 02 {0a,14,3c,50} ("Mercury II")
  If no match, send a more complicated query and look for 88 05 xx ("Mercury")

This patch adds the new EC query before the usual E7 query.  It is
presumed (hoped) that anything that isn't in the Pinnacle series will not
return "88 07 xx" or "88 08 xx".

Tested on:

Dell E6230 ("Rushmore" model from the "Pinnacle" series)
Dell E6430 (same as above, but with trackstick + more buttons)

On both PCs, the E7 report is 73 03 0a, and the EC report is 88 08 1d.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 drivers/input/mouse/alps.c |   93 ++++++++++++++++++++++++++++++++++++++++----
 drivers/input/mouse/alps.h |    6 +++
 2 files changed, 92 insertions(+), 7 deletions(-)
Peter Korsgaard - Jan. 26, 2013, 11:53 a.m.
>>>>> "Kevin" == Kevin Cernekee <cernekee@gmail.com> writes:

 Kevin> These touchpads mostly speak the V3 protocol, but they use a different
 Kevin> method for detection.  The manufacturer's driver follows a sequence that
 Kevin> looks something like:

 Kevin>   Send E7 query and look for an exact match: 73 03 50 ("Dolphin")
 Kevin>   If no match, send EC query and look for 88 {07,08} xx ("Pinnacle")
 Kevin>   If no match, send E7 query and look for 73 02 {0a,14,3c,50} ("Mercury II")
 Kevin>   If no match, send a more complicated query and look for 88 05 xx ("Mercury")

 Kevin> This patch adds the new EC query before the usual E7 query.  It is
 Kevin> presumed (hoped) that anything that isn't in the Pinnacle series will not
 Kevin> return "88 07 xx" or "88 08 xx".

 Kevin> Tested on:

 Kevin> Dell E6230 ("Rushmore" model from the "Pinnacle" series)
 Kevin> Dell E6430 (same as above, but with trackstick + more buttons)

 Kevin> On both PCs, the E7 report is 73 03 0a, and the EC report is 88 08 1d.

 Kevin> Signed-off-by: Kevin Cernekee <cernekee@gmail.com>

Thanks. I've tested it here on a e6230 (bios rev 08), and it gets
correctly detected (but twice?):

input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input14
input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input16

But the input events seem very noisy (E.G. the cursor jumps up and down
if I keep my finger pressed on the touchpad). Especially the Y
coordinate seems unstable:


Event: time 1359201123.864208, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1042
Event: time 1359201123.864208, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 669
Event: time 1359201123.864208, type 3 (EV_ABS), code 0 (ABS_X), value 1042
Event: time 1359201123.864208, type 3 (EV_ABS), code 1 (ABS_Y), value 669
Event: time 1359201123.864208, -------------- SYN_REPORT ------------
Event: time 1359201123.874130, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1043
Event: time 1359201123.874130, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 659
Event: time 1359201123.874130, type 3 (EV_ABS), code 0 (ABS_X), value 1043
Event: time 1359201123.874130, type 3 (EV_ABS), code 1 (ABS_Y), value 659
Event: time 1359201123.874130, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 32
Event: time 1359201123.874130, -------------- SYN_REPORT ------------
Event: time 1359201123.883495, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1038
Event: time 1359201123.883495, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 660
Event: time 1359201123.883495, type 3 (EV_ABS), code 0 (ABS_X), value 1038
Event: time 1359201123.883495, type 3 (EV_ABS), code 1 (ABS_Y), value 660
Event: time 1359201123.883495, -------------- SYN_REPORT ------------
Event: time 1359201123.893641, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1037
Event: time 1359201123.893641, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 655
Event: time 1359201123.893641, type 3 (EV_ABS), code 0 (ABS_X), value 1037
Event: time 1359201123.893641, type 3 (EV_ABS), code 1 (ABS_Y), value 655
Event: time 1359201123.893641, -------------- SYN_REPORT ------------
Event: time 1359201123.904044, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1039
Event: time 1359201123.904044, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 651
Event: time 1359201123.904044, type 3 (EV_ABS), code 0 (ABS_X), value 1039
Event: time 1359201123.904044, type 3 (EV_ABS), code 1 (ABS_Y), value 651
Event: time 1359201123.904044, -------------- SYN_REPORT ------------
Event: time 1359201123.914023, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1040
Event: time 1359201123.914023, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 645
Event: time 1359201123.914023, type 3 (EV_ABS), code 0 (ABS_X), value 1040
Event: time 1359201123.914023, type 3 (EV_ABS), code 1 (ABS_Y), value 645
Event: time 1359201123.914023, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 30
Event: time 1359201123.914023, -------------- SYN_REPORT ------------
Event: time 1359201123.924340, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1035
Event: time 1359201123.924340, type 3 (EV_ABS), code 0 (ABS_X), value 1035
Event: time 1359201123.924340, -------------- SYN_REPORT ------------
Event: time 1359201123.934719, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1040
Event: time 1359201123.934719, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 635
Event: time 1359201123.934719, type 3 (EV_ABS), code 0 (ABS_X), value 1040
Event: time 1359201123.934719, type 3 (EV_ABS), code 1 (ABS_Y), value 635
Event: time 1359201123.934719, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 29
Event: time 1359201123.934719, -------------- SYN_REPORT ------------
Event: time 1359201123.946719, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1050
Event: time 1359201123.946719, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 665
Event: time 1359201123.946719, type 3 (EV_ABS), code 0 (ABS_X), value 1050
Event: time 1359201123.946719, type 3 (EV_ABS), code 1 (ABS_Y), value 665
Event: time 1359201123.946719, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 23

Any idea why? Do you see this as well?
Kevin Cernekee - Jan. 26, 2013, 6:45 p.m.
On Sat, Jan 26, 2013 at 3:53 AM, Peter Korsgaard <jacmet@sunsite.dk> wrote:
> Thanks. I've tested it here on a e6230 (bios rev 08), and it gets
> correctly detected (but twice?):
>
> input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input14
> input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input16

It should show one input device for the trackstick, and one input
device for the touchpad:

[397682.041027] input: DualPoint Stick as
/devices/platform/i8042/serio1/input/input17
[397682.054959] input: AlpsPS/2 ALPS DualPoint TouchPad as
/devices/platform/i8042/serio1/input/input18

I'm not sure what would cause it to register two identical touchpads;
I don't see that on either E6230 or E6430.  Did you build psmouse.ko
from my DKMS sources, or apply the patches on top of some other
baseline?

> But the input events seem very noisy (E.G. the cursor jumps up and down
> if I keep my finger pressed on the touchpad). Especially the Y
> coordinate seems unstable:

OK - I do see this on E6230 but not E6430.  Normal usage is fine but
the "pressed finger" test fails on E6230.  I'll do some digging and
try to figure out why.

In another thread [1] it was mentioned that the ALPS_BITMAP_*
constants needed to be tweaked for the Rushmore touchpads.  This might
be related.

I also saw some "lost sync" errors in the kernel log on E6430 after
running for a few days, but I don't know how to reproduce the issue.
They did not seem to be associated with any obvious touchpad
misbehavior.

[1] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/606238
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Korsgaard - Jan. 26, 2013, 6:51 p.m.
>>>>> "Kevin" == Kevin Cernekee <cernekee@gmail.com> writes:

Hi,

 Kevin> It should show one input device for the trackstick, and one input
 Kevin> device for the touchpad:

 Kevin> [397682.041027] input: DualPoint Stick as
 Kevin> /devices/platform/i8042/serio1/input/input17
 Kevin> [397682.054959] input: AlpsPS/2 ALPS DualPoint TouchPad as
 Kevin> /devices/platform/i8042/serio1/input/input18

Hmm, odd - I rebooted and now it seems ok:

dmesg|egrep -i 'stick|alps'
input: DualPoint Stick as /devices/platform/i8042/serio1/input/input13
input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input14

What is this trackstick thing?


 Kevin> I'm not sure what would cause it to register two identical touchpads;
 Kevin> I don't see that on either E6230 or E6430.  Did you build psmouse.ko
 Kevin> from my DKMS sources, or apply the patches on top of some other
 Kevin> baseline?

I applied the series on top of 3.7.4.


 >> But the input events seem very noisy (E.G. the cursor jumps up and down
 >> if I keep my finger pressed on the touchpad). Especially the Y
 >> coordinate seems unstable:

 Kevin> OK - I do see this on E6230 but not E6430.  Normal usage is fine but
 Kevin> the "pressed finger" test fails on E6230.  I'll do some digging and
 Kevin> try to figure out why.

Great, thanks! Let me know if you want me to test something.
Kevin Cernekee - Jan. 26, 2013, 7:09 p.m.
On Sat, Jan 26, 2013 at 10:51 AM, Peter Korsgaard <jacmet@sunsite.dk> wrote:
> Hmm, odd - I rebooted and now it seems ok:
>
> dmesg|egrep -i 'stick|alps'
> input: DualPoint Stick as /devices/platform/i8042/serio1/input/input13
> input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input14

I hope this code does not fail intermittently...

> What is this trackstick thing?

On other laptops (e.g. Dell E6430) there is a trackstick on the
keyboard between the G/H/B keys, and its reports are handled by the
ALPS driver.

There was a suggestion in the launchpad.net thread to check a register
bit to see if the trackstick is present, but it isn't yet clear
whether this bit actually indicates the presence of the trackstick or
if it just "happens" to be set on the units that have tracksticks.

My suggestion was to avoid registering the trackstick if we have a
foolproof way of knowing it's missing, otherwise just register it
unconditionally to be safe.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Korsgaard - Jan. 26, 2013, 7:12 p.m.
>>>>> "Kevin" == Kevin Cernekee <cernekee@gmail.com> writes:

Hi,

 Kevin> I hope this code does not fail intermittently...

I'll run some more / do some more reboots and let you know.


 >> What is this trackstick thing?

 Kevin> On other laptops (e.g. Dell E6430) there is a trackstick on the
 Kevin> keyboard between the G/H/B keys, and its reports are handled by the
 Kevin> ALPS driver.

 Kevin> There was a suggestion in the launchpad.net thread to check a register
 Kevin> bit to see if the trackstick is present, but it isn't yet clear
 Kevin> whether this bit actually indicates the presence of the trackstick or
 Kevin> if it just "happens" to be set on the units that have tracksticks.

 Kevin> My suggestion was to avoid registering the trackstick if we have a
 Kevin> foolproof way of knowing it's missing, otherwise just register it
 Kevin> unconditionally to be safe.

yeah, seems like the safest approach.
Peter Korsgaard - May 6, 2013, 7:34 p.m.
>>>>> "Peter" == Peter Korsgaard <jacmet@sunsite.dk> writes:

Hi,

Old thread, but I only now got time to upgrade to 3.9 and retest.

 Peter> Thanks. I've tested it here on a e6230 (bios rev 08), and it gets
 Peter> correctly detected

 Peter> But the input events seem very noisy (E.G. the cursor jumps up and down
 Peter> if I keep my finger pressed on the touchpad). Especially the Y
 Peter> coordinate seems unstable:

 Peter> Event: time 1359201123.864208, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1042
 Peter> Event: time 1359201123.864208, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 669
 Peter> Event: time 1359201123.864208, type 3 (EV_ABS), code 0 (ABS_X), value 1042
 Peter> Event: time 1359201123.864208, type 3 (EV_ABS), code 1 (ABS_Y), value 669
 Peter> Event: time 1359201123.864208, -------------- SYN_REPORT ------------
 Peter> Event: time 1359201123.874130, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1043
 Peter> Event: time 1359201123.874130, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 659
 Peter> Event: time 1359201123.874130, type 3 (EV_ABS), code 0 (ABS_X), value 1043
 Peter> Event: time 1359201123.874130, type 3 (EV_ABS), code 1 (ABS_Y), value 659
 Peter> Event: time 1359201123.874130, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 32
 Peter> Event: time 1359201123.874130, -------------- SYN_REPORT ------------

I still see this noisy output with 3.9:

sudo evtest /dev/input/event16                                         ~
Input driver version is 1.0.1
Input device ID: bus 0x11 vendor 0x2 product 0x8 version 0x300
Input device name: "AlpsPS/2 ALPS GlidePoint"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 272 (BTN_LEFT)
    Event code 273 (BTN_RIGHT)
    Event code 274 (BTN_MIDDLE)
    Event code 325 (BTN_TOOL_FINGER)
    Event code 330 (BTN_TOUCH)
    Event code 333 (BTN_TOOL_DOUBLETAP)
    Event code 334 (BTN_TOOL_TRIPLETAP)
    Event code 335 (BTN_TOOL_QUADTAP)
  Event type 3 (EV_ABS)
    Event code 0 (ABS_X)
      Value    363
      Min        0
      Max     2000
    Event code 1 (ABS_Y)
      Value    295
      Min        0
      Max     1400
    Event code 24 (ABS_PRESSURE)
      Value      0
      Min        0
      Max      127
    Event code 47 (ABS_MT_SLOT)
      Value      0
      Min        0
      Max        1
    Event code 53 (ABS_MT_POSITION_X)
      Value      0
      Min        0
      Max     2000
    Event code 54 (ABS_MT_POSITION_Y)
      Value      0
      Min        0
      Max     1400
    Event code 57 (ABS_MT_TRACKING_ID)
      Value      0
      Min        0
      Max    65535
Properties:
  Property type 3 (INPUT_PROP_SEMI_MT)
Testing ... (interrupt to exit)

Event: time 1367868378.646499, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1147
Event: time 1367868378.646499, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 855
Event: time 1367868378.646499, type 3 (EV_ABS), code 0 (ABS_X), value 1147
Event: time 1367868378.646499, type 3 (EV_ABS), code 1 (ABS_Y), value 855
Event: time 1367868378.646499, -------------- SYN_REPORT ------------
Event: time 1367868378.656671, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1145
Event: time 1367868378.656671, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 858
Event: time 1367868378.656671, type 3 (EV_ABS), code 0 (ABS_X), value 1145
Event: time 1367868378.656671, type 3 (EV_ABS), code 1 (ABS_Y), value 858
Event: time 1367868378.656671, -------------- SYN_REPORT ------------
Event: time 1367868378.667997, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1144
Event: time 1367868378.667997, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 853
Event: time 1367868378.667997, type 3 (EV_ABS), code 0 (ABS_X), value 1144
Event: time 1367868378.667997, type 3 (EV_ABS), code 1 (ABS_Y), value 853
Event: time 1367868378.667997, -------------- SYN_REPORT ------------
Event: time 1367868378.677139, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1142
Event: time 1367868378.677139, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 851
Event: time 1367868378.677139, type 3 (EV_ABS), code 0 (ABS_X), value 1142
Event: time 1367868378.677139, type 3 (EV_ABS), code 1 (ABS_Y), value 851
Event: time 1367868378.677139, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 33
Event: time 1367868378.677139, -------------- SYN_REPORT ------------
Event: time 1367868378.687460, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1140
Event: time 1367868378.687460, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 849
Event: time 1367868378.687460, type 3 (EV_ABS), code 0 (ABS_X), value 1140
Event: time 1367868378.687460, type 3 (EV_ABS), code 1 (ABS_Y), value 849
Event: time 1367868378.687460, -------------- SYN_REPORT ------------
Event: time 1367868378.697723, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 1138
Event: time 1367868378.697723, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 843
Event: time 1367868378.697723, type 3 (EV_ABS), code 0 (ABS_X), value 1138
Event: time 1367868378.697723, type 3 (EV_ABS), code 1 (ABS_Y), value 843
Event: time 1367868378.697723, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 32

This is with a single finger stadily on the touchpad. X/Y/Z all seem to
move a bit around.

I added a few debug printks to alps.c and see that it correctly gets
detected as a rushmore/v3:

ALPS touchpad: E7=73 03 0a, EC=88 08 1d
alps_identify detected proto 3

This is the data sequence it generates:

alps decode af 46 2c 08 35 1b
alps decode 9f 46 2c 08 31 1b
alps decode 8f 46 2c 08 33 1b
alps decode 8f 46 2c 08 32 1b
alps decode 8f 46 2c 08 32 1b
alps decode bf 46 2c 08 25 1b
alps decode 9f 46 2c 08 32 1b
alps decode bf 46 2c 08 26 1b
alps decode 8f 46 2c 08 31 1b
alps decode 8f 46 2c 08 38 1b
alps decode 8f 46 2c 08 32 1c
alps decode 9f 46 2c 08 31 1c
alps decode bf 46 2c 08 30 1c
alps decode af 46 2c 08 36 1b
alps decode af 46 2c 08 35 1b
alps decode 9f 46 2c 08 35 1b
alps decode bf 46 2c 08 29 1b
alps decode 8f 46 2c 08 31 1c
alps decode 9f 46 2b 08 3e 1b
alps decode 9f 46 2c 08 38 1b
alps decode 9f 46 2c 08 32 1b
alps decode 9f 46 2c 08 35 1c
alps decode af 46 2c 08 37 1b

Is this expected behaviour? From a quick look at alps_decode_pinnacle()
it looks sensible. Anything I can do to debug it further?

Patch

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index bb99923..7d5e939 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -114,6 +114,10 @@  static const struct alps_model_info alps_model_data[] = {
 	{ { 0x73, 0x02, 0x64 },	0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 },
 };
 
+static const struct alps_model_info alps_model_rushmore = {
+	{ ALPS_RUSHMORE }, 0x00, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT
+};
+
 /*
  * XXX - this entry is suspicious. First byte has zero lower nibble,
  * which is what a normal mouse would report. Also, the value 0x0e
@@ -393,7 +397,7 @@  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;
+	int x, y, z, left, right, middle, divisor = 8;
 
 	/* Sanity check packet */
 	if (!(packet[0] & 0x40)) {
@@ -408,17 +412,24 @@  static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
 	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;
+	if (priv->i->signature[0] == ALPS_RUSHMORE) {
+		x = (s8)(((packet[0] & 0x20) << 2) | ((packet[1] << 1) & 0x7f));
+		y = (s8)(((packet[2] & 0x10) << 3) | ((packet[4] << 1) & 0x7f));
+		z = (packet[4] & 0x7c) >> 2;
+		divisor = 2;
+	} else {
+		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;
+	x /= divisor;
+	y /= divisor;
 
 	input_report_rel(dev, REL_X, x);
 	input_report_rel(dev, REL_Y, -y);
@@ -996,7 +1007,7 @@  static int alps_enter_command_mode(struct psmouse *psmouse,
 		return -1;
 	}
 
-	if (param[0] != 0x88 && param[1] != 0x07) {
+	if (param[0] != 0x88) {
 		psmouse_dbg(psmouse,
 			    "unknown response while entering command mode: %2.2x %2.2x %2.2x\n",
 			    param[0], param[1], param[2]);
@@ -1016,6 +1027,34 @@  static inline int alps_exit_command_mode(struct psmouse *psmouse)
 	return 0;
 }
 
+static const struct alps_model_info *alps_probe_pinnacle(
+	struct psmouse *psmouse, int *version)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param[4];
+	const struct alps_model_info *model = NULL;
+
+	if (alps_rpt_cmd(ps2dev, PSMOUSE_CMD_SETSTREAM, PSMOUSE_CMD_RESET_WRAP,
+			 param) ||
+	    param[0] != 0x88 ||
+	    (param[1] != 0x07 && param[1] != 0x08))
+		goto out;
+
+	/* For now this code has only been verified to detect Rushmore */
+	if (param[1] == 0x08)
+		model = &alps_model_rushmore;
+	else if (param[2] >= 0x80 && param[2] <= 0x8f)
+		psmouse_info(psmouse, "detected Pinnacle AG via EC report\n");
+	else if (param[2] >= 0x90 && param[2] <= 0x9d)
+		psmouse_info(psmouse, "detected Pinnacle AGx via EC report\n");
+	else if (param[2] < 0x80)
+		psmouse_info(psmouse, "detected Pinnacle via EC report\n");
+
+out:
+	alps_exit_command_mode(psmouse);
+	return model;
+}
+
 static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -1024,6 +1063,11 @@  static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
 	const struct alps_model_info *model = NULL;
 	int i;
 
+	/* Newer devices detect based on the EC report, not the E7 report */
+	model = alps_probe_pinnacle(psmouse, version);
+	if (model)
+		return model;
+
 	/*
 	 * First try "E6 report".
 	 * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
@@ -1285,6 +1329,38 @@  static int alps_absolute_mode_v3(struct psmouse *psmouse)
 	return 0;
 }
 
+static int alps_hw_init_rushmore(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	int reg_val, ret = -1;
+
+	if (alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
+	    alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
+		goto error;
+
+	reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
+	if (reg_val == -1)
+		goto error;
+	if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd))
+		goto error;
+
+	if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
+		goto error;
+
+	reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
+	if (reg_val == -1)
+		goto error;
+	if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
+		goto error;
+
+	alps_exit_command_mode(psmouse);
+	return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+error:
+	alps_exit_command_mode(psmouse);
+	return ret;
+}
+
 static int alps_hw_init_v3(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
@@ -1298,6 +1374,9 @@  static int alps_hw_init_v3(struct psmouse *psmouse)
 	if (alps_enter_command_mode(psmouse, NULL))
 		goto error;
 
+	if (priv->i->signature[0] == ALPS_RUSHMORE)
+		return alps_hw_init_rushmore(psmouse);
+
 	/* Check for trackstick */
 	reg_val = alps_command_mode_read_reg(psmouse, 0x0008);
 	if (reg_val == -1)
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index ae1ac35..152d96b 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -17,6 +17,12 @@ 
 #define ALPS_PROTO_V3	2
 #define ALPS_PROTO_V4	3
 
+/* These are in the same "Pinnacle" family but have different init sequences */
+#define ALPS_PIN	0x01
+#define ALPS_PINAG	0x02
+#define ALPS_PINAGX	0x03
+#define ALPS_RUSHMORE	0x04
+
 struct alps_model_info {
         unsigned char signature[3];
 	unsigned char command_mode_resp; /* v3/v4 only */