Merge branch 'for-3.15/hid-core-ll-transport-cleanup' into for-3.15/sony
[cascardo/linux.git] / drivers / hid / hid-sony.c
index 88401fc..908de27 100644 (file)
@@ -17,7 +17,8 @@
  * any later version.
  */
 
-/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
+/*
+ * NOTE: in order for the Sony PS3 BD Remote Control to be found by
  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
  *
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/leds.h>
 #include <linux/power_supply.h>
 #include <linux/spinlock.h>
+#include <linux/list.h>
 #include <linux/input/mt.h>
 
 #include "hid-ids.h"
 #define DUALSHOCK4_CONTROLLER_USB BIT(5)
 #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
 
-#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB)
-#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_USB)
+#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
+#define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
+                               DUALSHOCK4_CONTROLLER_BT)
+#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
+                               DUALSHOCK4_CONTROLLER)
+#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
+#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
 
 #define MAX_LEDS 4
 
@@ -77,7 +83,8 @@ static const u8 sixaxis_rdesc_fixup2[] = {
        0xb1, 0x02, 0xc0, 0xc0,
 };
 
-/* The default descriptor doesn't provide mapping for the accelerometers
+/*
+ * The default descriptor doesn't provide mapping for the accelerometers
  * or orientation sensors.  This fixed descriptor maps the accelerometers
  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
  * to usage values 0x43, 0x44 and 0x45.
@@ -336,7 +343,8 @@ static u8 dualshock4_usb_rdesc[] = {
        0xC0                /*  End Collection                      */
 };
 
-/* The default behavior of the Dualshock 4 is to send reports using report
+/*
+ * The default behavior of the Dualshock 4 is to send reports using report
  * type 1 when running over Bluetooth. However, as soon as it receives a
  * report of type 17 to set the LEDs or rumble it starts returning it's state
  * in report 17 instead of 1.  Since report 17 is undefined in the default HID
@@ -663,7 +671,8 @@ static const unsigned int ps3remote_keymap_remote_buttons[] = {
 };
 
 static const unsigned int buzz_keymap[] = {
-       /* The controller has 4 remote buzzers, each with one LED and 5
+       /*
+        * The controller has 4 remote buzzers, each with one LED and 5
         * buttons.
         * 
         * We use the mapping chosen by the controller, which is:
@@ -708,8 +717,12 @@ static enum power_supply_property sony_battery_props[] = {
        POWER_SUPPLY_PROP_STATUS,
 };
 
+static spinlock_t sony_dev_list_lock;
+static LIST_HEAD(sony_device_list);
+
 struct sony_sc {
        spinlock_t lock;
+       struct list_head list_node;
        struct hid_device *hdev;
        struct led_classdev *leds[MAX_LEDS];
        unsigned long quirks;
@@ -721,6 +734,8 @@ struct sony_sc {
        __u8 right;
 #endif
 
+       __u8 mac_address[6];
+       __u8 worker_initialized;
        __u8 cable_state;
        __u8 battery_charging;
        __u8 battery_capacity;
@@ -834,19 +849,21 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
        unsigned long flags;
        __u8 cable_state, battery_capacity, battery_charging;
 
-       /* The sixaxis is charging if the battery value is 0xee
+       /*
+        * The sixaxis is charging if the battery value is 0xee
         * and it is fully charged if the value is 0xef.
         * It does not report the actual level while charging so it
         * is set to 100% while charging is in progress.
         */
        if (rd[30] >= 0xee) {
                battery_capacity = 100;
-               battery_charging = rd[30] & 0x01;
+               battery_charging = !(rd[30] & 0x01);
        } else {
-               battery_capacity = sixaxis_battery_capacity[rd[30]];
+               __u8 index = rd[30] <= 5 ? rd[30] : 5;
+               battery_capacity = sixaxis_battery_capacity[index];
                battery_charging = 0;
        }
-       cable_state = (rd[31] >> 4) & 0x01;
+       cable_state = !(rd[31] & 0x04);
 
        spin_lock_irqsave(&sc->lock, flags);
        sc->cable_state = cable_state;
@@ -861,25 +878,37 @@ static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
                                                struct hid_input, list);
        struct input_dev *input_dev = hidinput->input;
        unsigned long flags;
-       int n, offset = 35;
+       int n, offset;
        __u8 cable_state, battery_capacity, battery_charging;
 
-       /* The lower 4 bits of byte 30 contain the battery level
+       /*
+        * Battery and touchpad data starts at byte 30 in the USB report and
+        * 32 in Bluetooth report.
+        */
+       offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
+
+       /*
+        * The lower 4 bits of byte 30 contain the battery level
         * and the 5th bit contains the USB cable state.
         */
-       cable_state = (rd[30] >> 4) & 0x01;
-       battery_capacity = rd[30] & 0x0F;
+       cable_state = (rd[offset] >> 4) & 0x01;
+       battery_capacity = rd[offset] & 0x0F;
 
-       /* On USB the Dualshock 4 battery level goes from 0 to 11.
-        * A battery level of 11 means fully charged.
+       /*
+        * When a USB power source is connected the battery level ranges from
+        * 0 to 10, and when running on battery power it ranges from 0 to 9.
+        * A battery level above 10 when plugged in means charge completed.
         */
-       if (cable_state && battery_capacity == 11)
+       if (!cable_state || battery_capacity > 10)
                battery_charging = 0;
        else
                battery_charging = 1;
 
+       if (!cable_state)
+               battery_capacity++;
        if (battery_capacity > 10)
-               battery_capacity--;
+               battery_capacity = 10;
+
        battery_capacity *= 10;
 
        spin_lock_irqsave(&sc->lock, flags);
@@ -888,7 +917,11 @@ static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
        sc->battery_charging = battery_charging;
        spin_unlock_irqrestore(&sc->lock, flags);
 
-       /* The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB.
+       offset += 5;
+
+       /*
+        * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
+        * and 37 on Bluetooth.
         * The first 7 bits of the first byte is a counter and bit 8 is a touch
         * indicator that is 0 when pressed and 1 when not pressed.
         * The next 3 bytes are two 12 bit touch coordinates, X and Y.
@@ -916,19 +949,20 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
 {
        struct sony_sc *sc = hid_get_drvdata(hdev);
 
-       /* Sixaxis HID report has acclerometers/gyro with MSByte first, this
+       /*
+        * Sixaxis HID report has acclerometers/gyro with MSByte first, this
         * has to be BYTE_SWAPPED before passing up to joystick interface
         */
-       if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
-                       rd[0] == 0x01 && size == 49) {
+       if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
                swap(rd[41], rd[42]);
                swap(rd[43], rd[44]);
                swap(rd[45], rd[46]);
                swap(rd[47], rd[48]);
 
                sixaxis_parse_report(sc, rd, size);
-       } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
-                       size == 64) {
+       } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
+                       size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
+                       && rd[0] == 0x11 && size == 78)) {
                dualshock4_parse_report(sc, rd, size);
        }
 
@@ -971,45 +1005,6 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
        return 0;
 }
 
-/*
- * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
- * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
- * so we need to override that forcing HID Output Reports on the Control EP.
- *
- * There is also another issue about HID Output Reports via USB, the Sixaxis
- * does not want the report_id as part of the data packet, so we have to
- * discard buf[0] when sending the actual control message, even for numbered
- * reports, humpf!
- */
-static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
-               size_t count, unsigned char report_type)
-{
-       struct usb_interface *intf = to_usb_interface(hid->dev.parent);
-       struct usb_device *dev = interface_to_usbdev(intf);
-       struct usb_host_interface *interface = intf->cur_altsetting;
-       int report_id = buf[0];
-       int ret;
-
-       if (report_type == HID_OUTPUT_REPORT) {
-               /* Don't send the Report ID */
-               buf++;
-               count--;
-       }
-
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-               HID_REQ_SET_REPORT,
-               USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-               ((report_type + 1) << 8) | report_id,
-               interface->desc.bInterfaceNumber, buf, count,
-               USB_CTRL_SET_TIMEOUT);
-
-       /* Count also the Report ID, in case of an Output report. */
-       if (ret > 0 && report_type == HID_OUTPUT_REPORT)
-               ret++;
-
-       return ret;
-}
-
 /*
  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
  * to "operational".  Without this, the ps3 controller will not report any
@@ -1037,8 +1032,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
 static int sixaxis_set_operational_bt(struct hid_device *hdev)
 {
        unsigned char buf[] = { 0xf4,  0x42, 0x03, 0x00, 0x00 };
-       return hid_output_raw_report(hdev, buf, sizeof(buf),
-                                    HID_FEATURE_REPORT);
+       return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+}
+
+/*
+ * Requesting feature report 0x02 in Bluetooth mode changes the state of the
+ * controller so that it sends full input reports of type 0x11.
+ */
+static int dualshock4_set_operational_bt(struct hid_device *hdev)
+{
+       __u8 buf[37] = { 0 };
+
+       return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf),
+                               HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 }
 
 static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds)
@@ -1068,8 +1075,7 @@ static void sony_set_leds(struct hid_device *hdev, const __u8 *leds, int count)
 
        if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) {
                buzz_set_leds(hdev, leds);
-       } else if ((drv_data->quirks & SIXAXIS_CONTROLLER_USB) ||
-                  (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB)) {
+       } else {
                for (n = 0; n < count; n++)
                        drv_data->led_state[n] = leds[n];
                schedule_work(&drv_data->state_worker);
@@ -1171,7 +1177,7 @@ static int sony_leds_init(struct hid_device *hdev)
                /* Validate expected report characteristics. */
                if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
                        return -ENODEV;
-       } else if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) {
+       } else if (drv_data->quirks & DUALSHOCK4_CONTROLLER) {
                drv_data->led_count = 3;
                max_brightness = 255;
                use_colors = 1;
@@ -1185,9 +1191,11 @@ static int sony_leds_init(struct hid_device *hdev)
                name_fmt = "%s::sony%d";
        }
 
-       /* Clear LEDs as we have no way of reading their initial state. This is
+       /*
+        * Clear LEDs as we have no way of reading their initial state. This is
         * only relevant if the driver is loaded after somebody actively set the
-        * LEDs to on */
+        * LEDs to on
+        */
        sony_set_leds(hdev, initial_values, drv_data->led_count);
 
        name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
@@ -1257,7 +1265,8 @@ static void sixaxis_state_worker(struct work_struct *work)
        buf[10] |= sc->led_state[2] << 3;
        buf[10] |= sc->led_state[3] << 4;
 
-       hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT);
+       hid_hw_raw_request(sc->hdev, 0x01, buf, sizeof(buf), HID_OUTPUT_REPORT,
+                       HID_REQ_SET_REPORT);
 }
 
 static void dualshock4_state_worker(struct work_struct *work)
@@ -1324,22 +1333,12 @@ static int sony_init_ff(struct hid_device *hdev)
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
 }
 
-static void sony_destroy_ff(struct hid_device *hdev)
-{
-       struct sony_sc *sc = hid_get_drvdata(hdev);
-
-       cancel_work_sync(&sc->state_worker);
-}
-
 #else
 static int sony_init_ff(struct hid_device *hdev)
 {
        return 0;
 }
 
-static void sony_destroy_ff(struct hid_device *hdev)
-{
-}
 #endif
 
 static int sony_battery_get_property(struct power_supply *psy,
@@ -1390,6 +1389,12 @@ static int sony_battery_probe(struct sony_sc *sc)
        struct hid_device *hdev = sc->hdev;
        int ret;
 
+       /*
+        * Set the default battery level to 100% to avoid low battery warnings
+        * if the battery is polled before the first device report is received.
+        */
+       sc->battery_capacity = 100;
+
        power_id = (unsigned long)atomic_inc_return(&power_id_seq);
 
        sc->battery.properties = sony_battery_props;
@@ -1447,6 +1452,133 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
        return 0;
 }
 
+/*
+ * If a controller is plugged in via USB while already connected via Bluetooth
+ * it will show up as two devices. A global list of connected controllers and
+ * their MAC addresses is maintained to ensure that a device is only connected
+ * once.
+ */
+static int sony_check_add_dev_list(struct sony_sc *sc)
+{
+       struct sony_sc *entry;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&sony_dev_list_lock, flags);
+
+       list_for_each_entry(entry, &sony_device_list, list_node) {
+               ret = memcmp(sc->mac_address, entry->mac_address,
+                               sizeof(sc->mac_address));
+               if (!ret) {
+                       ret = -EEXIST;
+                       hid_info(sc->hdev, "controller with MAC address %pMR already connected\n",
+                               sc->mac_address);
+                       goto unlock;
+               }
+       }
+
+       ret = 0;
+       list_add(&(sc->list_node), &sony_device_list);
+
+unlock:
+       spin_unlock_irqrestore(&sony_dev_list_lock, flags);
+       return ret;
+}
+
+static void sony_remove_dev_list(struct sony_sc *sc)
+{
+       unsigned long flags;
+
+       if (sc->list_node.next) {
+               spin_lock_irqsave(&sony_dev_list_lock, flags);
+               list_del(&(sc->list_node));
+               spin_unlock_irqrestore(&sony_dev_list_lock, flags);
+       }
+}
+
+static int sony_get_bt_devaddr(struct sony_sc *sc)
+{
+       int ret;
+
+       /* HIDP stores the device MAC address as a string in the uniq field. */
+       ret = strlen(sc->hdev->uniq);
+       if (ret != 17)
+               return -EINVAL;
+
+       ret = sscanf(sc->hdev->uniq,
+               "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+               &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
+               &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
+
+       if (ret != 6)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sony_check_add(struct sony_sc *sc)
+{
+       int n, ret;
+
+       if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
+           (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
+               /*
+                * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
+                * address from the uniq string where HIDP stores it.
+                * As uniq cannot be guaranteed to be a MAC address in all cases
+                * a failure of this function should not prevent the connection.
+                */
+               if (sony_get_bt_devaddr(sc) < 0) {
+                       hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
+                       return 0;
+               }
+       } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
+               __u8 buf[7];
+
+               /*
+                * The MAC address of a DS4 controller connected via USB can be
+                * retrieved with feature report 0x81. The address begins at
+                * offset 1.
+                */
+               ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf),
+                               HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+
+               if (ret != 7) {
+                       hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
+                       return ret < 0 ? ret : -EINVAL;
+               }
+
+               memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
+       } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
+               __u8 buf[18];
+
+               /*
+                * The MAC address of a Sixaxis controller connected via USB can
+                * be retrieved with feature report 0xf2. The address begins at
+                * offset 4.
+                */
+               ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf),
+                               HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+
+               if (ret != 18) {
+                       hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
+                       return ret < 0 ? ret : -EINVAL;
+               }
+
+               /*
+                * The Sixaxis device MAC in the report is big-endian and must
+                * be byte-swapped.
+                */
+               for (n = 0; n < 6; n++)
+                       sc->mac_address[5-n] = buf[4+n];
+       } else {
+               return 0;
+       }
+
+       return sony_check_add_dev_list(sc);
+}
+
+
 static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret;
