Linux Input Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] input - elantech: force query XY range after absolute mode
@ 2020-10-13  7:15 Benjamin Tissoires
  0 siblings, 0 replies; only message in thread
From: Benjamin Tissoires @ 2020-10-13  7:15 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Hans de Goede, linux-input, linux-kernel, Benjamin Tissoires, stable

For some v3 hw versions, if the ETP_FW_ID_QUERY command is
issued before the call to set_absolute_mode(), the returned
values are wrong.

Force an other ETP_FW_ID_QUERY after set_absolute_mode()
to get correct values.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=209027
Cc: stable@vger.kernel.org  # 5.3+
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/input/mouse/elantech.c | 161 +++++++++++++++++++--------------
 1 file changed, 91 insertions(+), 70 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 90f8765f9efc..ff8e5fb61dab 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1593,80 +1593,12 @@ static int elantech_set_properties(struct elantech_device_info *info)
 	return 0;
 }
 
-static int elantech_query_info(struct psmouse *psmouse,
-			       struct elantech_device_info *info)
+static int elantech_get_range(struct psmouse *psmouse,
+			      struct elantech_device_info *info)
 {
 	unsigned char param[3];
 	unsigned char traces;
 
-	memset(info, 0, sizeof(*info));
-
-	/*
-	 * Do the version query again so we can store the result
-	 */
-	if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-		psmouse_err(psmouse, "failed to query firmware version.\n");
-		return -EINVAL;
-	}
-	info->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
-
-	if (elantech_set_properties(info)) {
-		psmouse_err(psmouse, "unknown hardware version, aborting...\n");
-		return -EINVAL;
-	}
-	psmouse_info(psmouse,
-		     "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
-		     info->hw_version, param[0], param[1], param[2]);
-
-	if (info->send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
-	    info->capabilities)) {
-		psmouse_err(psmouse, "failed to query capabilities.\n");
-		return -EINVAL;
-	}
-	psmouse_info(psmouse,
-		     "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
-		     info->capabilities[0], info->capabilities[1],
-		     info->capabilities[2]);
-
-	if (info->hw_version != 1) {
-		if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, info->samples)) {
-			psmouse_err(psmouse, "failed to query sample data\n");
-			return -EINVAL;
-		}
-		psmouse_info(psmouse,
-			     "Elan sample query result %02x, %02x, %02x\n",
-			     info->samples[0],
-			     info->samples[1],
-			     info->samples[2]);
-	}
-
-	if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
-		/*
-		 * This module has a bug which makes absolute mode
-		 * unusable, so let's abort so we'll be using standard
-		 * PS/2 protocol.
-		 */
-		psmouse_info(psmouse,
-			     "absolute mode broken, forcing standard PS/2 protocol\n");
-		return -ENODEV;
-	}
-
-	/* The MSB indicates the presence of the trackpoint */
-	info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
-
-	info->x_res = 31;
-	info->y_res = 31;
-	if (info->hw_version == 4) {
-		if (elantech_get_resolution_v4(psmouse,
-					       &info->x_res,
-					       &info->y_res,
-					       &info->bus)) {
-			psmouse_warn(psmouse,
-				     "failed to query resolution data.\n");
-		}
-	}
-
-	/* query range information */
 	switch (info->hw_version) {
 	case 1:
 		info->x_min = ETP_XMIN_V1;
@@ -1745,6 +1677,87 @@ static int elantech_query_info(struct psmouse *psmouse,
 		break;
 	}
 
+	return 0;
+}
+
+static int elantech_query_info(struct psmouse *psmouse,
+			       struct elantech_device_info *info)
+{
+	unsigned char param[3];
+	int error;
+
+	memset(info, 0, sizeof(*info));
+
+	/*
+	 * Do the version query again so we can store the result
+	 */
+	if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
+		psmouse_err(psmouse, "failed to query firmware version.\n");
+		return -EINVAL;
+	}
+	info->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
+
+	if (elantech_set_properties(info)) {
+		psmouse_err(psmouse, "unknown hardware version, aborting...\n");
+		return -EINVAL;
+	}
+	psmouse_info(psmouse,
+		     "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
+		     info->hw_version, param[0], param[1], param[2]);
+
+	if (info->send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+	    info->capabilities)) {
+		psmouse_err(psmouse, "failed to query capabilities.\n");
+		return -EINVAL;
+	}
+	psmouse_info(psmouse,
+		     "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
+		     info->capabilities[0], info->capabilities[1],
+		     info->capabilities[2]);
+
+	if (info->hw_version != 1) {
+		if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, info->samples)) {
+			psmouse_err(psmouse, "failed to query sample data\n");
+			return -EINVAL;
+		}
+		psmouse_info(psmouse,
+			     "Elan sample query result %02x, %02x, %02x\n",
+			     info->samples[0],
+			     info->samples[1],
+			     info->samples[2]);
+	}
+
+	if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
+		/*
+		 * This module has a bug which makes absolute mode
+		 * unusable, so let's abort so we'll be using standard
+		 * PS/2 protocol.
+		 */
+		psmouse_info(psmouse,
+			     "absolute mode broken, forcing standard PS/2 protocol\n");
+		return -ENODEV;
+	}
+
+	/* The MSB indicates the presence of the trackpoint */
+	info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
+
+	info->x_res = 31;
+	info->y_res = 31;
+	if (info->hw_version == 4) {
+		if (elantech_get_resolution_v4(psmouse,
+					       &info->x_res,
+					       &info->y_res,
+					       &info->bus)) {
+			psmouse_warn(psmouse,
+				     "failed to query resolution data.\n");
+		}
+	}
+
+	/* query range information */
+	error = elantech_get_range(psmouse, info);
+	if (error)
+		return error;
+
 	/* check for the middle button: DMI matching or new v4 firmwares */
 	info->has_middle_button = dmi_check_system(elantech_dmi_has_middle_button) ||
 				  (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) &&
@@ -1942,6 +1955,14 @@ static int elantech_setup_ps2(struct psmouse *psmouse,
 		goto init_fail;
 	}
 
+	/*
+	 * some hardware v3 send wrong min max coordinates if the
+	 * call to get those is made before elantech_set_absolute_mode().
+	 */
+	error = elantech_get_range(psmouse, &etd->info);
+	if (error)
+		goto init_fail;
+
 	if (info->fw_version == 0x381f17) {
 		etd->original_set_rate = psmouse->set_rate;
 		psmouse->set_rate = elantech_set_rate_restore_reg_07;
-- 
2.26.2


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, back to index

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-13  7:15 [PATCH] input - elantech: force query XY range after absolute mode Benjamin Tissoires

Linux Input Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-input/0 linux-input/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-input linux-input/ https://lore.kernel.org/linux-input \
		linux-input@vger.kernel.org
	public-inbox-index linux-input

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-input


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git