aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)
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}
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 @@
12#ifndef _ALPS_H 12#ifndef _ALPS_H
13#define _ALPS_H 13#define _ALPS_H
14 14
15#define ALPS_PROTO_V1 0 15#define ALPS_PROTO_V1 1
16#define ALPS_PROTO_V2 1 16#define ALPS_PROTO_V2 2
17#define ALPS_PROTO_V3 2 17#define ALPS_PROTO_V3 3
18#define ALPS_PROTO_V4 3 18#define ALPS_PROTO_V4 4
19 19
20/** 20/**
21 * struct alps_model_info - touchpad ID table 21 * struct alps_model_info - touchpad ID table