Commit 6b9d363c authored by Dmitry Torokhov's avatar Dmitry Torokhov

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: default avatarDamjan Jovanovic <damjan.jov@gmail.com>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 014f6150
...@@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq; ...@@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq;
struct psmouse_protocol { struct psmouse_protocol {
enum psmouse_type type; enum psmouse_type type;
bool maxproto; bool maxproto;
bool ignore_parity; /* Protocol should ignore parity errors from KBC */
const char *name; const char *name;
const char *alias; const char *alias;
int (*detect)(struct psmouse *, bool); int (*detect)(struct psmouse *, bool);
...@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (psmouse->state == PSMOUSE_IGNORE) if (psmouse->state == PSMOUSE_IGNORE)
goto out; goto out;
if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { if (unlikely((flags & SERIO_TIMEOUT) ||
((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
if (psmouse->state == PSMOUSE_ACTIVATED) if (psmouse->state == PSMOUSE_ACTIVATED)
printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_TIMEOUT ? " timeout" : "",
...@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "PS/2", .name = "PS/2",
.alias = "bare", .alias = "bare",
.maxproto = true, .maxproto = true,
.ignore_parity = true,
.detect = ps2bare_detect, .detect = ps2bare_detect,
}, },
#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
...@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "ImPS/2", .name = "ImPS/2",
.alias = "imps", .alias = "imps",
.maxproto = true, .maxproto = true,
.ignore_parity = true,
.detect = intellimouse_detect, .detect = intellimouse_detect,
}, },
{ {
...@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "ImExPS/2", .name = "ImExPS/2",
.alias = "exps", .alias = "exps",
.maxproto = true, .maxproto = true,
.ignore_parity = true,
.detect = im_explorer_detect, .detect = im_explorer_detect,
}, },
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
...@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio)
static int psmouse_switch_protocol(struct psmouse *psmouse, static int psmouse_switch_protocol(struct psmouse *psmouse,
const struct psmouse_protocol *proto) const struct psmouse_protocol *proto)
{ {
const struct psmouse_protocol *selected_proto;
struct input_dev *input_dev = psmouse->dev; struct input_dev *input_dev = psmouse->dev;
input_dev->dev.parent = &psmouse->ps2dev.serio->dev; input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
...@@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, ...@@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
return -1; return -1;
psmouse->type = proto->type; psmouse->type = proto->type;
} else selected_proto = proto;
} else {
psmouse->type = psmouse_extensions(psmouse, psmouse->type = psmouse_extensions(psmouse,
psmouse_max_proto, true); 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 * 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, ...@@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
psmouse->resync_time = 0; psmouse->resync_time = 0;
snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", 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->name = psmouse->devname;
input_dev->phys = psmouse->phys; input_dev->phys = psmouse->phys;
......
...@@ -47,6 +47,7 @@ struct psmouse { ...@@ -47,6 +47,7 @@ struct psmouse {
unsigned char pktcnt; unsigned char pktcnt;
unsigned char pktsize; unsigned char pktsize;
unsigned char type; unsigned char type;
bool ignore_parity;
bool acks_disable_command; bool acks_disable_command;
unsigned int model; unsigned int model;
unsigned long last; unsigned long last;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment