<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"> Documentation/kernel-parameters.txt |    4 
 drivers/input/mouse/psmouse-base.c  |   69 +++++++++++---
 drivers/input/mouse/psmouse.h       |   22 +++-
 drivers/input/mouse/synaptics.c     |  172 ++++++++++++++++++++++++++++--------
 drivers/input/mouse/synaptics.h     |   15 ++-
 drivers/input/serio/serio.c         |   25 +++++
 include/linux/serio.h               |    3 
 7 files changed, 247 insertions(+), 63 deletions(-)

diff -puN Documentation/kernel-parameters.txt~p00005_synaptics-pass-through Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/Documentation/kernel-parameters.txt	2003-08-30 15:40:43.000000000 -0700
@@ -788,6 +788,10 @@ running once the system is up.
 
 	psmouse_noext	[HW,MOUSE] Disable probing for PS2 mouse protocol extensions
 
+	psmouse_resetafter=
+			[HW,MOUSE] Try to reset Synaptics Touchpad after so many
+			bad packets (0 = never).
+
 	pss=		[HW,OSS] Personal Sound System (ECHO ESC614)
 			Format: &lt;io&gt;,&lt;mss_io&gt;,&lt;mss_irq&gt;,&lt;mss_dma&gt;,&lt;mpu_io&gt;,&lt;mpu_irq&gt;
 
diff -puN drivers/input/mouse/psmouse-base.c~p00005_synaptics-pass-through drivers/input/mouse/psmouse-base.c
--- 25/drivers/input/mouse/psmouse-base.c~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/drivers/input/mouse/psmouse-base.c	2003-08-30 15:40:45.000000000 -0700
@@ -29,6 +29,8 @@ MODULE_PARM(psmouse_resolution, "i");
 MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
 MODULE_PARM(psmouse_smartscroll, "i");
 MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
+MODULE_PARM(psmouse_resetafter, "i");
+MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
 MODULE_LICENSE("GPL");
 
 #define PSMOUSE_LOGITECH_SMARTSCROLL	1
@@ -36,11 +38,12 @@ MODULE_LICENSE("GPL");
 static int psmouse_noext;
 int psmouse_resolution;
 int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL;
+unsigned int psmouse_resetafter;
 
 static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"};
 
 /*
- * psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
+ * psmouse_process_packet() analyzes the PS/2 mouse packet contents and
  * reports relevant events to the input module.
  */
 
@@ -108,6 +111,9 @@ static irqreturn_t psmouse_interrupt(str
 {
 	struct psmouse *psmouse = serio-&gt;private;
 
+	if (psmouse-&gt;state == PSMOUSE_IGNORE)
+		goto out;
+
 	if (psmouse-&gt;acking) {
 		switch (data) {
 			case PSMOUSE_RET_ACK:
@@ -132,31 +138,46 @@ static irqreturn_t psmouse_interrupt(str
 	}
 
 	if (psmouse-&gt;pktcnt &amp;&amp; time_after(jiffies, psmouse-&gt;last + HZ/2)) {
-		printk(KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n", psmouse-&gt;pktcnt);
+		printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
+		       psmouse-&gt;name, psmouse-&gt;phys, psmouse-&gt;pktcnt);
 		psmouse-&gt;pktcnt = 0;
 	}
 	
 	psmouse-&gt;last = jiffies;
 	psmouse-&gt;packet[psmouse-&gt;pktcnt++] = data;
 
-	if (psmouse-&gt;pktcnt == 3 + (psmouse-&gt;type &gt;= PSMOUSE_GENPS)) {
-		psmouse_process_packet(psmouse, regs);
-		psmouse-&gt;pktcnt = 0;
-		goto out;
+	if (psmouse-&gt;packet[0] == PSMOUSE_RET_BAT) {
+		if (psmouse-&gt;pktcnt == 1)
+			goto out;
+
+		if (psmouse-&gt;pktcnt == 2) {
+			if (psmouse-&gt;packet[1] == PSMOUSE_RET_ID) {
+				psmouse-&gt;state = PSMOUSE_IGNORE;
+				serio_rescan(serio);
+				goto out;
+			}
+			if (psmouse-&gt;type == PSMOUSE_SYNAPTICS) {
+				/* neither 0xAA nor 0x00 are valid first bytes
+				 * for a packet in absolute mode
+				 */
+				psmouse-&gt;pktcnt = 0;
+				goto out;
+			}
+		}
 	}
 
-	if (psmouse-&gt;pktcnt == 1 &amp;&amp; psmouse-&gt;type == PSMOUSE_SYNAPTICS) {
+	if (psmouse-&gt;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);
-		psmouse-&gt;pktcnt = 0;
 		goto out;
 	}
 
-	if (psmouse-&gt;pktcnt == 1 &amp;&amp; psmouse-&gt;packet[0] == PSMOUSE_RET_BAT) {
-		serio_rescan(serio);
+	if (psmouse-&gt;pktcnt == 3 + (psmouse-&gt;type &gt;= PSMOUSE_GENPS)) {
+		psmouse_process_packet(psmouse, regs);
+		psmouse-&gt;pktcnt = 0;
 		goto out;
 	}
 out:
@@ -227,7 +248,7 @@ int psmouse_command(struct psmouse *psmo
 	for (i = 0; i &lt; receive; i++)
 		param[i] = psmouse-&gt;cmdbuf[(receive - 1) - i];
 
-	if (psmouse-&gt;cmdcnt) 
+	if (psmouse-&gt;cmdcnt)
 		return (psmouse-&gt;cmdcnt = 0) - 1;
 
 	return 0;
@@ -450,14 +471,18 @@ static void psmouse_initialize(struct ps
  */
 
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
+}
 
 /*
- * Last, we enable the mouse so that we get reports from it.
+ * psmouse_activate() enables the mouse so that we get motion reports from it.
  */
 
+static void psmouse_activate(struct psmouse *psmouse)
+{
 	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
 		printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse-&gt;serio-&gt;phys);
 
+	psmouse-&gt;state = PSMOUSE_ACTIVATED;
 }
 
 /*
@@ -478,8 +503,9 @@ static void psmouse_cleanup(struct serio
 static void psmouse_disconnect(struct serio *serio)
 {
 	struct psmouse *psmouse = serio-&gt;private;
-	if (psmouse-&gt;type == PSMOUSE_SYNAPTICS)
-		synaptics_disconnect(psmouse);
+
+	psmouse-&gt;state = PSMOUSE_IGNORE;
+	synaptics_disconnect(psmouse);
 	input_unregister_device(&amp;psmouse-&gt;dev);
 	serio_close(serio);
 	kfree(psmouse);
@@ -494,7 +520,8 @@ static void psmouse_connect(struct serio
 {
 	struct psmouse *psmouse;
 	
-	if ((serio-&gt;type &amp; SERIO_TYPE) != SERIO_8042)
+	if ((serio-&gt;type &amp; SERIO_TYPE) != SERIO_8042 &amp;&amp;
+	    (serio-&gt;type &amp; SERIO_TYPE) != SERIO_PS_PSTHRU)
 		return;
 
 	if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
@@ -507,6 +534,7 @@ static void psmouse_connect(struct serio
 	psmouse-&gt;dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 	psmouse-&gt;dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
 
+	psmouse-&gt;state = PSMOUSE_NEW_DEVICE;
 	psmouse-&gt;serio = serio;
 	psmouse-&gt;dev.private = psmouse;
 
@@ -540,6 +568,10 @@ static void psmouse_connect(struct serio
 	printk(KERN_INFO "input: %s on %s\n", psmouse-&gt;devname, serio-&gt;phys);
 
 	psmouse_initialize(psmouse);
+
+	synaptics_pt_init(psmouse);
+
+	psmouse_activate(psmouse);
 }
 
 static struct serio_dev psmouse_dev = {
@@ -568,9 +600,16 @@ static int __init psmouse_smartscroll_se
 	return 1;
 }
 
+static int __init psmouse_resetafter_setup(char *str)
+{
+	get_option(&amp;str, &amp;psmouse_resetafter);
+	return 1;
+}
+
 __setup("psmouse_noext", psmouse_noext_setup);
 __setup("psmouse_resolution=", psmouse_resolution_setup);
 __setup("psmouse_smartscroll=", psmouse_smartscroll_setup);
+__setup("psmouse_resetafter=", psmouse_resetafter_setup);
 
 #endif
 
diff -puN drivers/input/mouse/psmouse.h~p00005_synaptics-pass-through drivers/input/mouse/psmouse.h
--- 25/drivers/input/mouse/psmouse.h~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/drivers/input/mouse/psmouse.h	2003-08-30 15:40:43.000000000 -0700
@@ -13,9 +13,15 @@
 #define PSMOUSE_CMD_RESET_BAT	0x02ff
 
 #define PSMOUSE_RET_BAT		0xaa
+#define PSMOUSE_RET_ID		0x00
 #define PSMOUSE_RET_ACK		0xfa
 #define PSMOUSE_RET_NAK		0xfe
 
+/* psmouse states */
+#define PSMOUSE_NEW_DEVICE	0
+#define PSMOUSE_ACTIVATED	1
+#define PSMOUSE_IGNORE		2
+
 struct psmouse {
 	void *private;
 	struct input_dev dev;
@@ -29,6 +35,7 @@ struct psmouse {
 	unsigned char type;
 	unsigned char model;
 	unsigned long last;
+	unsigned char state;
 	char acking;
 	volatile char ack;
 	char error;
@@ -36,16 +43,17 @@ struct psmouse {
 	char phys[32];
 };
 
-#define PSMOUSE_PS2	1
-#define PSMOUSE_PS2PP	2
-#define PSMOUSE_PS2TPP	3
-#define PSMOUSE_GENPS	4
-#define PSMOUSE_IMPS	5
-#define PSMOUSE_IMEX	6
-#define PSMOUSE_SYNAPTICS 7
+#define PSMOUSE_PS2		1
+#define PSMOUSE_PS2PP		2
+#define PSMOUSE_PS2TPP		3
+#define PSMOUSE_GENPS		4
+#define PSMOUSE_IMPS		5
+#define PSMOUSE_IMEX		6
+#define PSMOUSE_SYNAPTICS 	7
 
 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
 
 extern int psmouse_smartscroll;
+extern unsigned int psmouse_resetafter;
 
 #endif /* _PSMOUSE_H */
diff -puN drivers/input/mouse/synaptics.c~p00005_synaptics-pass-through drivers/input/mouse/synaptics.c
--- 25/drivers/input/mouse/synaptics.c~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/drivers/input/mouse/synaptics.c	2003-08-30 15:40:43.000000000 -0700
@@ -1,6 +1,9 @@
 /*
  * Synaptics TouchPad PS/2 mouse driver
  *
+ *   2003 Dmitry Torokhov &lt;dtor@mail.ru&gt;
+ *     Added support for pass-through port
+ *
  *   2003 Peter Osterlund &lt;petero2@telia.com&gt;
  *     Ported to 2.5 input device infrastructure.
  *
@@ -21,6 +24,7 @@
 
 #include &lt;linux/module.h&gt;
 #include &lt;linux/input.h&gt;
+#include &lt;linux/serio.h&gt;
 #include "psmouse.h"
 #include "synaptics.h"
 
@@ -71,7 +75,7 @@ static int synaptics_set_mode(struct psm
 
 	if (synaptics_special_cmd(psmouse, mode))
 		return -1;
-	param[0] = 0x14;
+	param[0] = SYN_PS_SET_MODE2;
 	if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE))
 		return -1;
 	return 0;
@@ -83,7 +87,7 @@ static int synaptics_reset(struct psmous
 
 	if (psmouse_command(psmouse, r, PSMOUSE_CMD_RESET_BAT))
 		return -1;
-	if (r[0] == 0xAA &amp;&amp; r[1] == 0x00)
+	if (r[0] == PSMOUSE_RET_BAT &amp;&amp; r[1] == PSMOUSE_RET_ID)
 		return 0;
 	return -1;
 }
@@ -143,13 +147,6 @@ static int synaptics_identify(struct psm
 	return -1;
 }
 
-static int synaptics_enable_device(struct psmouse *psmouse)
-{
-	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
-		return -1;
-	return 0;
-}
-
 static void print_ident(struct synaptics_data *priv)
 {
 	printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv-&gt;identity));
@@ -176,6 +173,8 @@ static void print_ident(struct synaptics
 			printk(KERN_INFO " -&gt; multifinger detection\n");
 		if (SYN_CAP_PALMDETECT(priv-&gt;capabilities))
 			printk(KERN_INFO " -&gt; palm detection\n");
+		if (SYN_CAP_PASS_THROUGH(priv-&gt;capabilities))
+			printk(KERN_INFO " -&gt; pass-through port\n");
 	}
 }
 
@@ -199,9 +198,96 @@ static int query_hardware(struct psmouse
 					 SYN_BIT_W_MODE)))
 		return -1;
 
-	synaptics_enable_device(psmouse);
+	return 0;
+}
 
-	print_ident(priv);
+/*****************************************************************************
+ *	Synaptics pass-through PS/2 port support
+ ****************************************************************************/
+static int synaptics_pt_open(struct serio *port)
+{
+	return 0;
+}
+
+static void synaptics_pt_close(struct serio *port)
+{
+}
+
+static int synaptics_pt_write(struct serio *port, unsigned char c)
+{
+	struct psmouse *parent = port-&gt;driver;
+	char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
+
+	if (synaptics_special_cmd(parent, c))
+		return -1;
+	if (psmouse_command(parent, &amp;rate_param, PSMOUSE_CMD_SETRATE))
+		return -1;
+	return 0;
+}
+
+static inline int synaptics_is_pt_packet(unsigned char *buf)
+{
+	return (buf[0] &amp; 0xFC) == 0x84 &amp;&amp; (buf[3] &amp; 0xCC) == 0xC4;
+}
+
+static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
+{
+	struct psmouse *child = ptport-&gt;private;
+
+	if (child) {
+		if (child-&gt;state == PSMOUSE_ACTIVATED) {
+			serio_interrupt(ptport, packet[1], 0, NULL);
+			serio_interrupt(ptport, packet[4], 0, NULL);
+			serio_interrupt(ptport, packet[5], 0, NULL);
+			if (child-&gt;type &gt;= PSMOUSE_GENPS)
+				serio_interrupt(ptport, packet[2], 0, NULL);
+		} else if (child-&gt;state != PSMOUSE_IGNORE) {
+			serio_interrupt(ptport, packet[1], 0, NULL);
+		}
+	}
+}
+
+int synaptics_pt_init(struct psmouse *psmouse)
+{
+	struct synaptics_data *priv = psmouse-&gt;private;
+	struct serio *port;
+	struct psmouse *child;
+
+	if (psmouse-&gt;type != PSMOUSE_SYNAPTICS)
+		return -1;
+	if (!SYN_CAP_EXTENDED(priv-&gt;capabilities))
+		return -1;
+	if (!SYN_CAP_PASS_THROUGH(priv-&gt;capabilities))
+		return -1;
+
+	priv-&gt;ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!port) {
+		printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n");
+		return -1;
+	}
+
+	memset(port, 0, sizeof(struct serio));
+	port-&gt;type = SERIO_PS_PSTHRU;
+	port-&gt;name = "Synaptics pass-through";
+	port-&gt;phys = "synaptics-pt/serio0";
+	port-&gt;write = synaptics_pt_write;
+	port-&gt;open = synaptics_pt_open;
+	port-&gt;close = synaptics_pt_close;
+	port-&gt;driver = psmouse;
+
+	printk(KERN_INFO "serio: %s port at %s\n", port-&gt;name, psmouse-&gt;phys);
+	serio_register_slave_port(port);
+
+	/* adjust the touchpad to child's choice of protocol */
+	child = port-&gt;private;
+	if (child &amp;&amp; child-&gt;type &gt;= PSMOUSE_GENPS) {
+		if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE |
+					 	 SYN_BIT_HIGH_RATE |
+					 	 SYN_BIT_DISABLE_GESTURE |
+						 SYN_BIT_FOUR_BYTE_CLIENT |
+					 	 SYN_BIT_W_MODE)))
+			printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
+	}
 
 	return 0;
 }
@@ -232,13 +318,15 @@ int synaptics_init(struct psmouse *psmou
 		return -1;
 	memset(priv, 0, sizeof(struct synaptics_data));
 
-	priv-&gt;inSync = 1;
+	priv-&gt;out_of_sync = 0;
 
 	if (query_hardware(psmouse)) {
 		printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n");
 		goto init_fail;
 	}
 
+	print_ident(priv);
+
 	/*
 	 * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
 	 * which says that they should be valid regardless of the actual size of
@@ -290,20 +378,22 @@ void synaptics_disconnect(struct psmouse
 {
 	struct synaptics_data *priv = psmouse-&gt;private;
 
-	/* Restore touchpad to power on default state */
-	synaptics_set_mode(psmouse, 0);
-
-	kfree(priv);
+	if (psmouse-&gt;type == PSMOUSE_SYNAPTICS &amp;&amp; priv) {
+		synaptics_set_mode(psmouse, 0);
+		if (priv-&gt;ptport) {
+			serio_unregister_slave_port(priv-&gt;ptport);
+			kfree(priv-&gt;ptport);
+		}
+		kfree(priv);
+	}
 }
 
 /*****************************************************************************
  *	Functions to interpret the absolute mode packets
  ****************************************************************************/
 
-static void synaptics_parse_hw_state(struct synaptics_data *priv, struct synaptics_hw_state *hw)
+static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
 {
-	unsigned char *buf = priv-&gt;proto_buf;
-
 	hw-&gt;x = (((buf[3] &amp; 0x10) &lt;&lt; 8) |
 		 ((buf[1] &amp; 0x0f) &lt;&lt; 8) |
 		 buf[4]);
@@ -317,7 +407,7 @@ static void synaptics_parse_hw_state(str
 		 ((buf[3] &amp; 0x04) &gt;&gt; 2));
 
 	hw-&gt;left  = (buf[0] &amp; 0x01) ? 1 : 0;
-	hw-&gt;right = (buf[0] &amp; 0x2) ? 1 : 0;
+	hw-&gt;right = (buf[0] &amp; 0x02) ? 1 : 0;
 	hw-&gt;up    = 0;
 	hw-&gt;down  = 0;
 	hw-&gt;b0    = 0;
@@ -366,7 +456,7 @@ static void synaptics_process_packet(str
 	struct synaptics_data *priv = psmouse-&gt;private;
 	struct synaptics_hw_state hw;
 
-	synaptics_parse_hw_state(priv, &amp;hw);
+	synaptics_parse_hw_state(psmouse-&gt;packet, priv, &amp;hw);
 
 	if (hw.z &gt; 0) {
 		int w_ok = 0;
@@ -431,35 +521,45 @@ void synaptics_process_byte(struct psmou
 {
 	struct input_dev *dev = &amp;psmouse-&gt;dev;
 	struct synaptics_data *priv = psmouse-&gt;private;
-	unsigned char *pBuf = priv-&gt;proto_buf;
-	unsigned char u = psmouse-&gt;packet[0];
+	unsigned char data = psmouse-&gt;packet[psmouse-&gt;pktcnt - 1];
 
 	input_regs(dev, regs);
 
-	pBuf[priv-&gt;proto_buf_tail++] = u;
-
 	/* check first byte */
-	if ((priv-&gt;proto_buf_tail == 1) &amp;&amp; ((u &amp; 0xC8) != 0x80)) {
-		priv-&gt;inSync = 0;
-		priv-&gt;proto_buf_tail = 0;
+	if (psmouse-&gt;pktcnt == 1 &amp;&amp; (data &amp; 0xC8) != 0x80) {
 		printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
+		priv-&gt;out_of_sync++;
+		psmouse-&gt;pktcnt = 0;
+	        if (psmouse_resetafter &gt; 0 &amp;&amp; priv-&gt;out_of_sync	== psmouse_resetafter) {
+			psmouse-&gt;state = PSMOUSE_IGNORE;
+			serio_rescan(psmouse-&gt;serio);
+		}
 		return;
 	}
 
 	/* check 4th byte */
-	if ((priv-&gt;proto_buf_tail == 4) &amp;&amp; ((u &amp; 0xc8) != 0xc0)) {
-		priv-&gt;inSync = 0;
-		priv-&gt;proto_buf_tail = 0;
+	if (psmouse-&gt;pktcnt == 4 &amp;&amp; (data &amp; 0xC8) != 0xC0) {
 		printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
+		priv-&gt;out_of_sync++;
+		psmouse-&gt;pktcnt = 0;
+	        if (psmouse_resetafter &gt; 0 &amp;&amp; priv-&gt;out_of_sync	== psmouse_resetafter) {
+			psmouse-&gt;state = PSMOUSE_IGNORE;
+			serio_rescan(psmouse-&gt;serio);
+		}
 		return;
 	}
 
-	if (priv-&gt;proto_buf_tail &gt;= 6) { /* Full packet received */
-		if (!priv-&gt;inSync) {
-			priv-&gt;inSync = 1;
+	if (psmouse-&gt;pktcnt &gt;= 6) { /* Full packet received */
+		if (priv-&gt;out_of_sync) {
+			priv-&gt;out_of_sync = 0;
 			printk(KERN_NOTICE "Synaptics driver resynced.\n");
 		}
-		synaptics_process_packet(psmouse);
-		priv-&gt;proto_buf_tail = 0;
+
+		if (priv-&gt;ptport &amp;&amp; synaptics_is_pt_packet(psmouse-&gt;packet))
+			synaptics_pass_pt_packet(priv-&gt;ptport, psmouse-&gt;packet);
+		else
+			synaptics_process_packet(psmouse);
+
+		psmouse-&gt;pktcnt = 0;
 	}
 }
diff -puN drivers/input/mouse/synaptics.h~p00005_synaptics-pass-through drivers/input/mouse/synaptics.h
--- 25/drivers/input/mouse/synaptics.h~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/drivers/input/mouse/synaptics.h	2003-08-30 15:40:43.000000000 -0700
@@ -12,6 +12,7 @@
 
 extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
 extern int synaptics_init(struct psmouse *psmouse);
+extern int synaptics_pt_init(struct psmouse *psmouse);
 extern void synaptics_disconnect(struct psmouse *psmouse);
 
 /* synaptics queries */
@@ -29,6 +30,7 @@ extern void synaptics_disconnect(struct 
 #define SYN_BIT_HIGH_RATE		(1 &lt;&lt; 6)
 #define SYN_BIT_SLEEP_MODE		(1 &lt;&lt; 3)
 #define SYN_BIT_DISABLE_GESTURE		(1 &lt;&lt; 2)
+#define SYN_BIT_FOUR_BYTE_CLIENT	(1 &lt;&lt; 1)
 #define SYN_BIT_W_MODE			(1 &lt;&lt; 0)
 
 /* synaptics model ID bits */
@@ -43,6 +45,7 @@ extern void synaptics_disconnect(struct 
 
 /* synaptics capability bits */
 #define SYN_CAP_EXTENDED(c)		((c) &amp; (1 &lt;&lt; 23))
+#define SYN_CAP_PASS_THROUGH(c)		((c) &amp; (1 &lt;&lt; 7))
 #define SYN_CAP_SLEEP(c)		((c) &amp; (1 &lt;&lt; 4))
 #define SYN_CAP_FOUR_BUTTON(c)		((c) &amp; (1 &lt;&lt; 3))
 #define SYN_CAP_MULTIFINGER(c)		((c) &amp; (1 &lt;&lt; 1))
@@ -65,6 +68,10 @@ extern void synaptics_disconnect(struct 
 #define SYN_ID_MINOR(i) 		(((i) &gt;&gt; 16) &amp; 0xff)
 #define SYN_ID_IS_SYNAPTICS(i)		((((i) &gt;&gt; 8) &amp; 0xff) == 0x47)
 
+/* synaptics special commands */
+#define SYN_PS_SET_MODE2		0x14
+#define SYN_PS_CLIENT_CMD		0x28
+
 /*
  * A structure to describe the state of the touchpad hardware (buttons and pad)
  */
@@ -96,12 +103,10 @@ struct synaptics_data {
 	unsigned long int identity;		/* Identification */
 
 	/* Data for normal processing */
-	unsigned char proto_buf[6];		/* Buffer for Packet */
-	unsigned char last_byte;		/* last received byte */
-	int inSync;				/* Packets in sync */
-	int proto_buf_tail;
-
+	unsigned int out_of_sync;		/* # of packets out of sync */
 	int old_w;				/* Previous w value */
+
+	struct serio *ptport;			/* pass-through port */
 };
 
 #endif /* _SYNAPTICS_H */
diff -puN drivers/input/serio/serio.c~p00005_synaptics-pass-through drivers/input/serio/serio.c
--- 25/drivers/input/serio/serio.c~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/drivers/input/serio/serio.c	2003-08-30 15:40:43.000000000 -0700
@@ -49,7 +49,9 @@ MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(serio_register_port);
+EXPORT_SYMBOL(serio_register_slave_port);
 EXPORT_SYMBOL(serio_unregister_port);
+EXPORT_SYMBOL(serio_unregister_slave_port);
 EXPORT_SYMBOL(serio_register_device);
 EXPORT_SYMBOL(serio_unregister_device);
 EXPORT_SYMBOL(serio_open);
@@ -166,6 +168,17 @@ void serio_register_port(struct serio *s
 	up(&amp;serio_sem);
 }
 
+/*
+ * Same as serio_register_port but does not try to acquire serio_sem.
+ * Should be used when registering a serio from other input device's
+ * connect() function.
+ */
+void serio_register_slave_port(struct serio *serio)
+{
+	list_add_tail(&amp;serio-&gt;node, &amp;serio_list);
+	serio_find_dev(serio);
+}
+
 void serio_unregister_port(struct serio *serio)
 {
 	down(&amp;serio_sem);
@@ -175,6 +188,18 @@ void serio_unregister_port(struct serio 
 	up(&amp;serio_sem);
 }
 
+/*
+ * Same as serio_unregister_port but does not try to acquire serio_sem.
+ * Should be used when unregistering a serio from other input device's
+ * disconnect() function.
+ */
+void serio_unregister_slave_port(struct serio *serio)
+{
+	list_del_init(&amp;serio-&gt;node);
+	if (serio-&gt;dev &amp;&amp; serio-&gt;dev-&gt;disconnect)
+		serio-&gt;dev-&gt;disconnect(serio);
+}
+
 void serio_register_device(struct serio_dev *dev)
 {
 	struct serio *serio;
diff -puN include/linux/serio.h~p00005_synaptics-pass-through include/linux/serio.h
--- 25/include/linux/serio.h~p00005_synaptics-pass-through	2003-08-30 15:40:43.000000000 -0700
+++ 25-akpm/include/linux/serio.h	2003-08-30 15:40:43.000000000 -0700
@@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio);
 irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
 
 void serio_register_port(struct serio *serio);
+void serio_register_slave_port(struct serio *serio);
 void serio_unregister_port(struct serio *serio);
+void serio_unregister_slave_port(struct serio *serio);
 void serio_register_device(struct serio_dev *dev);
 void serio_unregister_device(struct serio_dev *dev);
 
@@ -104,6 +106,7 @@ static __inline__ void serio_cleanup(str
 #define SERIO_RS232	0x02000000UL
 #define SERIO_HIL_MLC	0x03000000UL
 #define SERIO_PC9800	0x04000000UL
+#define SERIO_PS_PSTHRU	0x05000000UL
 
 #define SERIO_PROTO	0xFFUL
 #define SERIO_MSC	0x01

_
</pre></body></html>