Merge branches 'for-3.10/appleir', 'for-3.10/hid-debug', 'for-3.10/hid-driver-transpo...
[platform/kernel/linux-arm64.git] / drivers / hid / hid-core.c
index e7765ed..734b3d4 100644 (file)
@@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid)
                } else if (page == HID_UP_SENSOR &&
                        item.type == HID_ITEM_TYPE_MAIN &&
                        item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
-                       (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
-                       (hid->bus == BUS_USB || hid->bus == BUS_I2C))
+                       (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
                        hid->group = HID_GROUP_SENSOR_HUB;
        }
 
@@ -1265,7 +1264,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
        if (!hid)
                return -ENODEV;
 
-       if (down_trylock(&hid->driver_lock))
+       if (down_trylock(&hid->driver_input_lock))
                return -EBUSY;
 
        if (!hid->driver) {
@@ -1303,7 +1302,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
        ret = hid_report_raw_event(hid, type, data, size, interrupt);
 
 unlock:
-       up(&hid->driver_lock);
+       up(&hid->driver_input_lock);
        return ret;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
@@ -1481,8 +1480,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
@@ -1506,6 +1503,11 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
@@ -1824,6 +1826,11 @@ static int hid_device_probe(struct device *dev)
 
        if (down_interruptible(&hdev->driver_lock))
                return -EINTR;
+       if (down_interruptible(&hdev->driver_input_lock)) {
+               ret = -EINTR;
+               goto unlock_driver_lock;
+       }
+       hdev->io_started = false;
 
        if (!hdev->driver) {
                id = hid_match_device(hdev, hdrv);
@@ -1846,6 +1853,9 @@ static int hid_device_probe(struct device *dev)
                }
        }
 unlock:
+       if (!hdev->io_started)
+               up(&hdev->driver_input_lock);
+unlock_driver_lock:
        up(&hdev->driver_lock);
        return ret;
 }
@@ -1854,9 +1864,15 @@ static int hid_device_remove(struct device *dev)
 {
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        struct hid_driver *hdrv;
+       int ret = 0;
 
        if (down_interruptible(&hdev->driver_lock))
                return -EINTR;
+       if (down_interruptible(&hdev->driver_input_lock)) {
+               ret = -EINTR;
+               goto unlock_driver_lock;
+       }
+       hdev->io_started = false;
 
        hdrv = hdev->driver;
        if (hdrv) {
@@ -1868,8 +1884,11 @@ static int hid_device_remove(struct device *dev)
                hdev->driver = NULL;
        }
 
+       if (!hdev->io_started)
+               up(&hdev->driver_input_lock);
+unlock_driver_lock:
        up(&hdev->driver_lock);
-       return 0;
+       return ret;
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
@@ -2321,6 +2340,7 @@ struct hid_device *hid_allocate_device(void)
        INIT_LIST_HEAD(&hdev->debug_list);
        mutex_init(&hdev->debug_list_lock);
        sema_init(&hdev->driver_lock, 1);
+       sema_init(&hdev->driver_input_lock, 1);
 
        return hdev;
 }