Re: [PATCH] HID: i2c-hid: Add quirk for sleep before reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Jan 05 2017 or thereabouts, Brendan McGrath wrote:
> Support for the Asus Touchpad was recently added. It turns out this
> device can fail initialisation (and become unusable) when the RESET
> command is sent too soon after the POWER ON command.
> 
> Unfortunately the i2c-hid specification does not specify the need for
> a delay between these two commands. But it was discovered the Windows
> driver has a 1ms delay.
> 
> As a result, this patch adds a new QUIRK to the i2c-hid module that
> allows a device to specify a specific sleep inbetween the POWER ON and
> RESET commands.
> 
> See https://github.com/vlasenko/hid-asus-dkms/issues/24 for further
> details.
> 
> Signed-off-by: Brendan McGrath <redmcg@xxxxxxxxxxxxxxxxxxx>
> ---
> I considered three approaches for this patch:
> a) add a hardcoded sleep that would affect all devices;
> b) add a quirk with a hardcoded sleep value; or
> c) add a quirk with a configurable sleep value
> 
> Each was a trade off between flexibility and the amount of code/complexity required.

I am not a big fan of having to configure the sleep value in each quirk.
I think I'd actually prefer the solution a: no quirk and a small wait
(you wait less than 5ms, I would think this as acceptable). I wouldn't
be surprised if other devices would require such timing issues, so I
wouldn't mind waiting a tiny bit for those to be working without any
quirks.

If anyone prefer not having those timeouts, we can add some quirks, but
I would then prefer solution b.

Cheers,
Benjamin

> 
> In the end I chose c) as this allowed for the most flexibility; but would
> be happy to resubmit the patch using one of the other options (or any other
> alternative).
> 
>  drivers/hid/i2c-hid/i2c-hid.c | 30 ++++++++++++++++++++++++++----
>  1 file changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> index 8d53efe..fb1ebfa 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid.c
> @@ -45,6 +45,7 @@
>  
>  /* quirks to control the device */
>  #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)
> +#define I2C_HID_QUIRK_SLEEP_BEFORE_RESET	BIT(1)
>  
>  /* flags */
>  #define I2C_HID_STARTED		0
> @@ -156,17 +157,26 @@ struct i2c_hid {
>  
>  	bool			irq_wake_enabled;
>  	struct mutex		reset_lock;
> +
> +	__u32			reset_usleep_low;
> +	__u32			reset_usleep_high;
>  };
>  
>  static const struct i2c_hid_quirks {
>  	__u16 idVendor;
>  	__u16 idProduct;
>  	__u32 quirks;
> +	__u32 reset_usleep_low;
> +	__u32 reset_usleep_high;
>  } i2c_hid_quirks[] = {
>  	{ USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8752,
>  		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
>  	{ USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8755,
>  		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
> +	{ USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_TOUCHPAD,
> +		I2C_HID_QUIRK_SLEEP_BEFORE_RESET,
> +		 .reset_usleep_low = 750,
> +		 .reset_usleep_high = 5000 },
>  	{ 0, 0 }
>  };
>  
> @@ -177,16 +187,16 @@ static const struct i2c_hid_quirks {
>   *
>   * Returns: a u32 quirks value.
>   */
> -static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
> +static const struct i2c_hid_quirks* i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
>  {
> -	u32 quirks = 0;
> +	const struct i2c_hid_quirks *quirks = NULL;
>  	int n;
>  
>  	for (n = 0; i2c_hid_quirks[n].idVendor; n++)
>  		if (i2c_hid_quirks[n].idVendor == idVendor &&
>  		    (i2c_hid_quirks[n].idProduct == (__u16)HID_ANY_ID ||
>  		     i2c_hid_quirks[n].idProduct == idProduct))
> -			quirks = i2c_hid_quirks[n].quirks;
> +			quirks = &i2c_hid_quirks[n];
>  
>  	return quirks;
>  }
> @@ -425,6 +435,9 @@ static int i2c_hid_hwreset(struct i2c_client *client)
>  	if (ret)
>  		goto out_unlock;
>  
> +	if (ihid->quirks & I2C_HID_QUIRK_SLEEP_BEFORE_RESET)
> +		usleep_range(ihid->reset_usleep_low, ihid->reset_usleep_high);
> +
>  	i2c_hid_dbg(ihid, "resetting...\n");
>  
>  	ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
> @@ -1005,6 +1018,7 @@ static int i2c_hid_probe(struct i2c_client *client,
>  	struct i2c_hid *ihid;
>  	struct hid_device *hid;
>  	__u16 hidRegister;
> +	const struct i2c_hid_quirks *quirks;
>  	struct i2c_hid_platform_data *platform_data = client->dev.platform_data;
>  
>  	dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
> @@ -1091,7 +1105,15 @@ static int i2c_hid_probe(struct i2c_client *client,
>  		 client->name, hid->vendor, hid->product);
>  	strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
>  
> -	ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
> +	quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
> +
> +	if (quirks)
> +		ihid->quirks = quirks->quirks;
> +
> +	if (ihid->quirks & I2C_HID_QUIRK_SLEEP_BEFORE_RESET) {
> +		ihid->reset_usleep_low = quirks->reset_usleep_low;
> +		ihid->reset_usleep_high = quirks->reset_usleep_high;
> +	}
>  
>  	ret = hid_add_device(hid);
>  	if (ret) {
> -- 
> 2.7.4
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux