Skip to content

Commit a09221e

Browse files
committed
Input: ALPS - fix trackstick detection on some Dell Latitudes
On some Dell Latitudes we fail to identify presence of trackstick unless we reset the device. The issue is quite benign as we do perform reset in alps_init(), so the trackstick ends up working, but mouse name reported to userspace is not accurate. In order to fix the issue while avoiding the additional lengthy reset we move the resrt to alps_detect() and keep the discovered state to be used later in alps_init(). Reported-by: Pali Rohár <pali.rohar@gmail.com> Tested-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
1 parent 3296f71 commit a09221e

File tree

1 file changed

+56
-22
lines changed

1 file changed

+56
-22
lines changed

drivers/input/mouse/alps.c

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
17961796
* all.
17971797
*/
17981798
if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
1799-
psmouse_warn(psmouse, "trackstick E7 report failed\n");
1799+
psmouse_warn(psmouse, "Failed to initialize trackstick (E7 report failed)\n");
18001800
ret = -ENODEV;
18011801
} else {
18021802
psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
@@ -1961,8 +1961,6 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
19611961
ALPS_REG_BASE_RUSHMORE);
19621962
if (reg_val == -EIO)
19631963
goto error;
1964-
if (reg_val == -ENODEV)
1965-
priv->flags &= ~ALPS_DUALPOINT;
19661964
}
19671965

19681966
if (alps_enter_command_mode(psmouse) ||
@@ -2305,6 +2303,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
23052303
{
23062304
const struct alps_protocol_info *protocol;
23072305
unsigned char e6[4], e7[4], ec[4];
2306+
int error;
23082307

23092308
/*
23102309
* First try "E6 report".
@@ -2350,10 +2349,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
23502349
}
23512350
}
23522351

2353-
/* Save the Firmware version */
2354-
memcpy(priv->fw_ver, ec, 3);
2352+
if (priv) {
2353+
/* Save the Firmware version */
2354+
memcpy(priv->fw_ver, ec, 3);
2355+
error = alps_set_protocol(psmouse, priv, protocol);
2356+
if (error)
2357+
return error;
2358+
}
23552359

2356-
return alps_set_protocol(psmouse, priv, protocol);
2360+
return 0;
23572361
}
23582362

23592363
static int alps_reconnect(struct psmouse *psmouse)
@@ -2407,22 +2411,20 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
24072411

24082412
int alps_init(struct psmouse *psmouse)
24092413
{
2410-
struct alps_data *priv;
2414+
struct alps_data *priv = psmouse->private;
24112415
struct input_dev *dev1 = psmouse->dev, *dev2;
2416+
int error;
24122417

2413-
priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
24142418
dev2 = input_allocate_device();
2415-
if (!priv || !dev2)
2419+
if (!dev2) {
2420+
error = -ENOMEM;
24162421
goto init_fail;
2422+
}
24172423

24182424
priv->dev2 = dev2;
24192425

2420-
psmouse_reset(psmouse);
2421-
2422-
if (alps_identify(psmouse, priv) < 0)
2423-
goto init_fail;
2424-
2425-
if (priv->hw_init(psmouse))
2426+
error = priv->hw_init(psmouse);
2427+
if (error)
24262428
goto init_fail;
24272429

24282430
/*
@@ -2520,24 +2522,56 @@ int alps_init(struct psmouse *psmouse)
25202522
init_fail:
25212523
psmouse_reset(psmouse);
25222524
input_free_device(dev2);
2523-
kfree(priv);
2525+
/*
2526+
* Even though we did not allocate psmouse->private we do free
2527+
* it here.
2528+
*/
2529+
kfree(psmouse->private);
25242530
psmouse->private = NULL;
2525-
return -1;
2531+
return error;
25262532
}
25272533

25282534
int alps_detect(struct psmouse *psmouse, bool set_properties)
25292535
{
2530-
struct alps_data dummy;
2536+
struct alps_data *priv;
2537+
int error;
25312538

2532-
if (alps_identify(psmouse, &dummy) < 0)
2533-
return -1;
2539+
error = alps_identify(psmouse, NULL);
2540+
if (error)
2541+
return error;
2542+
2543+
/*
2544+
* Reset the device to make sure it is fully operational:
2545+
* on some laptops, like certain Dell Latitudes, we may
2546+
* fail to properly detect presence of trackstick if device
2547+
* has not been reset.
2548+
*/
2549+
psmouse_reset(psmouse);
2550+
2551+
priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
2552+
if (!priv)
2553+
return -ENOMEM;
2554+
2555+
error = alps_identify(psmouse, priv);
2556+
if (error)
2557+
return error;
25342558

25352559
if (set_properties) {
25362560
psmouse->vendor = "ALPS";
2537-
psmouse->name = dummy.flags & ALPS_DUALPOINT ?
2561+
psmouse->name = priv->flags & ALPS_DUALPOINT ?
25382562
"DualPoint TouchPad" : "GlidePoint";
2539-
psmouse->model = dummy.proto_version;
2563+
psmouse->model = priv->proto_version;
2564+
} else {
2565+
/*
2566+
* Destroy alps_data structure we allocated earlier since
2567+
* this was just a "trial run". Otherwise we'll keep it
2568+
* to be used by alps_init() which has to be called if
2569+
* we succeed and set_properties is true.
2570+
*/
2571+
kfree(priv);
2572+
psmouse->private = NULL;
25402573
}
2574+
25412575
return 0;
25422576
}
25432577

0 commit comments

Comments
 (0)