diff options
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/alps.c | 8 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.c | 148 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.h | 3 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.c | 140 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 11 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics_usb.c | 6 | ||||
-rw-r--r-- | drivers/input/mouse/trackpoint.c | 3 |
8 files changed, 291 insertions, 30 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a59a1a64b674..35a49bf57227 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -2234,8 +2234,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2234 | return 0; | 2234 | return 0; |
2235 | } | 2235 | } |
2236 | 2236 | ||
2237 | psmouse_info(psmouse, | 2237 | psmouse_dbg(psmouse, |
2238 | "Unknown ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2238 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
2239 | 2239 | ||
2240 | return -EINVAL; | 2240 | return -EINVAL; |
2241 | } | 2241 | } |
@@ -2373,6 +2373,10 @@ int alps_init(struct psmouse *psmouse) | |||
2373 | dev2->keybit[BIT_WORD(BTN_LEFT)] = | 2373 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
2374 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 2374 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
2375 | 2375 | ||
2376 | __set_bit(INPUT_PROP_POINTER, dev2->propbit); | ||
2377 | if (priv->flags & ALPS_DUALPOINT) | ||
2378 | __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); | ||
2379 | |||
2376 | if (input_register_device(priv->dev2)) | 2380 | if (input_register_device(priv->dev2)) |
2377 | goto init_fail; | 2381 | goto init_fail; |
2378 | 2382 | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index ee2a04d90d20..06fc6e76ffbe 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/input/mt.h> | 18 | #include <linux/input/mt.h> |
19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
20 | #include <linux/libps2.h> | 20 | #include <linux/libps2.h> |
21 | #include <asm/unaligned.h> | ||
21 | #include "psmouse.h" | 22 | #include "psmouse.h" |
22 | #include "elantech.h" | 23 | #include "elantech.h" |
23 | 24 | ||
@@ -403,6 +404,68 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
403 | input_sync(dev); | 404 | input_sync(dev); |
404 | } | 405 | } |
405 | 406 | ||
407 | static void elantech_report_trackpoint(struct psmouse *psmouse, | ||
408 | int packet_type) | ||
409 | { | ||
410 | /* | ||
411 | * byte 0: 0 0 sx sy 0 M R L | ||
412 | * byte 1:~sx 0 0 0 0 0 0 0 | ||
413 | * byte 2:~sy 0 0 0 0 0 0 0 | ||
414 | * byte 3: 0 0 ~sy ~sx 0 1 1 0 | ||
415 | * byte 4: x7 x6 x5 x4 x3 x2 x1 x0 | ||
416 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
417 | * | ||
418 | * x and y are written in two's complement spread | ||
419 | * over 9 bits with sx/sy the relative top bit and | ||
420 | * x7..x0 and y7..y0 the lower bits. | ||
421 | * The sign of y is opposite to what the input driver | ||
422 | * expects for a relative movement | ||
423 | */ | ||
424 | |||
425 | struct elantech_data *etd = psmouse->private; | ||
426 | struct input_dev *tp_dev = etd->tp_dev; | ||
427 | unsigned char *packet = psmouse->packet; | ||
428 | int x, y; | ||
429 | u32 t; | ||
430 | |||
431 | if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev, | ||
432 | !tp_dev, | ||
433 | psmouse_fmt("Unexpected trackpoint message\n"))) { | ||
434 | if (etd->debug == 1) | ||
435 | elantech_packet_dump(psmouse); | ||
436 | return; | ||
437 | } | ||
438 | |||
439 | t = get_unaligned_le32(&packet[0]); | ||
440 | |||
441 | switch (t & ~7U) { | ||
442 | case 0x06000030U: | ||
443 | case 0x16008020U: | ||
444 | case 0x26800010U: | ||
445 | case 0x36808000U: | ||
446 | x = packet[4] - (int)((packet[1]^0x80) << 1); | ||
447 | y = (int)((packet[2]^0x80) << 1) - packet[5]; | ||
448 | |||
449 | input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01); | ||
450 | input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02); | ||
451 | input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04); | ||
452 | |||
453 | input_report_rel(tp_dev, REL_X, x); | ||
454 | input_report_rel(tp_dev, REL_Y, y); | ||
455 | |||
456 | input_sync(tp_dev); | ||
457 | |||
458 | break; | ||
459 | |||
460 | default: | ||
461 | /* Dump unexpected packet sequences if debug=1 (default) */ | ||
462 | if (etd->debug == 1) | ||
463 | elantech_packet_dump(psmouse); | ||
464 | |||
465 | break; | ||
466 | } | ||
467 | } | ||
468 | |||
406 | /* | 469 | /* |
407 | * Interpret complete data packets and report absolute mode input events for | 470 | * Interpret complete data packets and report absolute mode input events for |
408 | * hardware version 3. (12 byte packets for two fingers) | 471 | * hardware version 3. (12 byte packets for two fingers) |
@@ -715,6 +778,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) | |||
715 | 778 | ||
716 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) | 779 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) |
717 | return PACKET_V3_TAIL; | 780 | return PACKET_V3_TAIL; |
781 | if ((packet[3] & 0x0f) == 0x06) | ||
782 | return PACKET_TRACKPOINT; | ||
718 | } | 783 | } |
719 | 784 | ||
720 | return PACKET_UNKNOWN; | 785 | return PACKET_UNKNOWN; |
@@ -791,14 +856,23 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | |||
791 | 856 | ||
792 | case 3: | 857 | case 3: |
793 | packet_type = elantech_packet_check_v3(psmouse); | 858 | packet_type = elantech_packet_check_v3(psmouse); |
794 | /* ignore debounce */ | 859 | switch (packet_type) { |
795 | if (packet_type == PACKET_DEBOUNCE) | 860 | case PACKET_UNKNOWN: |
796 | return PSMOUSE_FULL_PACKET; | ||
797 | |||
798 | if (packet_type == PACKET_UNKNOWN) | ||
799 | return PSMOUSE_BAD_DATA; | 861 | return PSMOUSE_BAD_DATA; |
800 | 862 | ||
801 | elantech_report_absolute_v3(psmouse, packet_type); | 863 | case PACKET_DEBOUNCE: |
864 | /* ignore debounce */ | ||
865 | break; | ||
866 | |||
867 | case PACKET_TRACKPOINT: | ||
868 | elantech_report_trackpoint(psmouse, packet_type); | ||
869 | break; | ||
870 | |||
871 | default: | ||
872 | elantech_report_absolute_v3(psmouse, packet_type); | ||
873 | break; | ||
874 | } | ||
875 | |||
802 | break; | 876 | break; |
803 | 877 | ||
804 | case 4: | 878 | case 4: |
@@ -1018,8 +1092,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
1018 | * Asus UX31 0x361f00 20, 15, 0e clickpad | 1092 | * Asus UX31 0x361f00 20, 15, 0e clickpad |
1019 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad | 1093 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad |
1020 | * Avatar AVIU-145A2 0x361f00 ? clickpad | 1094 | * Avatar AVIU-145A2 0x361f00 ? clickpad |
1095 | * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) | ||
1021 | * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons | 1096 | * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons |
1022 | * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) | 1097 | * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) |
1098 | * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*) | ||
1023 | * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons | 1099 | * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons |
1024 | * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad | 1100 | * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad |
1025 | * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad | 1101 | * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad |
@@ -1029,6 +1105,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
1029 | * Samsung RF710 0x450f00 ? 2 hw buttons | 1105 | * Samsung RF710 0x450f00 ? 2 hw buttons |
1030 | * System76 Pangolin 0x250f01 ? 2 hw buttons | 1106 | * System76 Pangolin 0x250f01 ? 2 hw buttons |
1031 | * (*) + 3 trackpoint buttons | 1107 | * (*) + 3 trackpoint buttons |
1108 | * (**) + 0 trackpoint buttons | ||
1109 | * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps | ||
1032 | */ | 1110 | */ |
1033 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) | 1111 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) |
1034 | { | 1112 | { |
@@ -1253,6 +1331,13 @@ static bool elantech_is_signature_valid(const unsigned char *param) | |||
1253 | if (param[1] == 0) | 1331 | if (param[1] == 0) |
1254 | return true; | 1332 | return true; |
1255 | 1333 | ||
1334 | /* | ||
1335 | * Some models have a revision higher then 20. Meaning param[2] may | ||
1336 | * be 10 or 20, skip the rates check for these. | ||
1337 | */ | ||
1338 | if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) | ||
1339 | return true; | ||
1340 | |||
1256 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 1341 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
1257 | if (param[2] == rates[i]) | 1342 | if (param[2] == rates[i]) |
1258 | return false; | 1343 | return false; |
@@ -1324,6 +1409,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
1324 | */ | 1409 | */ |
1325 | static void elantech_disconnect(struct psmouse *psmouse) | 1410 | static void elantech_disconnect(struct psmouse *psmouse) |
1326 | { | 1411 | { |
1412 | struct elantech_data *etd = psmouse->private; | ||
1413 | |||
1414 | if (etd->tp_dev) | ||
1415 | input_unregister_device(etd->tp_dev); | ||
1327 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | 1416 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
1328 | &elantech_attr_group); | 1417 | &elantech_attr_group); |
1329 | kfree(psmouse->private); | 1418 | kfree(psmouse->private); |
@@ -1438,8 +1527,10 @@ static int elantech_set_properties(struct elantech_data *etd) | |||
1438 | int elantech_init(struct psmouse *psmouse) | 1527 | int elantech_init(struct psmouse *psmouse) |
1439 | { | 1528 | { |
1440 | struct elantech_data *etd; | 1529 | struct elantech_data *etd; |
1441 | int i, error; | 1530 | int i; |
1531 | int error = -EINVAL; | ||
1442 | unsigned char param[3]; | 1532 | unsigned char param[3]; |
1533 | struct input_dev *tp_dev; | ||
1443 | 1534 | ||
1444 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); | 1535 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
1445 | if (!etd) | 1536 | if (!etd) |
@@ -1498,14 +1589,53 @@ int elantech_init(struct psmouse *psmouse) | |||
1498 | goto init_fail; | 1589 | goto init_fail; |
1499 | } | 1590 | } |
1500 | 1591 | ||
1592 | /* The MSB indicates the presence of the trackpoint */ | ||
1593 | if ((etd->capabilities[0] & 0x80) == 0x80) { | ||
1594 | tp_dev = input_allocate_device(); | ||
1595 | |||
1596 | if (!tp_dev) { | ||
1597 | error = -ENOMEM; | ||
1598 | goto init_fail_tp_alloc; | ||
1599 | } | ||
1600 | |||
1601 | etd->tp_dev = tp_dev; | ||
1602 | snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1", | ||
1603 | psmouse->ps2dev.serio->phys); | ||
1604 | tp_dev->phys = etd->tp_phys; | ||
1605 | tp_dev->name = "Elantech PS/2 TrackPoint"; | ||
1606 | tp_dev->id.bustype = BUS_I8042; | ||
1607 | tp_dev->id.vendor = 0x0002; | ||
1608 | tp_dev->id.product = PSMOUSE_ELANTECH; | ||
1609 | tp_dev->id.version = 0x0000; | ||
1610 | tp_dev->dev.parent = &psmouse->ps2dev.serio->dev; | ||
1611 | tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | ||
1612 | tp_dev->relbit[BIT_WORD(REL_X)] = | ||
1613 | BIT_MASK(REL_X) | BIT_MASK(REL_Y); | ||
1614 | tp_dev->keybit[BIT_WORD(BTN_LEFT)] = | ||
1615 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | | ||
1616 | BIT_MASK(BTN_RIGHT); | ||
1617 | |||
1618 | __set_bit(INPUT_PROP_POINTER, tp_dev->propbit); | ||
1619 | __set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit); | ||
1620 | |||
1621 | error = input_register_device(etd->tp_dev); | ||
1622 | if (error < 0) | ||
1623 | goto init_fail_tp_reg; | ||
1624 | } | ||
1625 | |||
1501 | psmouse->protocol_handler = elantech_process_byte; | 1626 | psmouse->protocol_handler = elantech_process_byte; |
1502 | psmouse->disconnect = elantech_disconnect; | 1627 | psmouse->disconnect = elantech_disconnect; |
1503 | psmouse->reconnect = elantech_reconnect; | 1628 | psmouse->reconnect = elantech_reconnect; |
1504 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; | 1629 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
1505 | 1630 | ||
1506 | return 0; | 1631 | return 0; |
1507 | 1632 | init_fail_tp_reg: | |
1633 | input_free_device(tp_dev); | ||
1634 | init_fail_tp_alloc: | ||
1635 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | ||
1636 | &elantech_attr_group); | ||
1508 | init_fail: | 1637 | init_fail: |
1638 | psmouse_reset(psmouse); | ||
1509 | kfree(etd); | 1639 | kfree(etd); |
1510 | return -1; | 1640 | return error; |
1511 | } | 1641 | } |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 9e0e2a1f340d..6f3afec02f03 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -94,6 +94,7 @@ | |||
94 | #define PACKET_V4_HEAD 0x05 | 94 | #define PACKET_V4_HEAD 0x05 |
95 | #define PACKET_V4_MOTION 0x06 | 95 | #define PACKET_V4_MOTION 0x06 |
96 | #define PACKET_V4_STATUS 0x07 | 96 | #define PACKET_V4_STATUS 0x07 |
97 | #define PACKET_TRACKPOINT 0x08 | ||
97 | 98 | ||
98 | /* | 99 | /* |
99 | * track up to 5 fingers for v4 hardware | 100 | * track up to 5 fingers for v4 hardware |
@@ -114,6 +115,8 @@ struct finger_pos { | |||
114 | }; | 115 | }; |
115 | 116 | ||
116 | struct elantech_data { | 117 | struct elantech_data { |
118 | struct input_dev *tp_dev; /* Relative device for trackpoint */ | ||
119 | char tp_phys[32]; | ||
117 | unsigned char reg_07; | 120 | unsigned char reg_07; |
118 | unsigned char reg_10; | 121 | unsigned char reg_10; |
119 | unsigned char reg_11; | 122 | unsigned char reg_11; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cff065f6261c..b4e1f014ddc2 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -670,6 +670,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse) | |||
670 | __set_bit(REL_X, input_dev->relbit); | 670 | __set_bit(REL_X, input_dev->relbit); |
671 | __set_bit(REL_Y, input_dev->relbit); | 671 | __set_bit(REL_Y, input_dev->relbit); |
672 | 672 | ||
673 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
674 | |||
673 | psmouse->set_rate = psmouse_set_rate; | 675 | psmouse->set_rate = psmouse_set_rate; |
674 | psmouse->set_resolution = psmouse_set_resolution; | 676 | psmouse->set_resolution = psmouse_set_resolution; |
675 | psmouse->poll = psmouse_poll; | 677 | psmouse->poll = psmouse_poll; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ef9e0b8a9aa7..fd23181c1fb7 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psmouse) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 119 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
120 | |||
121 | static bool cr48_profile_sensor; | ||
122 | |||
120 | struct min_max_quirk { | 123 | struct min_max_quirk { |
121 | const char * const *pnp_ids; | 124 | const char * const *pnp_ids; |
122 | int x_min, x_max, y_min, y_max; | 125 | int x_min, x_max, y_min, y_max; |
@@ -626,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
626 | ((buf[0] & 0x04) >> 1) | | 629 | ((buf[0] & 0x04) >> 1) | |
627 | ((buf[3] & 0x04) >> 2)); | 630 | ((buf[3] & 0x04) >> 2)); |
628 | 631 | ||
632 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
633 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | ||
634 | hw->w == 2) { | ||
635 | synaptics_parse_agm(buf, priv, hw); | ||
636 | return 1; | ||
637 | } | ||
638 | |||
639 | hw->x = (((buf[3] & 0x10) << 8) | | ||
640 | ((buf[1] & 0x0f) << 8) | | ||
641 | buf[4]); | ||
642 | hw->y = (((buf[3] & 0x20) << 7) | | ||
643 | ((buf[1] & 0xf0) << 4) | | ||
644 | buf[5]); | ||
645 | hw->z = buf[2]; | ||
646 | |||
629 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 647 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
630 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 648 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
631 | 649 | ||
632 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 650 | if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) { |
651 | /* | ||
652 | * ForcePads, like Clickpads, use middle button | ||
653 | * bits to report primary button clicks. | ||
654 | * Unfortunately they report primary button not | ||
655 | * only when user presses on the pad above certain | ||
656 | * threshold, but also when there are more than one | ||
657 | * finger on the touchpad, which interferes with | ||
658 | * out multi-finger gestures. | ||
659 | */ | ||
660 | if (hw->z == 0) { | ||
661 | /* No contacts */ | ||
662 | priv->press = priv->report_press = false; | ||
663 | } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { | ||
664 | /* | ||
665 | * Single-finger touch with pressure above | ||
666 | * the threshold. If pressure stays long | ||
667 | * enough, we'll start reporting primary | ||
668 | * button. We rely on the device continuing | ||
669 | * sending data even if finger does not | ||
670 | * move. | ||
671 | */ | ||
672 | if (!priv->press) { | ||
673 | priv->press_start = jiffies; | ||
674 | priv->press = true; | ||
675 | } else if (time_after(jiffies, | ||
676 | priv->press_start + | ||
677 | msecs_to_jiffies(50))) { | ||
678 | priv->report_press = true; | ||
679 | } | ||
680 | } else { | ||
681 | priv->press = false; | ||
682 | } | ||
683 | |||
684 | hw->left = priv->report_press; | ||
685 | |||
686 | } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | ||
633 | /* | 687 | /* |
634 | * Clickpad's button is transmitted as middle button, | 688 | * Clickpad's button is transmitted as middle button, |
635 | * however, since it is primary button, we will report | 689 | * however, since it is primary button, we will report |
@@ -648,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
648 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 702 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
649 | } | 703 | } |
650 | 704 | ||
651 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
652 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | ||
653 | hw->w == 2) { | ||
654 | synaptics_parse_agm(buf, priv, hw); | ||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | hw->x = (((buf[3] & 0x10) << 8) | | ||
659 | ((buf[1] & 0x0f) << 8) | | ||
660 | buf[4]); | ||
661 | hw->y = (((buf[3] & 0x20) << 7) | | ||
662 | ((buf[1] & 0xf0) << 4) | | ||
663 | buf[5]); | ||
664 | hw->z = buf[2]; | ||
665 | |||
666 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && | 705 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && |
667 | ((buf[0] ^ buf[3]) & 0x02)) { | 706 | ((buf[0] ^ buf[3]) & 0x02)) { |
668 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { | 707 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { |
@@ -1152,6 +1191,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse, | |||
1152 | priv->agm_pending = false; | 1191 | priv->agm_pending = false; |
1153 | } | 1192 | } |
1154 | 1193 | ||
1194 | static void synaptics_profile_sensor_process(struct psmouse *psmouse, | ||
1195 | struct synaptics_hw_state *sgm, | ||
1196 | int num_fingers) | ||
1197 | { | ||
1198 | struct input_dev *dev = psmouse->dev; | ||
1199 | struct synaptics_data *priv = psmouse->private; | ||
1200 | struct synaptics_hw_state *hw[2] = { sgm, &priv->agm }; | ||
1201 | struct input_mt_pos pos[2]; | ||
1202 | int slot[2], nsemi, i; | ||
1203 | |||
1204 | nsemi = clamp_val(num_fingers, 0, 2); | ||
1205 | |||
1206 | for (i = 0; i < nsemi; i++) { | ||
1207 | pos[i].x = hw[i]->x; | ||
1208 | pos[i].y = synaptics_invert_y(hw[i]->y); | ||
1209 | } | ||
1210 | |||
1211 | input_mt_assign_slots(dev, slot, pos, nsemi); | ||
1212 | |||
1213 | for (i = 0; i < nsemi; i++) { | ||
1214 | input_mt_slot(dev, slot[i]); | ||
1215 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); | ||
1216 | input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x); | ||
1217 | input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y); | ||
1218 | input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z); | ||
1219 | } | ||
1220 | |||
1221 | input_mt_drop_unused(dev); | ||
1222 | input_mt_report_pointer_emulation(dev, false); | ||
1223 | input_mt_report_finger_count(dev, num_fingers); | ||
1224 | |||
1225 | synaptics_report_buttons(psmouse, sgm); | ||
1226 | |||
1227 | input_sync(dev); | ||
1228 | } | ||
1229 | |||
1155 | /* | 1230 | /* |
1156 | * called for each full received packet from the touchpad | 1231 | * called for each full received packet from the touchpad |
1157 | */ | 1232 | */ |
@@ -1215,6 +1290,11 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
1215 | finger_width = 0; | 1290 | finger_width = 0; |
1216 | } | 1291 | } |
1217 | 1292 | ||
1293 | if (cr48_profile_sensor) { | ||
1294 | synaptics_profile_sensor_process(psmouse, &hw, num_fingers); | ||
1295 | return; | ||
1296 | } | ||
1297 | |||
1218 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | 1298 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) |
1219 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, | 1299 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, |
1220 | num_fingers); | 1300 | num_fingers); |
@@ -1360,6 +1440,9 @@ static void set_input_params(struct psmouse *psmouse, | |||
1360 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); | 1440 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); |
1361 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 1441 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
1362 | 1442 | ||
1443 | if (cr48_profile_sensor) | ||
1444 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
1445 | |||
1363 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { | 1446 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { |
1364 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | 1447 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
1365 | ABS_MT_POSITION_Y); | 1448 | ABS_MT_POSITION_Y); |
@@ -1371,11 +1454,16 @@ static void set_input_params(struct psmouse *psmouse, | |||
1371 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1454 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
1372 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); | 1455 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); |
1373 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | 1456 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { |
1374 | /* Non-image sensors with AGM use semi-mt */ | ||
1375 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
1376 | input_mt_init_slots(dev, 2, 0); | ||
1377 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | 1457 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
1378 | ABS_MT_POSITION_Y); | 1458 | ABS_MT_POSITION_Y); |
1459 | /* | ||
1460 | * Profile sensor in CR-48 tracks contacts reasonably well, | ||
1461 | * other non-image sensors with AGM use semi-mt. | ||
1462 | */ | ||
1463 | input_mt_init_slots(dev, 2, | ||
1464 | INPUT_MT_POINTER | | ||
1465 | (cr48_profile_sensor ? | ||
1466 | INPUT_MT_TRACK : INPUT_MT_SEMI_MT)); | ||
1379 | } | 1467 | } |
1380 | 1468 | ||
1381 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1469 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
@@ -1577,10 +1665,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = { | |||
1577 | { } | 1665 | { } |
1578 | }; | 1666 | }; |
1579 | 1667 | ||
1668 | static const struct dmi_system_id __initconst cr48_dmi_table[] = { | ||
1669 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
1670 | { | ||
1671 | /* Cr-48 Chromebook (Codename Mario) */ | ||
1672 | .matches = { | ||
1673 | DMI_MATCH(DMI_SYS_VENDOR, "IEC"), | ||
1674 | DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), | ||
1675 | }, | ||
1676 | }, | ||
1677 | #endif | ||
1678 | { } | ||
1679 | }; | ||
1680 | |||
1580 | void __init synaptics_module_init(void) | 1681 | void __init synaptics_module_init(void) |
1581 | { | 1682 | { |
1582 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 1683 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
1583 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | 1684 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
1685 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); | ||
1584 | } | 1686 | } |
1585 | 1687 | ||
1586 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | 1688 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index e594af0b264b..fb2e076738ae 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -78,6 +78,11 @@ | |||
78 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only | 78 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only |
79 | * reports 2. | 79 | * reports 2. |
80 | * 2 0x20 report min query 0x0f gives min coord reported | 80 | * 2 0x20 report min query 0x0f gives min coord reported |
81 | * 2 0x80 forcepad forcepad is a variant of clickpad that | ||
82 | * does not have physical buttons but rather | ||
83 | * uses pressure above certain threshold to | ||
84 | * report primary clicks. Forcepads also have | ||
85 | * clickpad bit set. | ||
81 | */ | 86 | */ |
82 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | 87 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ |
83 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ | 88 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ |
@@ -86,6 +91,7 @@ | |||
86 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | 91 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) |
87 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) | 92 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) |
88 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) | 93 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) |
94 | #define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000) | ||
89 | 95 | ||
90 | /* synaptics modes query bits */ | 96 | /* synaptics modes query bits */ |
91 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 97 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -177,6 +183,11 @@ struct synaptics_data { | |||
177 | */ | 183 | */ |
178 | struct synaptics_hw_state agm; | 184 | struct synaptics_hw_state agm; |
179 | bool agm_pending; /* new AGM packet received */ | 185 | bool agm_pending; /* new AGM packet received */ |
186 | |||
187 | /* ForcePad handling */ | ||
188 | unsigned long press_start; | ||
189 | bool press; | ||
190 | bool report_press; | ||
180 | }; | 191 | }; |
181 | 192 | ||
182 | void synaptics_module_init(void); | 193 | void synaptics_module_init(void); |
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c index e122bda16aab..6bcc0189c1c9 100644 --- a/drivers/input/mouse/synaptics_usb.c +++ b/drivers/input/mouse/synaptics_usb.c | |||
@@ -387,6 +387,7 @@ static int synusb_probe(struct usb_interface *intf, | |||
387 | __set_bit(EV_REL, input_dev->evbit); | 387 | __set_bit(EV_REL, input_dev->evbit); |
388 | __set_bit(REL_X, input_dev->relbit); | 388 | __set_bit(REL_X, input_dev->relbit); |
389 | __set_bit(REL_Y, input_dev->relbit); | 389 | __set_bit(REL_Y, input_dev->relbit); |
390 | __set_bit(INPUT_PROP_POINTING_STICK, input_dev->propbit); | ||
390 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); | 391 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); |
391 | } else { | 392 | } else { |
392 | input_set_abs_params(input_dev, ABS_X, | 393 | input_set_abs_params(input_dev, ABS_X, |
@@ -401,6 +402,11 @@ static int synusb_probe(struct usb_interface *intf, | |||
401 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 402 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
402 | } | 403 | } |
403 | 404 | ||
405 | if (synusb->flags & SYNUSB_TOUCHSCREEN) | ||
406 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); | ||
407 | else | ||
408 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
409 | |||
404 | __set_bit(BTN_LEFT, input_dev->keybit); | 410 | __set_bit(BTN_LEFT, input_dev->keybit); |
405 | __set_bit(BTN_RIGHT, input_dev->keybit); | 411 | __set_bit(BTN_RIGHT, input_dev->keybit); |
406 | __set_bit(BTN_MIDDLE, input_dev->keybit); | 412 | __set_bit(BTN_MIDDLE, input_dev->keybit); |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index ca843b6cf6bd..30c8b6998808 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
393 | if ((button_info & 0x0f) >= 3) | 393 | if ((button_info & 0x0f) >= 3) |
394 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 394 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
395 | 395 | ||
396 | __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit); | ||
397 | __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit); | ||
398 | |||
396 | trackpoint_defaults(psmouse->private); | 399 | trackpoint_defaults(psmouse->private); |
397 | 400 | ||
398 | error = trackpoint_power_on_reset(&psmouse->ps2dev); | 401 | error = trackpoint_power_on_reset(&psmouse->ps2dev); |