summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2013-02-13 22:19:59 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-02-14 09:17:57 -0800
commitb5d6b851eab7f346ea5e69f46247b363b32b3670 (patch)
tree10ada693aa80f6ea6bce2aacef57dee3b51d74df
parent24ba9707829818daab711eed7e41313d5e56d0b4 (diff)
downloadlinux-b5d6b851eab7f346ea5e69f46247b363b32b3670.tar.gz
linux-b5d6b851eab7f346ea5e69f46247b363b32b3670.tar.bz2
linux-b5d6b851eab7f346ea5e69f46247b363b32b3670.zip
Input: ALPS - rework detection sequence
If the E6 report test passes, get the E7 and EC reports right away and then try to match an entry in the table. Pass in the alps_data struct, so that the detection code will be able to set operating parameters based on information found during detection. Change the version (psmouse->model) to report the protocol version only, in preparation for supporting models that do not show up in the ID table. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Tested-by: Dave Turvene <dturvene@dahetral.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/mouse/alps.c124
-rw-r--r--drivers/input/mouse/alps.h8
2 files changed, 56 insertions, 76 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 1ca854b0b012..e6a27a5cbb1d 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1451,86 +1451,76 @@ static int alps_hw_init(struct psmouse *psmouse)
return ret;
}
-static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
+static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv,
+ unsigned char *e7, unsigned char *ec)
{
- static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
- unsigned char param[4];
- const struct alps_model_info *model = NULL;
+ const struct alps_model_info *model;
int i;
+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
+ model = &alps_model_data[i];
+
+ if (!memcmp(e7, model->signature, sizeof(model->signature)) &&
+ (!model->command_mode_resp ||
+ model->command_mode_resp == ec[2])) {
+
+ priv->proto_version = model->proto_version;
+ priv->flags = model->flags;
+ priv->byte0 = model->byte0;
+ priv->mask0 = model->mask0;
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
+{
+ unsigned char e6[4], e7[4], ec[4];
+
/*
* First try "E6 report".
* ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
* The bits 0-2 of the first byte will be 1s if some buttons are
* pressed.
*/
- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11,
- param))
- return NULL;
+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
+ PSMOUSE_CMD_SETSCALE11, e6))
+ return -EIO;
- if ((param[0] & 0xf8) != 0 || param[1] != 0 ||
- (param[2] != 10 && param[2] != 100))
- return NULL;
+ if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100))
+ return -EINVAL;
/*
- * Now try "E7 report". Allowed responses are in
- * alps_model_data[].signature
+ * Now get the "E7" and "EC" reports. These will uniquely identify
+ * most ALPS touchpads.
*/
- if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21,
- param))
- return NULL;
-
- if (version) {
- for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
- /* empty */;
- *version = (param[0] << 8) | (param[1] << 4) | i;
- }
-
- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
- if (!memcmp(param, alps_model_data[i].signature,
- sizeof(alps_model_data[i].signature))) {
- model = alps_model_data + i;
- break;
- }
- }
+ if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
+ PSMOUSE_CMD_SETSCALE21, e7) ||
+ alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
+ PSMOUSE_CMD_RESET_WRAP, ec) ||
+ alps_exit_command_mode(psmouse))
+ return -EIO;
- if (model && model->proto_version > ALPS_PROTO_V2) {
- /*
- * Need to check command mode response to identify
- * model
- */
- model = NULL;
- if (alps_enter_command_mode(psmouse, param)) {
- psmouse_warn(psmouse,
- "touchpad failed to enter command mode\n");
- } else {
- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
- if (alps_model_data[i].proto_version > ALPS_PROTO_V2 &&
- alps_model_data[i].command_mode_resp == param[0]) {
- model = alps_model_data + i;
- break;
- }
- }
- alps_exit_command_mode(psmouse);
+ if (alps_match_table(psmouse, priv, e7, ec) == 0)
+ return 0;
- if (!model)
- psmouse_dbg(psmouse,
- "Unknown command mode response %2.2x\n",
- param[0]);
- }
- }
+ psmouse_info(psmouse,
+ "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n",
+ e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]);
- return model;
+ return -EINVAL;
}
static int alps_reconnect(struct psmouse *psmouse)
{
- const struct alps_model_info *model;
+ struct alps_data *priv = psmouse->private;
psmouse_reset(psmouse);
- model = alps_get_model(psmouse, NULL);
- if (!model)
+ if (alps_identify(psmouse, priv) < 0)
return -1;
return alps_hw_init(psmouse);
@@ -1549,9 +1539,7 @@ static void alps_disconnect(struct psmouse *psmouse)
int alps_init(struct psmouse *psmouse)
{
struct alps_data *priv;
- const struct alps_model_info *model;
struct input_dev *dev1 = psmouse->dev, *dev2;
- int version;
priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
dev2 = input_allocate_device();
@@ -1565,15 +1553,9 @@ int alps_init(struct psmouse *psmouse)
psmouse_reset(psmouse);
- model = alps_get_model(psmouse, &version);
- if (!model)
+ if (alps_identify(psmouse, priv) < 0)
goto init_fail;
- priv->proto_version = model->proto_version;
- priv->byte0 = model->byte0;
- priv->mask0 = model->mask0;
- priv->flags = model->flags;
-
if (alps_hw_init(psmouse))
goto init_fail;
@@ -1678,18 +1660,16 @@ init_fail:
int alps_detect(struct psmouse *psmouse, bool set_properties)
{
- int version;
- const struct alps_model_info *model;
+ struct alps_data dummy;
- model = alps_get_model(psmouse, &version);
- if (!model)
+ if (alps_identify(psmouse, &dummy) < 0)
return -1;
if (set_properties) {
psmouse->vendor = "ALPS";
- psmouse->name = model->flags & ALPS_DUALPOINT ?
+ psmouse->name = dummy.flags & ALPS_DUALPOINT ?
"DualPoint TouchPad" : "GlidePoint";
- psmouse->model = version;
+ psmouse->model = dummy.proto_version << 8;
}
return 0;
}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index efd0eea9f001..a81b31830454 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -12,10 +12,10 @@
#ifndef _ALPS_H
#define _ALPS_H
-#define ALPS_PROTO_V1 0
-#define ALPS_PROTO_V2 1
-#define ALPS_PROTO_V3 2
-#define ALPS_PROTO_V4 3
+#define ALPS_PROTO_V1 1
+#define ALPS_PROTO_V2 2
+#define ALPS_PROTO_V3 3
+#define ALPS_PROTO_V4 4
/**
* struct alps_model_info - touchpad ID table