diff mbox

HID: i2c-hid: add retry in set power for fixing weida's issue

Message ID 1478515138-1922-1-git-send-email-hn.chen@weidahitech.com (mailing list archive)
State New, archived
Headers show

Commit Message

HungNien Chen Nov. 7, 2016, 10:38 a.m. UTC
From: HungNien Chen <hn.chen@weidahitech.com>

Just modify the set_power function to send the command twice.
It should be ok for other contorllers since it will jump out the loop after
the first command send out. If this is not a proper modification,
please tell me a proper way to fix this kind of issue.

Signed-off-by: HungNien Chen <hn.chen@weidahitech.com>
---
 drivers/hid/i2c-hid/i2c-hid.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

Comments

Jiri Kosina Nov. 7, 2016, 10:48 a.m. UTC | #1
On Mon, 7 Nov 2016, hn.chen@weidahitech.com wrote:

> From: HungNien Chen <hn.chen@weidahitech.com>
> 
> Just modify the set_power function to send the command twice.
> It should be ok for other contorllers since it will jump out the loop after
> the first command send out. If this is not a proper modification,
> please tell me a proper way to fix this kind of issue.
> 
> Signed-off-by: HungNien Chen <hn.chen@weidahitech.com>
> ---
>  drivers/hid/i2c-hid/i2c-hid.c | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> index b3ec4f2..d7423d9 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid.c
> @@ -49,6 +49,8 @@
>  #define I2C_HID_PWR_ON		0x00
>  #define I2C_HID_PWR_SLEEP	0x01
>  
> +#define	SET_PWR_RETRIES		2
> +
>  /* debug option */
>  static bool debug;
>  module_param(debug, bool, 0444);
> @@ -343,14 +345,26 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
>  {
>  	struct i2c_hid *ihid = i2c_get_clientdata(client);
>  	int ret;
> +	int retry;
>  
>  	i2c_hid_dbg(ihid, "%s\n", __func__);
>  
> -	ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
> -		0, NULL, 0, NULL, 0);
> -	if (ret)
> -		dev_err(&client->dev, "failed to change power setting.\n");
> +       /*
> +	* Some Weida's controllers require Set_Power twice on resume.
> +	* The 1st cmd wakeup the controller and the 2nd cmd will be executed.
> +	* It should be safe to controllers of other vendors.
> +	*/
> +	for (retry = 0; retry < SET_PWR_RETRIES; retry++) {
> +		ret = __i2c_hid_command(client, &hid_set_power_cmd,
> +			power_state, 0, NULL, 0, NULL, 0);
> +
> +		if (!ret)
> +			goto set_power_exit;

This is ugly, and we have no idea what this might do to any other 
(potential) devices. Can't you make this a quirk that'd be applied only to 
this specific device?
HungNien Chen Nov. 7, 2016, 11:02 a.m. UTC | #2
Hi Jiri,

Thanks for the tip.

Since I don't have any experience to add a quirk, may I have a sample code for reference ?
It should be a HID quirk, right ?

Hn.chen.

-----Original Message-----
From: Jiri Kosina [mailto:jikos@kernel.org] 
Sent: Monday, November 07, 2016 6:49 PM
To: Hn Chen
Cc: benjamin.tissoires@redhat.com; dmitry.torokhov@gmail.com; linux-input@vger.kernel.org
Subject: Re: [PATCH] HID: i2c-hid: add retry in set power for fixing weida's issue

On Mon, 7 Nov 2016, hn.chen@weidahitech.com wrote:

> From: HungNien Chen <hn.chen@weidahitech.com>
> 
> Just modify the set_power function to send the command twice.
> It should be ok for other contorllers since it will jump out the loop 
> after the first command send out. If this is not a proper 
> modification, please tell me a proper way to fix this kind of issue.
> 
> Signed-off-by: HungNien Chen <hn.chen@weidahitech.com>
> ---
>  drivers/hid/i2c-hid/i2c-hid.c | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c 
> b/drivers/hid/i2c-hid/i2c-hid.c index b3ec4f2..d7423d9 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid.c
> @@ -49,6 +49,8 @@
>  #define I2C_HID_PWR_ON		0x00
>  #define I2C_HID_PWR_SLEEP	0x01
>  
> +#define	SET_PWR_RETRIES		2
> +
>  /* debug option */
>  static bool debug;
>  module_param(debug, bool, 0444);
> @@ -343,14 +345,26 @@ static int i2c_hid_set_power(struct i2c_client 
> *client, int power_state)  {
>  	struct i2c_hid *ihid = i2c_get_clientdata(client);
>  	int ret;
> +	int retry;
>  
>  	i2c_hid_dbg(ihid, "%s\n", __func__);
>  
> -	ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
> -		0, NULL, 0, NULL, 0);
> -	if (ret)
> -		dev_err(&client->dev, "failed to change power setting.\n");
> +       /*
> +	* Some Weida's controllers require Set_Power twice on resume.
> +	* The 1st cmd wakeup the controller and the 2nd cmd will be executed.
> +	* It should be safe to controllers of other vendors.
> +	*/
> +	for (retry = 0; retry < SET_PWR_RETRIES; retry++) {
> +		ret = __i2c_hid_command(client, &hid_set_power_cmd,
> +			power_state, 0, NULL, 0, NULL, 0);
> +
> +		if (!ret)
> +			goto set_power_exit;

This is ugly, and we have no idea what this might do to any other
(potential) devices. Can't you make this a quirk that'd be applied only to this specific device?

--
Jiri Kosina
SUSE Labs

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jiri Kosina Nov. 7, 2016, 11:59 a.m. UTC | #3
On Mon, 7 Nov 2016, Hn Chen wrote:

> Since I don't have any experience to add a quirk, may I have a sample 
> code for reference ? It should be a HID quirk, right ?

Generic HID quirk might be over-stretching it, as i2c_hid_set_power() is 
being called from various places, so generalizing this requirement out 
into HID core wouldn't be clean either.

You can special-case this behavior by looking at wVendorID / wProductID / 
wVersionID from the report descriptor, can't you?

There is not a quirk mechanism for i2c-hid yet. If things start exploding 
like in usb-hid space, we'd definitely want to have a generic quirk 
mechanism one day. But if this has been a single case over the existence 
of the hid-over-i2c, I wouldn't bother (yet).
HungNien Chen Nov. 7, 2016, 1:35 p.m. UTC | #4
HI Jiri,

Ok. I see.  
I will do simple vid/pid filter to see if it's weida's controller.
Send the extra command if the answer is true.

hn.chen
diff mbox

Patch

diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index b3ec4f2..d7423d9 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -49,6 +49,8 @@ 
 #define I2C_HID_PWR_ON		0x00
 #define I2C_HID_PWR_SLEEP	0x01
 
+#define	SET_PWR_RETRIES		2
+
 /* debug option */
 static bool debug;
 module_param(debug, bool, 0444);
@@ -343,14 +345,26 @@  static int i2c_hid_set_power(struct i2c_client *client, int power_state)
 {
 	struct i2c_hid *ihid = i2c_get_clientdata(client);
 	int ret;
+	int retry;
 
 	i2c_hid_dbg(ihid, "%s\n", __func__);
 
-	ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
-		0, NULL, 0, NULL, 0);
-	if (ret)
-		dev_err(&client->dev, "failed to change power setting.\n");
+       /*
+	* Some Weida's controllers require Set_Power twice on resume.
+	* The 1st cmd wakeup the controller and the 2nd cmd will be executed.
+	* It should be safe to controllers of other vendors.
+	*/
+	for (retry = 0; retry < SET_PWR_RETRIES; retry++) {
+		ret = __i2c_hid_command(client, &hid_set_power_cmd,
+			power_state, 0, NULL, 0, NULL, 0);
+
+		if (!ret)
+			goto set_power_exit;
+	}
+
+	dev_err(&client->dev, "failed to change power setting.\n");
 
+set_power_exit:
 	return ret;
 }