Commit c0fbf5b6 authored by Dmitry Torokhov's avatar Dmitry Torokhov

[PATCH] Input: add psmouse_proto parameter

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.
parent 0f40c994
...@@ -790,7 +790,8 @@ running once the system is up. ...@@ -790,7 +790,8 @@ running once the system is up.
before loading. before loading.
See Documentation/ramdisk.txt. 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= psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many [HW,MOUSE] Try to reset Synaptics Touchpad after so many
......
...@@ -143,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse) ...@@ -143,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
* touchpad. * touchpad.
*/ */
int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
{ {
int i; int i;
static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 }; static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
...@@ -227,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) ...@@ -227,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
return 0; 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;
}
...@@ -13,5 +13,5 @@ ...@@ -13,5 +13,5 @@
struct psmouse; struct psmouse;
void ps2pp_process_packet(struct psmouse *psmouse); void ps2pp_process_packet(struct psmouse *psmouse);
void ps2pp_set_800dpi(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 #endif
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/input.h> #include <linux/input.h>
...@@ -24,23 +25,32 @@ ...@@ -24,23 +25,32 @@
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("PS/2 mouse driver"); 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"); MODULE_LICENSE("GPL");
static int psmouse_noext; 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; int psmouse_resolution = 200;
module_param(psmouse_resolution, uint, 0);
MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
unsigned int psmouse_rate = 100; 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; 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; 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"}; static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
...@@ -257,6 +267,59 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) ...@@ -257,6 +267,59 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
return 0; 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 * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have. * the mouse may have.
...@@ -264,43 +327,29 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) ...@@ -264,43 +327,29 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
static int psmouse_extensions(struct psmouse *psmouse) static int psmouse_extensions(struct psmouse *psmouse)
{ {
unsigned char param[4];
param[0] = 0;
psmouse->vendor = "Generic"; psmouse->vendor = "Generic";
psmouse->name = "Mouse"; psmouse->name = "Mouse";
psmouse->model = 0; psmouse->model = 0;
if (psmouse_noext)
return PSMOUSE_PS2;
/* /*
* Try Synaptics TouchPad * Try Synaptics TouchPad
*/ */
if (synaptics_detect(psmouse) == 0) { if (psmouse_max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) {
psmouse->vendor = "Synaptics"; psmouse->vendor = "Synaptics";
psmouse->name = "TouchPad"; psmouse->name = "TouchPad";
#if CONFIG_MOUSE_PS2_SYNAPTICS #if CONFIG_MOUSE_PS2_SYNAPTICS
if (synaptics_init(psmouse) == 0) if (psmouse_max_proto > PSMOUSE_IMEX && synaptics_init(psmouse) == 0)
return PSMOUSE_SYNAPTICS; return PSMOUSE_SYNAPTICS;
#endif #endif
/*
* Synaptics hardware (according to Peter Berg Larsen) can get confused
* by protocol probes below so we have to stop here
*/
return PSMOUSE_PS2; return PSMOUSE_PS2;
} }
/* if (psmouse_max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
* 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) {
set_bit(BTN_EXTRA, psmouse->dev.keybit); set_bit(BTN_EXTRA, psmouse->dev.keybit);
set_bit(BTN_SIDE, psmouse->dev.keybit); set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(REL_WHEEL, psmouse->dev.relbit);
...@@ -310,54 +359,16 @@ static int psmouse_extensions(struct psmouse *psmouse) ...@@ -310,54 +359,16 @@ static int psmouse_extensions(struct psmouse *psmouse)
return PSMOUSE_GENPS; return PSMOUSE_GENPS;
} }
/* if (psmouse_max_proto > PSMOUSE_IMEX) {
* Try Logitech magic ID. int type = ps2pp_detect(psmouse);
*/
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 (type) if (type)
return type; return type;
} }
/* if (psmouse_max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) {
* 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) {
set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(REL_WHEEL, psmouse->dev.relbit);
/* if (psmouse_max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse)) {
* 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) {
set_bit(BTN_SIDE, psmouse->dev.keybit); set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(BTN_EXTRA, psmouse->dev.keybit); set_bit(BTN_EXTRA, psmouse->dev.keybit);
...@@ -463,7 +474,7 @@ static void psmouse_initialize(struct psmouse *psmouse) ...@@ -463,7 +474,7 @@ static void psmouse_initialize(struct psmouse *psmouse)
* We set the mouse report rate, resolution and scaling. * We set the mouse report rate, resolution and scaling.
*/ */
if (!psmouse_noext) { if (psmouse_max_proto != PSMOUSE_PS2) {
psmouse_set_rate(psmouse); psmouse_set_rate(psmouse);
psmouse_set_resolution(psmouse); psmouse_set_resolution(psmouse);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
...@@ -673,47 +684,29 @@ static struct serio_dev psmouse_dev = { ...@@ -673,47 +684,29 @@ static struct serio_dev psmouse_dev = {
.cleanup = psmouse_cleanup, .cleanup = psmouse_cleanup,
}; };
#ifndef MODULE static inline void psmouse_parse_proto(void)
static int __init psmouse_noext_setup(char *str)
{ {
psmouse_noext = 1; if (psmouse_noext) {
return 1; printk(KERN_WARNING "psmouse: 'psmouse_noext' option is deprecated, please use 'psmouse_proto'\n");
} psmouse_max_proto = PSMOUSE_PS2;
}
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) /* even is psmouse_noext is present psmouse_proto overrides it */
{ if (psmouse_proto) {
get_option(&str, &psmouse_rate); if (!strcmp(psmouse_proto, "bare"))
return 1; 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) int __init psmouse_init(void)
{ {
psmouse_parse_proto();
serio_register_device(&psmouse_dev); serio_register_device(&psmouse_dev);
return 0; return 0;
} }
......
...@@ -377,7 +377,7 @@ static int synaptics_reconnect(struct psmouse *psmouse) ...@@ -377,7 +377,7 @@ static int synaptics_reconnect(struct psmouse *psmouse)
struct synaptics_data *priv = psmouse->private; struct synaptics_data *priv = psmouse->private;
struct synaptics_data old_priv = *priv; struct synaptics_data old_priv = *priv;
if (synaptics_detect(psmouse)) if (!synaptics_detect(psmouse))
return -1; return -1;
if (synaptics_query_hardware(psmouse)) { if (synaptics_query_hardware(psmouse)) {
...@@ -411,7 +411,7 @@ int synaptics_detect(struct psmouse *psmouse) ...@@ -411,7 +411,7 @@ int synaptics_detect(struct psmouse *psmouse)
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
return param[1] == 0x47 ? 0 : -1; return param[1] == 0x47;
} }
int synaptics_init(struct psmouse *psmouse) int synaptics_init(struct psmouse *psmouse)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment