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);
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" : "",
synaptics_hardware = true;
if (max_proto > PSMOUSE_IMEX) {
- if (!set_properties || synaptics_init(psmouse) == 0)
+/*
+ * Try activating protocol, but check if support is enabled first, since
+ * we try detecting Synaptics even when protocol is disabled.
+ */
+ if (synaptics_supported() &&
+ (!set_properties || synaptics_init(psmouse) == 0)) {
return PSMOUSE_SYNAPTICS;
+ }
+
/*
* Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
* Unfortunately Logitech/Genius probes confuse some firmware versions so
max_proto = PSMOUSE_IMEX;
}
-/*
- * Try Finger Sensing Pad
- */
- if (max_proto > PSMOUSE_IMEX) {
- if (fsp_detect(psmouse, set_properties) == 0) {
- if (!set_properties || fsp_init(psmouse) == 0)
- return PSMOUSE_FSP;
-/*
- * Init failed, try basic relative protocols
- */
- max_proto = PSMOUSE_IMEX;
- }
- }
if (max_proto > PSMOUSE_IMEX) {
if (genius_detect(psmouse, set_properties) == 0)
}
/*
+ * Try Finger Sensing Pad. We do it here because its probe upsets
+ * Trackpoint devices (causing TP_READ_ID command to time out).
+ */
+ if (max_proto > PSMOUSE_IMEX) {
+ if (fsp_detect(psmouse, set_properties) == 0) {
+ if (!set_properties || fsp_init(psmouse) == 0)
+ return PSMOUSE_FSP;
+/*
+ * Init failed, try basic relative protocols
+ */
+ max_proto = PSMOUSE_IMEX;
+ }
+ }
+
+/*
* Reset to defaults in case the device got confused by extended
* protocol probes. Note that we follow up with full reset because
* some mice put themselves to sleep when they see PSMOUSE_RESET_DIS.
.name = "PS/2",
.alias = "bare",
.maxproto = true,
+ .ignore_parity = true,
.detect = ps2bare_detect,
},
#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
.name = "ImPS/2",
.alias = "imps",
.maxproto = true,
+ .ignore_parity = true,
.detect = intellimouse_detect,
},
{
.name = "ImExPS/2",
.alias = "exps",
.maxproto = true,
+ .ignore_parity = true,
.detect = im_explorer_detect,
},
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
psmouse_deactivate(parent);
}
- psmouse_deactivate(psmouse);
+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
+ /*
+ * Disable stream mode so cleanup routine can proceed undisturbed.
+ */
+ if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
+ printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
if (psmouse->cleanup)
psmouse->cleanup(psmouse);
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;
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
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;