diff options
-rw-r--r-- | drivers/input/mouse/elantech.c | 44 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.h | 1 |
2 files changed, 41 insertions, 4 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 57b2637e153a..8551dcaf24db 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -672,6 +672,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) | |||
672 | */ | 672 | */ |
673 | static int elantech_packet_check_v3(struct psmouse *psmouse) | 673 | static int elantech_packet_check_v3(struct psmouse *psmouse) |
674 | { | 674 | { |
675 | struct elantech_data *etd = psmouse->private; | ||
675 | const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; | 676 | const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; |
676 | unsigned char *packet = psmouse->packet; | 677 | unsigned char *packet = psmouse->packet; |
677 | 678 | ||
@@ -682,19 +683,48 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) | |||
682 | if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) | 683 | if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) |
683 | return PACKET_DEBOUNCE; | 684 | return PACKET_DEBOUNCE; |
684 | 685 | ||
685 | if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) | 686 | /* |
686 | return PACKET_V3_HEAD; | 687 | * If the hardware flag 'crc_enabled' is set the packets have |
688 | * different signatures. | ||
689 | */ | ||
690 | if (etd->crc_enabled) { | ||
691 | if ((packet[3] & 0x09) == 0x08) | ||
692 | return PACKET_V3_HEAD; | ||
693 | |||
694 | if ((packet[3] & 0x09) == 0x09) | ||
695 | return PACKET_V3_TAIL; | ||
696 | } else { | ||
697 | if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) | ||
698 | return PACKET_V3_HEAD; | ||
687 | 699 | ||
688 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) | 700 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) |
689 | return PACKET_V3_TAIL; | 701 | return PACKET_V3_TAIL; |
702 | } | ||
690 | 703 | ||
691 | return PACKET_UNKNOWN; | 704 | return PACKET_UNKNOWN; |
692 | } | 705 | } |
693 | 706 | ||
694 | static int elantech_packet_check_v4(struct psmouse *psmouse) | 707 | static int elantech_packet_check_v4(struct psmouse *psmouse) |
695 | { | 708 | { |
709 | struct elantech_data *etd = psmouse->private; | ||
696 | unsigned char *packet = psmouse->packet; | 710 | unsigned char *packet = psmouse->packet; |
697 | unsigned char packet_type = packet[3] & 0x03; | 711 | unsigned char packet_type = packet[3] & 0x03; |
712 | bool sanity_check; | ||
713 | |||
714 | /* | ||
715 | * Sanity check based on the constant bits of a packet. | ||
716 | * The constant bits change depending on the value of | ||
717 | * the hardware flag 'crc_enabled' but are the same for | ||
718 | * every packet, regardless of the type. | ||
719 | */ | ||
720 | if (etd->crc_enabled) | ||
721 | sanity_check = ((packet[3] & 0x08) == 0x00); | ||
722 | else | ||
723 | sanity_check = ((packet[0] & 0x0c) == 0x04 && | ||
724 | (packet[3] & 0x1c) == 0x10); | ||
725 | |||
726 | if (!sanity_check) | ||
727 | return PACKET_UNKNOWN; | ||
698 | 728 | ||
699 | switch (packet_type) { | 729 | switch (packet_type) { |
700 | case 0: | 730 | case 0: |
@@ -1313,6 +1343,12 @@ static int elantech_set_properties(struct elantech_data *etd) | |||
1313 | etd->reports_pressure = true; | 1343 | etd->reports_pressure = true; |
1314 | } | 1344 | } |
1315 | 1345 | ||
1346 | /* | ||
1347 | * The signatures of v3 and v4 packets change depending on the | ||
1348 | * value of this hardware flag. | ||
1349 | */ | ||
1350 | etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000); | ||
1351 | |||
1316 | return 0; | 1352 | return 0; |
1317 | } | 1353 | } |
1318 | 1354 | ||
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 46db3be45ac9..036a04abaef7 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -129,6 +129,7 @@ struct elantech_data { | |||
129 | bool paritycheck; | 129 | bool paritycheck; |
130 | bool jumpy_cursor; | 130 | bool jumpy_cursor; |
131 | bool reports_pressure; | 131 | bool reports_pressure; |
132 | bool crc_enabled; | ||
132 | unsigned char hw_version; | 133 | unsigned char hw_version; |
133 | unsigned int fw_version; | 134 | unsigned int fw_version; |
134 | unsigned int single_finger_reports; | 135 | unsigned int single_finger_reports; |