summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/alps.c78
1 files changed, 56 insertions, 22 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b97832b622cb..d164690bfdf7 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1796,7 +1796,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
* all.
*/
if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
- psmouse_warn(psmouse, "trackstick E7 report failed\n");
+ psmouse_warn(psmouse, "Failed to initialize trackstick (E7 report failed)\n");
ret = -ENODEV;
} else {
psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
@@ -1961,8 +1961,6 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
ALPS_REG_BASE_RUSHMORE);
if (reg_val == -EIO)
goto error;
- if (reg_val == -ENODEV)
- priv->flags &= ~ALPS_DUALPOINT;
}
if (alps_enter_command_mode(psmouse) ||
@@ -2305,6 +2303,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
{
const struct alps_protocol_info *protocol;
unsigned char e6[4], e7[4], ec[4];
+ int error;
/*
* First try "E6 report".
@@ -2350,10 +2349,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
}
}
- /* Save the Firmware version */
- memcpy(priv->fw_ver, ec, 3);
+ if (priv) {
+ /* Save the Firmware version */
+ memcpy(priv->fw_ver, ec, 3);
+ error = alps_set_protocol(psmouse, priv, protocol);
+ if (error)
+ return error;
+ }
- return alps_set_protocol(psmouse, priv, protocol);
+ return 0;
}
static int alps_reconnect(struct psmouse *psmouse)
@@ -2407,22 +2411,20 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
int alps_init(struct psmouse *psmouse)
{
- struct alps_data *priv;
+ struct alps_data *priv = psmouse->private;
struct input_dev *dev1 = psmouse->dev, *dev2;
+ int error;
- priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
dev2 = input_allocate_device();
- if (!priv || !dev2)
+ if (!dev2) {
+ error = -ENOMEM;
goto init_fail;
+ }
priv->dev2 = dev2;
- psmouse_reset(psmouse);
-
- if (alps_identify(psmouse, priv) < 0)
- goto init_fail;
-
- if (priv->hw_init(psmouse))
+ error = priv->hw_init(psmouse);
+ if (error)
goto init_fail;
/*
@@ -2520,24 +2522,56 @@ int alps_init(struct psmouse *psmouse)
init_fail:
psmouse_reset(psmouse);
input_free_device(dev2);
- kfree(priv);
+ /*
+ * Even though we did not allocate psmouse->private we do free
+ * it here.
+ */
+ kfree(psmouse->private);
psmouse->private = NULL;
- return -1;
+ return error;
}
int alps_detect(struct psmouse *psmouse, bool set_properties)
{
- struct alps_data dummy;
+ struct alps_data *priv;
+ int error;
- if (alps_identify(psmouse, &dummy) < 0)
- return -1;
+ error = alps_identify(psmouse, NULL);
+ if (error)
+ return error;
+
+ /*
+ * Reset the device to make sure it is fully operational:
+ * on some laptops, like certain Dell Latitudes, we may
+ * fail to properly detect presence of trackstick if device
+ * has not been reset.
+ */
+ psmouse_reset(psmouse);
+
+ priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ error = alps_identify(psmouse, priv);
+ if (error)
+ return error;
if (set_properties) {
psmouse->vendor = "ALPS";
- psmouse->name = dummy.flags & ALPS_DUALPOINT ?
+ psmouse->name = priv->flags & ALPS_DUALPOINT ?
"DualPoint TouchPad" : "GlidePoint";
- psmouse->model = dummy.proto_version;
+ psmouse->model = priv->proto_version;
+ } else {
+ /*
+ * Destroy alps_data structure we allocated earlier since
+ * this was just a "trial run". Otherwise we'll keep it
+ * to be used by alps_init() which has to be called if
+ * we succeed and set_properties is true.
+ */
+ kfree(priv);
+ psmouse->private = NULL;
}
+
return 0;
}