diff options
author | Matteo Delfino <kendatsuba@gmail.com> | 2013-08-15 03:09:41 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-08-24 20:52:35 -0400 |
commit | acc0444bf83ea559fa84b527b1f49cf20b0df253 (patch) | |
tree | 5b059d18f611ff16d89084148d91ddb552dcd802 /drivers/input/mouse/elantech.c | |
parent | f41a64eeabbb2daa70f2b39d0dfb59c91904a1b0 (diff) |
Input: elantech - fix packet check for v3 and v4 hardware
The signatures of v3 and v4 packets change depending on the value of a
hardware flag called 'crc_enabled'. The packet type detection must change
accordingly.
This patch also restores a consistency check for v4 packets inadvertently
removed by commit:
9eebed7de660c0b5ab129a9de4f89d20b60de68c
Input: elantech - fix for newer hardware versions (v7)
A note about the naming convention: v3 hardware is associated with IC body
v5 while v4 hardware is associated with IC body v6 and v7. The above commit
refers to IC body v7, not to v7 hardware.
Tested on Samsung NP730U3E (fw = 0x675f05, ICv7, crc_enabled = 1)
Tested-by: Giovanni Frigione <gio.frigione@gmail.com>
Signed-off-by: Matteo Delfino <kendatsuba@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/mouse/elantech.c')
-rw-r--r-- | drivers/input/mouse/elantech.c | 44 |
1 files changed, 40 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 | ||