Merge branch 'for-4.18/i2c-hid' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Fri, 8 Jun 2018 08:23:34 +0000 (10:23 +0200)
committerJiri Kosina <jkosina@suse.cz>
Fri, 8 Jun 2018 08:23:34 +0000 (10:23 +0200)
Assorted smaller fixes to i2c-hid driver

1  2 
drivers/hid/i2c-hid/i2c-hid.c

@@@ -47,7 -47,6 +47,7 @@@
  /* quirks to control the device */
  #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV      BIT(0)
  #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET      BIT(1)
 +#define I2C_HID_QUIRK_RESEND_REPORT_DESCR     BIT(2)
  
  /* flags */
  #define I2C_HID_STARTED               0
@@@ -131,8 -130,6 +131,6 @@@ static const struct i2c_hid_cmd hid_no_
   * static const struct i2c_hid_cmd hid_set_protocol_cmd = { I2C_HID_CMD(0x07) };
   */
  
- static DEFINE_MUTEX(i2c_hid_open_mut);
  /* The main device structure */
  struct i2c_hid {
        struct i2c_client       *client;        /* i2c client */
@@@ -172,10 -169,6 +170,10 @@@ static const struct i2c_hid_quirks 
                I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
        { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
                I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
 +      { I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118,
 +              I2C_HID_QUIRK_RESEND_REPORT_DESCR },
 +      { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
 +              I2C_HID_QUIRK_RESEND_REPORT_DESCR },
        { 0, 0 }
  };
  
@@@ -868,6 -861,15 +866,15 @@@ static int i2c_hid_fetch_hid_descriptor
  }
  
  #ifdef CONFIG_ACPI
+ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = {
+       /*
+        * The CHPN0001 ACPI device, which is used to describe the Chipone
+        * ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible.
+        */
+       {"CHPN0001", 0 },
+       { },
+ };
  static int i2c_hid_acpi_pdata(struct i2c_client *client,
                struct i2c_hid_platform_data *pdata)
  {
        acpi_handle handle;
  
        handle = ACPI_HANDLE(&client->dev);
-       if (!handle || acpi_bus_get_device(handle, &adev))
+       if (!handle || acpi_bus_get_device(handle, &adev)) {
+               dev_err(&client->dev, "Error could not get ACPI device\n");
+               return -ENODEV;
+       }
+       if (acpi_match_device_ids(adev, i2c_hid_acpi_blacklist) == 0)
                return -ENODEV;
  
        obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid, 1, 1, NULL,
                                      ACPI_TYPE_INTEGER);
        if (!obj) {
-               dev_err(&client->dev, "device _DSM execution failed\n");
+               dev_err(&client->dev, "Error _DSM call to get HID descriptor address failed\n");
                return -ENODEV;
        }
  
@@@ -1000,11 -1007,8 +1012,8 @@@ static int i2c_hid_probe(struct i2c_cli
                        goto err;
        } else if (!platform_data) {
                ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
-               if (ret) {
-                       dev_err(&client->dev,
-                               "HID register address not provided\n");
+               if (ret)
                        goto err;
-               }
        } else {
                ihid->pdata = *platform_data;
        }
        pm_runtime_enable(&client->dev);
        device_enable_async_suspend(&client->dev);
  
+       /* Make sure there is something at this address */
+       ret = i2c_smbus_read_byte(client);
+       if (ret < 0) {
+               dev_dbg(&client->dev, "nothing at this address: %d\n", ret);
+               ret = -ENXIO;
+               goto err_pm;
+       }
        ret = i2c_hid_fetch_hid_descriptor(ihid);
        if (ret < 0)
                goto err_pm;
@@@ -1225,16 -1237,6 +1242,16 @@@ static int i2c_hid_resume(struct devic
        if (ret)
                return ret;
  
 +      /* RAYDIUM device (2386:3118) need to re-send report descr cmd
 +       * after resume, after this it will be back normal.
 +       * otherwise it issues too many incomplete reports.
 +       */
 +      if (ihid->quirks & I2C_HID_QUIRK_RESEND_REPORT_DESCR) {
 +              ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
 +              if (ret)
 +                      return ret;
 +      }
 +
        if (hid->driver && hid->driver->reset_resume) {
                ret = hid->driver->reset_resume(hid);
                return ret;