Commit e9b15897 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Vojtech Pavlik

Input: do not modify device's properties when probing for protocol

       extensions on reconnect as it may interfere with reconnect
       process
parent bbed529f
...@@ -103,14 +103,11 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse) ...@@ -103,14 +103,11 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse)
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
if (psmouse_smartscroll == 1) if (psmouse_smartscroll < 2) {
param[0] = 1; /* 0 - disabled, 1 - enabled */
else param[0] = psmouse_smartscroll;
if (psmouse_smartscroll > 2)
return;
/* else leave param[0] == 0 to disable */
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
}
} }
/* /*
...@@ -128,48 +125,47 @@ void ps2pp_set_800dpi(struct psmouse *psmouse) ...@@ -128,48 +125,47 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
psmouse_command(psmouse, &param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, &param, PSMOUSE_CMD_SETRES);
} }
static int is_model_in_list(unsigned char model, int *model_list)
{
int i;
for (i = 0; model_list[i] != -1; i++)
if (model == model_list[i])
return 1;
return 0;
}
/* /*
* Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or * Set up input device's properties based on the detected mouse model.
* touchpad.
*/ */
static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) static void ps2pp_set_properties(struct psmouse *psmouse, unsigned char protocol,
unsigned char model, unsigned char buttons)
{ {
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 };
static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, 112, -1 }; static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, 112, -1 };
static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
76, 80, 81, 83, 88, 96, 97, 112, -1 };
static int logitech_mx[] = { 61, 112, -1 }; static int logitech_mx[] = { 61, 112, -1 };
psmouse->vendor = "Logitech"; psmouse->vendor = "Logitech";
psmouse->model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); psmouse->model = model;
if (param[1] < 3) if (buttons < 3)
clear_bit(BTN_MIDDLE, psmouse->dev.keybit); clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
if (param[1] < 2) if (buttons < 2)
clear_bit(BTN_RIGHT, psmouse->dev.keybit); clear_bit(BTN_RIGHT, psmouse->dev.keybit);
psmouse->type = PSMOUSE_PS2; if (protocol == PSMOUSE_PS2PP) {
for (i = 0; logitech_ps2pp[i] != -1; i++) if (is_model_in_list(model, logitech_4btn))
if (logitech_ps2pp[i] == psmouse->model)
psmouse->type = PSMOUSE_PS2PP;
if (psmouse->type == PSMOUSE_PS2PP) {
for (i = 0; logitech_4btn[i] != -1; i++)
if (logitech_4btn[i] == psmouse->model)
set_bit(BTN_SIDE, psmouse->dev.keybit); set_bit(BTN_SIDE, psmouse->dev.keybit);
for (i = 0; logitech_wheel[i] != -1; i++) if (is_model_in_list(model, logitech_wheel)) {
if (logitech_wheel[i] == psmouse->model) {
set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(REL_WHEEL, psmouse->dev.relbit);
psmouse->name = "Wheel Mouse"; psmouse->name = "Wheel Mouse";
} }
for (i = 0; logitech_mx[i] != -1; i++) if (is_model_in_list(model, logitech_mx)) {
if (logitech_mx[i] == psmouse->model) {
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);
set_bit(BTN_BACK, psmouse->dev.keybit); set_bit(BTN_BACK, psmouse->dev.keybit);
...@@ -177,62 +173,80 @@ static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) ...@@ -177,62 +173,80 @@ static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
set_bit(BTN_TASK, psmouse->dev.keybit); set_bit(BTN_TASK, psmouse->dev.keybit);
psmouse->name = "MX Mouse"; psmouse->name = "MX Mouse";
} }
}
if (protocol == PSMOUSE_PS2TPP) {
set_bit(REL_WHEEL, psmouse->dev.relbit);
set_bit(REL_HWHEEL, psmouse->dev.relbit);
psmouse->name = "TouchPad 3";
}
}
/* /*
* Do Logitech PS2++ / PS2T++ magic init. * Logitech magic init. Detect whether the mouse is a Logitech one
* and its exact model and try turning on extended protocol for ones
* that support it.
*/ */
if (psmouse->model == 97) { /* TouchPad 3 */ int ps2pp_init(struct psmouse *psmouse, int set_properties)
{
static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
76, 80, 81, 83, 88, 96, 97, 112, -1 };
unsigned char param[4];
unsigned char protocol = PSMOUSE_PS2;
unsigned char model, buttons;
set_bit(REL_WHEEL, psmouse->dev.relbit); param[0] = 0;
set_bit(REL_HWHEEL, psmouse->dev.relbit); 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);
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */ if (param[1] != 0) {
model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
buttons = param[1];
/*
* Do Logitech PS2++ / PS2T++ magic init.
*/
if (model == 97) { /* Touch Pad 3 */
/* Unprotect RAM */
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68;
psmouse_command(psmouse, param, 0x30d1); psmouse_command(psmouse, param, 0x30d1);
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */ /* Enable features */
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b;
psmouse_command(psmouse, param, 0x30d1); psmouse_command(psmouse, param, 0x30d1);
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */ /* Enable PS2++ */
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3;
psmouse_command(psmouse, param, 0x30d1); psmouse_command(psmouse, param, 0x30d1);
param[0] = 0; param[0] = 0;
if (!psmouse_command(psmouse, param, 0x13d1) && if (!psmouse_command(psmouse, param, 0x13d1) &&
param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
psmouse->name = "TouchPad 3"; protocol = PSMOUSE_PS2TPP;
return PSMOUSE_PS2TPP;
} }
} else { } else if (is_model_in_list(model, logitech_ps2pp)) {
param[0] = param[1] = param[2] = 0; param[0] = param[1] = param[2] = 0;
ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */ ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
ps2pp_cmd(psmouse, param, 0xDB); ps2pp_cmd(psmouse, param, 0xDB);
if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 && if ((param[0] & 0x78) == 0x48 &&
(param[2] & 3) == ((param[1] >> 2) & 3)) { (param[1] & 0xf3) == 0xc2 &&
(param[2] & 0x03) == ((param[1] >> 2) & 3)) {
ps2pp_set_smartscroll(psmouse); ps2pp_set_smartscroll(psmouse);
return PSMOUSE_PS2PP; protocol = PSMOUSE_PS2PP;
}
} }
} }
return 0; if (set_properties)
} ps2pp_set_properties(psmouse, protocol, model, buttons);
}
/*
* 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; return protocol;
} }
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
#ifndef _LOGIPS2PP_H #ifndef _LOGIPS2PP_H
#define _LOGIPS2PP_H #define _LOGIPS2PP_H
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(struct psmouse *psmouse); int ps2pp_init(struct psmouse *psmouse, int set_properties);
#endif #endif
...@@ -410,22 +410,21 @@ static int im_explorer_detect(struct psmouse *psmouse) ...@@ -410,22 +410,21 @@ static int im_explorer_detect(struct psmouse *psmouse)
* the mouse may have. * the mouse may have.
*/ */
static int psmouse_extensions(struct psmouse *psmouse, unsigned int max_proto) static int psmouse_extensions(struct psmouse *psmouse,
unsigned int max_proto, int set_properties)
{ {
int synaptics_hardware = 0; int synaptics_hardware = 0;
psmouse->vendor = "Generic";
psmouse->name = "Mouse";
psmouse->model = 0;
psmouse->protocol_handler = psmouse_process_byte;
/* /*
* Try Synaptics TouchPad * Try Synaptics TouchPad
*/ */
if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) { if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) {
synaptics_hardware = 1; synaptics_hardware = 1;
if (set_properties) {
psmouse->vendor = "Synaptics"; psmouse->vendor = "Synaptics";
psmouse->name = "TouchPad"; psmouse->name = "TouchPad";
}
if (max_proto > PSMOUSE_IMEX) { if (max_proto > PSMOUSE_IMEX) {
if (synaptics_init(psmouse) == 0) if (synaptics_init(psmouse) == 0)
...@@ -444,33 +443,44 @@ static int psmouse_extensions(struct psmouse *psmouse, unsigned int max_proto) ...@@ -444,33 +443,44 @@ static int psmouse_extensions(struct psmouse *psmouse, unsigned int max_proto)
} }
if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) { if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
if (set_properties) {
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);
psmouse->vendor = "Genius"; psmouse->vendor = "Genius";
psmouse->name = "Wheel Mouse"; psmouse->name = "Wheel Mouse";
}
return PSMOUSE_GENPS; return PSMOUSE_GENPS;
} }
if (max_proto > PSMOUSE_IMEX) { if (max_proto > PSMOUSE_IMEX) {
int type = ps2pp_detect(psmouse); int type = ps2pp_init(psmouse, set_properties);
if (type) if (type > PSMOUSE_PS2)
return type; return type;
} }
if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) { if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) {
if (set_properties) {
set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(REL_WHEEL, psmouse->dev.relbit);
if (!psmouse->name)
psmouse->name = "Wheel Mouse";
}
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse)) { if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse)) {
if (!set_properties) {
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);
if (!psmouse->name)
psmouse->name = "Explorer Mouse"; psmouse->name = "Explorer Mouse";
}
return PSMOUSE_IMEX; return PSMOUSE_IMEX;
} }
psmouse->name = "Wheel Mouse";
return PSMOUSE_IMPS; return PSMOUSE_IMPS;
} }
...@@ -520,12 +530,7 @@ static int psmouse_probe(struct psmouse *psmouse) ...@@ -520,12 +530,7 @@ static int psmouse_probe(struct psmouse *psmouse)
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS)) if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS))
printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys); printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys);
/* return 0;
* And here we try to determine if it has any extensions over the
* basic PS/2 3-button mouse.
*/
return psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto);
} }
/* /*
...@@ -663,7 +668,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -663,7 +668,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
psmouse->state = PSMOUSE_CMD_MODE; psmouse->state = PSMOUSE_CMD_MODE;
psmouse->serio = serio; psmouse->serio = serio;
psmouse->dev.private = psmouse; psmouse->dev.private = psmouse;
...@@ -675,13 +679,21 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -675,13 +679,21 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return; return;
} }
if (psmouse_probe(psmouse) <= 0) { if (psmouse_probe(psmouse) < 0) {
serio_close(serio); serio_close(serio);
kfree(psmouse); kfree(psmouse);
serio->private = NULL; serio->private = NULL;
return; return;
} }
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
if (!psmouse->vendor)
psmouse->vendor = "Generic";
if (!psmouse->name)
psmouse->name = "Mouse";
if (!psmouse->protocol_handler)
psmouse->protocol_handler = psmouse_process_byte;
sprintf(psmouse->devname, "%s %s %s", sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
sprintf(psmouse->phys, "%s/input0", sprintf(psmouse->phys, "%s/input0",
...@@ -715,28 +727,24 @@ static int psmouse_reconnect(struct serio *serio) ...@@ -715,28 +727,24 @@ static int psmouse_reconnect(struct serio *serio)
{ {
struct psmouse *psmouse = serio->private; struct psmouse *psmouse = serio->private;
struct serio_dev *dev = serio->dev; struct serio_dev *dev = serio->dev;
int old_type;
if (!dev || !psmouse) { if (!dev || !psmouse) {
printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n"); printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
return -1; return -1;
} }
old_type = psmouse->type;
psmouse->state = PSMOUSE_CMD_MODE; psmouse->state = PSMOUSE_CMD_MODE;
psmouse->type = psmouse->acking = 0; psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
if (psmouse->reconnect) { if (psmouse->reconnect) {
if (psmouse->reconnect(psmouse)) if (psmouse->reconnect(psmouse))
return -1; return -1;
} else if (psmouse_probe(psmouse) != old_type) } else if (psmouse_probe(psmouse) < 0 ||
psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
return -1; return -1;
/* ok, the device type (and capabilities) match the old one, /* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization * we can continue using it, complete intialization
*/ */
psmouse->type = old_type;
psmouse_initialize(psmouse); psmouse_initialize(psmouse);
if (psmouse->ptport) { if (psmouse->ptport) {
......
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