2009-10-31 02:10:20

by Maxim Levitsky

[permalink] [raw]
Subject: ALPS touchpad with 4 directions button doesnt work as intended

I have a acer 5720G laptop, and its touchpad (ALPS) has three buttons,
usual left/right, and middle button that can be pressed in 4 directions.
Up/down direction work fine, but left/right doesn't. This means that
left direction produces middle button click, and right direction
doesn't work at all.
I took a look at source, and I see that driver doesn't even know about
such configuration.

Now I am sure its very easy to figure out what is send when no working
button is pressed, but I am a bit confused what BTN_* event to assign to
it, so it will work as horizontal scroll as intended.
And unassign middle button from other direction....

Can you help me a bit?

I am ccing authors of alps.c

Best regards,
Maxim Levitsky



2009-11-02 05:38:36

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

Hi Maxim,

On Sat, Oct 31, 2009 at 04:10:18AM +0200, Maxim Levitsky wrote:
> I have a acer 5720G laptop, and its touchpad (ALPS) has three buttons,
> usual left/right, and middle button that can be pressed in 4 directions.
> Up/down direction work fine, but left/right doesn't. This means that
> left direction produces middle button click, and right direction
> doesn't work at all.
> I took a look at source, and I see that driver doesn't even know about
> such configuration.
>
> Now I am sure its very easy to figure out what is send when no working
> button is pressed, but I am a bit confused what BTN_* event to assign to
> it, so it will work as horizontal scroll as intended.
> And unassign middle button from other direction....
>

Synaptics driver maps multi-button to BTN_0...BTN_8 and it looks like
synaptics X driver maps teh 4-button case by default to
up/down/left/right scroll so I'd map ALPS the same.

--
Dmitry

2009-11-02 17:20:29

by Maxim Levitsky

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

On Sun, 2009-11-01 at 21:38 -0800, Dmitry Torokhov wrote:
> Hi Maxim,
>
> On Sat, Oct 31, 2009 at 04:10:18AM +0200, Maxim Levitsky wrote:
> > I have a acer 5720G laptop, and its touchpad (ALPS) has three buttons,
> > usual left/right, and middle button that can be pressed in 4 directions.
> > Up/down direction work fine, but left/right doesn't. This means that
> > left direction produces middle button click, and right direction
> > doesn't work at all.
> > I took a look at source, and I see that driver doesn't even know about
> > such configuration.
> >
> > Now I am sure its very easy to figure out what is send when no working
> > button is pressed, but I am a bit confused what BTN_* event to assign to
> > it, so it will work as horizontal scroll as intended.
> > And unassign middle button from other direction....
> >
>
> Synaptics driver maps multi-button to BTN_0...BTN_8 and it looks like
> synaptics X driver maps teh 4-button case by default to
> up/down/left/right scroll so I'd map ALPS the same.
>
Thanks!

One question, should I expect some resistance because the button won't
work as middle button by default? (I am sure that in X its easy remap it
back)

Best regards,
Maxim Levitsky

2009-11-02 18:00:26

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

On Mon, Nov 02, 2009 at 07:20:26PM +0200, Maxim Levitsky wrote:
> On Sun, 2009-11-01 at 21:38 -0800, Dmitry Torokhov wrote:
> > Hi Maxim,
> >
> > On Sat, Oct 31, 2009 at 04:10:18AM +0200, Maxim Levitsky wrote:
> > > I have a acer 5720G laptop, and its touchpad (ALPS) has three buttons,
> > > usual left/right, and middle button that can be pressed in 4 directions.
> > > Up/down direction work fine, but left/right doesn't. This means that
> > > left direction produces middle button click, and right direction
> > > doesn't work at all.
> > > I took a look at source, and I see that driver doesn't even know about
> > > such configuration.
> > >
> > > Now I am sure its very easy to figure out what is send when no working
> > > button is pressed, but I am a bit confused what BTN_* event to assign to
> > > it, so it will work as horizontal scroll as intended.
> > > And unassign middle button from other direction....
> > >
> >
> > Synaptics driver maps multi-button to BTN_0...BTN_8 and it looks like
> > synaptics X driver maps teh 4-button case by default to
> > up/down/left/right scroll so I'd map ALPS the same.
> >
> Thanks!
>
> One question, should I expect some resistance because the button won't
> work as middle button by default? (I am sure that in X its easy remap it
> back)
>

I am pretty sure these kind of buttons allow 5 distinct presses - left,
right, up, down and "straight" (which may be reported either with
distinct packet or by reporting both up/down or left/right presses) so
you don't have to loose the middle button. This is a speculation
though...

--
Dmitry

2009-11-02 22:16:29

by Maxim Levitsky

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

On Tue, 2009-11-03 at 00:12 +0200, Maxim Levitsky wrote:
> On Mon, 2009-11-02 at 10:00 -0800, Dmitry Torokhov wrote:
> > On Mon, Nov 02, 2009 at 07:20:26PM +0200, Maxim Levitsky wrote:
> > > On Sun, 2009-11-01 at 21:38 -0800, Dmitry Torokhov wrote:
> > > > Hi Maxim,
> > > >
> > > > On Sat, Oct 31, 2009 at 04:10:18AM +0200, Maxim Levitsky wrote:
> > > > > I have a acer 5720G laptop, and its touchpad (ALPS) has three buttons,
> > > > > usual left/right, and middle button that can be pressed in 4 directions.
> > > > > Up/down direction work fine, but left/right doesn't. This means that
> > > > > left direction produces middle button click, and right direction
> > > > > doesn't work at all.
> > > > > I took a look at source, and I see that driver doesn't even know about
> > > > > such configuration.
> > > > >
> > > > > Now I am sure its very easy to figure out what is send when no working
> > > > > button is pressed, but I am a bit confused what BTN_* event to assign to
> > > > > it, so it will work as horizontal scroll as intended.
> > > > > And unassign middle button from other direction....
> > > > >
> > > >
> > > > Synaptics driver maps multi-button to BTN_0...BTN_8 and it looks like
> > > > synaptics X driver maps teh 4-button case by default to
> > > > up/down/left/right scroll so I'd map ALPS the same.
> > > >
> > > Thanks!
> > >
> > > One question, should I expect some resistance because the button won't
> > > work as middle button by default? (I am sure that in X its easy remap it
> > > back)
> > >
> >
> > I am pretty sure these kind of buttons allow 5 distinct presses - left,
> > right, up, down and "straight" (which may be reported either with
> > distinct packet or by reporting both up/down or left/right presses) so
> > you don't have to loose the middle button. This is a speculation
> > though...
> >
>
> Mine doesn't unfortunately, this is if I press it 'straight' I both feel
> physicaly 4 different presses and it reports currently, 'back button'
> 'forward button' and 'middle button' as I press it.
>
> It is possible to implement emulation, but I think that pressing it
> straight might also put some stress and damage it in long run.
>
>
> I think that pressing left+right buttons will be enough for the
> replacement. If not, xmodmap can be used to map each of the 4 buttons
> (or all of them to middle one)
>
>
> Best regards,
> Maxim Levitsky
>


Sorry, forgot to CC lkml...


2009-11-02 22:25:40

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

On Monday 02 November 2009 02:16:28 pm Maxim Levitsky wrote:
> On Tue, 2009-11-03 at 00:12 +0200, Maxim Levitsky wrote:
> > On Mon, 2009-11-02 at 10:00 -0800, Dmitry Torokhov wrote:
> > > On Mon, Nov 02, 2009 at 07:20:26PM +0200, Maxim Levitsky wrote:
> > > > On Sun, 2009-11-01 at 21:38 -0800, Dmitry Torokhov wrote:
> > > > > Hi Maxim,
> > > > >
> > > > > On Sat, Oct 31, 2009 at 04:10:18AM +0200, Maxim Levitsky wrote:
> > > > > > I have a acer 5720G laptop, and its touchpad (ALPS) has three
> > > > > > buttons, usual left/right, and middle button that can be pressed
> > > > > > in 4 directions. Up/down direction work fine, but left/right
> > > > > > doesn't. This means that left direction produces middle button
> > > > > > click, and right direction doesn't work at all.
> > > > > > I took a look at source, and I see that driver doesn't even know
> > > > > > about such configuration.
> > > > > >
> > > > > > Now I am sure its very easy to figure out what is send when no
> > > > > > working button is pressed, but I am a bit confused what BTN_*
> > > > > > event to assign to it, so it will work as horizontal scroll as
> > > > > > intended.
> > > > > > And unassign middle button from other direction....
> > > > >
> > > > > Synaptics driver maps multi-button to BTN_0...BTN_8 and it looks
> > > > > like synaptics X driver maps teh 4-button case by default to
> > > > > up/down/left/right scroll so I'd map ALPS the same.
> > > >
> > > > Thanks!
> > > >
> > > > One question, should I expect some resistance because the button
> > > > won't work as middle button by default? (I am sure that in X its easy
> > > > remap it back)
> > >
> > > I am pretty sure these kind of buttons allow 5 distinct presses - left,
> > > right, up, down and "straight" (which may be reported either with
> > > distinct packet or by reporting both up/down or left/right presses) so
> > > you don't have to loose the middle button. This is a speculation
> > > though...
> >
> > Mine doesn't unfortunately, this is if I press it 'straight' I both feel
> > physicaly 4 different presses and it reports currently, 'back button'
> > 'forward button' and 'middle button' as I press it.
> >
> > It is possible to implement emulation, but I think that pressing it
> > straight might also put some stress and damage it in long run.
> >
> >
> > I think that pressing left+right buttons will be enough for the
> > replacement. If not, xmodmap can be used to map each of the 4 buttons
> > (or all of them to middle one)
> >
> >
> > Best regards,
> > Maxim Levitsky
>
> Sorry, forgot to CC lkml...
>

OK, fair enough.

--
Dmitry

2009-11-02 23:21:28

by Maxim Levitsky

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

On Mon, 2009-11-02 at 14:25 -0800, Dmitry Torokhov wrote:
> On Monday 02 November 2009 02:16:28 pm Maxim Levitsky wrote:
> > On Tue, 2009-11-03 at 00:12 +0200, Maxim Levitsky wrote:
> > > On Mon, 2009-11-02 at 10:00 -0800, Dmitry Torokhov wrote:
> > > > On Mon, Nov 02, 2009 at 07:20:26PM +0200, Maxim Levitsky wrote:
> > > > > On Sun, 2009-11-01 at 21:38 -0800, Dmitry Torokhov wrote:
> > > > > > Hi Maxim,
> > > > > >
> > > > > > On Sat, Oct 31, 2009 at 04:10:18AM +0200, Maxim Levitsky wrote:
> > > > > > > I have a acer 5720G laptop, and its touchpad (ALPS) has three
> > > > > > > buttons, usual left/right, and middle button that can be pressed
> > > > > > > in 4 directions. Up/down direction work fine, but left/right
> > > > > > > doesn't. This means that left direction produces middle button
> > > > > > > click, and right direction doesn't work at all.
> > > > > > > I took a look at source, and I see that driver doesn't even know
> > > > > > > about such configuration.
> > > > > > >
> > > > > > > Now I am sure its very easy to figure out what is send when no
> > > > > > > working button is pressed, but I am a bit confused what BTN_*
> > > > > > > event to assign to it, so it will work as horizontal scroll as
> > > > > > > intended.
> > > > > > > And unassign middle button from other direction....
> > > > > >
> > > > > > Synaptics driver maps multi-button to BTN_0...BTN_8 and it looks
> > > > > > like synaptics X driver maps teh 4-button case by default to
> > > > > > up/down/left/right scroll so I'd map ALPS the same.
> > > > >
> > > > > Thanks!
> > > > >
> > > > > One question, should I expect some resistance because the button
> > > > > won't work as middle button by default? (I am sure that in X its easy
> > > > > remap it back)
> > > >
> > > > I am pretty sure these kind of buttons allow 5 distinct presses - left,
> > > > right, up, down and "straight" (which may be reported either with
> > > > distinct packet or by reporting both up/down or left/right presses) so
> > > > you don't have to loose the middle button. This is a speculation
> > > > though...
> > >
> > > Mine doesn't unfortunately, this is if I press it 'straight' I both feel
> > > physicaly 4 different presses and it reports currently, 'back button'
> > > 'forward button' and 'middle button' as I press it.
> > >
> > > It is possible to implement emulation, but I think that pressing it
> > > straight might also put some stress and damage it in long run.
> > >
> > >
> > > I think that pressing left+right buttons will be enough for the
> > > replacement. If not, xmodmap can be used to map each of the 4 buttons
> > > (or all of them to middle one)
> > >
> > >
> > > Best regards,
> > > Maxim Levitsky
> >
> > Sorry, forgot to CC lkml...
> >
>
> OK, fair enough.
>
Thanks, no more questions.

Best regards,
Maxim Levitsky

2009-11-10 09:55:41

by Maxim Levitsky

[permalink] [raw]
Subject: Re: ALPS touchpad with 4 directions button doesnt work as intended

On Sat, 2009-10-31 at 04:10 +0200, Maxim Levitsky wrote:
> I have a acer 5720G laptop, and its touchpad (ALPS) has three buttons,
> usual left/right, and middle button that can be pressed in 4 directions.
> Up/down direction work fine, but left/right doesn't. This means that
> left direction produces middle button click, and right direction
> doesn't work at all.
> I took a look at source, and I see that driver doesn't even know about
> such configuration.
>
> Now I am sure its very easy to figure out what is send when no working
> button is pressed, but I am a bit confused what BTN_* event to assign to
> it, so it will work as horizontal scroll as intended.
> And unassign middle button from other direction....

I have written now the patch to resolve this issue on my laptop.
However I had to put a dmi check for my system, because I afraid I break
others.

The problem is that the device reports 4way button in bizarre way, this
is it reports left way click as a middle button.

I can't test for laptops that really have just middle button and thus
reporting it as the left way scroll is wrong.

Testing for hardware version probably won't help, I am afraid that this
is laptop specific. Windows .INF file has plenty of suspicious entries
about that.

The ALPS touchpad on my notebook reports 0x73, 0x02, 0x50 for the
version.

Also up/down directions are now reported by BTN_0, BTN_1
Feel free to ask me not to do so if there is a reason to do so.
Here it works both ways.


Best regards,
Maxim Levitsky

2009-11-10 10:03:48

by Maxim Levitsky

[permalink] [raw]
Subject: [PATCH] ALPS: Add support for 4 directions button on Acer Aspire 5720

>From 4aefbe6c09df53881c4738c1a524be595a388e28 Mon Sep 17 00:00:00 2001
From: Maxim Levitsky <[email protected]>
Date: Tue, 10 Nov 2009 11:57:56 +0200
Subject: [PATCH] ALPS: Add support for 4 directions button on Acer Aspire 5720
Implemented using DMI due to uncertainty about systems that have
only the middle button

Signed-off-by: Maxim Levitsky <[email protected]>
---
drivers/input/mouse/alps.c | 81 +++++++++++++++++++++++++++++++++++--------
drivers/input/mouse/alps.h | 2 +-
2 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index f361106..06a5709 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -17,6 +17,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/libps2.h>
+#include <linux/dmi.h>

#include "psmouse.h"
#include "alps.h"
@@ -28,13 +29,17 @@
#define dbg(format, arg...) do {} while (0)
#endif

-#define ALPS_DUALPOINT 0x01
-#define ALPS_WHEEL 0x02
-#define ALPS_FW_BK_1 0x04
-#define ALPS_4BTN 0x08
-#define ALPS_OLDPROTO 0x10
-#define ALPS_PASS 0x20
-#define ALPS_FW_BK_2 0x40
+
+#define ALPS_OLDPROTO 0x01 /* old style input */
+#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
+#define ALPS_PASS 0x04 /* select which device to address each time */
+
+
+#define ALPS_WHEEL 0x08 /* hardware wheel present */
+#define ALPS_FW_BK_1 0x10 /* front & back buttons present */
+#define ALPS_FW_BK_2 0x20 /* front & back buttons present */
+#define ALPS_EXTRA 0x40 /* 4 direction button present */
+

static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -147,7 +152,13 @@ static void alps_process_packet(struct psmouse *psmouse)

input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
- input_report_key(dev, BTN_MIDDLE, middle);
+
+
+ /* middle button serves as left scroll button */
+ if ((priv->i->flags & ALPS_EXTRA))
+ input_report_key(dev, BTN_2, middle);
+ else
+ input_report_key(dev, BTN_MIDDLE, middle);

/* Convert hardware tap to a reasonable Z value */
if (ges && !fin) z = 40;
@@ -181,10 +192,13 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));

if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
- input_report_key(dev, BTN_FORWARD, forward);
- input_report_key(dev, BTN_BACK, back);
+ input_report_key(dev, BTN_0, forward);
+ input_report_key(dev, BTN_1, back);
}

+ if (priv->i->flags & ALPS_EXTRA)
+ input_report_key(dev, BTN_3, packet[0] & 0x20);
+
input_sync(dev);
}

@@ -216,9 +230,10 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
return PSMOUSE_GOOD_DATA;
}

-static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
+static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
+ struct alps_model_info *model_info;
static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
unsigned char param[4];
int i;
@@ -268,9 +283,16 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int

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_info = kmalloc(sizeof(struct alps_model_info),
+ GFP_KERNEL);

+ memcpy(model_info, alps_model_data + i,
+ sizeof(struct alps_model_info));
+
+ return model_info;
+ }
return NULL;
}

@@ -393,6 +415,25 @@ static int alps_poll(struct psmouse *psmouse)
return 0;
}

+static int alps_dmi_flags;
+static int alps_acer_5720_flags(const struct dmi_system_id *d)
+{
+ alps_dmi_flags = ALPS_EXTRA | ALPS_FW_BK_1;
+ return 0;
+}
+
+static struct dmi_system_id alps_dmi_table[] = {
+ {
+ .callback = alps_acer_5720_flags,
+ .ident = "Acer Aspire 5720",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+ },
+ },
+ {}
+};
+
static int alps_hw_init(struct psmouse *psmouse, int *version)
{
struct alps_data *priv = psmouse->private;
@@ -401,6 +442,10 @@ static int alps_hw_init(struct psmouse *psmouse, int *version)
if (!priv->i)
return -1;

+ dmi_check_system(alps_dmi_table);
+ if (alps_dmi_flags)
+ priv->i->flags = alps_dmi_flags;
+
if ((priv->i->flags & ALPS_PASS) &&
alps_passthrough_mode(psmouse, true)) {
return -1;
@@ -446,6 +491,7 @@ static void alps_disconnect(struct psmouse *psmouse)

psmouse_reset(psmouse);
input_unregister_device(priv->dev2);
+ kfree(priv->i);
kfree(priv);
}

@@ -483,8 +529,13 @@ int alps_init(struct psmouse *psmouse)
}

if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
- dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
- dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
+ dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
+ dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
+ }
+
+ if (priv->i->flags & ALPS_EXTRA) {
+ dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
+ dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
}

snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index bc87936..92505d5 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -21,7 +21,7 @@ struct alps_model_info {
struct alps_data {
struct input_dev *dev2; /* Relative device */
char phys[32]; /* Phys */
- const struct alps_model_info *i;/* Info */
+ struct alps_model_info *i; /* Info */
int prev_fin; /* Finger bit from previous packet */
};

--
1.6.3.3


2009-11-10 17:30:50

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH] ALPS: Add support for 4 directions button on Acer Aspire 5720

Hi Maxim,

On Tue, Nov 10, 2009 at 12:03:47PM +0200, Maxim Levitsky wrote:
> @@ -483,8 +529,13 @@ int alps_init(struct psmouse *psmouse)
> }
>
> if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
> - dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
> - dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
> + dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
> + dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
> + }
> +
> + if (priv->i->flags & ALPS_EXTRA) {
> + dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
> + dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
> }
>

Please don;t do this, you are breaking existing users. Add
ALPS_FOUR_BUTTONS flag and use it to report BTN_0..BTN_3 in your case.

I am also unsure if we need to do DMI entry, I'll try to dig original
submisison for that signature and see...

Thanks.

--
Dmitry

2009-11-11 09:09:55

by Maxim Levitsky

[permalink] [raw]
Subject: [PATCH v2] ALPS: Add support for 4 directions button on Acer Aspire 5720

>From 6b263982ffd62ae4621a5202f0084983af8dc093 Mon Sep 17 00:00:00 2001
From: Maxim Levitsky <[email protected]>
Date: Wed, 11 Nov 2009 11:03:35 +0200
Subject: [PATCH] ALPS: Add support for 4 directions button on Acer Aspire 5720
Implemented using DMI due to uncertainty about systems that have
only the middle button

Signed-off-by: Maxim Levitsky <[email protected]>
---
drivers/input/mouse/alps.c | 75 +++++++++++++++++++++++++++++++++++++-------
drivers/input/mouse/alps.h | 2 +-
2 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index f361106..96fa093 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -17,6 +17,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/libps2.h>
+#include <linux/dmi.h>

#include "psmouse.h"
#include "alps.h"
@@ -28,13 +29,16 @@
#define dbg(format, arg...) do {} while (0)
#endif

-#define ALPS_DUALPOINT 0x01
-#define ALPS_WHEEL 0x02
-#define ALPS_FW_BK_1 0x04
-#define ALPS_4BTN 0x08
-#define ALPS_OLDPROTO 0x10
-#define ALPS_PASS 0x20
-#define ALPS_FW_BK_2 0x40
+
+#define ALPS_OLDPROTO 0x01 /* old style input */
+#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
+#define ALPS_PASS 0x04 /* select which device to address each time */
+
+#define ALPS_WHEEL 0x08 /* hardware wheel present */
+#define ALPS_FW_BK_1 0x10 /* front & back buttons present */
+#define ALPS_FW_BK_2 0x20 /* front & back buttons present */
+#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
+

static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -117,7 +121,7 @@ static void alps_process_packet(struct psmouse *psmouse)
z = packet[5];
}

- if (priv->i->flags & ALPS_FW_BK_1) {
+ if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FOUR_BUTTONS)) {
back = packet[0] & 0x10;
forward = packet[2] & 4;
}
@@ -147,7 +151,9 @@ static void alps_process_packet(struct psmouse *psmouse)

input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
- input_report_key(dev, BTN_MIDDLE, middle);
+
+ if (!(priv->i->flags & ALPS_FOUR_BUTTONS))
+ input_report_key(dev, BTN_MIDDLE, middle);

/* Convert hardware tap to a reasonable Z value */
if (ges && !fin) z = 40;
@@ -185,6 +191,13 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_key(dev, BTN_BACK, back);
}

+ if (priv->i->flags & ALPS_FOUR_BUTTONS) {
+ input_report_key(dev, BTN_0, forward);
+ input_report_key(dev, BTN_1, back);
+ input_report_key(dev, BTN_2, middle);
+ input_report_key(dev, BTN_3, packet[0] & 0x20);
+ }
+
input_sync(dev);
}

@@ -216,7 +229,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
return PSMOUSE_GOOD_DATA;
}

-static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
+static 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 };
@@ -268,9 +282,15 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int

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_info = kmalloc(sizeof(struct alps_model_info),
+ GFP_KERNEL);

+ memcpy(model_info, alps_model_data + i,
+ sizeof(struct alps_model_info));
+ return model_info;
+ }
return NULL;
}

@@ -393,6 +413,25 @@ static int alps_poll(struct psmouse *psmouse)
return 0;
}

+static int alps_dmi_flags;
+static int alps_acer_5720_flags(const struct dmi_system_id *d)
+{
+ alps_dmi_flags = ALPS_FOUR_BUTTONS;
+ return 0;
+}
+
+static struct dmi_system_id alps_dmi_table[] = {
+ {
+ .callback = alps_acer_5720_flags,
+ .ident = "Acer Aspire 5720",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+ },
+ },
+ {}
+};
+
static int alps_hw_init(struct psmouse *psmouse, int *version)
{
struct alps_data *priv = psmouse->private;
@@ -401,6 +440,10 @@ static int alps_hw_init(struct psmouse *psmouse, int *version)
if (!priv->i)
return -1;

+ dmi_check_system(alps_dmi_table);
+ if (alps_dmi_flags)
+ priv->i->flags = alps_dmi_flags;
+
if ((priv->i->flags & ALPS_PASS) &&
alps_passthrough_mode(psmouse, true)) {
return -1;
@@ -446,6 +489,7 @@ static void alps_disconnect(struct psmouse *psmouse)

psmouse_reset(psmouse);
input_unregister_device(priv->dev2);
+ kfree(priv->i);
kfree(priv);
}

@@ -487,6 +531,13 @@ int alps_init(struct psmouse *psmouse)
dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
}

+ if (priv->i->flags & ALPS_FOUR_BUTTONS) {
+ dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
+ dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
+ dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
+ dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+ }
+
snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
dev2->phys = priv->phys;
dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index bc87936..92505d5 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -21,7 +21,7 @@ struct alps_model_info {
struct alps_data {
struct input_dev *dev2; /* Relative device */
char phys[32]; /* Phys */
- const struct alps_model_info *i;/* Info */
+ struct alps_model_info *i; /* Info */
int prev_fin; /* Finger bit from previous packet */
};

--
1.6.3.3


2009-11-15 08:53:15

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2] ALPS: Add support for 4 directions button on Acer Aspire 5720

Hi Maxim,

On Wed, Nov 11, 2009 at 11:09:50AM +0200, Maxim Levitsky wrote:
> >From 6b263982ffd62ae4621a5202f0084983af8dc093 Mon Sep 17 00:00:00 2001
> From: Maxim Levitsky <[email protected]>
> Date: Wed, 11 Nov 2009 11:03:35 +0200
> Subject: [PATCH] ALPS: Add support for 4 directions button on Acer Aspire 5720
> Implemented using DMI due to uncertainty about systems that have
> only the middle button
>
> Signed-off-by: Maxim Levitsky <[email protected]>

I don't think that we need to do DMI checking. I looked through my mails
and it looks like all Acers with that signature have 4-directional
button while Volstro 1400 only has left and right button and so won't be
affected. Also Synaptics driver treats BTN_0 as BTN_FORWARD and BTN_1
as BTN_BACK by default so we should still be compatible.

Could you please try the patch below? It assumes that psmosue core does
not set up BTN_MIDDLE capability ahead of time though (see a patch
posted earlier today).

--
Dmitry

Input: ALPS - add support for 4 directions button on Acer Aspire 5720

From: Maxim Levitsky <[email protected]>

Signed-off-by: Maxim Levitsky <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
---

drivers/input/mouse/alps.c | 61 ++++++++++++++++++++++++++++++--------------
1 files changed, 42 insertions(+), 19 deletions(-)


diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index f361106..01d354f 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -28,13 +28,16 @@
#define dbg(format, arg...) do {} while (0)
#endif

-#define ALPS_DUALPOINT 0x01
-#define ALPS_WHEEL 0x02
-#define ALPS_FW_BK_1 0x04
-#define ALPS_4BTN 0x08
-#define ALPS_OLDPROTO 0x10
-#define ALPS_PASS 0x20
-#define ALPS_FW_BK_2 0x40
+
+#define ALPS_OLDPROTO 0x01 /* old style input */
+#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
+#define ALPS_PASS 0x04 /* device has a pass-through port */
+
+#define ALPS_WHEEL 0x08 /* hardware wheel present */
+#define ALPS_FW_BK_1 0x10 /* front & back buttons present */
+#define ALPS_FW_BK_2 0x20 /* front & back buttons present */
+#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
+

static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -56,7 +59,7 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */
+ { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */
};

/*
@@ -83,6 +86,7 @@ static const struct alps_model_info alps_model_data[] = {
static void alps_process_packet(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
+ const struct alps_model_info *model = priv->i;
unsigned char *packet = psmouse->packet;
struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = priv->dev2;
@@ -101,7 +105,7 @@ static void alps_process_packet(struct psmouse *psmouse)
return;
}

- if (priv->i->flags & ALPS_OLDPROTO) {
+ if (model->flags & ALPS_OLDPROTO) {
left = packet[2] & 0x10;
right = packet[2] & 0x08;
middle = 0;
@@ -117,12 +121,12 @@ static void alps_process_packet(struct psmouse *psmouse)
z = packet[5];
}

- if (priv->i->flags & ALPS_FW_BK_1) {
+ if (model->flags & ALPS_FW_BK_1) {
back = packet[0] & 0x10;
forward = packet[2] & 4;
}

- if (priv->i->flags & ALPS_FW_BK_2) {
+ if (model->flags & ALPS_FW_BK_2) {
back = packet[3] & 4;
forward = packet[2] & 4;
if ((middle = forward && back))
@@ -132,7 +136,7 @@ static void alps_process_packet(struct psmouse *psmouse)
ges = packet[2] & 1;
fin = packet[2] & 2;

- if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
+ if ((model->flags & ALPS_DUALPOINT) && z == 127) {
input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));

@@ -150,7 +154,8 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_key(dev, BTN_MIDDLE, middle);

/* Convert hardware tap to a reasonable Z value */
- if (ges && !fin) z = 40;
+ if (ges && !fin)
+ z = 40;

/*
* A "tap and drag" operation is reported by the hardware as a transition
@@ -166,8 +171,10 @@ static void alps_process_packet(struct psmouse *psmouse)
}
priv->prev_fin = fin;

- if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
- if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
+ if (z > 30)
+ input_report_key(dev, BTN_TOUCH, 1);
+ if (z < 25)
+ input_report_key(dev, BTN_TOUCH, 0);

if (z > 0) {
input_report_abs(dev, ABS_X, x);
@@ -177,14 +184,21 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_abs(dev, ABS_PRESSURE, z);
input_report_key(dev, BTN_TOOL_FINGER, z > 0);

- if (priv->i->flags & ALPS_WHEEL)
+ if (model->flags & ALPS_WHEEL)
input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));

- if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
+ if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
input_report_key(dev, BTN_FORWARD, forward);
input_report_key(dev, BTN_BACK, back);
}

+ if (model->flags & ALPS_FOUR_BUTTONS) {
+ input_report_key(dev, BTN_0, packet[2] & 4);
+ input_report_key(dev, BTN_1, packet[0] & 0x10);
+ input_report_key(dev, BTN_2, packet[3] & 4);
+ input_report_key(dev, BTN_3, packet[0] & 0x20);
+ }
+
input_sync(dev);
}

@@ -469,8 +483,8 @@ int alps_init(struct psmouse *psmouse)
dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
- dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
- BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ dev1->keybit[BIT_WORD(BTN_LEFT)] |=
+ 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);
@@ -487,6 +501,15 @@ int alps_init(struct psmouse *psmouse)
dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
}

+ if (priv->i->flags & ALPS_FOUR_BUTTONS) {
+ dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
+ dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
+ dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
+ dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+ } else {
+ dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
+ }
+
snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
dev2->phys = priv->phys;
dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";

2009-11-16 18:05:50

by Maxim Levitsky

[permalink] [raw]
Subject: Re: [PATCH v2] ALPS: Add support for 4 directions button on Acer Aspire 5720

On Sun, 2009-11-15 at 00:53 -0800, Dmitry Torokhov wrote:
> Hi Maxim,
>
> On Wed, Nov 11, 2009 at 11:09:50AM +0200, Maxim Levitsky wrote:
> > >From 6b263982ffd62ae4621a5202f0084983af8dc093 Mon Sep 17 00:00:00 2001
> > From: Maxim Levitsky <[email protected]>
> > Date: Wed, 11 Nov 2009 11:03:35 +0200
> > Subject: [PATCH] ALPS: Add support for 4 directions button on Acer Aspire 5720
> > Implemented using DMI due to uncertainty about systems that have
> > only the middle button
> >
> > Signed-off-by: Maxim Levitsky <[email protected]>
>
> I don't think that we need to do DMI checking. I looked through my mails
> and it looks like all Acers with that signature have 4-directional
> button while Volstro 1400 only has left and right button and so won't be
> affected. Also Synaptics driver treats BTN_0 as BTN_FORWARD and BTN_1
> as BTN_BACK by default so we should still be compatible.
>
> Could you please try the patch below? It assumes that psmosue core does
> not set up BTN_MIDDLE capability ahead of time though (see a patch
> posted earlier today).
>
> --
> Dmitry
>
> Input: ALPS - add support for 4 directions button on Acer Aspire 5720
>
> From: Maxim Levitsky <[email protected]>
>
> Signed-off-by: Maxim Levitsky <[email protected]>
> Signed-off-by: Dmitry Torokhov <[email protected]>
> ---

Works just fine!

Best regards,
Maxim Levitsky