Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jul 2017 16:22:48 +0000 (09:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jul 2017 16:22:48 +0000 (09:22 -0700)
Pull HID updates from Jiri Kosina:

 - open/close tracking improvements from Dmitry Torokhov

 - battery support improvements in Wacom driver from Jason Gerecke

 - Win8 support fixes from Benjamin Tissories and Hans de Geode

 - misc fixes to Intel-ISH driver from Arnd Bergmann

 - support for quite a few new devices and small assorted fixes here and
   there

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (35 commits)
  HID: intel-ish-hid: Enable Gemini Lake ish driver
  HID: intel-ish-hid: Enable Cannon Lake ish driver
  HID: wacom: fix mistake in printk
  HID: multitouch: optimize the sticky fingers timer
  HID: multitouch: fix rare Win 8 cases when the touch up event gets missing
  HID: multitouch: use BIT macro
  HID: Add driver for Retrode2 joypad adapter
  HID: multitouch: Add support for Google Rose Touchpad
  HID: multitouch: Support PTP Stick and Touchpad device
  HID: core: don't use negative operands when shift
  HID: apple: Use country code to detect ISO keyboards
  HID: remove no longer used hid->open field
  greybus: hid: remove custom locking from gb_hid_open/close
  HID: usbhid: remove custom locking from usbhid_open/close
  HID: i2c-hid: remove custom locking from i2c_hid_open/close
  HID: serialize hid_hw_open and hid_hw_close
  HID: usbhid: do not rely on hid->open when deciding to do IO
  HID: hiddev: use hid_hw_power instead of usbhid_get/put_power
  HID: hiddev: use hid_hw_open/close instead of usbhid_open/close
  HID: asus: Add support for Zen AiO MD-5110 keyboard
  ...

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

diff --combined drivers/hid/hid-core.c
index 2241e7913c0d1f7d24d17242a748e743938e6943,539d1dd888deda938f59dc76a26e8e2ad988e323..6fd01a692197af4e70c9e1bb4bfd0bd8ffb4f348
@@@ -1070,7 -1070,7 +1070,7 @@@ static s32 snto32(__u32 value, unsigne
        case 16: return ((__s16)value);
        case 32: return ((__s32)value);
        }
-       return value & (1 << (n - 1)) ? value | (-1 << n) : value;
+       return value & (1 << (n - 1)) ? value | (~0U << n) : value;
  }
  
  s32 hid_snto32(__u32 value, unsigned n)
@@@ -1774,6 -1774,94 +1774,94 @@@ void hid_disconnect(struct hid_device *
  }
  EXPORT_SYMBOL_GPL(hid_disconnect);
  
