|
Lines 11-24
Link Here
|
| 11 |
*/ |
11 |
*/ |
| 12 |
|
12 |
|
| 13 |
#include <linux/delay.h> |
13 |
#include <linux/delay.h> |
| 14 |
#include <linux/dmi.h> |
|
|
| 15 |
#include <linux/slab.h> |
14 |
#include <linux/slab.h> |
| 16 |
#include <linux/module.h> |
15 |
#include <linux/module.h> |
| 17 |
#include <linux/input.h> |
16 |
#include <linux/input.h> |
| 18 |
#include <linux/input/mt.h> |
17 |
#include <linux/input/mt.h> |
| 19 |
#include <linux/serio.h> |
18 |
#include <linux/serio.h> |
| 20 |
#include <linux/libps2.h> |
19 |
#include <linux/libps2.h> |
| 21 |
#include <asm/unaligned.h> |
|
|
| 22 |
#include "psmouse.h" |
20 |
#include "psmouse.h" |
| 23 |
#include "elantech.h" |
21 |
#include "elantech.h" |
| 24 |
|
22 |
|
|
Lines 315-321
static void elantech_report_semi_mt_data
Link Here
|
| 315 |
unsigned int x2, unsigned int y2) |
313 |
unsigned int x2, unsigned int y2) |
| 316 |
{ |
314 |
{ |
| 317 |
elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); |
315 |
elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); |
| 318 |
elantech_set_slot(dev, 1, num_fingers >= 2, x2, y2); |
316 |
elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); |
| 319 |
} |
317 |
} |
| 320 |
|
318 |
|
| 321 |
/* |
319 |
/* |
|
Lines 404-463
static void elantech_report_absolute_v2(
Link Here
|
| 404 |
input_sync(dev); |
402 |
input_sync(dev); |
| 405 |
} |
403 |
} |
| 406 |
|
404 |
|
| 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 |
t = get_unaligned_le32(&packet[0]); |
| 432 |
|
| 433 |
switch (t & ~7U) { |
| 434 |
case 0x06000030U: |
| 435 |
case 0x16008020U: |
| 436 |
case 0x26800010U: |
| 437 |
case 0x36808000U: |
| 438 |
x = packet[4] - (int)((packet[1]^0x80) << 1); |
| 439 |
y = (int)((packet[2]^0x80) << 1) - packet[5]; |
| 440 |
|
| 441 |
input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01); |
| 442 |
input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02); |
| 443 |
input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04); |
| 444 |
|
| 445 |
input_report_rel(tp_dev, REL_X, x); |
| 446 |
input_report_rel(tp_dev, REL_Y, y); |
| 447 |
|
| 448 |
input_sync(tp_dev); |
| 449 |
|
| 450 |
break; |
| 451 |
|
| 452 |
default: |
| 453 |
/* Dump unexpected packet sequences if debug=1 (default) */ |
| 454 |
if (etd->debug == 1) |
| 455 |
elantech_packet_dump(psmouse); |
| 456 |
|
| 457 |
break; |
| 458 |
} |
| 459 |
} |
| 460 |
|
| 461 |
/* |
405 |
/* |
| 462 |
* Interpret complete data packets and report absolute mode input events for |
406 |
* Interpret complete data packets and report absolute mode input events for |
| 463 |
* hardware version 3. (12 byte packets for two fingers) |
407 |
* hardware version 3. (12 byte packets for two fingers) |
|
Lines 528-542
static void elantech_report_absolute_v3(
Link Here
|
| 528 |
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
472 |
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
| 529 |
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
473 |
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
| 530 |
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
474 |
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
| 531 |
|
475 |
input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
| 532 |
/* For clickpads map both buttons to BTN_LEFT */ |
476 |
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
| 533 |
if (etd->fw_version & 0x001000) { |
|
|
| 534 |
input_report_key(dev, BTN_LEFT, packet[0] & 0x03); |
| 535 |
} else { |
| 536 |
input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
| 537 |
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
| 538 |
} |
| 539 |
|
| 540 |
input_report_abs(dev, ABS_PRESSURE, pres); |
477 |
input_report_abs(dev, ABS_PRESSURE, pres); |
| 541 |
input_report_abs(dev, ABS_TOOL_WIDTH, width); |
478 |
input_report_abs(dev, ABS_TOOL_WIDTH, width); |
| 542 |
|
479 |
|
|
Lines 546-563
static void elantech_report_absolute_v3(
Link Here
|
| 546 |
static void elantech_input_sync_v4(struct psmouse *psmouse) |
483 |
static void elantech_input_sync_v4(struct psmouse *psmouse) |
| 547 |
{ |
484 |
{ |
| 548 |
struct input_dev *dev = psmouse->dev; |
485 |
struct input_dev *dev = psmouse->dev; |
| 549 |
struct elantech_data *etd = psmouse->private; |
|
|
| 550 |
unsigned char *packet = psmouse->packet; |
486 |
unsigned char *packet = psmouse->packet; |
| 551 |
|
487 |
|
| 552 |
/* For clickpads map both buttons to BTN_LEFT */ |
488 |
input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
| 553 |
if (etd->fw_version & 0x001000) { |
489 |
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
| 554 |
input_report_key(dev, BTN_LEFT, packet[0] & 0x03); |
|
|
| 555 |
} else { |
| 556 |
input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
| 557 |
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
| 558 |
input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04); |
| 559 |
} |
| 560 |
|
| 561 |
input_mt_report_pointer_emulation(dev, true); |
490 |
input_mt_report_pointer_emulation(dev, true); |
| 562 |
input_sync(dev); |
491 |
input_sync(dev); |
| 563 |
} |
492 |
} |
|
Lines 744-750
static int elantech_packet_check_v2(stru
Link Here
|
| 744 |
*/ |
673 |
*/ |
| 745 |
static int elantech_packet_check_v3(struct psmouse *psmouse) |
674 |
static int elantech_packet_check_v3(struct psmouse *psmouse) |
| 746 |
{ |
675 |
{ |
| 747 |
struct elantech_data *etd = psmouse->private; |
|
|
| 748 |
const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; |
676 |
const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; |
| 749 |
unsigned char *packet = psmouse->packet; |
677 |
unsigned char *packet = psmouse->packet; |
| 750 |
|
678 |
|
|
Lines 755-818
static int elantech_packet_check_v3(stru
Link Here
|
| 755 |
if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) |
683 |
if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) |
| 756 |
return PACKET_DEBOUNCE; |
684 |
return PACKET_DEBOUNCE; |
| 757 |
|
685 |
|
| 758 |
/* |
686 |
if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) |
| 759 |
* If the hardware flag 'crc_enabled' is set the packets have |
687 |
return PACKET_V3_HEAD; |
| 760 |
* different signatures. |
|
|
| 761 |
*/ |
| 762 |
if (etd->crc_enabled) { |
| 763 |
if ((packet[3] & 0x09) == 0x08) |
| 764 |
return PACKET_V3_HEAD; |
| 765 |
|
| 766 |
if ((packet[3] & 0x09) == 0x09) |
| 767 |
return PACKET_V3_TAIL; |
| 768 |
} else { |
| 769 |
if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) |
| 770 |
return PACKET_V3_HEAD; |
| 771 |
|
688 |
|
| 772 |
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) |
689 |
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) |
| 773 |
return PACKET_V3_TAIL; |
690 |
return PACKET_V3_TAIL; |
| 774 |
if ((packet[3] & 0x0f) == 0x06) |
|
|
| 775 |
return PACKET_TRACKPOINT; |
| 776 |
} |
| 777 |
|
691 |
|
| 778 |
return PACKET_UNKNOWN; |
692 |
return PACKET_UNKNOWN; |
| 779 |
} |
693 |
} |
| 780 |
|
694 |
|
| 781 |
static int elantech_packet_check_v4(struct psmouse *psmouse) |
695 |
static int elantech_packet_check_v4(struct psmouse *psmouse) |
| 782 |
{ |
696 |
{ |
| 783 |
struct elantech_data *etd = psmouse->private; |
|
|
| 784 |
unsigned char *packet = psmouse->packet; |
697 |
unsigned char *packet = psmouse->packet; |
| 785 |
unsigned char packet_type = packet[3] & 0x03; |
698 |
unsigned char packet_type = packet[3] & 0x03; |
| 786 |
bool sanity_check; |
|
|
| 787 |
|
| 788 |
if (etd->tp_dev && (packet[3] & 0x0f) == 0x06) |
| 789 |
return PACKET_TRACKPOINT; |
| 790 |
|
| 791 |
/* |
| 792 |
* Sanity check based on the constant bits of a packet. |
| 793 |
* The constant bits change depending on the value of |
| 794 |
* the hardware flag 'crc_enabled' but are the same for |
| 795 |
* every packet, regardless of the type. |
| 796 |
*/ |
| 797 |
if (etd->crc_enabled) |
| 798 |
sanity_check = ((packet[3] & 0x08) == 0x00); |
| 799 |
else |
| 800 |
sanity_check = ((packet[0] & 0x0c) == 0x04 && |
| 801 |
(packet[3] & 0x1c) == 0x10); |
| 802 |
|
| 803 |
if (!sanity_check) |
| 804 |
return PACKET_UNKNOWN; |
| 805 |
|
| 806 |
switch (packet_type) { |
| 807 |
case 0: |
| 808 |
return PACKET_V4_STATUS; |
| 809 |
|
699 |
|
| 810 |
case 1: |
700 |
if (packet_type == 0x01) |
| 811 |
return PACKET_V4_HEAD; |
701 |
return PACKET_V4_HEAD; |
| 812 |
|
702 |
|
| 813 |
case 2: |
703 |
if (packet_type == 0x02) |
| 814 |
return PACKET_V4_MOTION; |
704 |
return PACKET_V4_MOTION; |
| 815 |
} |
705 |
|
|
|
706 |
if (packet_type == 0x00) |
| 707 |
return PACKET_V4_STATUS; |
| 816 |
|
708 |
|
| 817 |
return PACKET_UNKNOWN; |
709 |
return PACKET_UNKNOWN; |
| 818 |
} |
710 |
} |
|
Lines 852-891
static psmouse_ret_t elantech_process_by
Link Here
|
| 852 |
|
744 |
|
| 853 |
case 3: |
745 |
case 3: |
| 854 |
packet_type = elantech_packet_check_v3(psmouse); |
746 |
packet_type = elantech_packet_check_v3(psmouse); |
| 855 |
switch (packet_type) { |
747 |
/* ignore debounce */ |
| 856 |
case PACKET_UNKNOWN: |
748 |
if (packet_type == PACKET_DEBOUNCE) |
| 857 |
return PSMOUSE_BAD_DATA; |
749 |
return PSMOUSE_FULL_PACKET; |
| 858 |
|
|
|
| 859 |
case PACKET_DEBOUNCE: |
| 860 |
/* ignore debounce */ |
| 861 |
break; |
| 862 |
|
| 863 |
case PACKET_TRACKPOINT: |
| 864 |
elantech_report_trackpoint(psmouse, packet_type); |
| 865 |
break; |
| 866 |
|
750 |
|
| 867 |
default: |
751 |
if (packet_type == PACKET_UNKNOWN) |
| 868 |
elantech_report_absolute_v3(psmouse, packet_type); |
752 |
return PSMOUSE_BAD_DATA; |
| 869 |
break; |
|
|
| 870 |
} |
| 871 |
|
753 |
|
|
|
754 |
elantech_report_absolute_v3(psmouse, packet_type); |
| 872 |
break; |
755 |
break; |
| 873 |
|
756 |
|
| 874 |
case 4: |
757 |
case 4: |
| 875 |
packet_type = elantech_packet_check_v4(psmouse); |
758 |
packet_type = elantech_packet_check_v4(psmouse); |
| 876 |
switch (packet_type) { |
759 |
if (packet_type == PACKET_UNKNOWN) |
| 877 |
case PACKET_UNKNOWN: |
|
|
| 878 |
return PSMOUSE_BAD_DATA; |
760 |
return PSMOUSE_BAD_DATA; |
| 879 |
|
761 |
|
| 880 |
case PACKET_TRACKPOINT: |
762 |
elantech_report_absolute_v4(psmouse, packet_type); |
| 881 |
elantech_report_trackpoint(psmouse, packet_type); |
|
|
| 882 |
break; |
| 883 |
|
| 884 |
default: |
| 885 |
elantech_report_absolute_v4(psmouse, packet_type); |
| 886 |
break; |
| 887 |
} |
| 888 |
|
| 889 |
break; |
763 |
break; |
| 890 |
} |
764 |
} |
| 891 |
|
765 |
|
|
Lines 893-913
static psmouse_ret_t elantech_process_by
Link Here
|
| 893 |
} |
767 |
} |
| 894 |
|
768 |
|
| 895 |
/* |
769 |
/* |
| 896 |
* This writes the reg_07 value again to the hardware at the end of every |
|
|
| 897 |
* set_rate call because the register loses its value. reg_07 allows setting |
| 898 |
* absolute mode on v4 hardware |
| 899 |
*/ |
| 900 |
static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse, |
| 901 |
unsigned int rate) |
| 902 |
{ |
| 903 |
struct elantech_data *etd = psmouse->private; |
| 904 |
|
| 905 |
etd->original_set_rate(psmouse, rate); |
| 906 |
if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) |
| 907 |
psmouse_err(psmouse, "restoring reg_07 failed\n"); |
| 908 |
} |
| 909 |
|
| 910 |
/* |
| 911 |
* Put the touchpad into absolute mode |
770 |
* Put the touchpad into absolute mode |
| 912 |
*/ |
771 |
*/ |
| 913 |
static int elantech_set_absolute_mode(struct psmouse *psmouse) |
772 |
static int elantech_set_absolute_mode(struct psmouse *psmouse) |
|
Lines 940-950
static int elantech_set_absolute_mode(st
Link Here
|
| 940 |
break; |
799 |
break; |
| 941 |
|
800 |
|
| 942 |
case 3: |
801 |
case 3: |
| 943 |
if (etd->set_hw_resolution) |
802 |
etd->reg_10 = 0x0b; |
| 944 |
etd->reg_10 = 0x0b; |
|
|
| 945 |
else |
| 946 |
etd->reg_10 = 0x01; |
| 947 |
|
| 948 |
if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) |
803 |
if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) |
| 949 |
rc = -1; |
804 |
rc = -1; |
| 950 |
|
805 |
|
|
Lines 1098-1165
static int elantech_get_resolution_v4(st
Link Here
|
| 1098 |
} |
953 |
} |
| 1099 |
|
954 |
|
| 1100 |
/* |
955 |
/* |
| 1101 |
* Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in |
|
|
| 1102 |
* fw_version for this is based on the following fw_version & caps table: |
| 1103 |
* |
| 1104 |
* Laptop-model: fw_version: caps: buttons: |
| 1105 |
* Acer S3 0x461f00 10, 13, 0e clickpad |
| 1106 |
* Acer S7-392 0x581f01 50, 17, 0d clickpad |
| 1107 |
* Acer V5-131 0x461f02 01, 16, 0c clickpad |
| 1108 |
* Acer V5-551 0x461f00 ? clickpad |
| 1109 |
* Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons |
| 1110 |
* Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons |
| 1111 |
* Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons |
| 1112 |
* Asus TP500LN 0x381f17 10, 14, 0e clickpad |
| 1113 |
* Asus X750JN 0x381f17 10, 14, 0e clickpad |
| 1114 |
* Asus UX31 0x361f00 20, 15, 0e clickpad |
| 1115 |
* Asus UX32VD 0x361f02 00, 15, 0e clickpad |
| 1116 |
* Avatar AVIU-145A2 0x361f00 ? clickpad |
| 1117 |
* Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons |
| 1118 |
* Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons |
| 1119 |
* Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) |
| 1120 |
* Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons |
| 1121 |
* Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) |
| 1122 |
* Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*) |
| 1123 |
* Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons |
| 1124 |
* Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad |
| 1125 |
* Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad |
| 1126 |
* Samsung NP900X3E-A02 0x575f03 ? clickpad |
| 1127 |
* Samsung NP-QX410 0x851b00 19, 14, 0c clickpad |
| 1128 |
* Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons |
| 1129 |
* Samsung RF710 0x450f00 ? 2 hw buttons |
| 1130 |
* System76 Pangolin 0x250f01 ? 2 hw buttons |
| 1131 |
* (*) + 3 trackpoint buttons |
| 1132 |
* (**) + 0 trackpoint buttons |
| 1133 |
* Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps |
| 1134 |
*/ |
| 1135 |
static void elantech_set_buttonpad_prop(struct psmouse *psmouse) |
| 1136 |
{ |
| 1137 |
struct input_dev *dev = psmouse->dev; |
| 1138 |
struct elantech_data *etd = psmouse->private; |
| 1139 |
|
| 1140 |
if (etd->fw_version & 0x001000) { |
| 1141 |
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); |
| 1142 |
__clear_bit(BTN_RIGHT, dev->keybit); |
| 1143 |
} |
| 1144 |
} |
| 1145 |
|
| 1146 |
/* |
| 1147 |
* Some hw_version 4 models do have a middle button |
| 1148 |
*/ |
| 1149 |
static const struct dmi_system_id elantech_dmi_has_middle_button[] = { |
| 1150 |
#if defined(CONFIG_DMI) && defined(CONFIG_X86) |
| 1151 |
{ |
| 1152 |
/* Fujitsu H730 has a middle button */ |
| 1153 |
.matches = { |
| 1154 |
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 1155 |
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"), |
| 1156 |
}, |
| 1157 |
}, |
| 1158 |
#endif |
| 1159 |
{ } |
| 1160 |
}; |
| 1161 |
|
| 1162 |
/* |
| 1163 |
* Set the appropriate event bits for the input subsystem |
956 |
* Set the appropriate event bits for the input subsystem |
| 1164 |
*/ |
957 |
*/ |
| 1165 |
static int elantech_set_input_params(struct psmouse *psmouse) |
958 |
static int elantech_set_input_params(struct psmouse *psmouse) |
|
Lines 1178-1185
static int elantech_set_input_params(str
Link Here
|
| 1178 |
__clear_bit(EV_REL, dev->evbit); |
971 |
__clear_bit(EV_REL, dev->evbit); |
| 1179 |
|
972 |
|
| 1180 |
__set_bit(BTN_LEFT, dev->keybit); |
973 |
__set_bit(BTN_LEFT, dev->keybit); |
| 1181 |
if (dmi_check_system(elantech_dmi_has_middle_button)) |
|
|
| 1182 |
__set_bit(BTN_MIDDLE, dev->keybit); |
| 1183 |
__set_bit(BTN_RIGHT, dev->keybit); |
974 |
__set_bit(BTN_RIGHT, dev->keybit); |
| 1184 |
|
975 |
|
| 1185 |
__set_bit(BTN_TOUCH, dev->keybit); |
976 |
__set_bit(BTN_TOUCH, dev->keybit); |
|
Lines 1204-1211
static int elantech_set_input_params(str
Link Here
|
| 1204 |
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit); |
995 |
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit); |
| 1205 |
/* fall through */ |
996 |
/* fall through */ |
| 1206 |
case 3: |
997 |
case 3: |
| 1207 |
if (etd->hw_version == 3) |
|
|
| 1208 |
elantech_set_buttonpad_prop(psmouse); |
| 1209 |
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
998 |
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
| 1210 |
input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
999 |
input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
| 1211 |
if (etd->reports_pressure) { |
1000 |
if (etd->reports_pressure) { |
|
Lines 1227-1233
static int elantech_set_input_params(str
Link Here
|
| 1227 |
*/ |
1016 |
*/ |
| 1228 |
psmouse_warn(psmouse, "couldn't query resolution data.\n"); |
1017 |
psmouse_warn(psmouse, "couldn't query resolution data.\n"); |
| 1229 |
} |
1018 |
} |
| 1230 |
elantech_set_buttonpad_prop(psmouse); |
1019 |
/* v4 is clickpad, with only one button. */ |
|
|
1020 |
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); |
| 1021 |
//__clear_bit(BTN_RIGHT, dev->keybit); |
| 1231 |
__set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
1022 |
__set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
| 1232 |
/* For X to recognize me as touchpad. */ |
1023 |
/* For X to recognize me as touchpad. */ |
| 1233 |
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
1024 |
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
|
Lines 1341-1347
ELANTECH_INT_ATTR(reg_25, 0x25);
Link Here
|
| 1341 |
ELANTECH_INT_ATTR(reg_26, 0x26); |
1132 |
ELANTECH_INT_ATTR(reg_26, 0x26); |
| 1342 |
ELANTECH_INT_ATTR(debug, 0); |
1133 |
ELANTECH_INT_ATTR(debug, 0); |
| 1343 |
ELANTECH_INT_ATTR(paritycheck, 0); |
1134 |
ELANTECH_INT_ATTR(paritycheck, 0); |
| 1344 |
ELANTECH_INT_ATTR(crc_enabled, 0); |
|
|
| 1345 |
|
1135 |
|
| 1346 |
static struct attribute *elantech_attrs[] = { |
1136 |
static struct attribute *elantech_attrs[] = { |
| 1347 |
&psmouse_attr_reg_07.dattr.attr, |
1137 |
&psmouse_attr_reg_07.dattr.attr, |
|
Lines 1356-1362
static struct attribute *elantech_attrs[
Link Here
|
| 1356 |
&psmouse_attr_reg_26.dattr.attr, |
1146 |
&psmouse_attr_reg_26.dattr.attr, |
| 1357 |
&psmouse_attr_debug.dattr.attr, |
1147 |
&psmouse_attr_debug.dattr.attr, |
| 1358 |
&psmouse_attr_paritycheck.dattr.attr, |
1148 |
&psmouse_attr_paritycheck.dattr.attr, |
| 1359 |
&psmouse_attr_crc_enabled.dattr.attr, |
|
|
| 1360 |
NULL |
1149 |
NULL |
| 1361 |
}; |
1150 |
}; |
| 1362 |
|
1151 |
|
|
Lines 1375-1388
static bool elantech_is_signature_valid(
Link Here
|
| 1375 |
if (param[1] == 0) |
1164 |
if (param[1] == 0) |
| 1376 |
return true; |
1165 |
return true; |
| 1377 |
|
1166 |
|
| 1378 |
/* |
|
|
| 1379 |
* Some hw_version >= 4 models have a revision higher then 20. Meaning |
| 1380 |
* that param[2] may be 10 or 20, skip the rates check for these. |
| 1381 |
*/ |
| 1382 |
if ((param[0] & 0x0f) >= 0x06 && (param[1] & 0xaf) == 0x0f && |
| 1383 |
param[2] < 40) |
| 1384 |
return true; |
| 1385 |
|
| 1386 |
for (i = 0; i < ARRAY_SIZE(rates); i++) |
1167 |
for (i = 0; i < ARRAY_SIZE(rates); i++) |
| 1387 |
if (param[2] == rates[i]) |
1168 |
if (param[2] == rates[i]) |
| 1388 |
return false; |
1169 |
return false; |
|
Lines 1454-1463
int elantech_detect(struct psmouse *psmo
Link Here
|
| 1454 |
*/ |
1235 |
*/ |
| 1455 |
static void elantech_disconnect(struct psmouse *psmouse) |
1236 |
static void elantech_disconnect(struct psmouse *psmouse) |
| 1456 |
{ |
1237 |
{ |
| 1457 |
struct elantech_data *etd = psmouse->private; |
|
|
| 1458 |
|
| 1459 |
if (etd->tp_dev) |
| 1460 |
input_unregister_device(etd->tp_dev); |
| 1461 |
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
1238 |
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
| 1462 |
&elantech_attr_group); |
1239 |
&elantech_attr_group); |
| 1463 |
kfree(psmouse->private); |
1240 |
kfree(psmouse->private); |
|
Lines 1484-1536
static int elantech_reconnect(struct psm
Link Here
|
| 1484 |
} |
1261 |
} |
| 1485 |
|
1262 |
|
| 1486 |
/* |
1263 |
/* |
| 1487 |
* Some hw_version 4 models do not work with crc_disabled |
|
|
| 1488 |
*/ |
| 1489 |
static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { |
| 1490 |
#if defined(CONFIG_DMI) && defined(CONFIG_X86) |
| 1491 |
{ |
| 1492 |
/* Fujitsu H730 does not work with crc_enabled == 0 */ |
| 1493 |
.matches = { |
| 1494 |
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 1495 |
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"), |
| 1496 |
}, |
| 1497 |
}, |
| 1498 |
{ |
| 1499 |
/* Fujitsu LIFEBOOK E554 does not work with crc_enabled == 0 */ |
| 1500 |
.matches = { |
| 1501 |
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 1502 |
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E554"), |
| 1503 |
}, |
| 1504 |
}, |
| 1505 |
{ |
| 1506 |
/* Fujitsu LIFEBOOK E544 does not work with crc_enabled == 0 */ |
| 1507 |
.matches = { |
| 1508 |
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 1509 |
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E544"), |
| 1510 |
}, |
| 1511 |
}, |
| 1512 |
#endif |
| 1513 |
{ } |
| 1514 |
}; |
| 1515 |
|
| 1516 |
/* |
| 1517 |
* Some hw_version 3 models go into error state when we try to set |
| 1518 |
* bit 3 and/or bit 1 of r10. |
| 1519 |
*/ |
| 1520 |
static const struct dmi_system_id no_hw_res_dmi_table[] = { |
| 1521 |
#if defined(CONFIG_DMI) && defined(CONFIG_X86) |
| 1522 |
{ |
| 1523 |
/* Gigabyte U2442 */ |
| 1524 |
.matches = { |
| 1525 |
DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), |
| 1526 |
DMI_MATCH(DMI_PRODUCT_NAME, "U2442"), |
| 1527 |
}, |
| 1528 |
}, |
| 1529 |
#endif |
| 1530 |
{ } |
| 1531 |
}; |
| 1532 |
|
| 1533 |
/* |
| 1534 |
* determine hardware version and set some properties according to it. |
1264 |
* determine hardware version and set some properties according to it. |
| 1535 |
*/ |
1265 |
*/ |
| 1536 |
static int elantech_set_properties(struct elantech_data *etd) |
1266 |
static int elantech_set_properties(struct elantech_data *etd) |
|
Lines 1552-1562
static int elantech_set_properties(struc
Link Here
|
| 1552 |
break; |
1282 |
break; |
| 1553 |
case 6: |
1283 |
case 6: |
| 1554 |
case 7: |
1284 |
case 7: |
| 1555 |
case 8: |
|
|
| 1556 |
case 9: |
| 1557 |
case 10: |
| 1558 |
case 13: |
| 1559 |
case 14: |
| 1560 |
etd->hw_version = 4; |
1285 |
etd->hw_version = 4; |
| 1561 |
break; |
1286 |
break; |
| 1562 |
default: |
1287 |
default: |
|
Lines 1587-1602
static int elantech_set_properties(struc
Link Here
|
| 1587 |
etd->reports_pressure = true; |
1312 |
etd->reports_pressure = true; |
| 1588 |
} |
1313 |
} |
| 1589 |
|
1314 |
|
| 1590 |
/* |
|
|
| 1591 |
* The signatures of v3 and v4 packets change depending on the |
| 1592 |
* value of this hardware flag. |
| 1593 |
*/ |
| 1594 |
etd->crc_enabled = (etd->fw_version & 0x4000) == 0x4000 || |
| 1595 |
dmi_check_system(elantech_dmi_force_crc_enabled); |
| 1596 |
|
| 1597 |
/* Enable real hardware resolution on hw_version 3 ? */ |
| 1598 |
etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table); |
| 1599 |
|
| 1600 |
return 0; |
1315 |
return 0; |
| 1601 |
} |
1316 |
} |
| 1602 |
|
1317 |
|
|
Lines 1606-1615
static int elantech_set_properties(struc
Link Here
|
| 1606 |
int elantech_init(struct psmouse *psmouse) |
1321 |
int elantech_init(struct psmouse *psmouse) |
| 1607 |
{ |
1322 |
{ |
| 1608 |
struct elantech_data *etd; |
1323 |
struct elantech_data *etd; |
| 1609 |
int i; |
1324 |
int i, error; |
| 1610 |
int error = -EINVAL; |
|
|
| 1611 |
unsigned char param[3]; |
1325 |
unsigned char param[3]; |
| 1612 |
struct input_dev *tp_dev; |
|
|
| 1613 |
|
1326 |
|
| 1614 |
psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
1327 |
psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
| 1615 |
if (!etd) |
1328 |
if (!etd) |
|
Lines 1654-1664
int elantech_init(struct psmouse *psmous
Link Here
|
| 1654 |
goto init_fail; |
1367 |
goto init_fail; |
| 1655 |
} |
1368 |
} |
| 1656 |
|
1369 |
|
| 1657 |
if (etd->fw_version == 0x381f17) { |
|
|
| 1658 |
etd->original_set_rate = psmouse->set_rate; |
| 1659 |
psmouse->set_rate = elantech_set_rate_restore_reg_07; |
| 1660 |
} |
| 1661 |
|
| 1662 |
if (elantech_set_input_params(psmouse)) { |
1370 |
if (elantech_set_input_params(psmouse)) { |
| 1663 |
psmouse_err(psmouse, "failed to query touchpad range.\n"); |
1371 |
psmouse_err(psmouse, "failed to query touchpad range.\n"); |
| 1664 |
goto init_fail; |
1372 |
goto init_fail; |
|
Lines 1673-1725
int elantech_init(struct psmouse *psmous
Link Here
|
| 1673 |
goto init_fail; |
1381 |
goto init_fail; |
| 1674 |
} |
1382 |
} |
| 1675 |
|
1383 |
|
| 1676 |
/* The MSB indicates the presence of the trackpoint */ |
|
|
| 1677 |
if ((etd->capabilities[0] & 0x80) == 0x80) { |
| 1678 |
tp_dev = input_allocate_device(); |
| 1679 |
|
| 1680 |
if (!tp_dev) { |
| 1681 |
error = -ENOMEM; |
| 1682 |
goto init_fail_tp_alloc; |
| 1683 |
} |
| 1684 |
|
| 1685 |
etd->tp_dev = tp_dev; |
| 1686 |
snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1", |
| 1687 |
psmouse->ps2dev.serio->phys); |
| 1688 |
tp_dev->phys = etd->tp_phys; |
| 1689 |
tp_dev->name = "Elantech PS/2 TrackPoint"; |
| 1690 |
tp_dev->id.bustype = BUS_I8042; |
| 1691 |
tp_dev->id.vendor = 0x0002; |
| 1692 |
tp_dev->id.product = PSMOUSE_ELANTECH; |
| 1693 |
tp_dev->id.version = 0x0000; |
| 1694 |
tp_dev->dev.parent = &psmouse->ps2dev.serio->dev; |
| 1695 |
tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
| 1696 |
tp_dev->relbit[BIT_WORD(REL_X)] = |
| 1697 |
BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
| 1698 |
tp_dev->keybit[BIT_WORD(BTN_LEFT)] = |
| 1699 |
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | |
| 1700 |
BIT_MASK(BTN_RIGHT); |
| 1701 |
|
| 1702 |
__set_bit(INPUT_PROP_POINTER, tp_dev->propbit); |
| 1703 |
__set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit); |
| 1704 |
|
| 1705 |
error = input_register_device(etd->tp_dev); |
| 1706 |
if (error < 0) |
| 1707 |
goto init_fail_tp_reg; |
| 1708 |
} |
| 1709 |
|
| 1710 |
psmouse->protocol_handler = elantech_process_byte; |
1384 |
psmouse->protocol_handler = elantech_process_byte; |
| 1711 |
psmouse->disconnect = elantech_disconnect; |
1385 |
psmouse->disconnect = elantech_disconnect; |
| 1712 |
psmouse->reconnect = elantech_reconnect; |
1386 |
psmouse->reconnect = elantech_reconnect; |
| 1713 |
psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
1387 |
psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
| 1714 |
|
1388 |
|
| 1715 |
return 0; |
1389 |
return 0; |
| 1716 |
init_fail_tp_reg: |
1390 |
|
| 1717 |
input_free_device(tp_dev); |
|
|
| 1718 |
init_fail_tp_alloc: |
| 1719 |
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
| 1720 |
&elantech_attr_group); |
| 1721 |
init_fail: |
1391 |
init_fail: |
| 1722 |
psmouse_reset(psmouse); |
|
|
| 1723 |
kfree(etd); |
1392 |
kfree(etd); |
| 1724 |
return error; |
1393 |
return -1; |
| 1725 |
} |
1394 |
} |