diff mbox

[3/3] input: handle bad parity PS/2 packets in mouse drivers better

Message ID 201004272112.o3RLCeTc020088@imap1.linux-foundation.org (mailing list archive)
State New, archived
Headers show

Commit Message

Andrew Morton April 27, 2010, 9:12 p.m. UTC
None
diff mbox

Patch

diff -puN drivers/input/mouse/alps.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/alps.c
--- a/drivers/input/mouse/alps.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/alps.c
@@ -379,10 +379,16 @@  static psmouse_ret_t alps_process_byte(s
 	struct alps_data *priv = psmouse->private;
 	const struct alps_model_info *model = priv->i;
 
+	if (psmouse->pktcnt == 1 && psmouse->badparity)
+		return PSMOUSE_BAD_DATA;
+
 	if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
 		if (psmouse->pktcnt == 3) {
-			alps_report_bare_ps2_packet(psmouse, psmouse->packet,
-						    true);
+			if (psmouse->badparity) {
+				alps_report_bare_ps2_packet(psmouse,
+							    psmouse->packet,
+							    true);
+			}
 			return PSMOUSE_FULL_PACKET;
 		}
 		return PSMOUSE_GOOD_DATA;
@@ -392,6 +398,8 @@  static psmouse_ret_t alps_process_byte(s
 
 	if ((model->flags & ALPS_PS2_INTERLEAVED) &&
 	    psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
+		if (psmouse->badparity)
+			return PSMOUSE_BAD_DATA;
 		return alps_handle_interleaved_ps2(psmouse);
 	}
 
@@ -410,7 +418,8 @@  static psmouse_ret_t alps_process_byte(s
 	}
 
 	if (psmouse->pktcnt == 6) {
-		alps_process_packet(psmouse);
+		if (!psmouse->badparity)
+			alps_process_packet(psmouse);
 		return PSMOUSE_FULL_PACKET;
 	}
 
diff -puN drivers/input/mouse/elantech.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/elantech.c
--- a/drivers/input/mouse/elantech.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/elantech.c
@@ -325,6 +325,9 @@  static psmouse_ret_t elantech_process_by
 	if (psmouse->pktcnt < psmouse->pktsize)
 		return PSMOUSE_GOOD_DATA;
 
+	if (psmouse->pktcnt == psmouse->pktsize && psmouse->badparity)
+		return PSMOUSE_FULL_PACKET;
+
 	if (etd->debug > 1)
 		elantech_packet_dump(psmouse->packet, psmouse->pktsize);
 
diff -puN drivers/input/mouse/hgpk.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/hgpk.c
--- a/drivers/input/mouse/hgpk.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/hgpk.c
@@ -188,7 +188,8 @@  static psmouse_ret_t hgpk_process_byte(s
 	}
 
 	if (psmouse->pktcnt >= psmouse->pktsize) {
-		hgpk_process_packet(psmouse);
+		if (!psmouse->badparity)
+			hgpk_process_packet(psmouse);
 		return PSMOUSE_FULL_PACKET;
 	}
 
diff -puN drivers/input/mouse/lifebook.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/lifebook.c
--- a/drivers/input/mouse/lifebook.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/lifebook.c
@@ -139,6 +139,9 @@  static psmouse_ret_t lifebook_process_by
 	unsigned char *packet = psmouse->packet;
 	bool relative_packet = packet[0] & 0x08;
 
+	if (psmouse->pktcnt == 1 && psmouse->badparity)
+		return PSMOUSE_BAD_DATA;
+
 	if (relative_packet || !lifebook_use_6byte_proto) {
 		if (psmouse->pktcnt != 3)
 			return PSMOUSE_GOOD_DATA;
@@ -167,6 +170,9 @@  static psmouse_ret_t lifebook_process_by
 		}
 	}
 
+	if (psmouse->badparity)
+		return PSMOUSE_FULL_PACKET;
+
 	if (relative_packet) {
 		if (!dev2)
 			printk(KERN_WARNING "lifebook.c: got relative packet "
diff -puN drivers/input/mouse/logips2pp.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/logips2pp.c
--- a/drivers/input/mouse/logips2pp.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/logips2pp.c
@@ -51,6 +51,9 @@  static psmouse_ret_t ps2pp_process_byte(
  * Full packet accumulated, process it
  */
 
+	if (psmouse->badparity)
+		return PSMOUSE_FULL_PACKET;
+
 	if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
 
 		/* Logitech extended packet */
diff -puN drivers/input/mouse/psmouse-base.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/psmouse-base.c
@@ -134,6 +134,9 @@  static psmouse_ret_t psmouse_process_byt
  * Full packet accumulated, process it
  */
 
+	if (psmouse->badparity)
+		return PSMOUSE_FULL_PACKET;
+
 /*
  * Scroll wheel on IntelliMice, scroll buttons on NetMice
  */
@@ -218,6 +221,7 @@  void psmouse_queue_work(struct psmouse *
 static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
 {
 	psmouse->state = new_state;
+	psmouse->badparity = 0;
 	psmouse->pktcnt = psmouse->out_of_sync_cnt = 0;
 	psmouse->ps2dev.flags = 0;
 	psmouse->last = jiffies;
@@ -258,10 +262,12 @@  static int psmouse_handle_byte(struct ps
 					return -1;
 				}
 			}
+			psmouse->badparity = 0;
 			psmouse->pktcnt = 0;
 			break;
 
 		case PSMOUSE_FULL_PACKET:
+			psmouse->badparity = 0;
 			psmouse->pktcnt = 0;
 			if (psmouse->out_of_sync_cnt) {
 				psmouse->out_of_sync_cnt = 0;
@@ -271,6 +277,7 @@  static int psmouse_handle_byte(struct ps
 			break;
 
 		case PSMOUSE_GOOD_DATA:
+			psmouse->badparity = 0;
 			break;
 	}
 	return 0;
@@ -296,8 +303,12 @@  static irqreturn_t psmouse_interrupt(str
 			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
 				flags & SERIO_TIMEOUT ? " timeout" : "",
 				flags & SERIO_PARITY ? " bad parity" : "");
-		ps2_cmd_aborted(&psmouse->ps2dev);
-		goto out;
+		if (flags & SERIO_TIMEOUT) {
+			ps2_cmd_aborted(&psmouse->ps2dev);
+			goto out;
+		} else {
+			psmouse->badparity = 1;
+		}
 	}
 
 	if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK))
diff -puN drivers/input/mouse/psmouse.h~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/psmouse.h
--- a/drivers/input/mouse/psmouse.h~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/psmouse.h
@@ -43,6 +43,7 @@  struct psmouse {
 	char *vendor;
 	char *name;
 	unsigned char packet[8];
+	int badparity;
 	unsigned char badbyte;
 	unsigned char pktcnt;
 	unsigned char pktsize;
diff -puN drivers/input/mouse/sentelic.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/sentelic.c
--- a/drivers/input/mouse/sentelic.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/sentelic.c
@@ -638,6 +638,9 @@  static psmouse_ret_t fsp_process_byte(st
 	 * Full packet accumulated, process it
 	 */
 
+	if (psmouse->badparity)
+		return PSMOUSE_FULL_PACKET;
+
 	switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
 	case FSP_PKT_TYPE_ABS:
 		dev_warn(&psmouse->ps2dev.serio->dev,
diff -puN drivers/input/mouse/synaptics.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/synaptics.c
--- a/drivers/input/mouse/synaptics.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/synaptics.c
@@ -554,6 +554,9 @@  static psmouse_ret_t synaptics_process_b
 	struct synaptics_data *priv = psmouse->private;
 
 	if (psmouse->pktcnt >= 6) { /* Full packet received */
+		if (psmouse->badparity)
+			return PSMOUSE_FULL_PACKET;
+
 		if (unlikely(priv->pkt_type == SYN_NEWABS))
 			priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
diff -puN drivers/input/mouse/touchkit_ps2.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better drivers/input/mouse/touchkit_ps2.c
--- a/drivers/input/mouse/touchkit_ps2.c~input-handle-bad-parity-ps-2-packets-in-mouse-drivers-better
+++ a/drivers/input/mouse/touchkit_ps2.c
@@ -58,6 +58,9 @@  static psmouse_ret_t touchkit_ps2_proces
 	if (psmouse->pktcnt != 5)
 		return PSMOUSE_GOOD_DATA;
 
+	if (psmouse->badparity)
+		return PSMOUSE_FULL_PACKET;
+
 	input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
 	input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
 	input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet));