|
@@ -563,6 +563,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
|
|
} else {
|
|
} else {
|
|
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
|
|
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
|
|
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
|
|
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
|
|
|
|
+ input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04);
|
|
}
|
|
}
|
|
|
|
|
|
input_mt_report_pointer_emulation(dev, true);
|
|
input_mt_report_pointer_emulation(dev, true);
|
|
@@ -792,6 +793,9 @@ static int elantech_packet_check_v4(struct psmouse *psmouse)
|
|
unsigned char packet_type = packet[3] & 0x03;
|
|
unsigned char packet_type = packet[3] & 0x03;
|
|
bool sanity_check;
|
|
bool sanity_check;
|
|
|
|
|
|
|
|
+ if ((packet[3] & 0x0f) == 0x06)
|
|
|
|
+ return PACKET_TRACKPOINT;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Sanity check based on the constant bits of a packet.
|
|
* Sanity check based on the constant bits of a packet.
|
|
* The constant bits change depending on the value of
|
|
* The constant bits change depending on the value of
|
|
@@ -877,10 +881,19 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
|
|
|
|
|
|
case 4:
|
|
case 4:
|
|
packet_type = elantech_packet_check_v4(psmouse);
|
|
packet_type = elantech_packet_check_v4(psmouse);
|
|
- if (packet_type == PACKET_UNKNOWN)
|
|
|
|
|
|
+ switch (packet_type) {
|
|
|
|
+ case PACKET_UNKNOWN:
|
|
return PSMOUSE_BAD_DATA;
|
|
return PSMOUSE_BAD_DATA;
|
|
|
|
|
|
- elantech_report_absolute_v4(psmouse, packet_type);
|
|
|
|
|
|
+ case PACKET_TRACKPOINT:
|
|
|
|
+ elantech_report_trackpoint(psmouse, packet_type);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ elantech_report_absolute_v4(psmouse, packet_type);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1119,6 +1132,22 @@ static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Some hw_version 4 models do have a middle button
|
|
|
|
+ */
|
|
|
|
+static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
|
|
|
|
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
|
|
|
+ {
|
|
|
|
+ /* Fujitsu H730 has a middle button */
|
|
|
|
+ .matches = {
|
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
|
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+#endif
|
|
|
|
+ { }
|
|
|
|
+};
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Set the appropriate event bits for the input subsystem
|
|
* Set the appropriate event bits for the input subsystem
|
|
*/
|
|
*/
|
|
@@ -1138,6 +1167,8 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
|
__clear_bit(EV_REL, dev->evbit);
|
|
__clear_bit(EV_REL, dev->evbit);
|
|
|
|
|
|
__set_bit(BTN_LEFT, dev->keybit);
|
|
__set_bit(BTN_LEFT, dev->keybit);
|
|
|
|
+ if (dmi_check_system(elantech_dmi_has_middle_button))
|
|
|
|
+ __set_bit(BTN_MIDDLE, dev->keybit);
|
|
__set_bit(BTN_RIGHT, dev->keybit);
|
|
__set_bit(BTN_RIGHT, dev->keybit);
|
|
|
|
|
|
__set_bit(BTN_TOUCH, dev->keybit);
|
|
__set_bit(BTN_TOUCH, dev->keybit);
|
|
@@ -1299,6 +1330,7 @@ ELANTECH_INT_ATTR(reg_25, 0x25);
|
|
ELANTECH_INT_ATTR(reg_26, 0x26);
|
|
ELANTECH_INT_ATTR(reg_26, 0x26);
|
|
ELANTECH_INT_ATTR(debug, 0);
|
|
ELANTECH_INT_ATTR(debug, 0);
|
|
ELANTECH_INT_ATTR(paritycheck, 0);
|
|
ELANTECH_INT_ATTR(paritycheck, 0);
|
|
|
|
+ELANTECH_INT_ATTR(crc_enabled, 0);
|
|
|
|
|
|
static struct attribute *elantech_attrs[] = {
|
|
static struct attribute *elantech_attrs[] = {
|
|
&psmouse_attr_reg_07.dattr.attr,
|
|
&psmouse_attr_reg_07.dattr.attr,
|
|
@@ -1313,6 +1345,7 @@ static struct attribute *elantech_attrs[] = {
|
|
&psmouse_attr_reg_26.dattr.attr,
|
|
&psmouse_attr_reg_26.dattr.attr,
|
|
&psmouse_attr_debug.dattr.attr,
|
|
&psmouse_attr_debug.dattr.attr,
|
|
&psmouse_attr_paritycheck.dattr.attr,
|
|
&psmouse_attr_paritycheck.dattr.attr,
|
|
|
|
+ &psmouse_attr_crc_enabled.dattr.attr,
|
|
NULL
|
|
NULL
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1438,6 +1471,22 @@ static int elantech_reconnect(struct psmouse *psmouse)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Some hw_version 4 models do not work with crc_disabled
|
|
|
|
+ */
|
|
|
|
+static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
|
|
|
|
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
|
|
|
+ {
|
|
|
|
+ /* Fujitsu H730 does not work with crc_enabled == 0 */
|
|
|
|
+ .matches = {
|
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
|
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+#endif
|
|
|
|
+ { }
|
|
|
|
+};
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Some hw_version 3 models go into error state when we try to set
|
|
* Some hw_version 3 models go into error state when we try to set
|
|
* bit 3 and/or bit 1 of r10.
|
|
* bit 3 and/or bit 1 of r10.
|
|
@@ -1513,7 +1562,8 @@ static int elantech_set_properties(struct elantech_data *etd)
|
|
* The signatures of v3 and v4 packets change depending on the
|
|
* The signatures of v3 and v4 packets change depending on the
|
|
* value of this hardware flag.
|
|
* value of this hardware flag.
|
|
*/
|
|
*/
|
|
- etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
|
|
|
|
|
|
+ etd->crc_enabled = (etd->fw_version & 0x4000) == 0x4000 ||
|
|
|
|
+ dmi_check_system(elantech_dmi_force_crc_enabled);
|
|
|
|
|
|
/* Enable real hardware resolution on hw_version 3 ? */
|
|
/* Enable real hardware resolution on hw_version 3 ? */
|
|
etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
|
|
etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
|