diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/alps.c | 78 |
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) | |||
1796 | * all. | 1796 | * all. |
1797 | */ | 1797 | */ |
1798 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { | 1798 | 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"); |
1800 | ret = -ENODEV; | 1800 | ret = -ENODEV; |
1801 | } else { | 1801 | } else { |
1802 | psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); | 1802 | psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); |
@@ -1961,8 +1961,6 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | |||
1961 | ALPS_REG_BASE_RUSHMORE); | 1961 | ALPS_REG_BASE_RUSHMORE); |
1962 | if (reg_val == -EIO) | 1962 | if (reg_val == -EIO) |
1963 | goto error; | 1963 | goto error; |
1964 | if (reg_val == -ENODEV) | ||
1965 | priv->flags &= ~ALPS_DUALPOINT; | ||
1966 | } | 1964 | } |
1967 | 1965 | ||
1968 | if (alps_enter_command_mode(psmouse) || | 1966 | if (alps_enter_command_mode(psmouse) || |
@@ -2305,6 +2303,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2305 | { | 2303 | { |
2306 | const struct alps_protocol_info *protocol; | 2304 | const struct alps_protocol_info *protocol; |
2307 | unsigned char e6[4], e7[4], ec[4]; | 2305 | unsigned char e6[4], e7[4], ec[4]; |
2306 | int error; | ||
2308 | 2307 | ||
2309 | /* | 2308 | /* |
2310 | * First try "E6 report". | 2309 | * First try "E6 report". |
@@ -2350,10 +2349,15 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2350 | } | 2349 | } |
2351 | } | 2350 | } |
2352 | 2351 | ||
2353 | /* Save the Firmware version */ | 2352 | if (priv) { |
2354 | memcpy(priv->fw_ver, ec, 3); | 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 | } | ||
2355 | 2359 | ||
2356 | return alps_set_protocol(psmouse, priv, protocol); | 2360 | return 0; |
2357 | } | 2361 | } |
2358 | 2362 | ||
2359 | static int alps_reconnect(struct psmouse *psmouse) | 2363 | static int alps_reconnect(struct psmouse *psmouse) |
@@ -2407,22 +2411,20 @@ static void alps_set_abs_params_mt(struct alps_data *priv, | |||
2407 | 2411 | ||
2408 | int alps_init(struct psmouse *psmouse) | 2412 | int alps_init(struct psmouse *psmouse) |
2409 | { | 2413 | { |
2410 | struct alps_data *priv; | 2414 | struct alps_data *priv = psmouse->private; |
2411 | struct input_dev *dev1 = psmouse->dev, *dev2; | 2415 | struct input_dev *dev1 = psmouse->dev, *dev2; |
2416 | int error; | ||
2412 | 2417 | ||
2413 | priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); | ||
2414 | dev2 = input_allocate_device(); | 2418 | dev2 = input_allocate_device(); |
2415 | if (!priv || !dev2) | 2419 | if (!dev2) { |
2420 | error = -ENOMEM; | ||
2416 | goto init_fail; | 2421 | goto init_fail; |
2422 | } | ||
2417 | 2423 | ||
2418 | priv->dev2 = dev2; | 2424 | priv->dev2 = dev2; |
2419 | 2425 | ||
2420 | psmouse_reset(psmouse); | 2426 | error = priv->hw_init(psmouse); |
2421 | 2427 | if (error) | |
2422 | if (alps_identify(psmouse, priv) < 0) | ||
2423 | goto init_fail; | ||
2424 | |||
2425 | if (priv->hw_init(psmouse)) | ||
2426 | goto init_fail; | 2428 | goto init_fail; |
2427 | 2429 | ||
2428 | /* | 2430 | /* |
@@ -2520,24 +2522,56 @@ int alps_init(struct psmouse *psmouse) | |||
2520 | init_fail: | 2522 | init_fail: |
2521 | psmouse_reset(psmouse); | 2523 | psmouse_reset(psmouse); |
2522 | input_free_device(dev2); | 2524 | 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); | ||
2524 | psmouse->private = NULL; | 2530 | psmouse->private = NULL; |
2525 | return -1; | 2531 | return error; |
2526 | } | 2532 | } |
2527 | 2533 | ||
2528 | int alps_detect(struct psmouse *psmouse, bool set_properties) | 2534 | int alps_detect(struct psmouse *psmouse, bool set_properties) |
2529 | { | 2535 | { |
2530 | struct alps_data dummy; | 2536 | struct alps_data *priv; |
2537 | int error; | ||
2531 | 2538 | ||
2532 | if (alps_identify(psmouse, &dummy) < 0) | 2539 | error = alps_identify(psmouse, NULL); |
2533 | return -1; | 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; | ||
2534 | 2558 | ||
2535 | if (set_properties) { | 2559 | if (set_properties) { |
2536 | psmouse->vendor = "ALPS"; | 2560 | psmouse->vendor = "ALPS"; |
2537 | psmouse->name = dummy.flags & ALPS_DUALPOINT ? | 2561 | psmouse->name = priv->flags & ALPS_DUALPOINT ? |
2538 | "DualPoint TouchPad" : "GlidePoint"; | 2562 | "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; | ||
2540 | } | 2573 | } |
2574 | |||
2541 | return 0; | 2575 | return 0; |
2542 | } | 2576 | } |
2543 | 2577 | ||