+ /**
+  * hid_hw_start - start underlying HW
+  * @hdev: hid device
+  * @connect_mask: which outputs to connect, see HID_CONNECT_*
+  *
+  * Call this in probe function *after* hid_parse. This will setup HW
+  * buffers and start the device (if not defeirred to device open).
+  * hid_hw_stop must be called if this was successful.
+  */
+ int hid_hw_start(struct hid_device *hdev, unsigned int connect_mask)
+ {
+       int error;
+       error = hdev->ll_driver->start(hdev);
+       if (error)
+               return error;
+       if (connect_mask) {
+               error = hid_connect(hdev, connect_mask);
+               if (error) {
+                       hdev->ll_driver->stop(hdev);
+                       return error;
+               }
+       }
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(hid_hw_start);
+ /**
+  * hid_hw_stop - stop underlying HW
+  * @hdev: hid device
+  *
+  * This is usually called from remove function or from probe when something
+  * failed and hid_hw_start was called already.
+  */
+ void hid_hw_stop(struct hid_device *hdev)
+ {
+       hid_disconnect(hdev);
+       hdev->ll_driver->stop(hdev);
+ }
+ EXPORT_SYMBOL_GPL(hid_hw_stop);
+ /**
+  * hid_hw_open - signal underlying HW to start delivering events
+  * @hdev: hid device
+  *
+  * Tell underlying HW to start delivering events from the device.
+  * This function should be called sometime after successful call
+  * to hid_hiw_start().
+  */
+ int hid_hw_open(struct hid_device *hdev)
+ {
+       int ret;
+       ret = mutex_lock_killable(&hdev->ll_open_lock);
+       if (ret)
+               return ret;
+       if (!hdev->ll_open_count++) {
+               ret = hdev->ll_driver->open(hdev);
+               if (ret)
+                       hdev->ll_open_count--;
+       }
+       mutex_unlock(&hdev->ll_open_lock);
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(hid_hw_open);
+ /**
+  * hid_hw_close - signal underlaying HW to stop delivering events
+  *
+  * @hdev: hid device
+  *
+  * This function indicates that we are not interested in the events
+  * from this device anymore. Delivery of events may or may not stop,
+  * depending on the number of users still outstanding.
+  */
+ void hid_hw_close(struct hid_device *hdev)
+ {
+       mutex_lock(&hdev->ll_open_lock);
+       if (!--hdev->ll_open_count)
+               hdev->ll_driver->close(hdev);
+       mutex_unlock(&hdev->ll_open_lock);
+ }
+ EXPORT_SYMBOL_GPL(hid_hw_close);
  /*
   * A list of devices for which there is a specialized driver on HID bus.
   *
@@@ -1892,6 -1980,8 +1980,8 @@@ static const struct hid_device_id hid_h
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
  #endif
  #if IS_ENABLED(CONFIG_HID_AUREAL)
        { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
  #if IS_ENABLED(CONFIG_HID_CHICONY)
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
  #endif
  #if IS_ENABLED(CONFIG_HID_CMEDIA)
        { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
  #if IS_ENABLED(CONFIG_HID_ICADE)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
  #endif
+ #if IS_ENABLED(CONFIG_HID_ITE)
+       { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
+ #endif
  #if IS_ENABLED(CONFIG_HID_KENSINGTON)
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
  #endif
  #if IS_ENABLED(CONFIG_HID_PRODIKEYS)
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
  #endif
+ #if IS_ENABLED(CONFIG_HID_RETRODE)
+       { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) },
+ #endif
  #if IS_ENABLED(CONFIG_HID_RMI)
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
@@@ -2307,7 -2402,7 +2402,7 @@@ struct hid_dynid 
   * Adds a new dynamic hid device ID to this driver,
   * and causes the driver to probe for all devices again.
   */
 -static ssize_t store_new_id(struct device_driver *drv, const char *buf,
 +static ssize_t new_id_store(struct device_driver *drv, const char *buf,
                size_t count)
  {
        struct hid_driver *hdrv = to_hid_driver(drv);
  
        return ret ? : count;
  }
 -static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
 +static DRIVER_ATTR_WO(new_id);
 +
 +static struct attribute *hid_drv_attrs[] = {
 +      &driver_attr_new_id.attr,
 +      NULL,
 +};
 +ATTRIBUTE_GROUPS(hid_drv);
  
  static void hid_free_dynids(struct hid_driver *hdrv)
  {
@@@ -2509,7 -2598,6 +2604,7 @@@ static int hid_uevent(struct device *de
  static struct bus_type hid_bus_type = {
        .name           = "hid",
        .dev_groups     = hid_dev_groups,
 +      .drv_groups     = hid_drv_groups,
        .match          = hid_bus_match,
        .probe          = hid_device_probe,
        .remove         = hid_device_remove,
@@@ -2914,6 -3002,7 +3009,7 @@@ struct hid_device *hid_allocate_device(
        spin_lock_init(&hdev->debug_list_lock);
        sema_init(&hdev->driver_lock, 1);
        sema_init(&hdev->driver_input_lock, 1);
+       mutex_init(&hdev->ll_open_lock);
  
        return hdev;
  }
@@@ -2949,6 -3038,8 +3045,6 @@@ EXPORT_SYMBOL_GPL(hid_destroy_device)
  int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
                const char *mod_name)
  {
 -      int ret;
 -
        hdrv->driver.name = hdrv->name;
        hdrv->driver.bus = &hid_bus_type;
        hdrv->driver.owner = owner;
        INIT_LIST_HEAD(&hdrv->dyn_list);
        spin_lock_init(&hdrv->dyn_lock);
  
 -      ret = driver_register(&hdrv->driver);
 -      if (ret)
 -              return ret;
 -
 -      ret = driver_create_file(&hdrv->driver, &driver_attr_new_id);
 -      if (ret)
 -              driver_unregister(&hdrv->driver);
 -
 -      return ret;
 +      return driver_register(&hdrv->driver);
  }
  EXPORT_SYMBOL_GPL(__hid_register_driver);
  
  void hid_unregister_driver(struct hid_driver *hdrv)
  {
 -      driver_remove_file(&hdrv->driver, &driver_attr_new_id);
        driver_unregister(&hdrv->driver);
        hid_free_dynids(hdrv);
  }
index 04015032a35a204b10593f71faac6812b82e45e8,1c8a026a5c7508c09264f7bf409a3a75ede85143..046f692fd0a2675ceb98f800b3e73f76e8da286b
@@@ -40,7 -40,7 +40,7 @@@
  #include <linux/of.h>
  #include <linux/regulator/consumer.h>
  
- #include <linux/i2c/i2c-hid.h>
+ #include <linux/platform_data/i2c-hid.h>
  
  #include "../hid-ids.h"
  
@@@ -743,18 -743,12 +743,12 @@@ static int i2c_hid_open(struct hid_devi
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        int ret = 0;
  
-       mutex_lock(&i2c_hid_open_mut);
-       if (!hid->open++) {
-               ret = pm_runtime_get_sync(&client->dev);
-               if (ret < 0) {
-                       hid->open--;
-                       goto done;
-               }
-               set_bit(I2C_HID_STARTED, &ihid->flags);
-       }
- done:
-       mutex_unlock(&i2c_hid_open_mut);
-       return ret < 0 ? ret : 0;
+       ret = pm_runtime_get_sync(&client->dev);
+       if (ret < 0)
+               return ret;
+       set_bit(I2C_HID_STARTED, &ihid->flags);
+       return 0;
  }
  
  static void i2c_hid_close(struct hid_device *hid)
        struct i2c_client *client = hid->driver_data;
        struct i2c_hid *ihid = i2c_get_clientdata(client);
  
-       /* protecting hid->open to make sure we don't restart
-        * data acquistion due to a resumption we no longer
-        * care about
-        */
-       mutex_lock(&i2c_hid_open_mut);
-       if (!--hid->open) {
-               clear_bit(I2C_HID_STARTED, &ihid->flags);
+       clear_bit(I2C_HID_STARTED, &ihid->flags);
  
-               /* Save some power */
-               pm_runtime_put(&client->dev);
-       }
-       mutex_unlock(&i2c_hid_open_mut);
+       /* Save some power */
+       pm_runtime_put(&client->dev);
  }
  
  static int i2c_hid_power(struct hid_device *hid, int lvl)
@@@ -872,9 -858,10 +858,9 @@@ static int i2c_hid_fetch_hid_descriptor
  static int i2c_hid_acpi_pdata(struct i2c_client *client,
                struct i2c_hid_platform_data *pdata)
  {
 -      static u8 i2c_hid_guid[] = {
 -              0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
 -              0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
 -      };
 +      static guid_t i2c_hid_guid =
 +              GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
 +                        0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
        union acpi_object *obj;
        struct acpi_device *adev;
        acpi_handle handle;
        if (!handle || acpi_bus_get_device(handle, &adev))
                return -ENODEV;
  
 -      obj = acpi_evaluate_dsm_typed(handle, i2c_hid_guid, 1, 1, NULL,
 +      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");