aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/mouse/logips2pp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse/logips2pp.c')
-rw-r--r--drivers/input/mouse/logips2pp.c213
1 files changed, 119 insertions, 94 deletions
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 0f69ff46c1a..136e222e2a1 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -19,6 +19,7 @@
#define PS2PP_KIND_WHEEL 1
#define PS2PP_KIND_MX 2
#define PS2PP_KIND_TP3 3
+#define PS2PP_KIND_TRACKMAN 4
/* Logitech mouse features */
#define PS2PP_WHEEL 0x01
@@ -29,16 +30,16 @@
#define PS2PP_NAV_BTN 0x20
struct ps2pp_info {
- const int model;
- unsigned const int kind;
- unsigned const int features;
+ u8 model;
+ u8 kind;
+ u16 features;
};
/*
* Process a PS2++ or PS2T++ packet.
*/
-static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
@@ -50,44 +51,42 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs
* Full packet accumulated, process it
*/
- input_regs(dev, regs);
-
if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
/* Logitech extended packet */
switch ((packet[1] >> 4) | (packet[0] & 0x30)) {
- case 0x0d: /* Mouse extra info */
+ case 0x0d: /* Mouse extra info */
- input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
- (int) (packet[2] & 8) - (int) (packet[2] & 7));
- input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1);
- input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1);
+ input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
+ (int) (packet[2] & 8) - (int) (packet[2] & 7));
+ input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1);
+ input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1);
- break;
+ break;
- case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
+ case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
- input_report_key(dev, BTN_SIDE, (packet[2]) & 1);
- input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1);
- input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1);
- input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1);
- input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1);
+ input_report_key(dev, BTN_SIDE, (packet[2]) & 1);
+ input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1);
+ input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1);
+ input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1);
+ input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1);
- break;
+ break;
- case 0x0f: /* TouchPad extra info */
+ case 0x0f: /* TouchPad extra info */
- input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
- (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7));
- packet[0] = packet[2] | 0x08;
- break;
+ input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
+ (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7));
+ packet[0] = packet[2] | 0x08;
+ break;
-#ifdef DEBUG
- default:
- printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
- (packet[1] >> 4) | (packet[0] & 0x30));
-#endif
+ default:
+ psmouse_dbg(psmouse,
+ "Received PS2++ packet #%x, but don't know how to handle.\n",
+ (packet[1] >> 4) | (packet[0] & 0x30));
+ break;
}
} else {
/* Standard PS/2 motion data */
@@ -117,7 +116,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
if (psmouse_sliced_command(psmouse, command))
return -1;
- if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL))
+ if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))
return -1;
return 0;
@@ -131,14 +130,11 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
* 0 - disabled
*/
-static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscroll)
+static void ps2pp_set_smartscroll(struct psmouse *psmouse, bool smartscroll)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
- if (smartscroll > 1)
- smartscroll = 1;
-
ps2pp_cmd(psmouse, param, 0x32);
param[0] = 0;
@@ -150,18 +146,23 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
}
-static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf)
+static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse,
+ void *data, char *buf)
{
- return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
+ return sprintf(buf, "%d\n", psmouse->smartscroll);
}
-static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
+static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count)
{
- unsigned long value;
- char *rest;
+ unsigned int value;
+ int err;
+
+ err = kstrtouint(buf, 10, &value);
+ if (err)
+ return err;
- value = simple_strtoul(buf, &rest, 10);
- if (*rest || value > 1)
+ if (value > 1)
return -EINVAL;
ps2pp_set_smartscroll(psmouse, value);
@@ -198,9 +199,10 @@ static void ps2pp_disconnect(struct psmouse *psmouse)
device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
}
-static struct ps2pp_info *get_model_info(unsigned char model)
+static const struct ps2pp_info *get_model_info(unsigned char model)
{
- static struct ps2pp_info ps2pp_list[] = {
+ static const struct ps2pp_info ps2pp_list[] = {
+ { 1, 0, 0 }, /* Simple 2-button mouse */
{ 12, 0, PS2PP_SIDE_BTN},
{ 13, 0, 0 },
{ 15, PS2PP_KIND_MX, /* MX1000 */
@@ -214,39 +216,45 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 51, 0, 0 },
{ 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 56, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, /* Cordless MouseMan Wheel */
{ 61, PS2PP_KIND_MX, /* MX700 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
- { 73, 0, PS2PP_SIDE_BTN },
+ { 66, PS2PP_KIND_MX, /* MX3100 receiver */
+ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
+ PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
+ { 72, PS2PP_KIND_TRACKMAN, 0 }, /* T-CH11: TrackMan Marble */
+ { 73, PS2PP_KIND_TRACKMAN, PS2PP_SIDE_BTN }, /* TrackMan FX */
{ 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 79, PS2PP_KIND_TRACKMAN, PS2PP_WHEEL }, /* TrackMan with wheel */
{ 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
+ { 99, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
- { 111, PS2PP_KIND_MX, /* MX300 */
- PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+ { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */
{ 112, PS2PP_KIND_MX, /* MX500 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
{ 114, PS2PP_KIND_MX, /* MX310 */
PS2PP_WHEEL | PS2PP_SIDE_BTN |
- PS2PP_TASK_BTN | PS2PP_EXTRA_BTN },
- { }
+ PS2PP_TASK_BTN | PS2PP_EXTRA_BTN }
};
int i;
- for (i = 0; ps2pp_list[i].model; i++)
+ for (i = 0; i < ARRAY_SIZE(ps2pp_list); i++)
if (model == ps2pp_list[i].model)
return &ps2pp_list[i];
- printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
return NULL;
}
@@ -254,53 +262,59 @@ static struct ps2pp_info *get_model_info(unsigned char model)
* Set up input device's properties based on the detected mouse model.
*/
-static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info,
- int using_ps2pp)
+static void ps2pp_set_model_properties(struct psmouse *psmouse,
+ const struct ps2pp_info *model_info,
+ bool using_ps2pp)
{
struct input_dev *input_dev = psmouse->dev;
if (model_info->features & PS2PP_SIDE_BTN)
- set_bit(BTN_SIDE, input_dev->keybit);
+ __set_bit(BTN_SIDE, input_dev->keybit);
if (model_info->features & PS2PP_EXTRA_BTN)
- set_bit(BTN_EXTRA, input_dev->keybit);
+ __set_bit(BTN_EXTRA, input_dev->keybit);
if (model_info->features & PS2PP_TASK_BTN)
- set_bit(BTN_TASK, input_dev->keybit);
+ __set_bit(BTN_TASK, input_dev->keybit);
if (model_info->features & PS2PP_NAV_BTN) {
- set_bit(BTN_FORWARD, input_dev->keybit);
- set_bit(BTN_BACK, input_dev->keybit);
+ __set_bit(BTN_FORWARD, input_dev->keybit);
+ __set_bit(BTN_BACK, input_dev->keybit);
}
if (model_info->features & PS2PP_WHEEL)
- set_bit(REL_WHEEL, input_dev->relbit);
+ __set_bit(REL_WHEEL, input_dev->relbit);
if (model_info->features & PS2PP_HWHEEL)
- set_bit(REL_HWHEEL, input_dev->relbit);
+ __set_bit(REL_HWHEEL, input_dev->relbit);
switch (model_info->kind) {
- case PS2PP_KIND_WHEEL:
- psmouse->name = "Wheel Mouse";
- break;
- case PS2PP_KIND_MX:
- psmouse->name = "MX Mouse";
- break;
-
- case PS2PP_KIND_TP3:
- psmouse->name = "TouchPad 3";
- break;
-
- default:
- /*
- * Set name to "Mouse" only when using PS2++,
- * otherwise let other protocols define suitable
- * name
- */
- if (using_ps2pp)
- psmouse->name = "Mouse";
- break;
+ case PS2PP_KIND_WHEEL:
+ psmouse->name = "Wheel Mouse";
+ break;
+
+ case PS2PP_KIND_MX:
+ psmouse->name = "MX Mouse";
+ break;
+
+ case PS2PP_KIND_TP3:
+ psmouse->name = "TouchPad 3";
+ break;
+
+ case PS2PP_KIND_TRACKMAN:
+ psmouse->name = "TrackMan";
+ break;
+
+ default:
+ /*
+ * Set name to "Mouse" only when using PS2++,
+ * otherwise let other protocols define suitable
+ * name
+ */
+ if (using_ps2pp)
+ psmouse->name = "Mouse";
+ break;
}
}
@@ -311,13 +325,14 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_inf
* that support it.
*/
-int ps2pp_init(struct psmouse *psmouse, int set_properties)
+int ps2pp_init(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
unsigned char model, buttons;
- struct ps2pp_info *model_info;
- int use_ps2pp = 0;
+ const struct ps2pp_info *model_info;
+ bool use_ps2pp = false;
+ int error;
param[0] = 0;
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
@@ -327,18 +342,19 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
param[1] = 0;
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
- if (!param[1])
- return -1;
-
model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
buttons = param[1];
- if ((model_info = get_model_info(model)) != NULL) {
+ if (!model || !buttons)
+ return -1;
+
+ model_info = get_model_info(model);
+ if (model_info) {
/*
* Do Logitech PS2++ / PS2T++ magic init.
*/
- if (model == 97) { /* Touch Pad 3 */
+ if (model_info->kind == PS2PP_KIND_TP3) { /* Touch Pad 3 */
/* Unprotect RAM */
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68;
@@ -353,7 +369,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
param[0] = 0;
if (!ps2_command(ps2dev, param, 0x13d1) &&
param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
- use_ps2pp = 1;
+ use_ps2pp = true;
}
} else {
@@ -365,10 +381,13 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
if ((param[0] & 0x78) == 0x48 &&
(param[1] & 0xf3) == 0xc2 &&
(param[2] & 0x03) == ((param[1] >> 2) & 3)) {
- ps2pp_set_smartscroll(psmouse, psmouse->smartscroll);
- use_ps2pp = 1;
+ ps2pp_set_smartscroll(psmouse, false);
+ use_ps2pp = true;
}
}
+
+ } else {
+ psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model);
}
if (set_properties) {
@@ -383,13 +402,19 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
psmouse->set_resolution = ps2pp_set_resolution;
psmouse->disconnect = ps2pp_disconnect;
- device_create_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_smartscroll.dattr);
+ error = device_create_file(&psmouse->ps2dev.serio->dev,
+ &psmouse_attr_smartscroll.dattr);
+ if (error) {
+ psmouse_err(psmouse,
+ "failed to create smartscroll sysfs attribute, error: %d\n",
+ error);
+ return -1;
+ }
}
}
- if (buttons < 3)
- clear_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ if (buttons >= 3)
+ __set_bit(BTN_MIDDLE, psmouse->dev->keybit);
if (model_info)
ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);