@@ -1484,25 +1616,61 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
        }
 
        if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
-               hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
+               /*
+                * The Sony Sixaxis does not handle HID Output Reports on the
+                * Interrupt EP like it could, so we need to force HID Output
+                * Reports to use HID_REQ_SET_REPORT on the Control EP.
+                *
+                * There is also another issue about HID Output Reports via USB,
+                * the Sixaxis does not want the report_id as part of the data
+                * packet, so we have to discard buf[0] when sending the actual
+                * control message, even for numbered reports, humpf!
+                */
+               hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
+               hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
                ret = sixaxis_set_operational_usb(hdev);
+               sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, sixaxis_state_worker);
-       }
-       else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+       } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
+               /*
+                * The Sixaxis wants output reports sent on the ctrl endpoint
+                * when connected via Bluetooth.
+                */
+               hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
                ret = sixaxis_set_operational_bt(hdev);
-       else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
-               /* The Dualshock 4 touchpad supports 2 touches and has a
+               sc->worker_initialized = 1;
+               INIT_WORK(&sc->state_worker, sixaxis_state_worker);
+       } else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
+               if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
+                       /*
+                        * The DualShock 4 wants output reports sent on the ctrl
+                        * endpoint when connected via Bluetooth.
+                        */
+                       hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
+                       ret = dualshock4_set_operational_bt(hdev);
+                       if (ret < 0) {
+                               hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
+                               goto err_stop;
+                       }
+               }
+               /*
+                * The Dualshock 4 touchpad supports 2 touches and has a
                 * resolution of 1920x940.
                 */
                ret = sony_register_touchpad(sc, 2, 1920, 940);
                if (ret < 0)
                        goto err_stop;
 
+               sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, dualshock4_state_worker);
        } else {
                ret = 0;
        }
 
+       if (ret < 0)
+               goto err_stop;
+
+       ret = sony_check_add(sc);
        if (ret < 0)
                goto err_stop;
 
@@ -1525,9 +1693,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
                }
        }
 
-       ret = sony_init_ff(hdev);
-       if (ret < 0)
-               goto err_close;
+       if (sc->quirks & SONY_FF_SUPPORT) {
+               ret = sony_init_ff(hdev);
+               if (ret < 0)
+                       goto err_close;
+       }
 
        return 0;
 err_close:
@@ -1537,6 +1707,9 @@ err_stop:
                sony_leds_remove(hdev);
        if (sc->quirks & SONY_BATTERY_SUPPORT)
                sony_battery_remove(sc);
+       if (sc->worker_initialized)
+               cancel_work_sync(&sc->state_worker);
+       sony_remove_dev_list(sc);
        hid_hw_stop(hdev);
        return ret;
 }
@@ -1553,7 +1726,10 @@ static void sony_remove(struct hid_device *hdev)
                sony_battery_remove(sc);
        }
 
-       sony_destroy_ff(hdev);
+       if (sc->worker_initialized)
+               cancel_work_sync(&sc->state_worker);
+
+       sony_remove_dev_list(sc);
 
        hid_hw_stop(hdev);
 }