mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 16:49:22 +00:00
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>
This commit is contained in:
parent
014f61504a
commit
6b9d363c49
2 changed files with 16 additions and 3 deletions
|
@ -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,
|
||||||
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[] = {
|
||||||
.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[] = {
|
||||||
.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[] = {
|
||||||
.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)
|
||||||
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,
|
||||||
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,
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue