--- 5b2339aefda7e310c84d6ca7cb68d31c09097685 +++ fda35e615abf9c7b594d905dfed0027575e78a49 @@ -24,10 +24,6 @@ printk(KERN_DEBUG format, ##arg); \ } while (0) -static bool force_elantech; -module_param_named(force_elantech, force_elantech, bool, 0644); -MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); - /* * Send a Synaptics style sliced query command */ @@ -182,44 +178,36 @@ static void elantech_report_absolute_v1( struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; int fingers; + static int old_fingers; - if (etd->fw_version < 0x020000) { - /* - * byte 0: D U p1 p2 1 p3 R L - * byte 1: f 0 th tw x9 x8 y9 y8 - */ + if (etd->fw_version_maj == 0x01) { + /* byte 0: D U p1 p2 1 p3 R L + byte 1: f 0 th tw x9 x8 y9 y8 */ fingers = ((packet[1] & 0x80) >> 7) + ((packet[1] & 0x30) >> 4); } else { - /* - * byte 0: n1 n0 p2 p1 1 p3 R L - * byte 1: 0 0 0 0 x9 x8 y9 y8 - */ + /* byte 0: n1 n0 p2 p1 1 p3 R L + byte 1: 0 0 0 0 x9 x8 y9 y8 */ fingers = (packet[0] & 0xc0) >> 6; } if (etd->jumpy_cursor) { - if (fingers != 1) { - etd->single_finger_reports = 0; - } else if (etd->single_finger_reports < 2) { - /* Discard first 2 reports of one finger, bogus */ - etd->single_finger_reports++; + /* Discard packets that are likely to have bogus coordinates */ + if (fingers > old_fingers) { elantech_debug("elantech.c: discarding packet\n"); - return; + goto discard_packet_v1; } } input_report_key(dev, BTN_TOUCH, fingers != 0); - /* - * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 - * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 - */ + /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 + byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ if (fingers) { input_report_abs(dev, ABS_X, ((packet[1] & 0x0c) << 6) | packet[2]); - input_report_abs(dev, ABS_Y, - ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); + input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - + (((packet[1] & 0x03) << 8) | packet[3])); } input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); @@ -228,7 +216,7 @@ static void elantech_report_absolute_v1( input_report_key(dev, BTN_LEFT, packet[0] & 0x01); input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - if (etd->fw_version < 0x020000 && + if ((etd->fw_version_maj == 0x01) && (etd->capabilities & ETP_CAP_HAS_ROCKER)) { /* rocker up */ input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); @@ -237,6 +225,9 @@ static void elantech_report_absolute_v1( } input_sync(dev); + + discard_packet_v1: + old_fingers = fingers; } /* @@ -255,47 +246,34 @@ static void elantech_report_absolute_v2( switch (fingers) { case 1: - /* - * byte 1: . . . . . x10 x9 x8 - * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 - */ - input_report_abs(dev, ABS_X, - ((packet[1] & 0x07) << 8) | packet[2]); - /* - * byte 4: . . . . . . y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ - input_report_abs(dev, ABS_Y, - ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); + /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 + byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ + input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); + /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 + byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ + input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - + ((packet[4] << 8) | packet[5])); break; case 2: - /* - * The coordinate of each finger is reported separately - * with a lower resolution for two finger touches: - * byte 0: . . ay8 ax8 . . . . - * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ + /* The coordinate of each finger is reported separately with + a lower resolution for two finger touches */ + /* byte 0: . . ay8 ax8 . . . . + byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ x1 = ((packet[0] & 0x10) << 4) | packet[1]; /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); - /* - * byte 3: . . by8 bx8 . . . . - * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 - */ + /* byte 3: . . by8 bx8 . . . . + byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ x2 = ((packet[3] & 0x10) << 4) | packet[4]; /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); - /* - * For compatibility with the X Synaptics driver scale up - * one coordinate and report as ordinary mouse movent - */ + /* For compatibility with the X Synaptics driver scale up one + coordinate and report as ordinary mouse movent */ input_report_abs(dev, ABS_X, x1 << 2); input_report_abs(dev, ABS_Y, y1 << 2); - /* - * For compatibility with the proprietary X Elantech driver - * report both coordinates as hat coordinates - */ + /* For compatibility with the proprietary X Elantech driver + report both coordinates as hat coordinates */ input_report_abs(dev, ABS_HAT0X, x1); input_report_abs(dev, ABS_HAT0Y, y1); input_report_abs(dev, ABS_HAT1X, x2); @@ -319,7 +297,7 @@ static int elantech_check_parity_v1(stru unsigned char p1, p2, p3; /* Parity bits are placed differently */ - if (etd->fw_version < 0x020000) { + if (etd->fw_version_maj == 0x01) { /* byte 0: D U p1 p2 1 p3 R L */ p1 = (packet[0] & 0x20) >> 5; p2 = (packet[0] & 0x10) >> 4; @@ -442,7 +420,6 @@ static void elantech_set_input_params(st __set_bit(EV_KEY, dev->evbit); __set_bit(EV_ABS, dev->evbit); - __clear_bit(EV_REL, dev->evbit); __set_bit(BTN_LEFT, dev->keybit); __set_bit(BTN_RIGHT, dev->keybit); @@ -455,7 +432,7 @@ static void elantech_set_input_params(st switch (etd->hw_version) { case 1: /* Rocker button */ - if (etd->fw_version < 0x020000 && + if ((etd->fw_version_maj == 0x01) && (etd->capabilities & ETP_CAP_HAS_ROCKER)) { __set_bit(BTN_FORWARD, dev->keybit); __set_bit(BTN_BACK, dev->keybit); @@ -573,24 +550,6 @@ static struct attribute_group elantech_a .attrs = elantech_attrs, }; -static bool elantech_is_signature_valid(const unsigned char *param) -{ - static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; - int i; - - if (param[0] == 0) - return false; - - if (param[1] == 0) - return true; - - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (param[2] == rates[i]) - return false; - - return true; -} - /* * Use magic knock to detect Elantech touchpad */ @@ -634,13 +593,9 @@ int elantech_detect(struct psmouse *psmo pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", param[0], param[1], param[2]); - if (!elantech_is_signature_valid(param)) { - if (!force_elantech) { - pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); - return -1; - } - - pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); + if (param[0] == 0 || param[1] != 0) { + pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); + return -1; } if (set_properties) { @@ -702,14 +657,14 @@ int elantech_init(struct psmouse *psmous pr_err("elantech.c: failed to query firmware version.\n"); goto init_fail; } - - etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; + etd->fw_version_maj = param[0]; + etd->fw_version_min = param[2]; /* * Assume every version greater than this is new EeePC style * hardware with 6 byte packets */ - if (etd->fw_version >= 0x020030) { + if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { etd->hw_version = 2; /* For now show extra debug information */ etd->debug = 1; @@ -719,9 +674,8 @@ int elantech_init(struct psmouse *psmous etd->hw_version = 1; etd->paritycheck = 1; } - - pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", - etd->hw_version, param[0], param[1], param[2]); + pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", + etd->hw_version, etd->fw_version_maj, etd->fw_version_min); if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { pr_err("elantech.c: failed to query capabilities.\n"); @@ -732,14 +686,14 @@ int elantech_init(struct psmouse *psmous etd->capabilities = param[0]; /* - * This firmware suffers from misreporting coordinates when + * This firmware seems to suffer from misreporting coordinates when * a touch action starts causing the mouse cursor or scrolled page * to jump. Enable a workaround. */ - if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { - pr_info("elantech.c: firmware version 2.0.34/2.6.0 detected, " + if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { + pr_info("elantech.c: firmware version 2.34 detected, " "enabling jumpy cursor workaround\n"); - etd->jumpy_cursor = true; + etd->jumpy_cursor = 1; } if (elantech_set_absolute_mode(psmouse)) {