#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
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"};
return 0;
}
+/*
+ * 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);
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);
* 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);
.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;
-}
+ if (psmouse_noext) {
+ printk(KERN_WARNING "psmouse: 'psmouse_noext' option is deprecated, please use 'psmouse_proto'\n");
+ psmouse_max_proto = PSMOUSE_PS2;
+ }
-static int __init psmouse_rate_setup(char *str)
-{
- get_option(&str, &psmouse_rate);
- return 1;
+ /* 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;
}