From: Dmitry Torokhov <dtor_core@ameritech.net>

move "reconnect after so many errors" handling from synaptics driver to
psmouse so it can be used by other PS/2 protcol drivers (but so far only
synaptics knows how to validate incoming data)


---

 25-akpm/Documentation/kernel-parameters.txt |    4 -
 25-akpm/drivers/input/mouse/psmouse-base.c  |   61 +++++++++++++++++++---------
 25-akpm/drivers/input/mouse/psmouse.h       |    9 +++-
 25-akpm/drivers/input/mouse/synaptics.c     |   24 +++--------
 25-akpm/drivers/input/mouse/synaptics.h     |    3 -
 5 files changed, 62 insertions(+), 39 deletions(-)

diff -puN Documentation/kernel-parameters.txt~new-set-of-input-patches-psmouse-reconnect-after-error Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~new-set-of-input-patches-psmouse-reconnect-after-error	2004-04-27 01:31:50.757332456 -0700
+++ 25-akpm/Documentation/kernel-parameters.txt	2004-04-27 01:31:50.766331088 -0700
@@ -896,8 +896,8 @@ running once the system is up.
 	psmouse.rate=	[HW,MOUSE] Set desired mouse report rate, in reports
 			per second.
 	psmouse.resetafter=
-			[HW,MOUSE] Try to reset Synaptics Touchpad after so many
-			bad packets (0 = never).
+			[HW,MOUSE] Try to reset the device after so many bad packets
+			(0 = never).
 	psmouse.resolution=
 			[HW,MOUSE] Set desired mouse resolution, in dpi.
 	psmouse.smartscroll=
diff -puN drivers/input/mouse/psmouse-base.c~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/psmouse-base.c
--- 25/drivers/input/mouse/psmouse-base.c~new-set-of-input-patches-psmouse-reconnect-after-error	2004-04-27 01:31:50.759332152 -0700
+++ 25-akpm/drivers/input/mouse/psmouse-base.c	2004-04-27 01:31:50.768330784 -0700
@@ -43,9 +43,9 @@ int psmouse_smartscroll = 1;
 module_param_named(smartscroll, psmouse_smartscroll, bool, 0);
 MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
 
-unsigned int psmouse_resetafter;
+static unsigned int psmouse_resetafter;
 module_param_named(resetafter, psmouse_resetafter, uint, 0);
-MODULE_PARM_DESC(resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
+MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
 
 __obsolete_setup("psmouse_noext");
 __obsolete_setup("psmouse_resolution=");
@@ -56,15 +56,22 @@ __obsolete_setup("psmouse_rate=");
 static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
 
 /*
- * psmouse_process_packet() analyzes the PS/2 mouse packet contents and
- * reports relevant events to the input module.
+ * psmouse_process_byte() analyzes the PS/2 data stream and reports
+ * relevant events to the input module once full packet has arrived.
  */
 
-static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
 	struct input_dev *dev = &psmouse->dev;
 	unsigned char *packet = psmouse->packet;
 
+	if (psmouse->pktcnt < 3 + (psmouse->type >= PSMOUSE_GENPS))
+		return PSMOUSE_GOOD_DATA;
+
+/*
+ * Full packet accumulated, process it
+ */
+
 	input_regs(dev, regs);
 
 /*
@@ -112,6 +119,8 @@ static void psmouse_process_packet(struc
 	input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
 
 	input_sync(dev);
+
+	return PSMOUSE_FULL_PACKET;
 }
 
 /*
@@ -123,6 +132,7 @@ static irqreturn_t psmouse_interrupt(str
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
 	struct psmouse *psmouse = serio->private;
+	psmouse_ret_t rc;
 
 	if (psmouse->state == PSMOUSE_IGNORE)
 		goto out;
@@ -193,19 +203,33 @@ static irqreturn_t psmouse_interrupt(str
 		}
 	}
 
-	if (psmouse->type == PSMOUSE_SYNAPTICS) {
-		/*
-		 * The synaptics driver has its own resync logic,
-		 * so it needs to receive all bytes one at a time.
-		 */
-		synaptics_process_byte(psmouse, regs);
-		goto out;
-	}
+	rc = psmouse->type == PSMOUSE_SYNAPTICS ?
+		synaptics_process_byte(psmouse, regs) : psmouse_process_byte(psmouse, regs);
 
-	if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
-		psmouse_process_packet(psmouse, regs);
-		psmouse->pktcnt = 0;
-		goto out;
+	switch (rc) {
+		case PSMOUSE_BAD_DATA:
+			printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
+				psmouse->name, psmouse->phys, psmouse->pktcnt);
+			psmouse->pktcnt = 0;
+
+			if (++psmouse->out_of_sync == psmouse_resetafter) {
+				psmouse->state = PSMOUSE_IGNORE;
+				printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+				serio_reconnect(psmouse->serio);
+			}
+			break;
+
+		case PSMOUSE_FULL_PACKET:
+			psmouse->pktcnt = 0;
+			if (psmouse->out_of_sync) {
+				psmouse->out_of_sync = 0;
+				printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
+					psmouse->name, psmouse->phys);
+			}
+			break;
+
+		case PSMOUSE_GOOD_DATA:
+			break;
 	}
 out:
 	return IRQ_HANDLED;
@@ -677,7 +701,8 @@ static int psmouse_reconnect(struct seri
 	old_type = psmouse->type;
 
 	psmouse->state = PSMOUSE_CMD_MODE;
-	psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0;
+	psmouse->type = psmouse->acking = 0;
+	psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
 	if (psmouse->reconnect) {
 	       if (psmouse->reconnect(psmouse))
 			return -1;
diff -puN drivers/input/mouse/psmouse.h~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/psmouse.h
--- 25/drivers/input/mouse/psmouse.h~new-set-of-input-patches-psmouse-reconnect-after-error	2004-04-27 01:31:50.760332000 -0700
+++ 25-akpm/drivers/input/mouse/psmouse.h	2004-04-27 01:31:50.768330784 -0700
@@ -22,6 +22,13 @@
 #define PSMOUSE_ACTIVATED	1
 #define PSMOUSE_IGNORE		2
 
+/* psmouse protocol handler return codes */
+typedef enum {
+	PSMOUSE_BAD_DATA,
+	PSMOUSE_GOOD_DATA,
+	PSMOUSE_FULL_PACKET
+} psmouse_ret_t;
+
 struct psmouse;
 
 struct psmouse_ptport {
@@ -45,6 +52,7 @@ struct psmouse {
 	unsigned char type;
 	unsigned char model;
 	unsigned long last;
+	unsigned long out_of_sync;
 	unsigned char state;
 	char acking;
 	volatile char ack;
@@ -69,6 +77,5 @@ int psmouse_reset(struct psmouse *psmous
 
 extern int psmouse_smartscroll;
 extern unsigned int psmouse_rate;
-extern unsigned int psmouse_resetafter;
 
 #endif /* _PSMOUSE_H */
diff -puN drivers/input/mouse/synaptics.c~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/synaptics.c
--- 25/drivers/input/mouse/synaptics.c~new-set-of-input-patches-psmouse-reconnect-after-error	2004-04-27 01:31:50.762331696 -0700
+++ 25-akpm/drivers/input/mouse/synaptics.c	2004-04-27 01:31:50.769330632 -0700
@@ -599,6 +599,9 @@ static int synaptics_validate_byte(unsig
 	static unsigned char oldabs_mask[]	= { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
 	static unsigned char oldabs_rslt[]	= { 0xC0, 0x00, 0x00, 0x80, 0x00 };
 
+	if (idx < 0 || idx > 4)
+		return 0;
+
 	switch (pkt_type) {
 		case SYN_NEWABS:
 		case SYN_NEWABS_RELAXED:
@@ -629,7 +632,7 @@ static unsigned char synaptics_detect_pk
 	return SYN_NEWABS_STRICT;
 }
 
-void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
 	struct input_dev *dev = &psmouse->dev;
 	struct synaptics_data *priv = psmouse->private;
@@ -637,11 +640,6 @@ void synaptics_process_byte(struct psmou
 	input_regs(dev, regs);
 
 	if (psmouse->pktcnt >= 6) { /* Full packet received */
-		if (priv->out_of_sync) {
-			priv->out_of_sync = 0;
-			printk(KERN_NOTICE "Synaptics driver resynced.\n");
-		}
-
 		if (unlikely(priv->pkt_type == SYN_NEWABS))
 			priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
@@ -649,16 +647,10 @@ void synaptics_process_byte(struct psmou
 			synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
 		else
 			synaptics_process_packet(psmouse);
-		psmouse->pktcnt = 0;
 
-	} else if (psmouse->pktcnt &&
-		   !synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type)) {
-		printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt);
-		psmouse->pktcnt = 0;
-		if (++priv->out_of_sync == psmouse_resetafter) {
-			psmouse->state = PSMOUSE_IGNORE;
-			printk(KERN_NOTICE "synaptics: issuing reconnect request\n");
-			serio_reconnect(psmouse->serio);
-		}
+		return PSMOUSE_FULL_PACKET;
 	}
+
+	return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
+		PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
 }
diff -puN drivers/input/mouse/synaptics.h~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/synaptics.h
--- 25/drivers/input/mouse/synaptics.h~new-set-of-input-patches-psmouse-reconnect-after-error	2004-04-27 01:31:50.763331544 -0700
+++ 25-akpm/drivers/input/mouse/synaptics.h	2004-04-27 01:31:50.769330632 -0700
@@ -9,7 +9,7 @@
 #ifndef _SYNAPTICS_H
 #define _SYNAPTICS_H
 
-extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
+extern psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
 extern int synaptics_detect(struct psmouse *psmouse);
 extern int synaptics_init(struct psmouse *psmouse);
 extern void synaptics_reset(struct psmouse *psmouse);
@@ -103,7 +103,6 @@ struct synaptics_data {
 	unsigned long int identity;		/* Identification */
 
 	/* Data for normal processing */
-	unsigned int out_of_sync;		/* # of packets out of sync */
 	int old_w;				/* Previous w value */
 	unsigned char pkt_type;			/* packet type - old, new, etc */
 };

_