From: Dmitry Torokhov <dtor_core@ameritech.net>

New parameter psmouse_proto to replace psmouse_noext.  Allows to specify
highest PS/2 protocol extension that kernel has permission to negotiate
(bare|imps|exps).  psmouse_noext marked as deprecated and emits a warning
when used.  parameter parsing converted to the new scheme.



 Documentation/kernel-parameters.txt |    3 
 drivers/input/mouse/logips2pp.c     |   21 +++
 drivers/input/mouse/logips2pp.h     |    2 
 drivers/input/mouse/psmouse-base.c  |  213 +++++++++++++++++-------------------
 drivers/input/mouse/synaptics.c     |    4 
 5 files changed, 128 insertions(+), 115 deletions(-)

diff -puN Documentation/kernel-parameters.txt~input-02-add-psmouse_proto Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~input-02-add-psmouse_proto	2003-12-16 22:47:29.000000000 -0800
+++ 25-akpm/Documentation/kernel-parameters.txt	2003-12-16 22:47:29.000000000 -0800
@@ -790,7 +790,8 @@ running once the system is up.
 			before loading.
 			See Documentation/ramdisk.txt.
 
-	psmouse_noext	[HW,MOUSE] Disable probing for PS2 mouse protocol extensions
+	psmouse_proto=  [HW,MOUSE] Highest PS2 mouse protocol extension to
+			probe for (bare|imps|exps).
 
 	psmouse_resetafter=
 			[HW,MOUSE] Try to reset Synaptics Touchpad after so many
diff -puN drivers/input/mouse/logips2pp.c~input-02-add-psmouse_proto drivers/input/mouse/logips2pp.c
--- 25/drivers/input/mouse/logips2pp.c~input-02-add-psmouse_proto	2003-12-16 22:47:29.000000000 -0800
+++ 25-akpm/drivers/input/mouse/logips2pp.c	2003-12-16 22:47:29.000000000 -0800
@@ -143,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *ps
  * touchpad.
  */
 
-int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
+static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
 {
 	int i;
 	static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
@@ -227,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *p
 
 	return 0;
 }
+
+/*
+ * Logitech magic init.
+ */
+int ps2pp_detect(struct psmouse *psmouse)
+{
+	unsigned char param[4];
+
+	param[0] = 0;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	param[1] = 0;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+
+	return param[1] != 0 ? ps2pp_detect_model(psmouse, param) : 0;
+}
+
diff -puN drivers/input/mouse/logips2pp.h~input-02-add-psmouse_proto drivers/input/mouse/logips2pp.h
--- 25/drivers/input/mouse/logips2pp.h~input-02-add-psmouse_proto	2003-12-16 22:47:29.000000000 -0800
+++ 25-akpm/drivers/input/mouse/logips2pp.h	2003-12-16 22:47:29.000000000 -0800
@@ -13,5 +13,5 @@
 struct psmouse;
 void ps2pp_process_packet(struct psmouse *psmouse);
 void ps2pp_set_800dpi(struct psmouse *psmouse);
-int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param);
+int ps2pp_detect(struct psmouse *psmouse);
 #endif
diff -puN drivers/input/mouse/psmouse-base.c~input-02-add-psmouse_proto drivers/input/mouse/psmouse-base.c
--- 25/drivers/input/mouse/psmouse-base.c~input-02-add-psmouse_proto	2003-12-16 22:47:29.000000000 -0800
+++ 25-akpm/drivers/input/mouse/psmouse-base.c	2003-12-16 22:47:29.000000000 -0800
@@ -12,6 +12,7 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
@@ -24,23 +25,32 @@
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("PS/2 mouse driver");
-MODULE_PARM(psmouse_noext, "1i");
-MODULE_PARM_DESC(psmouse_noext, "Disable any protocol extensions. Useful for KVM switches.");
-MODULE_PARM(psmouse_resolution, "i");
-MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
-MODULE_PARM(psmouse_rate, "i");
-MODULE_PARM_DESC(psmouse_rate, "Report rate, in reports per second.");
-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");
 
 static int psmouse_noext;
+module_param(psmouse_noext, int, 0);
+MODULE_PARM_DESC(psmouse_noext, "[DEPRECATED] Disable any protocol extensions. Useful for KVM switches.");
+
+static char *psmouse_proto;
+static unsigned int psmouse_max_proto = -1UL;
+module_param(psmouse_proto, charp, 0);
+MODULE_PARM_DESC(psmouse_proto, "Highest protocol extension to probe (bare, imps, exps). Useful for KVM switches.");
+
 int psmouse_resolution = 200;
+module_param(psmouse_resolution, uint, 0);
+MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
+
 unsigned int psmouse_rate = 100;
+module_param(psmouse_rate, uint, 0);
+MODULE_PARM_DESC(psmouse_rate, "Report rate, in reports per second.");
+
 int psmouse_smartscroll = 1;
+module_param(psmouse_smartscroll, bool, 0);
+MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
+
 unsigned int psmouse_resetafter;
+module_param(psmouse_resetafter, uint, 0);
+MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
 
 static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
 
@@ -258,49 +268,88 @@ int psmouse_command(struct psmouse *psmo
 }
 
 /*
+ * Genius NetMouse magic init.
+ */
+static int genius_detect(struct psmouse *psmouse)
+{
+	unsigned char param[4];
+
+	param[0] = 3;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+
+	return param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55;
+}
+
+/*
+ * IntelliMouse magic init.
+ */
+static int intellimouse_detect(struct psmouse *psmouse)
+{
+	unsigned char param[2];
+
+	param[0] = 200;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	param[0] = 100;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	param[0] =  80;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
+
+	return param[0] == 3;
+}
+
+/*
+ * Try IntelliMouse/Explorer magic init.
+ */
+static int im_explorer_detect(struct psmouse *psmouse)
+{
+	unsigned char param[2];
+
+	param[0] = 200;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	param[0] = 200;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	param[0] =  80;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
+
+	return param[0] == 4;
+}
+
+/*
  * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
  * the mouse may have.
  */
 
 static int psmouse_extensions(struct psmouse *psmouse)
 {
-	unsigned char param[4];
-
-	param[0] = 0;
 	psmouse->vendor = "Generic";
 	psmouse->name = "Mouse";
 	psmouse->model = 0;
 
-	if (psmouse_noext)
-		return PSMOUSE_PS2;
-
 /*
  * Try Synaptics TouchPad
  */
-	if (synaptics_detect(psmouse) == 0) {
+	if (psmouse_max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) {
 		psmouse->vendor = "Synaptics";
 		psmouse->name = "TouchPad";
 
 #if CONFIG_MOUSE_PS2_SYNAPTICS
-		if (synaptics_init(psmouse) == 0)
+		if (psmouse_max_proto > PSMOUSE_IMEX && synaptics_init(psmouse) == 0)
 			return PSMOUSE_SYNAPTICS;
 #endif
+		/*
+		 * Synaptics hardware (according to Peter Berg Larsen) can get confused
+		 * by protocol probes below so we have to stop here
+		 */
 		return PSMOUSE_PS2;
 	}
 
-/*
- * Try Genius NetMouse magic init.
- */
-
-	param[0] = 3;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
-
-	if (param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55) {
-
+	if (psmouse_max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
 		set_bit(BTN_EXTRA, psmouse->dev.keybit);
 		set_bit(BTN_SIDE, psmouse->dev.keybit);
 		set_bit(REL_WHEEL, psmouse->dev.relbit);
@@ -310,54 +359,16 @@ static int psmouse_extensions(struct psm
 		return PSMOUSE_GENPS;
 	}
 
-/*
- * Try Logitech magic ID.
- */
-
-	param[0] = 0;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	param[1] = 0;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
-
-	if (param[1]) {
-		int type = ps2pp_detect_model(psmouse, param);
+	if (psmouse_max_proto > PSMOUSE_IMEX) {
+		int type = ps2pp_detect(psmouse);
 		if (type)
 			return type;
 	}
 
-/*
- * Try IntelliMouse magic init.
- */
-
-	param[0] = 200;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-	param[0] = 100;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-	param[0] =  80;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-	psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
-	
-	if (param[0] == 3) {
-
+	if (psmouse_max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) {
 		set_bit(REL_WHEEL, psmouse->dev.relbit);
 
-/*
- * Try IntelliMouse/Explorer magic init.
- */
-
-		param[0] = 200;
-		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-		param[0] = 200;
-		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-		param[0] =  80;
-		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-		psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
-
-		if (param[0] == 4) {
-
+		if (psmouse_max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse)) {
 			set_bit(BTN_SIDE, psmouse->dev.keybit);
 			set_bit(BTN_EXTRA, psmouse->dev.keybit);
 
@@ -463,7 +474,7 @@ static void psmouse_initialize(struct ps
  * We set the mouse report rate, resolution and scaling.
  */
 
-	if (!psmouse_noext) {
+	if (psmouse_max_proto != PSMOUSE_PS2) {
 		psmouse_set_rate(psmouse);
 		psmouse_set_resolution(psmouse);
 		psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
@@ -673,47 +684,29 @@ static struct serio_dev psmouse_dev = {
 	.cleanup =	psmouse_cleanup,
 };
 
-#ifndef MODULE
-static int __init psmouse_noext_setup(char *str)
+static inline void psmouse_parse_proto(void)
 {
-	psmouse_noext = 1;
-	return 1;
-}
-
-static int __init psmouse_resolution_setup(char *str)
-{
-	get_option(&str, &psmouse_resolution);
-	return 1;
-}
-
-static int __init psmouse_smartscroll_setup(char *str)
-{
-	get_option(&str, &psmouse_smartscroll);
-	return 1;
-}
-
-static int __init psmouse_resetafter_setup(char *str)
-{
-	get_option(&str, &psmouse_resetafter);
-	return 1;
-}
-
-static int __init psmouse_rate_setup(char *str)
-{
-	get_option(&str, &psmouse_rate);
-	return 1;
+	if (psmouse_noext) {
+		printk(KERN_WARNING "psmouse: 'psmouse_noext' option is deprecated, please use 'psmouse_proto'\n");
+		psmouse_max_proto = PSMOUSE_PS2;
+	}
+
+	/* even is psmouse_noext is present psmouse_proto overrides it */
+	if (psmouse_proto) {
+		if (!strcmp(psmouse_proto, "bare"))
+			psmouse_max_proto = PSMOUSE_PS2;
+		else if (!strcmp(psmouse_proto, "imps"))
+			psmouse_max_proto = PSMOUSE_IMPS;
+		else if (!strcmp(psmouse_proto, "exps"))
+			psmouse_max_proto = PSMOUSE_IMEX;
+		else
+			printk(KERN_ERR "psmouse: unknown protocol type '%s'\n", psmouse_proto);
+	}
 }
 
-__setup("psmouse_noext", psmouse_noext_setup);
-__setup("psmouse_resolution=", psmouse_resolution_setup);
-__setup("psmouse_smartscroll=", psmouse_smartscroll_setup);
-__setup("psmouse_resetafter=", psmouse_resetafter_setup);
-__setup("psmouse_rate=", psmouse_rate_setup);
-
-#endif
-
 int __init psmouse_init(void)
 {
+	psmouse_parse_proto();
 	serio_register_device(&psmouse_dev);
 	return 0;
 }
diff -puN drivers/input/mouse/synaptics.c~input-02-add-psmouse_proto drivers/input/mouse/synaptics.c
--- 25/drivers/input/mouse/synaptics.c~input-02-add-psmouse_proto	2003-12-16 22:47:29.000000000 -0800
+++ 25-akpm/drivers/input/mouse/synaptics.c	2003-12-16 22:47:29.000000000 -0800
@@ -377,7 +377,7 @@ static int synaptics_reconnect(struct ps
 	struct synaptics_data *priv = psmouse->private;
 	struct synaptics_data old_priv = *priv;
 
-	if (synaptics_detect(psmouse))
+	if (!synaptics_detect(psmouse))
 		return -1;
 
 	if (synaptics_query_hardware(psmouse)) {
@@ -411,7 +411,7 @@ int synaptics_detect(struct psmouse *psm
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
 	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
 
-	return param[1] == 0x47 ? 0 : -1;
+	return param[1] == 0x47;
 }
 
 int synaptics_init(struct psmouse *psmouse)

_