Permalink
Browse files

alps: Add support for Dell Latitude E6430 touchpad

This appears to be a protocol v3 device but requires a different
initialization procedure. Still need to sort out what the initialization
procedure means.
  • Loading branch information...
1 parent 3a89248 commit 1527416a726b823225f97c4d733dcdd9df7f50d6 @bgamari committed Aug 15, 2012
Showing with 130 additions and 0 deletions.
  1. +128 −0 drivers/input/mouse/alps.c
  2. +1 −0 drivers/input/mouse/alps.h
  3. +1 −0 drivers/input/mouse/psmouse-base.c
View
@@ -15,6 +15,7 @@
* the Free Software Foundation.
*/
+#define DEBUG
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
@@ -112,6 +113,8 @@ static const struct alps_model_info alps_model_data[] = {
{ { 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 },
+ /* Dell Latitude E6430 */
+ { { 0x73, 0x03, 0x0a }, 0x1d, ALPS_PROTO_V5, 0x8f, 0x8f, ALPS_DUALPOINT },
};
/*
@@ -712,6 +715,9 @@ static void alps_process_packet(struct psmouse *psmouse)
case ALPS_PROTO_V4:
alps_process_packet_v4(psmouse);
break;
+ case ALPS_PROTO_V5:
+ alps_process_packet_v3(psmouse);
+ break;
}
}
@@ -1519,6 +1525,124 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
return -1;
}
+static int alps_hw_init_v5(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char param[4];
+ unsigned int i=0;
+
+#define DO_CMD(cmd) i++; \
+ if (ps2_command(ps2dev, NULL, cmd)) { \
+ psmouse_err(psmouse, "Failed to init: %d (cmd=%02x)\n", i, cmd); \
+ return -1; \
+ }
+#define DO_CMD_ARG(arg, cmd) \
+ i++; \
+ param[0] = arg; \
+ if (ps2_command(ps2dev, param, cmd)) { \
+ psmouse_err(psmouse, "Failed to init with arg: %d (cmd=%02x, arg=%02x)\n", i, cmd, arg); \
+ return -1; \
+ }
+
+ DO_CMD(PSMOUSE_CMD_RESET_BAT);
+ DO_CMD(PSMOUSE_CMD_RESET_BAT);
+
+ DO_CMD(PSMOUSE_CMD_SETSTREAM);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ DO_CMD_ARG(0, PSMOUSE_CMD_GETINFO);
+
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ DO_CMD_ARG(0x01, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD_ARG(0x01, PSMOUSE_CMD_SETRES);
+ DO_CMD_ARG(0x64, PSMOUSE_CMD_SETRATE);
+ DO_CMD_ARG(0, PSMOUSE_CMD_GETINFO);
+ DO_CMD_ARG(0x64, PSMOUSE_CMD_SETRATE);
+ DO_CMD(PSMOUSE_CMD_RESET_DIS);
+ DO_CMD(PSMOUSE_CMD_SETSTREAM);
+
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+ DO_CMD(PSMOUSE_CMD_SETSCALE11);
+ DO_CMD(PSMOUSE_CMD_SETSCALE11);
+ DO_CMD(PSMOUSE_CMD_SETSCALE11);
+ param[0] = 0xc8;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ param[0] = 0x14;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ DO_CMD(PSMOUSE_CMD_SETSTREAM);
+
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ param[0] = 0x64;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ param[0] = 0x64;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ param[0] = 0x14;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+ DO_CMD(PSMOUSE_CMD_SETPOLL);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ param[0] = 0xc8;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ param[0] = 0x00;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETPOLL);
+ DO_CMD(PSMOUSE_CMD_SETPOLL);
+ DO_CMD(PSMOUSE_CMD_RESET_WRAP);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ param[0] = 0x01;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+ param[0] = 0x64;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+ param[0] = 0x64;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ DO_CMD(PSMOUSE_CMD_SETSCALE21);
+ DO_CMD(PSMOUSE_CMD_SETSTREAM);
+ param[0] = 0x64;
+ ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+ ps2_command(ps2dev, param, PSMOUSE_CMD_ENABLE);
+
+ return 0;
+}
+
static int alps_hw_init(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
@@ -1536,6 +1660,9 @@ static int alps_hw_init(struct psmouse *psmouse)
case ALPS_PROTO_V4:
ret = alps_hw_init_v4(psmouse);
break;
+ case ALPS_PROTO_V5:
+ ret = alps_hw_init_v5(psmouse);
+ break;
}
return ret;
@@ -1619,6 +1746,7 @@ int alps_init(struct psmouse *psmouse)
break;
case ALPS_PROTO_V3:
case ALPS_PROTO_V4:
+ case ALPS_PROTO_V5:
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);
@@ -16,6 +16,7 @@
#define ALPS_PROTO_V2 1
#define ALPS_PROTO_V3 2
#define ALPS_PROTO_V4 3
+#define ALPS_PROTO_V5 4
struct alps_model_info {
unsigned char signature[3];
@@ -11,6 +11,7 @@
* the Free Software Foundation.
*/
+#define DEBUG
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define psmouse_fmt(fmt) fmt

23 comments on commit 1527416

Since this patch appears to fix https://bugzilla.redhat.com/show_bug.cgi?id=812111, can you please submit it upstream for review?

Owner

bgamari replied Aug 23, 2012

Yes, I do intend on submitting this upstream. Unfortunately before that can happen someone needs to clean up the initialization code (which constitutes the bulk of the patch). I'm fairly certain the current approach of blindly parroting the initialization sequence of the Windows driver would not be accepted upstream. There is a good chance that the command structure resembles that of the v3 protocol, so decomposing it through that lens might be a good place to start. I've been meaning to do this but life has been in the way recently. Perhaps this weekend I'll have an opportunity to do this.

pfoo replied Aug 30, 2012

working on my e6530 ;) Good job !

Hi, Ben!
I haven't tried the patch so far because I don't have enough knowledge to try it. I'm one of those Inspiron 15R N5110 users whose got the same problem as yours. I just hope your code solves this issue for my hardware too, I'm eager to try it!

Thanks for your work! ;)

Hi Ben,

I have tried your patch with UBUNTU 12.04.1 LTS (kernel 3.2.0-29) on DELL Latitude E6430 and it works great. Many thanks for your work! There are a plenty of people out there waiting exactly for this fix...

-alex-

seebk replied Sep 6, 2012

@alexmerx How did you compile the patch with kernel 3.2? I get the error/warning that psmouse_reset is an unknown symbol...

@seebk Of course you have to adapt the alps.c, alps.h and psmouse-base.c of the original kernel 3.2 sources. You can't take the complete files of Ben 1:1 for kernel 3.2 because they are adaptions to kernel 3.5-sources. I will send you alps.c, alps.h and psmouse-base.c regarding kernel 3.2 per mail and you can test it by yourself.

-alex-

seebk replied Sep 6, 2012

@alexmerx Thanks. That would be great!

seebk replied Sep 6, 2012

seebk replied Sep 6, 2012

Great it works!! 2 finger scrolling is a bit strange and not smooth. But edge scrolling is fine! Thank you very much.

Gosh, I'm so jealous! Hope someone will work out something similar for the Dell Inspiron 15R.

Is that possible to make Dell Vostro 3360 touchpad work?

Hi, Latitude E6430 here, Archlinux kernel 3.5.3:
I compiled a patched psmouse.ko and now xinput list shows correcly "AlpsPS/2 ALPS DualPoint TouchPad".
Still Xorg can't use the driver through synaptics. Here is the error:

11.927 LoadModule: "synaptics"
11.927 Loading /usr/lib/xorg/modules/input/synaptics_drv.so
11.927 Module synaptics: vendor="X.Org Foundation"
[ 11.927] compiled for 1.12.2, module version = 1.6.2
[ 11.927] Module class: X.Org XInput Driver
[ 11.927] ABI class: X.Org XInput driver, version 16.0
11.927 Using input driver 'synaptics' for 'AlpsPS/2 ALPS DualPoint TouchPad'
11.927 AlpsPS/2 ALPS DualPoint TouchPad: always reports core events
11.927 Option "Device" "/dev/input/mouse1"
11.930 synaptics: AlpsPS/2 ALPS DualPoint TouchPad: Synaptics driver unable to detect protocol
11.930 PreInit returned 11 for "AlpsPS/2 ALPS DualPoint TouchPad"
11.930 UnloadModule: "synaptics"

Any clue?

Also I would like to add that the preinstalled Ubuntu on this laptop had edge scrolling and even two-fingers scrolling when it came. How did they do it???

adq replied Sep 9, 2012

Hi, this makes the touchpad on my Dell Precision M6700 work properly too; nice one!

After applying the patch, xinit correctly sees the touchpad of my Dell Latitude E6230. However, it doesn't seem to work in Xorg: even after restarting, the touchpad and buttons remain completely inactive. Any idea on how to debug this situation?

I inspected the recovery partition with Ubuntu that was preinstalled on my system: turns out that there is a binary userspace driver from a company called cirque, that even has a grafical configuration utility, written in java. It gets installed from a .deb package badly converted from an .rpm, so there should be an rpm somewhere as well.

It uses a system daemon called glided, and a user session daemon called glideusd. Both with no manpages or --help options or other documentation.
In xinput the device is listed as "GlidePoint Virtual Touchpad".

I have so far not found any webpage or link for this driver. I don't think many are aware of its existance.
It works decently though and does not need this patch. I'll contact the company about it in the next days.

@soulrebel could you please make some extraction of that utils and upload it somewhere?

On xorg startup, my E6430's touchpad is recognized, thanks much:

4363.084 synaptics: AlpsPS/2 ALPS DualPoint TouchPad: touchpad found

Good luck getting this into the linus kernel!

Hi,

thanks a lot, this patch (copy&paste by emacs) works also on my Dell M6700 on a 3.7.1-2-desktop kernel.
By the way: I got the link to this via Dell-Support in Germany....
But compiling the whole kernel with all SuSE12.2 modules took "ages"...

In xorg.conf one needs to say:

Section "InputDevice"
Driver "synaptics"
Identifier "TouchPad"
Option "SendCoreEvents"
Option "Protocol" "auto-dev"
Option "SHMConfig" "on"
Option "VertEdgeScroll" "on"
EndSection

and

Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0"
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
InputDevice "TouchPad" "CorePointer"
EndSection

Then you can tweak the settings via:
xinput set-prop 6 "Synaptics Tap Action" 1 1 1 1 1 1 1
xinput set-prop 6 "Synaptics Edge Scrolling" 1 1 1

Hopefuly, soon in the main kernel tree.

Thanks again for your effort!

Michael

Owner

bgamari replied Dec 21, 2012

I'm glad to hear that it works for you! I should note that Dave Turvene and others have been doing some excellent work to generalize this patch. Their work is documented on the Launchpad issue. It seems that initialization sequence may actually be stored in the ACPI DSDT table, which would remove a lot of the messiness from this patch.

avar replied Feb 14, 2013

I've got this working on a Dell Latitude E6330 on Debian 7.0. I
rebased your patch on top of the v3.7 tag in linux-2.6.git since I was
running that version, and then built the kernel per these
instructions
. Now
synclient -l returns all the configuration, and the touchpad is
listed as such by xinput:

$ xinput --list|head -n 4
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ DualPoint Stick                           id=12   [slave  pointer  (2)]
⎜   ↳ AlpsPS/2 ALPS DualPoint TouchPad          id=13   [slave  pointer  (2)]

dmesg after boot reports the following:

$ dmesg|grep -i alps
[   13.400695] psmouse serio1: alps: E6 report: 00 00 64
[   13.419878] psmouse serio1: alps: E7 report: 73 03 0a
[   13.871696] psmouse serio1: alps: E6 report: 00 00 64
[   13.889948] psmouse serio1: alps: E7 report: 73 03 0a
[   15.059881] input: AlpsPS/2 ALPS DualPoint TouchPad as /devices/platform/i8042/serio1/input/input17

Have you (@bgamari) made any attempt to upstream this with the Alps
maintainers?

I'd be keen to see support for this in the upstream kernel so I don't
have to build my own version forever. I could help with that if
needed.

The initialization procedure you added seems really odd compared to
the init procedure for v1-v4. Your commit message indicates that you
don't understand what it means, how did you get this initialization
procedure? Was it reverse engineered from a Windows driver or
something?

Owner

bgamari replied Feb 14, 2013

@avar, I'm very glad to hear that this is working for you. While I've had little time to push this farther forward, there are thankfully numerous others who have. The majority of the work is documented (albeit not in a terribly readable way) on the Launchpad issue.

As you've noted, the initialization procedure isn't terribly well understood. I reverse engineered this from the Windows driver and while it works for some models, the hardware is quite varied. While it works, I've been reluctant to submit this upstream until the initialization procedure is understood.

It seems that Kevin Cernekee has put into some effort into cleaning up and restructuring the work into a mergable form which is currently being discussed on the linux-input list. You may want to have a look at this.

Please sign in to comment.