Merge tag 'for-linus-3.11-merge-window-part-1' of git://git.kernel.org/pub/scm/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / hid / hid-wiimote-core.c
index ea00030defd62dc6a38c248f076de99a868bd16d..0c06054cab8f01033404f35375c0e12584db3c51 100644 (file)
@@ -452,6 +452,8 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
                return WIIMOTE_EXT_CLASSIC_CONTROLLER;
        if (rmem[4] == 0x04 && rmem[5] == 0x02)
                return WIIMOTE_EXT_BALANCE_BOARD;
+       if (rmem[4] == 0x01 && rmem[5] == 0x20)
+               return WIIMOTE_EXT_PRO_CONTROLLER;
 
        return WIIMOTE_EXT_UNKNOWN;
 }
@@ -601,6 +603,15 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = {
                WIIMOD_NO_MP,
                WIIMOD_NULL,
        },
+       [WIIMOTE_DEV_PRO_CONTROLLER] = (const __u8[]) {
+               WIIMOD_BATTERY,
+               WIIMOD_LED1,
+               WIIMOD_LED2,
+               WIIMOD_LED3,
+               WIIMOD_LED4,
+               WIIMOD_NO_MP,
+               WIIMOD_NULL,
+       },
 };
 
 static void wiimote_modules_load(struct wiimote_data *wdata,
@@ -785,6 +796,7 @@ static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = {
        [WIIMOTE_DEV_GEN10] = "Nintendo Wii Remote (Gen 1)",
        [WIIMOTE_DEV_GEN20] = "Nintendo Wii Remote Plus (Gen 2)",
        [WIIMOTE_DEV_BALANCE_BOARD] = "Nintendo Wii Balance Board",
+       [WIIMOTE_DEV_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
 };
 
 /* Try to guess the device type based on all collected information. We
@@ -805,6 +817,9 @@ static void wiimote_init_set_type(struct wiimote_data *wdata,
        if (exttype == WIIMOTE_EXT_BALANCE_BOARD) {
                devtype = WIIMOTE_DEV_BALANCE_BOARD;
                goto done;
+       } else if (exttype == WIIMOTE_EXT_PRO_CONTROLLER) {
+               devtype = WIIMOTE_DEV_PRO_CONTROLLER;
+               goto done;
        }
 
        if (!strcmp(name, "Nintendo RVL-CNT-01")) {
@@ -816,6 +831,9 @@ static void wiimote_init_set_type(struct wiimote_data *wdata,
        } else if (!strcmp(name, "Nintendo RVL-WBC-01")) {
                devtype = WIIMOTE_DEV_BALANCE_BOARD;
                goto done;
+       } else if (!strcmp(name, "Nintendo RVL-CNT-01-UC")) {
+               devtype = WIIMOTE_DEV_PRO_CONTROLLER;
+               goto done;
        }
 
        if (vendor == USB_VENDOR_ID_NINTENDO) {
@@ -1058,6 +1076,7 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
        [WIIMOTE_EXT_NUNCHUK] = "Nintendo Wii Nunchuk",
        [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller",
        [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
+       [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
 };
 
 /*
@@ -1276,11 +1295,19 @@ static bool valid_ext_handler(const struct wiimod_ops *ops, size_t len)
 static void handler_ext(struct wiimote_data *wdata, const __u8 *payload,
                        size_t len)
 {
+       static const __u8 invalid[21] = { 0xff, 0xff, 0xff, 0xff,
+                                         0xff, 0xff, 0xff, 0xff,
+                                         0xff, 0xff, 0xff, 0xff,
+                                         0xff, 0xff, 0xff, 0xff,
+                                         0xff, 0xff, 0xff, 0xff,
+                                         0xff };
        const __u8 *iter, *mods;
        const struct wiimod_ops *ops;
        bool is_mp;
 
-       if (len < 6)
+       if (len > 21)
+               len = 21;
+       if (len < 6 || !memcmp(payload, invalid, len))
                return;
 
        /* if MP is active, track MP slot hotplugging */
@@ -1634,6 +1661,8 @@ static ssize_t wiimote_ext_show(struct device *dev,
                return sprintf(buf, "classic\n");
        case WIIMOTE_EXT_BALANCE_BOARD:
                return sprintf(buf, "balanceboard\n");
+       case WIIMOTE_EXT_PRO_CONTROLLER:
+               return sprintf(buf, "procontroller\n");
        case WIIMOTE_EXT_UNKNOWN:
                /* fallthrough */
        default:
@@ -1680,6 +1709,8 @@ static ssize_t wiimote_dev_show(struct device *dev,
                return sprintf(buf, "gen20\n");
        case WIIMOTE_DEV_BALANCE_BOARD:
                return sprintf(buf, "balanceboard\n");
+       case WIIMOTE_DEV_PRO_CONTROLLER:
+               return sprintf(buf, "procontroller\n");
        case WIIMOTE_DEV_PENDING:
                return sprintf(buf, "pending\n");
        case WIIMOTE_DEV_UNKNOWN: