diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-04-19 00:42:16 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-04-19 00:50:42 -0700 |
commit | 6b9d363c49d22395d0cf8729c5963f83cfbb6d69 (patch) | |
tree | 00055d67fae36484e7801ddcc7dab15fea183afe /drivers/input | |
parent | 014f61504af276ba9d9544d8a7401d8f8526eb73 (diff) |
Input: psmouse - ignore parity error for basic protocols
Observing behavior of the other OS it appears that parity errors reported
by the keyboard controller are being ignored and the data is processed
as usual. Let's do the same for standard PS/2 protocols (bare, Intellimouse
and Intellimouse Explorer) to provide better compatibility. Thsi should fix
teh following bug:
https://bugzilla.kernel.org/show_bug.cgi?id=6105
Thanks for Damjan Jovanovic for locating the source of issue and ideas
for the patch.
Tested-by: Damjan Jovanovic <damjan.jov@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 18 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse.h | 1 |
2 files changed, 16 insertions, 3 deletions
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d6992..cbc80726494 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq; struct psmouse_protocol { enum psmouse_type type; bool maxproto; + bool ignore_parity; /* Protocol should ignore parity errors from KBC */ const char *name; const char *alias; int (*detect)(struct psmouse *, bool); @@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (psmouse->state == PSMOUSE_IGNORE) goto out; - if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { + if (unlikely((flags & SERIO_TIMEOUT) || + ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { + if (psmouse->state == PSMOUSE_ACTIVATED) printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", flags & SERIO_TIMEOUT ? " timeout" : "", @@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "PS/2", .alias = "bare", .maxproto = true, + .ignore_parity = true, .detect = ps2bare_detect, }, #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP @@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "ImPS/2", .alias = "imps", .maxproto = true, + .ignore_parity = true, .detect = intellimouse_detect, }, { @@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { .name = "ImExPS/2", .alias = "exps", .maxproto = true, + .ignore_parity = true, .detect = im_explorer_detect, }, #ifdef CONFIG_MOUSE_PS2_SYNAPTICS @@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse_protocol *proto) { + const struct psmouse_protocol *selected_proto; struct input_dev *input_dev = psmouse->dev; input_dev->dev.parent = &psmouse->ps2dev.serio->dev; @@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, return -1; psmouse->type = proto->type; - } else + selected_proto = proto; + } else { psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, true); + selected_proto = psmouse_protocol_by_type(psmouse->type); + } + + psmouse->ignore_parity = selected_proto->ignore_parity; /* * If mouse's packet size is 3 there is no point in polling the @@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, psmouse->resync_time = 0; snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", - psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); + selected_proto->name, psmouse->vendor, psmouse->name); input_dev->name = psmouse->devname; input_dev->phys = psmouse->phys; diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e053bdd137f..593e910bfc7 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -47,6 +47,7 @@ struct psmouse { unsigned char pktcnt; unsigned char pktsize; unsigned char type; + bool ignore_parity; bool acks_disable_command; unsigned int model; unsigned long last; |