aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/elantech.c44
-rw-r--r--drivers/input/mouse/elantech.h1
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 */
673static int elantech_packet_check_v3(struct psmouse *psmouse) 673static 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
694static int elantech_packet_check_v4(struct psmouse *psmouse) 707static 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;