aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/alps.c
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2013-02-14 01:19:59 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-02-14 12:17:57 -0500
commitb5d6b851eab7f346ea5e69f46247b363b32b3670 (patch)
tree10ada693aa80f6ea6bce2aacef57dee3b51d74df /drivers/input/mouse/alps.c
parent24ba9707829818daab711eed7e41313d5e56d0b4 (diff)
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>
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r--drivers/input/mouse/alps.c124
1 files changed, 52 insertions, 72 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)
1451 return ret; 1451 return ret;
1452} 1452}
1453 1453
1454static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) 1454static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv,
1455 unsigned char *e7, unsigned char *ec)
1455{ 1456{
1456 static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; 1457 const struct alps_model_info *model;
1457 unsigned char param[4];
1458 const struct alps_model_info *model = NULL;
1459 int i; 1458 int i;
1460 1459
1460 for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
1461 model = &alps_model_data[i];
1462
1463 if (!memcmp(e7, model->signature, sizeof(model->signature)) &&
1464 (!model->command_mode_resp ||
1465 model->command_mode_resp == ec[2])) {
1466
1467 priv->proto_version = model->proto_version;
1468 priv->flags = model->flags;
1469 priv->byte0 = model->byte0;
1470 priv->mask0 = model->mask0;
1471
1472 return 0;
1473 }
1474 }
1475
1476 return -EINVAL;
1477}
1478
1479static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
1480{
1481 unsigned char e6[4], e7[4], ec[4];
1482
1461 /* 1483 /*
1462 * First try "E6 report". 1484 * First try "E6 report".
1463 * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. 1485 * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
1464 * The bits 0-2 of the first byte will be 1s if some buttons are 1486 * The bits 0-2 of the first byte will be 1s if some buttons are
1465 * pressed. 1487 * pressed.
1466 */ 1488 */
1467 if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE11, 1489 if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
1468 param)) 1490 PSMOUSE_CMD_SETSCALE11, e6))
1469 return NULL; 1491 return -EIO;
1470 1492
1471 if ((param[0] & 0xf8) != 0 || param[1] != 0 || 1493 if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100))
1472 (param[2] != 10 && param[2] != 100)) 1494 return -EINVAL;
1473 return NULL;
1474 1495
1475 /* 1496 /*
1476 * Now try "E7 report". Allowed responses are in 1497 * Now get the "E7" and "EC" reports. These will uniquely identify
1477 * alps_model_data[].signature 1498 * most ALPS touchpads.
1478 */ 1499 */
1479 if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, PSMOUSE_CMD_SETSCALE21, 1500 if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
1480 param)) 1501 PSMOUSE_CMD_SETSCALE21, e7) ||
1481 return NULL; 1502 alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
1482 1503 PSMOUSE_CMD_RESET_WRAP, ec) ||
1483 if (version) { 1504 alps_exit_command_mode(psmouse))
1484 for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) 1505 return -EIO;
1485 /* empty */;
1486 *version = (param[0] << 8) | (param[1] << 4) | i;
1487 }
1488
1489 for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
1490 if (!memcmp(param, alps_model_data[i].signature,
1491 sizeof(alps_model_data[i].signature))) {
1492 model = alps_model_data + i;
1493 break;
1494 }
1495 }
1496 1506
1497 if (model && model->proto_version > ALPS_PROTO_V2) { 1507 if (alps_match_table(psmouse, priv, e7, ec) == 0)
1498 /* 1508 return 0;
1499 * Need to check command mode response to identify
1500 * model
1501 */
1502 model = NULL;
1503 if (alps_enter_command_mode(psmouse, param)) {
1504 psmouse_warn(psmouse,
1505 "touchpad failed to enter command mode\n");
1506 } else {
1507 for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
1508 if (alps_model_data[i].proto_version > ALPS_PROTO_V2 &&
1509 alps_model_data[i].command_mode_resp == param[0]) {
1510 model = alps_model_data + i;
1511 break;
1512 }
1513 }
1514 alps_exit_command_mode(psmouse);
1515 1509
1516 if (!model) 1510 psmouse_info(psmouse,
1517 psmouse_dbg(psmouse, 1511 "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n",
1518 "Unknown command mode response %2.2x\n", 1512 e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]);
1519 param[0]);
1520 }
1521 }
1522 1513
1523 return model; 1514 return -EINVAL;
1524} 1515}
1525 1516
1526static int alps_reconnect(struct psmouse *psmouse) 1517static int alps_reconnect(struct psmouse *psmouse)
1527{ 1518{
1528 const struct alps_model_info *model; 1519 struct alps_data *priv = psmouse->private;
1529 1520
1530 psmouse_reset(psmouse); 1521 psmouse_reset(psmouse);
1531 1522
1532 model = alps_get_model(psmouse, NULL); 1523 if (alps_identify(psmouse, priv) < 0)
1533 if (!model)
1534 return -1; 1524 return -1;
1535 1525
1536 return alps_hw_init(psmouse); 1526 return alps_hw_init(psmouse);
@@ -1549,9 +1539,7 @@ static void alps_disconnect(struct psmouse *psmouse)
1549int alps_init(struct psmouse *psmouse) 1539int alps_init(struct psmouse *psmouse)
1550{ 1540{
1551 struct alps_data *priv; 1541 struct alps_data *priv;
1552 const struct alps_model_info *model;
1553 struct input_dev *dev1 = psmouse->dev, *dev2; 1542 struct input_dev *dev1 = psmouse->dev, *dev2;
1554 int version;
1555 1543
1556 priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); 1544 priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
1557 dev2 = input_allocate_device(); 1545 dev2 = input_allocate_device();
@@ -1565,15 +1553,9 @@ int alps_init(struct psmouse *psmouse)
1565 1553
1566 psmouse_reset(psmouse); 1554 psmouse_reset(psmouse);
1567 1555
1568 model = alps_get_model(psmouse, &version); 1556 if (alps_identify(psmouse, priv) < 0)
1569 if (!model)
1570 goto init_fail; 1557 goto init_fail;
1571 1558
1572 priv->proto_version = model->proto_version;
1573 priv->byte0 = model->byte0;
1574 priv->mask0 = model->mask0;
1575 priv->flags = model->flags;
1576
1577 if (alps_hw_init(psmouse)) 1559 if (alps_hw_init(psmouse))
1578 goto init_fail; 1560 goto init_fail;
1579 1561
@@ -1678,18 +1660,16 @@ init_fail:
1678 1660
1679int alps_detect(struct psmouse *psmouse, bool set_properties) 1661int alps_detect(struct psmouse *psmouse, bool set_properties)
1680{ 1662{
1681 int version; 1663 struct alps_data dummy;
1682 const struct alps_model_info *model;
1683 1664
1684 model = alps_get_model(psmouse, &version); 1665 if (alps_identify(psmouse, &dummy) < 0)
1685 if (!model)
1686 return -1; 1666 return -1;
1687 1667
1688 if (set_properties) { 1668 if (set_properties) {
1689 psmouse->vendor = "ALPS"; 1669 psmouse->vendor = "ALPS";
1690 psmouse->name = model->flags & ALPS_DUALPOINT ? 1670 psmouse->name = dummy.flags & ALPS_DUALPOINT ?
1691 "DualPoint TouchPad" : "GlidePoint"; 1671 "DualPoint TouchPad" : "GlidePoint";
1692 psmouse->model = version; 1672 psmouse->model = dummy.proto_version << 8;
1693 } 1673 }
1694 return 0; 1674 return 0;
1695} 1675}