Merge branch 'release' of master.kernel.org:/pub/scm/linux/kernel/git/lenb/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / usb / input / hid-core.c
index a6738a83ff5b109ecb1886961ddb0152e040d8f4..a49644b7c58e1492a19d21d533105254138f78f7 100644 (file)
@@ -270,7 +270,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
  * Read data value from item.
  */
 
-static __inline__ __u32 item_udata(struct hid_item *item)
+static u32 item_udata(struct hid_item *item)
 {
        switch (item->size) {
                case 1: return item->data.u8;
@@ -280,7 +280,7 @@ static __inline__ __u32 item_udata(struct hid_item *item)
        return 0;
 }
 
-static __inline__ __s32 item_sdata(struct hid_item *item)
+static s32 item_sdata(struct hid_item *item)
 {
        switch (item->size) {
                case 1: return item->data.s8;
@@ -727,7 +727,7 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
  * done by hand.
  */
 
-static __inline__ __s32 snto32(__u32 value, unsigned n)
+static s32 snto32(__u32 value, unsigned n)
 {
        switch (n) {
                case 8:  return ((__s8)value);
@@ -741,30 +741,65 @@ static __inline__ __s32 snto32(__u32 value, unsigned n)
  * Convert a signed 32-bit integer to a signed n-bit integer.
  */
 
-static __inline__ __u32 s32ton(__s32 value, unsigned n)
+static u32 s32ton(__s32 value, unsigned n)
 {
-       __s32 a = value >> (n - 1);
+       s32 a = value >> (n - 1);
        if (a && a != -1)
                return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
        return value & ((1 << n) - 1);
 }
 
 /*
- * Extract/implement a data field from/to a report.
+ * Extract/implement a data field from/to a little endian report (bit array).
+ *
+ * Code sort-of follows HID spec:
+ *     http://www.usb.org/developers/devclass_docs/HID1_11.pdf
+ *
+ * While the USB HID spec allows unlimited length bit fields in "report
+ * descriptors", most devices never use more than 16 bits.
+ * One model of UPS is claimed to report "LINEV" as a 32-bit field.
+ * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
  */
 
 static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
 {
-       report += (offset >> 5) << 2; offset &= 31;
-       return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1);
+       u64 x;
+
+       WARN_ON(n > 32);
+
+       report += offset >> 3;  /* adjust byte index */
+       offset &= 7;            /* now only need bit offset into one byte */
+       x = get_unaligned((u64 *) report);
+       x = le64_to_cpu(x);
+       x = (x >> offset) & ((1ULL << n) - 1);  /* extract bit field */
+       return (u32) x;
 }
 
+/*
+ * "implement" : set bits in a little endian bit stream.
+ * Same concepts as "extract" (see comments above).
+ * The data mangled in the bit stream remains in little endian
+ * order the whole time. It make more sense to talk about
+ * endianness of register values by considering a register
+ * a "cached" copy of the little endiad bit stream.
+ */
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
 {
-       report += (offset >> 5) << 2; offset &= 31;
-       put_unaligned((get_unaligned((__le64*)report)
-               & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
-               | cpu_to_le64((__u64)value << offset), (__le64*)report);
+       u64 x;
+       u64 m = (1ULL << n) - 1;
+
+       WARN_ON(n > 32);
+
+       WARN_ON(value > m);
+       value &= m;
+
+       report += offset >> 3;
+       offset &= 7;
+
+       x = get_unaligned((u64 *)report);
+       x &= cpu_to_le64(~(m << offset));
+       x |= cpu_to_le64(((u64) value) << offset);
+       put_unaligned(x, (u64 *) report);
 }
 
 /*
@@ -933,20 +968,29 @@ static void hid_retry_timeout(unsigned long _hid)
                hid_io_error(hid);
 }
 
-/* Workqueue routine to reset the device */
+/* Workqueue routine to reset the device or clear a halt */
 static void hid_reset(void *_hid)
 {
        struct hid_device *hid = (struct hid_device *) _hid;
-       int rc_lock, rc;
-
-       dev_dbg(&hid->intf->dev, "resetting device\n");
-       rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
-       if (rc_lock >= 0) {
-               rc = usb_reset_composite_device(hid->dev, hid->intf);
-               if (rc_lock)
-                       usb_unlock_device(hid->dev);
+       int rc_lock, rc = 0;
+
+       if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
+               dev_dbg(&hid->intf->dev, "clear halt\n");
+               rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
+               clear_bit(HID_CLEAR_HALT, &hid->iofl);
+               hid_start_in(hid);
+       }
+
+       else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
+               dev_dbg(&hid->intf->dev, "resetting device\n");
+               rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+               if (rc_lock >= 0) {
+                       rc = usb_reset_composite_device(hid->dev, hid->intf);
+                       if (rc_lock)
+                               usb_unlock_device(hid->dev);
+               }
+               clear_bit(HID_RESET_PENDING, &hid->iofl);
        }
-       clear_bit(HID_RESET_PENDING, &hid->iofl);
 
        switch (rc) {
        case 0:
@@ -988,9 +1032,8 @@ static void hid_io_error(struct hid_device *hid)
 
                /* Retries failed, so do a port reset */
                if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
-                       if (schedule_work(&hid->reset_work))
-                               goto done;
-                       clear_bit(HID_RESET_PENDING, &hid->iofl);
+                       schedule_work(&hid->reset_work);
+                       goto done;
                }
        }
 
@@ -1014,6 +1057,11 @@ static void hid_irq_in(struct urb *urb)
                        hid->retry_delay = 0;
                        hid_input_report(HID_INPUT_REPORT, urb, 1);
                        break;
+               case -EPIPE:            /* stall */
+                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+                       set_bit(HID_CLEAR_HALT, &hid->iofl);
+                       schedule_work(&hid->reset_work);
+                       return;
                case -ECONNRESET:       /* unlink */
                case -ENOENT:
                case -ESHUTDOWN:        /* unplug */
@@ -1381,6 +1429,9 @@ void hid_close(struct hid_device *hid)
 
 #define USB_VENDOR_ID_PANJIT           0x134c
 
+#define USB_VENDOR_ID_TURBOX           0x062a
+#define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
+
 /*
  * Initialize all reports
  */
@@ -1589,6 +1640,19 @@ void hid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_APPLE            0x05ac
 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE        0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI      0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO       0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI        0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI       0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO        0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS        0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI       0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO        0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS        0x021c
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
 
 #define USB_VENDOR_ID_CHERRY           0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
@@ -1602,6 +1666,9 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_SUN              0x0430
 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE       0xcdab
 
+#define USB_VENDOR_ID_AIRCABLE         0x16CA
+#define USB_DEVICE_ID_AIRCABLE1                0x1502
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1619,6 +1686,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
@@ -1752,22 +1820,27 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
 
-       { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
 
        { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
 
+       { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+       
        { 0, 0 }
 };
 
@@ -1940,7 +2013,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
                        interval = hid_mousepoll_interval;
 
-               if (endpoint->bEndpointAddress & USB_DIR_IN) {
+               if (usb_endpoint_dir_in(endpoint)) {
                        if (hid->urbin)
                                continue;
                        if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
@@ -2022,13 +2095,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        return hid;
 
 fail:
-
-       if (hid->urbin)
-               usb_free_urb(hid->urbin);
-       if (hid->urbout)
-               usb_free_urb(hid->urbout);
-       if (hid->urbctrl)
-               usb_free_urb(hid->urbctrl);
+       usb_free_urb(hid->urbin);
+       usb_free_urb(hid->urbout);
+       usb_free_urb(hid->urbctrl);
        hid_free_buffers(dev, hid);
        hid_free_device(hid);
 
@@ -2059,8 +2128,7 @@ static void hid_disconnect(struct usb_interface *intf)
 
        usb_free_urb(hid->urbin);
        usb_free_urb(hid->urbctrl);
-       if (hid->urbout)
-               usb_free_urb(hid->urbout);
+       usb_free_urb(hid->urbout);
 
        hid_free_buffers(hid->dev, hid);
        hid_free_device(hid);