[SRU,Xenial,Yakkety,1/1] Input: ALPS - fix V8+ protocol handling (73 03 28)

Message ID 62311d36a7d9215c7c8ba950c6bb96175c4a02f7.1491489951.git.joseph.salisbury@canonical.com
State New
Headers show

Commit Message

Joseph Salisbury April 6, 2017, 3:25 p.m.
From: Masaki Ota <masaki.ota@jp.alps.com>

BugLink: http://bugs.launchpad.net/bugs/1662589

Devices identified as E7="73 03 28" use slightly modified version of V8
protocol, with lower count per electrode, different offsets, and different
feature bits in OTP data.

Fixes: aeaa881f9b17 ("Input: ALPS - set DualPoint flag for 74 03 28 devices")
Signed-off-by: Masaki Ota <masaki.ota@jp.alps.com>
Acked-by: Pali Rohar <pali.rohar@gmail.com>
Tested-by: Paul Donohue <linux-kernel@PaulSD.com>
Tested-by: Nick Fletcher <nick.m.fletcher@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
(backported from commit e7348396c6d51b57c95c6646c390cd078e038e19)
Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
---
 drivers/input/mouse/alps.c | 66 +++++++++++++++++++++++++++++++++++-----------
 drivers/input/mouse/alps.h | 21 ++++++++++++++-
 2 files changed, 70 insertions(+), 17 deletions(-)

Comments

Tim Gardner April 6, 2017, 3:47 p.m. | #1
Good test results, upstream stable commit
Colin King April 6, 2017, 3:52 p.m. | #2
On 06/04/17 16:25, Joseph Salisbury wrote:
> From: Masaki Ota <masaki.ota@jp.alps.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1662589
> 
> Devices identified as E7="73 03 28" use slightly modified version of V8
> protocol, with lower count per electrode, different offsets, and different
> feature bits in OTP data.
> 
> Fixes: aeaa881f9b17 ("Input: ALPS - set DualPoint flag for 74 03 28 devices")
> Signed-off-by: Masaki Ota <masaki.ota@jp.alps.com>
> Acked-by: Pali Rohar <pali.rohar@gmail.com>
> Tested-by: Paul Donohue <linux-kernel@PaulSD.com>
> Tested-by: Nick Fletcher <nick.m.fletcher@gmail.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> (backported from commit e7348396c6d51b57c95c6646c390cd078e038e19)
> Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
> ---
>  drivers/input/mouse/alps.c | 66 +++++++++++++++++++++++++++++++++++-----------
>  drivers/input/mouse/alps.h | 21 ++++++++++++++-
>  2 files changed, 70 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
> index d10b14f..0fd78c3 100644
> --- a/drivers/input/mouse/alps.c
> +++ b/drivers/input/mouse/alps.c
> @@ -2458,14 +2458,34 @@ static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
>  	int num_y_electrode;
>  	int x_pitch, y_pitch, x_phys, y_phys;
>  
> -	num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
> -	num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
> +	if (IS_SS4PLUS_DEV(priv->dev_id)) {
> +		num_x_electrode =
> +			SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F);
> +		num_y_electrode =
> +			SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F);
>  
> -	priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
> -	priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
> +		priv->x_max =
> +			(num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
> +		priv->y_max =
> +			(num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
>  
> -	x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
> -	y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
> +		x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
> +		y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM;
> +
> +	} else {
> +		num_x_electrode =
> +			SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
> +		num_y_electrode =
> +			SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
> +
> +		priv->x_max =
> +			(num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
> +		priv->y_max =
> +			(num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
> +
> +		x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
> +		y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
> +	}
>  
>  	x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
>  	y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
> @@ -2481,7 +2501,10 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
>  {
>  	unsigned char is_btnless;
>  
> -	is_btnless = (otp[1][1] >> 3) & 0x01;
> +	if (IS_SS4PLUS_DEV(priv->dev_id))
> +		is_btnless = (otp[1][0] >> 1) & 0x01;
> +	else
> +		is_btnless = (otp[1][1] >> 3) & 0x01;
>  
>  	if (is_btnless)
>  		priv->flags |= ALPS_BUTTONPAD;
> @@ -2489,6 +2512,21 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
>  	return 0;
>  }
>  
> +static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
> +				       struct alps_data *priv)
> +{
> +	bool is_dual = false;
> +
> +	if (IS_SS4PLUS_DEV(priv->dev_id))
> +		is_dual = (otp[0][0] >> 4) & 0x01;
> +
> +	if (is_dual)
> +		priv->flags |= ALPS_DUALPOINT |
> +					ALPS_DUALPOINT_WITH_PRESSURE;
> +
> +	return 0;
> +}
> +
>  static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
>  				    struct alps_data *priv)
>  {
> @@ -2504,6 +2542,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
>  
>  	alps_update_btn_info_ss4_v2(otp, priv);
>  
> +	alps_update_dual_info_ss4_v2(otp, priv);
> +
>  	return 0;
>  }
>  
> @@ -2741,10 +2781,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
>  		if (alps_set_defaults_ss4_v2(psmouse, priv))
>  			return -EIO;
>  
> -		if (priv->fw_ver[1] == 0x1)
> -			priv->flags |= ALPS_DUALPOINT |
> -					ALPS_DUALPOINT_WITH_PRESSURE;
> -
>  		break;
>  	}
>  
> @@ -2815,10 +2851,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
>  			   ec[2] >= 0x90 && ec[2] <= 0x9d) {
>  			protocol = &alps_v3_protocol_data;
>  		} else if (e7[0] == 0x73 && e7[1] == 0x03 &&
> -			   e7[2] == 0x14 && ec[1] == 0x02) {
> -			protocol = &alps_v8_protocol_data;
> -		} else if (e7[0] == 0x73 && e7[1] == 0x03 &&
> -			   e7[2] == 0x28 && ec[1] == 0x01) {
> +			   (e7[2] == 0x14 || e7[2] == 0x28)) {
>  			protocol = &alps_v8_protocol_data;
>  		} else {
>  			psmouse_dbg(psmouse,
> @@ -2828,7 +2861,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
>  	}
>  
>  	if (priv) {
> -		/* Save the Firmware version */
> +		/* Save Device ID and Firmware version */
> +		memcpy(priv->dev_id, e7, 3);
>  		memcpy(priv->fw_ver, ec, 3);
>  		error = alps_set_protocol(psmouse, priv, protocol);
>  		if (error)
> diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
> index b9417e2..31c06df 100644
> --- a/drivers/input/mouse/alps.h
> +++ b/drivers/input/mouse/alps.h
> @@ -54,7 +54,25 @@ enum SS4_PACKET_ID {
>  
>  #define SS4_MASK_NORMAL_BUTTONS		0x07
>  
> -#define SS4_1F_X_V2(_b)		((_b[0] & 0x0007) |		\
> +#define SS4PLUS_COUNT_PER_ELECTRODE	128
> +#define SS4PLUS_NUMSENSOR_XOFFSET	16
> +#define SS4PLUS_NUMSENSOR_YOFFSET	5
> +#define SS4PLUS_MIN_PITCH_MM		37
> +
> +#define IS_SS4PLUS_DEV(_b)	(((_b[0]) == 0x73) &&	\
> +				 ((_b[1]) == 0x03) &&	\
> +				 ((_b[2]) == 0x28)		\
> +				)
> +
> +#define SS4_IS_IDLE_V2(_b)	(((_b[0]) == 0x18) &&		\
> +				 ((_b[1]) == 0x10) &&		\
> +				 ((_b[2]) == 0x00) &&		\
> +				 ((_b[3] & 0x88) == 0x08) &&	\
> +				 ((_b[4]) == 0x10) &&		\
> +				 ((_b[5]) == 0x00)		\
> +				)
> +
> +#define SS4_1F_X_V2(_b)		(((_b[0]) & 0x0007) |		\
>  				 ((_b[1] << 3) & 0x0078) |	\
>  				 ((_b[1] << 2) & 0x0380) |	\
>  				 ((_b[2] << 5) & 0x1C00)	\
> @@ -263,6 +281,7 @@ struct alps_data {
>  	int addr_command;
>  	u16 proto_version;
>  	u8 byte0, mask0;
> +	u8 dev_id[3];
>  	u8 fw_ver[3];
>  	int flags;
>  	int x_max;
> 

Upstream fix, has known test results and limit device scope, so..

Acked-by: Colin Ian King <colin.king@canonical.com>

Patch

diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index d10b14f..0fd78c3 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -2458,14 +2458,34 @@  static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
 	int num_y_electrode;
 	int x_pitch, y_pitch, x_phys, y_phys;
 
-	num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
-	num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
+	if (IS_SS4PLUS_DEV(priv->dev_id)) {
+		num_x_electrode =
+			SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F);
+		num_y_electrode =
+			SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F);
 
-	priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
-	priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
+		priv->x_max =
+			(num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
+		priv->y_max =
+			(num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
 
-	x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
-	y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
+		x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
+		y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM;
+
+	} else {
+		num_x_electrode =
+			SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
+		num_y_electrode =
+			SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
+
+		priv->x_max =
+			(num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
+		priv->y_max =
+			(num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
+
+		x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
+		y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
+	}
 
 	x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
 	y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
@@ -2481,7 +2501,10 @@  static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
 {
 	unsigned char is_btnless;
 
-	is_btnless = (otp[1][1] >> 3) & 0x01;
+	if (IS_SS4PLUS_DEV(priv->dev_id))
+		is_btnless = (otp[1][0] >> 1) & 0x01;
+	else
+		is_btnless = (otp[1][1] >> 3) & 0x01;
 
 	if (is_btnless)
 		priv->flags |= ALPS_BUTTONPAD;
@@ -2489,6 +2512,21 @@  static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
 	return 0;
 }
 
+static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
+				       struct alps_data *priv)
+{
+	bool is_dual = false;
+
+	if (IS_SS4PLUS_DEV(priv->dev_id))
+		is_dual = (otp[0][0] >> 4) & 0x01;
+
+	if (is_dual)
+		priv->flags |= ALPS_DUALPOINT |
+					ALPS_DUALPOINT_WITH_PRESSURE;
+
+	return 0;
+}
+
 static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
 				    struct alps_data *priv)
 {
@@ -2504,6 +2542,8 @@  static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
 
 	alps_update_btn_info_ss4_v2(otp, priv);
 
+	alps_update_dual_info_ss4_v2(otp, priv);
+
 	return 0;
 }
 
@@ -2741,10 +2781,6 @@  static int alps_set_protocol(struct psmouse *psmouse,
 		if (alps_set_defaults_ss4_v2(psmouse, priv))
 			return -EIO;
 
-		if (priv->fw_ver[1] == 0x1)
-			priv->flags |= ALPS_DUALPOINT |
-					ALPS_DUALPOINT_WITH_PRESSURE;
-
 		break;
 	}
 
@@ -2815,10 +2851,7 @@  static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
 			   ec[2] >= 0x90 && ec[2] <= 0x9d) {
 			protocol = &alps_v3_protocol_data;
 		} else if (e7[0] == 0x73 && e7[1] == 0x03 &&
-			   e7[2] == 0x14 && ec[1] == 0x02) {
-			protocol = &alps_v8_protocol_data;
-		} else if (e7[0] == 0x73 && e7[1] == 0x03 &&
-			   e7[2] == 0x28 && ec[1] == 0x01) {
+			   (e7[2] == 0x14 || e7[2] == 0x28)) {
 			protocol = &alps_v8_protocol_data;
 		} else {
 			psmouse_dbg(psmouse,
@@ -2828,7 +2861,8 @@  static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
 	}
 
 	if (priv) {
-		/* Save the Firmware version */
+		/* Save Device ID and Firmware version */
+		memcpy(priv->dev_id, e7, 3);
 		memcpy(priv->fw_ver, ec, 3);
 		error = alps_set_protocol(psmouse, priv, protocol);
 		if (error)
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index b9417e2..31c06df 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -54,7 +54,25 @@  enum SS4_PACKET_ID {
 
 #define SS4_MASK_NORMAL_BUTTONS		0x07
 
-#define SS4_1F_X_V2(_b)		((_b[0] & 0x0007) |		\
+#define SS4PLUS_COUNT_PER_ELECTRODE	128
+#define SS4PLUS_NUMSENSOR_XOFFSET	16
+#define SS4PLUS_NUMSENSOR_YOFFSET	5
+#define SS4PLUS_MIN_PITCH_MM		37
+
+#define IS_SS4PLUS_DEV(_b)	(((_b[0]) == 0x73) &&	\
+				 ((_b[1]) == 0x03) &&	\
+				 ((_b[2]) == 0x28)		\
+				)
+
+#define SS4_IS_IDLE_V2(_b)	(((_b[0]) == 0x18) &&		\
+				 ((_b[1]) == 0x10) &&		\
+				 ((_b[2]) == 0x00) &&		\
+				 ((_b[3] & 0x88) == 0x08) &&	\
+				 ((_b[4]) == 0x10) &&		\
+				 ((_b[5]) == 0x00)		\
+				)
+
+#define SS4_1F_X_V2(_b)		(((_b[0]) & 0x0007) |		\
 				 ((_b[1] << 3) & 0x0078) |	\
 				 ((_b[1] << 2) & 0x0380) |	\
 				 ((_b[2] << 5) & 0x1C00)	\
@@ -263,6 +281,7 @@  struct alps_data {
 	int addr_command;
 	u16 proto_version;
 	u8 byte0, mask0;
+	u8 dev_id[3];
 	u8 fw_ver[3];
 	int flags;
 	int x_max;