diff options
Diffstat (limited to 'drivers/input/mouse/psmouse-base.c')
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 104 |
1 files changed, 61 insertions, 43 deletions
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d6992c..979c50215282 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; | |||
110 | struct psmouse_protocol { | 110 | struct psmouse_protocol { |
111 | enum psmouse_type type; | 111 | enum psmouse_type type; |
112 | bool maxproto; | 112 | bool maxproto; |
113 | bool ignore_parity; /* Protocol should ignore parity errors from KBC */ | ||
113 | const char *name; | 114 | const char *name; |
114 | const char *alias; | 115 | const char *alias; |
115 | int (*detect)(struct psmouse *, bool); | 116 | int (*detect)(struct psmouse *, bool); |
@@ -146,18 +147,18 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) | |||
146 | 147 | ||
147 | if (psmouse->type == PSMOUSE_IMEX) { | 148 | if (psmouse->type == PSMOUSE_IMEX) { |
148 | switch (packet[3] & 0xC0) { | 149 | switch (packet[3] & 0xC0) { |
149 | case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ | 150 | case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ |
150 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); | 151 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); |
151 | break; | 152 | break; |
152 | case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ | 153 | case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ |
153 | input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); | 154 | input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); |
154 | break; | 155 | break; |
155 | case 0x00: | 156 | case 0x00: |
156 | case 0xC0: | 157 | case 0xC0: |
157 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); | 158 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); |
158 | input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); | 159 | input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); |
159 | input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); | 160 | input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); |
160 | break; | 161 | break; |
161 | } | 162 | } |
162 | } | 163 | } |
163 | 164 | ||
@@ -246,31 +247,31 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
246 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse); | 247 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse); |
247 | 248 | ||
248 | switch (rc) { | 249 | switch (rc) { |
249 | case PSMOUSE_BAD_DATA: | 250 | case PSMOUSE_BAD_DATA: |
250 | if (psmouse->state == PSMOUSE_ACTIVATED) { | 251 | if (psmouse->state == PSMOUSE_ACTIVATED) { |
251 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | 252 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", |
252 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 253 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
253 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { | 254 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { |
254 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 255 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
255 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 256 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); |
256 | serio_reconnect(psmouse->ps2dev.serio); | 257 | serio_reconnect(psmouse->ps2dev.serio); |
257 | return -1; | 258 | return -1; |
258 | } | ||
259 | } | ||
260 | psmouse->pktcnt = 0; | ||
261 | break; | ||
262 | |||
263 | case PSMOUSE_FULL_PACKET: | ||
264 | psmouse->pktcnt = 0; | ||
265 | if (psmouse->out_of_sync_cnt) { | ||
266 | psmouse->out_of_sync_cnt = 0; | ||
267 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
268 | psmouse->name, psmouse->phys); | ||
269 | } | 259 | } |
270 | break; | 260 | } |
261 | psmouse->pktcnt = 0; | ||
262 | break; | ||
263 | |||
264 | case PSMOUSE_FULL_PACKET: | ||
265 | psmouse->pktcnt = 0; | ||
266 | if (psmouse->out_of_sync_cnt) { | ||
267 | psmouse->out_of_sync_cnt = 0; | ||
268 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
269 | psmouse->name, psmouse->phys); | ||
270 | } | ||
271 | break; | ||
271 | 272 | ||
272 | case PSMOUSE_GOOD_DATA: | 273 | case PSMOUSE_GOOD_DATA: |
273 | break; | 274 | break; |
274 | } | 275 | } |
275 | return 0; | 276 | return 0; |
276 | } | 277 | } |
@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
288 | if (psmouse->state == PSMOUSE_IGNORE) | 289 | if (psmouse->state == PSMOUSE_IGNORE) |
289 | goto out; | 290 | goto out; |
290 | 291 | ||
291 | if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { | 292 | if (unlikely((flags & SERIO_TIMEOUT) || |
293 | ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { | ||
294 | |||
292 | if (psmouse->state == PSMOUSE_ACTIVATED) | 295 | if (psmouse->state == PSMOUSE_ACTIVATED) |
293 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", | 296 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", |
294 | flags & SERIO_TIMEOUT ? " timeout" : "", | 297 | flags & SERIO_TIMEOUT ? " timeout" : "", |
@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
759 | .name = "PS/2", | 762 | .name = "PS/2", |
760 | .alias = "bare", | 763 | .alias = "bare", |
761 | .maxproto = true, | 764 | .maxproto = true, |
765 | .ignore_parity = true, | ||
762 | .detect = ps2bare_detect, | 766 | .detect = ps2bare_detect, |
763 | }, | 767 | }, |
764 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 768 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
786 | .name = "ImPS/2", | 790 | .name = "ImPS/2", |
787 | .alias = "imps", | 791 | .alias = "imps", |
788 | .maxproto = true, | 792 | .maxproto = true, |
793 | .ignore_parity = true, | ||
789 | .detect = intellimouse_detect, | 794 | .detect = intellimouse_detect, |
790 | }, | 795 | }, |
791 | { | 796 | { |
@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
793 | .name = "ImExPS/2", | 798 | .name = "ImExPS/2", |
794 | .alias = "exps", | 799 | .alias = "exps", |
795 | .maxproto = true, | 800 | .maxproto = true, |
801 | .ignore_parity = true, | ||
796 | .detect = im_explorer_detect, | 802 | .detect = im_explorer_detect, |
797 | }, | 803 | }, |
798 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 804 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) | |||
1222 | static int psmouse_switch_protocol(struct psmouse *psmouse, | 1228 | static int psmouse_switch_protocol(struct psmouse *psmouse, |
1223 | const struct psmouse_protocol *proto) | 1229 | const struct psmouse_protocol *proto) |
1224 | { | 1230 | { |
1231 | const struct psmouse_protocol *selected_proto; | ||
1225 | struct input_dev *input_dev = psmouse->dev; | 1232 | struct input_dev *input_dev = psmouse->dev; |
1226 | 1233 | ||
1227 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; | 1234 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; |
@@ -1238,16 +1245,21 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, | |||
1238 | psmouse->pktsize = 3; | 1245 | psmouse->pktsize = 3; |
1239 | 1246 | ||
1240 | if (proto && (proto->detect || proto->init)) { | 1247 | if (proto && (proto->detect || proto->init)) { |
1241 | if (proto->detect && proto->detect(psmouse, 1) < 0) | 1248 | if (proto->detect && proto->detect(psmouse, true) < 0) |
1242 | return -1; | 1249 | return -1; |
1243 | 1250 | ||
1244 | if (proto->init && proto->init(psmouse) < 0) | 1251 | if (proto->init && proto->init(psmouse) < 0) |
1245 | return -1; | 1252 | return -1; |
1246 | 1253 | ||
1247 | psmouse->type = proto->type; | 1254 | psmouse->type = proto->type; |
1248 | } else | 1255 | selected_proto = proto; |
1256 | } else { | ||
1249 | psmouse->type = psmouse_extensions(psmouse, | 1257 | psmouse->type = psmouse_extensions(psmouse, |
1250 | psmouse_max_proto, true); | 1258 | psmouse_max_proto, true); |
1259 | selected_proto = psmouse_protocol_by_type(psmouse->type); | ||
1260 | } | ||
1261 | |||
1262 | psmouse->ignore_parity = selected_proto->ignore_parity; | ||
1251 | 1263 | ||
1252 | /* | 1264 | /* |
1253 | * If mouse's packet size is 3 there is no point in polling the | 1265 | * 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 | psmouse->resync_time = 0; | 1279 | psmouse->resync_time = 0; |
1268 | 1280 | ||
1269 | snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", | 1281 | snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", |
1270 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1282 | selected_proto->name, psmouse->vendor, psmouse->name); |
1271 | 1283 | ||
1272 | input_dev->name = psmouse->devname; | 1284 | input_dev->name = psmouse->devname; |
1273 | input_dev->phys = psmouse->phys; | 1285 | input_dev->phys = psmouse->phys; |
@@ -1382,6 +1394,7 @@ static int psmouse_reconnect(struct serio *serio) | |||
1382 | struct psmouse *psmouse = serio_get_drvdata(serio); | 1394 | struct psmouse *psmouse = serio_get_drvdata(serio); |
1383 | struct psmouse *parent = NULL; | 1395 | struct psmouse *parent = NULL; |
1384 | struct serio_driver *drv = serio->drv; | 1396 | struct serio_driver *drv = serio->drv; |
1397 | unsigned char type; | ||
1385 | int rc = -1; | 1398 | int rc = -1; |
1386 | 1399 | ||
1387 | if (!drv || !psmouse) { | 1400 | if (!drv || !psmouse) { |
@@ -1401,10 +1414,15 @@ static int psmouse_reconnect(struct serio *serio) | |||
1401 | if (psmouse->reconnect) { | 1414 | if (psmouse->reconnect) { |
1402 | if (psmouse->reconnect(psmouse)) | 1415 | if (psmouse->reconnect(psmouse)) |
1403 | goto out; | 1416 | goto out; |
1404 | } else if (psmouse_probe(psmouse) < 0 || | 1417 | } else { |
1405 | psmouse->type != psmouse_extensions(psmouse, | 1418 | psmouse_reset(psmouse); |
1406 | psmouse_max_proto, false)) { | 1419 | |
1407 | goto out; | 1420 | if (psmouse_probe(psmouse) < 0) |
1421 | goto out; | ||
1422 | |||
1423 | type = psmouse_extensions(psmouse, psmouse_max_proto, false); | ||
1424 | if (psmouse->type != type) | ||
1425 | goto out; | ||
1408 | } | 1426 | } |
1409 | 1427 | ||
1410 | /* ok, the device type (and capabilities) match the old one, | 1428 | /* ok, the device type (and capabilities) match the old one, |