xref: /linux/drivers/hid/hid-sony.c (revision 2a2429327711558aa23fd73d770b6fd5e0d10de7)
1bd28ce00SJiri Slaby /*
2077147a3SFrank Praznik  *  HID driver for Sony / PS2 / PS3 / PS4 BD devices.
3bd28ce00SJiri Slaby  *
4bd28ce00SJiri Slaby  *  Copyright (c) 1999 Andreas Gal
5bd28ce00SJiri Slaby  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6bd28ce00SJiri Slaby  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7bd28ce00SJiri Slaby  *  Copyright (c) 2008 Jiri Slaby
8078328daSJiri Kosina  *  Copyright (c) 2012 David Dillow <dave@thedillows.org>
9078328daSJiri Kosina  *  Copyright (c) 2006-2013 Jiri Kosina
10f04d5140SColin Leitner  *  Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
11077147a3SFrank Praznik  *  Copyright (c) 2014 Frank Praznik <frank.praznik@gmail.com>
12bd28ce00SJiri Slaby  */
13bd28ce00SJiri Slaby 
14bd28ce00SJiri Slaby /*
15bd28ce00SJiri Slaby  * This program is free software; you can redistribute it and/or modify it
16bd28ce00SJiri Slaby  * under the terms of the GNU General Public License as published by the Free
17bd28ce00SJiri Slaby  * Software Foundation; either version 2 of the License, or (at your option)
18bd28ce00SJiri Slaby  * any later version.
19bd28ce00SJiri Slaby  */
20bd28ce00SJiri Slaby 
21ad142b9eSFrank Praznik /*
22ad142b9eSFrank Praznik  * NOTE: in order for the Sony PS3 BD Remote Control to be found by
23078328daSJiri Kosina  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
24078328daSJiri Kosina  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
25078328daSJiri Kosina  *
26078328daSJiri Kosina  * There will be no PIN request from the device.
27078328daSJiri Kosina  */
28078328daSJiri Kosina 
29bd28ce00SJiri Slaby #include <linux/device.h>
30bd28ce00SJiri Slaby #include <linux/hid.h>
31bd28ce00SJiri Slaby #include <linux/module.h>
325a0e3ad6STejun Heo #include <linux/slab.h>
3340e32ee6SJiri Kosina #include <linux/leds.h>
34d902f472SFrank Praznik #include <linux/power_supply.h>
35d902f472SFrank Praznik #include <linux/spinlock.h>
36d2d782fcSFrank Praznik #include <linux/list.h>
378025087aSFrank Praznik #include <linux/idr.h>
38e5606230SFrank Praznik #include <linux/input/mt.h>
39bd28ce00SJiri Slaby 
40bd28ce00SJiri Slaby #include "hid-ids.h"
41bd28ce00SJiri Slaby 
42f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT       BIT(0)
43f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB    BIT(1)
44f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT     BIT(2)
45f1c458caSSven Eckelmann #define BUZZ_CONTROLLER           BIT(3)
46f1c458caSSven Eckelmann #define PS3REMOTE                 BIT(4)
478ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5)
488ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
49b3bca326SSimon Wood #define MOTION_CONTROLLER_USB     BIT(7)
50b3bca326SSimon Wood #define MOTION_CONTROLLER_BT      BIT(8)
514545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9)
524545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT  BIT(10)
5374500cc8SScott Moreau #define SINO_LITE_CONTROLLER      BIT(11)
54cc6e0bbbSJiri Kosina 
55fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
56b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
574545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\
584545ee0aSSimon Wood 				NAVIGATION_CONTROLLER_BT)
5968330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
6068330d83SFrank Praznik 				DUALSHOCK4_CONTROLLER_BT)
61fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
624545ee0aSSimon Wood 				DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
634545ee0aSSimon Wood 				NAVIGATION_CONTROLLER)
6412e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
654545ee0aSSimon Wood 				MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
66c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
67c5e0c1c4SFrank Praznik 				MOTION_CONTROLLER)
680f398230SFrank Praznik #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\
690f398230SFrank Praznik 			MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT)
7060781cf4SFrank Praznik 
7160781cf4SFrank Praznik #define MAX_LEDS 4
720a286ef2SSven Eckelmann 
734c3e8298SFrank Praznik /*
744c3e8298SFrank Praznik  * The Sixaxis reports both digital and analog values for each button on the
754c3e8298SFrank Praznik  * controller except for Start, Select and the PS button.  The controller ends
764c3e8298SFrank Praznik  * up reporting 27 axes which causes them to spill over into the multi-touch
774c3e8298SFrank Praznik  * axis values.  Additionally, the controller only has 20 actual, physical axes
784c3e8298SFrank Praznik  * so there are several unused axes in between the used ones.
794c3e8298SFrank Praznik  */
801adf904eSPavel Machek static u8 sixaxis_rdesc[] = {
81fb705a6dSAntonio Ospite 	0x05, 0x01,         /*  Usage Page (Desktop),               */
824c3e8298SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
83fb705a6dSAntonio Ospite 	0xA1, 0x01,         /*  Collection (Application),           */
84fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
85fb705a6dSAntonio Ospite 	0x85, 0x01,         /*          Report ID (1),              */
86fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
87fb705a6dSAntonio Ospite 	0x95, 0x01,         /*          Report Count (1),           */
88fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
89fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
90fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
91fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
92fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
93fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
94fb705a6dSAntonio Ospite 	0x25, 0x01,         /*          Logical Maximum (1),        */
95fb705a6dSAntonio Ospite 	0x35, 0x00,         /*          Physical Minimum (0),       */
96fb705a6dSAntonio Ospite 	0x45, 0x01,         /*          Physical Maximum (1),       */
97fb705a6dSAntonio Ospite 	0x05, 0x09,         /*          Usage Page (Button),        */
98fb705a6dSAntonio Ospite 	0x19, 0x01,         /*          Usage Minimum (01h),        */
99fb705a6dSAntonio Ospite 	0x29, 0x13,         /*          Usage Maximum (13h),        */
100fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
101fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
102fb705a6dSAntonio Ospite 	0x95, 0x0D,         /*          Report Count (13),          */
103fb705a6dSAntonio Ospite 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
104fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
105fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
106fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
107fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
108fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
109fb705a6dSAntonio Ospite 	0xA1, 0x00,         /*          Collection (Physical),      */
110fb705a6dSAntonio Ospite 	0x75, 0x08,         /*              Report Size (8),        */
111fb705a6dSAntonio Ospite 	0x95, 0x04,         /*              Report Count (4),       */
112fb705a6dSAntonio Ospite 	0x35, 0x00,         /*              Physical Minimum (0),   */
113fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
114fb705a6dSAntonio Ospite 	0x09, 0x30,         /*              Usage (X),              */
115fb705a6dSAntonio Ospite 	0x09, 0x31,         /*              Usage (Y),              */
116fb705a6dSAntonio Ospite 	0x09, 0x32,         /*              Usage (Z),              */
117fb705a6dSAntonio Ospite 	0x09, 0x35,         /*              Usage (Rz),             */
118fb705a6dSAntonio Ospite 	0x81, 0x02,         /*              Input (Variable),       */
119fb705a6dSAntonio Ospite 	0xC0,               /*          End Collection,             */
120fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
121fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
122fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
123fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
124fb705a6dSAntonio Ospite 	0x95, 0x0C,         /*          Report Count (12),          */
125fb705a6dSAntonio Ospite 	0x81, 0x01,         /*          Input (Constant),           */
126fb705a6dSAntonio Ospite 	0x75, 0x10,         /*          Report Size (16),           */
127fb705a6dSAntonio Ospite 	0x95, 0x04,         /*          Report Count (4),           */
128fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
129fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
130fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
131fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
132fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
133fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
134fb705a6dSAntonio Ospite 	0x85, 0x02,         /*          Report ID (2),              */
135fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
136fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
137fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
138fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
139fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
140fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
141fb705a6dSAntonio Ospite 	0x85, 0xEE,         /*          Report ID (238),            */
142fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
143fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
144fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
145fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
146fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
147fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
148fb705a6dSAntonio Ospite 	0x85, 0xEF,         /*          Report ID (239),            */
149fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
150fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
151fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
152fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
153fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
154fb705a6dSAntonio Ospite 	0xC0                /*  End Collection                      */
155e57a67daSMauro Carvalho Chehab };
156e57a67daSMauro Carvalho Chehab 
157c5e0c1c4SFrank Praznik /* PS/3 Motion controller */
1581adf904eSPavel Machek static u8 motion_rdesc[] = {
159c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
160c5e0c1c4SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
161c5e0c1c4SFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
162c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
163c5e0c1c4SFrank Praznik 	0x85, 0x01,         /*          Report ID (1),              */
164c5e0c1c4SFrank Praznik 	0x75, 0x01,         /*          Report Size (1),            */
1658b2513c3SSimon Wood 	0x95, 0x15,         /*          Report Count (21),          */
166c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
167c5e0c1c4SFrank Praznik 	0x25, 0x01,         /*          Logical Maximum (1),        */
168c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*          Physical Minimum (0),       */
169c5e0c1c4SFrank Praznik 	0x45, 0x01,         /*          Physical Maximum (1),       */
170c5e0c1c4SFrank Praznik 	0x05, 0x09,         /*          Usage Page (Button),        */
171c5e0c1c4SFrank Praznik 	0x19, 0x01,         /*          Usage Minimum (01h),        */
1728b2513c3SSimon Wood 	0x29, 0x15,         /*          Usage Maximum (15h),        */
1738b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           * Buttons */
1748b2513c3SSimon Wood 	0x95, 0x0B,         /*          Report Count (11),          */
175c5e0c1c4SFrank Praznik 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1768b2513c3SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), * Padding */
177c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
178c5e0c1c4SFrank Praznik 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
179c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
180c5e0c1c4SFrank Praznik 	0xA1, 0x00,         /*          Collection (Physical),      */
181c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*              Report Size (8),        */
1828b2513c3SSimon Wood 	0x95, 0x01,         /*              Report Count (1),       */
183c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*              Physical Minimum (0),   */
184c5e0c1c4SFrank Praznik 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
185c5e0c1c4SFrank Praznik 	0x09, 0x30,         /*              Usage (X),              */
1868b2513c3SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       * Trigger */
187c5e0c1c4SFrank Praznik 	0xC0,               /*          End Collection,             */
1888b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1898b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
1908b2513c3SSimon Wood 	0x95, 0x07,         /*          Report Count (7),           * skip 7 bytes */
1918b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
192c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
193c5e0c1c4SFrank Praznik 	0x75, 0x10,         /*          Report Size (16),           */
1948b2513c3SSimon Wood 	0x46, 0xFF, 0xFF,   /*          Physical Maximum (65535),   */
1958b2513c3SSimon Wood 	0x27, 0xFF, 0xFF, 0x00, 0x00, /*      Logical Maximum (65535),    */
1968b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Accels */
1978b2513c3SSimon Wood 	0x09, 0x33,         /*              Usage (rX),             */
1988b2513c3SSimon Wood 	0x09, 0x34,         /*              Usage (rY),             */
1998b2513c3SSimon Wood 	0x09, 0x35,         /*              Usage (rZ),             */
200c5e0c1c4SFrank Praznik 	0x81, 0x02,         /*          Input (Variable),           */
2018b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2028b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Accels 2nd frame */
2038b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2048b2513c3SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
2058b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2068b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Gyros */
2078b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2088b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2098b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Gyros 2nd frame */
2108b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2118b2513c3SSimon Wood 	0x75, 0x0C,         /*          Report Size (12),           */
2128b2513c3SSimon Wood 	0x46, 0xFF, 0x0F,   /*          Physical Maximum (4095),    */
2138b2513c3SSimon Wood 	0x26, 0xFF, 0x0F,   /*          Logical Maximum (4095),     */
2148b2513c3SSimon Wood 	0x95, 0x04,         /*          Report Count (4),           * Skip Temp and Magnetometers */
2158b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2168b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2178b2513c3SSimon Wood 	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
2188b2513c3SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
2198b2513c3SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           * Skip Timestamp and Extension Bytes */
2208b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2218b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2228b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2238b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2248b2513c3SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
2258b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2268b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2278b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2288b2513c3SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
229c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
230c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
231c5e0c1c4SFrank Praznik 	0x85, 0x02,         /*          Report ID (2),              */
232c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
233c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
234c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
235c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
236c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
237c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
238c5e0c1c4SFrank Praznik 	0x85, 0xEE,         /*          Report ID (238),            */
239c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
240c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
241c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
242c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
243c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
244c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
245c5e0c1c4SFrank Praznik 	0x85, 0xEF,         /*          Report ID (239),            */
246c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
247c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
248c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
249c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
250c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
251c5e0c1c4SFrank Praznik 	0xC0                /*  End Collection                      */
252c5e0c1c4SFrank Praznik };
253c5e0c1c4SFrank Praznik 
254b2723eb7SSimon Wood /* PS/3 Navigation controller */
2551adf904eSPavel Machek static u8 navigation_rdesc[] = {
256b2723eb7SSimon Wood 	0x05, 0x01,         /*  Usage Page (Desktop),               */
257d542176fSAntonio Ospite 	0x09, 0x04,         /*  Usage (Joystick),                   */
258b2723eb7SSimon Wood 	0xA1, 0x01,         /*  Collection (Application),           */
259b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
260b2723eb7SSimon Wood 	0x85, 0x01,         /*          Report ID (1),              */
261b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
262b2723eb7SSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
263b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
264b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
265b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
266b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
267b2723eb7SSimon Wood 	0x95, 0x13,         /*          Report Count (19),          */
268b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
269b2723eb7SSimon Wood 	0x25, 0x01,         /*          Logical Maximum (1),        */
270b2723eb7SSimon Wood 	0x35, 0x00,         /*          Physical Minimum (0),       */
271b2723eb7SSimon Wood 	0x45, 0x01,         /*          Physical Maximum (1),       */
272b2723eb7SSimon Wood 	0x05, 0x09,         /*          Usage Page (Button),        */
273b2723eb7SSimon Wood 	0x19, 0x01,         /*          Usage Minimum (01h),        */
274b2723eb7SSimon Wood 	0x29, 0x13,         /*          Usage Maximum (13h),        */
275b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
276b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
277b2723eb7SSimon Wood 	0x95, 0x0D,         /*          Report Count (13),          */
278b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
279b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
280b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
281b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
282b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
283b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
284b2723eb7SSimon Wood 	0xA1, 0x00,         /*          Collection (Physical),      */
285b2723eb7SSimon Wood 	0x75, 0x08,         /*              Report Size (8),        */
286b2723eb7SSimon Wood 	0x95, 0x02,         /*              Report Count (2),       */
287b2723eb7SSimon Wood 	0x35, 0x00,         /*              Physical Minimum (0),   */
288b2723eb7SSimon Wood 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
289b2723eb7SSimon Wood 	0x09, 0x30,         /*              Usage (X),              */
290b2723eb7SSimon Wood 	0x09, 0x31,         /*              Usage (Y),              */
291b2723eb7SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       */
292b2723eb7SSimon Wood 	0xC0,               /*          End Collection,             */
293b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
294b2723eb7SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           */
295b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
296b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
297b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
298b2723eb7SSimon Wood 	0x95, 0x05,         /*          Report Count (5),           */
299b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
300b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
301b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3022259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3032259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3042259b5bbSSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
3052259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3062259b5bbSSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
3072259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3082259b5bbSSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3092259b5bbSSimon Wood 	0x95, 0x1E,         /*          Report Count (24),          */
310b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
311b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
312b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
313b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
314b2723eb7SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
315b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
316b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
317b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
318b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
319b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
320b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
321b2723eb7SSimon Wood 	0x85, 0x02,         /*          Report ID (2),              */
322b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
323b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
324b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
325b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
326b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
327b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
328b2723eb7SSimon Wood 	0x85, 0xEE,         /*          Report ID (238),            */
329b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
330b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
331b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
332b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
333b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
334b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
335b2723eb7SSimon Wood 	0x85, 0xEF,         /*          Report ID (239),            */
336b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
337b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
338b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
339b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
340b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
341b2723eb7SSimon Wood 	0xC0                /*  End Collection                      */
342b2723eb7SSimon Wood };
343c5e0c1c4SFrank Praznik 
344ad142b9eSFrank Praznik /*
345ad142b9eSFrank Praznik  * The default descriptor doesn't provide mapping for the accelerometers
34658d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
34758d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
34858d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
34958d7027bSFrank Praznik  */
350ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
35158d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
35258d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
35358d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
35458d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
35558d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
35658d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
35758d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
35858d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
35958d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36058d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
36158d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
36258d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
36358d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
36458d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
36558d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36658d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
36758d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
36858d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
36958d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
37058d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
37158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
37258d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
37358d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
37458d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
37558d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
37658d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
37758d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
37858d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
37958d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
38058d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
38158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
38258d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
38358d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
38458d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
38558d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
38658d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
387fb291cbdSFrank Praznik 	0x25, 0x3F,         /*      Logical Maximum (63),           */
38858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
38958d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
39058d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
39158d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
39258d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
39358d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
39458d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
39558d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
39658d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39758d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
39858d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
39958d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40058d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40158d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
40258d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
40358d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
40458d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
40558d7027bSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
40658d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
40758d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40958d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
41058d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
411fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
412fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
41358d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
41458d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41558d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
41658d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
41758d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
418fb291cbdSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
41958d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
42058d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
42158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
42258d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
42358d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
42458d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
42558d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
42658d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
42758d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
42858d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
42958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43058d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
43158d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
43258d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
43358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43458d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
43558d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
43658d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
43758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43858d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
43958d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
44058d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
44158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44258d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
44358d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
44458d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
44558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44658d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
44758d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
44858d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
44958d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
45058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45158d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
45258d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
45358d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
45458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45558d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
45658d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
45758d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
45858d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
45958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46058d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
46158d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
46258d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
46358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46458d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
46558d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
46658d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
46758d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
46858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46958d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
47058d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
47158d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
47258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47358d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
47458d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
47558d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
47658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47758d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
47858d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
47958d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
48058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48158d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
48258d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
48358d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
48458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48558d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
48658d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
48758d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
48858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48958d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
49058d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
49158d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
49258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49358d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
49458d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
49558d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
49658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49758d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
49858d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
49958d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
50058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50158d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
50258d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
50358d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
50458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50558d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
50658d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
50758d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
50858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50958d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
51058d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
51158d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51358d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
51458d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
51558d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51758d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
51858d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
51958d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
52058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52158d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
52258d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
52358d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
52458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52558d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
52658d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
52758d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
52858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52958d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
53058d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
53158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
53258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53358d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
53458d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
53558d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
53658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53758d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
53858d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
53958d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
54058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54158d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
54258d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
54358d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54558d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
54658d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
54758d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54958d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
55058d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
55158d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55358d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
55458d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
55558d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55758d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
55858d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
55958d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
56058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56158d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
56258d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
56358d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56558d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
56658d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
56758d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56958d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
57058d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
57158d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
57258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57358d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
57458d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
57558d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
57658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57758d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
57858d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
57958d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58158d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
58258d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
58358d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58558d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
58658d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
58758d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
58858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58958d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
59058d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
59158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
59258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59358d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
59458d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
59558d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
59658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59758d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
59858d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
59958d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
60058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
60158d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
602ed19d8cfSFrank Praznik };
603ed19d8cfSFrank Praznik 
604ad142b9eSFrank Praznik /*
605ad142b9eSFrank Praznik  * The default behavior of the Dualshock 4 is to send reports using report
606077147a3SFrank Praznik  * type 1 when running over Bluetooth. However, when feature report 2 is
607077147a3SFrank Praznik  * requested during the controller initialization it starts sending input
608077147a3SFrank Praznik  * reports in report 17.  Since report 17 is undefined in the default HID
609d829674dSFrank Praznik  * descriptor the button and axis definitions must be moved to report 17 or
610077147a3SFrank Praznik  * the HID layer won't process the received input.
611d829674dSFrank Praznik  */
612d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = {
613d829674dSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
614d829674dSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
615d829674dSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
616d829674dSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
617d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
618d829674dSFrank Praznik 	0x95, 0x0A,         /*      Report Count (9),               */
619d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
620d829674dSFrank Praznik 	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
621d829674dSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
622d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
623d829674dSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
624d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
625d829674dSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
626d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
627d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
628d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
629d829674dSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
630d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
631d829674dSFrank Praznik 	0x95, 0x28,         /*      Report Count (40),              */
632d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
633d829674dSFrank Praznik 	0x85, 0x06,         /*      Report ID (6),                  */
634d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
635d829674dSFrank Praznik 	0x95, 0x34,         /*      Report Count (52),              */
636d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
637d829674dSFrank Praznik 	0x85, 0x07,         /*      Report ID (7),                  */
638d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
639d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
640d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
641d829674dSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
642d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
643d829674dSFrank Praznik 	0x95, 0x2F,         /*      Report Count (47),              */
644d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
645d829674dSFrank Praznik 	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
646d829674dSFrank Praznik 	0x85, 0x03,         /*      Report ID (3),                  */
647d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
648d829674dSFrank Praznik 	0x95, 0x26,         /*      Report Count (38),              */
649d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
650d829674dSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
651d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
652d829674dSFrank Praznik 	0x95, 0x2E,         /*      Report Count (46),              */
653d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
654d829674dSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
655d829674dSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
656d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
657d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
658d829674dSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
659d829674dSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
660d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
661d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
662d829674dSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
663d829674dSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
664d829674dSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
665d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
666d829674dSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
667d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
668d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
669d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
670d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
671d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
672d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
673d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
674d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
675d829674dSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
676d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
677d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
678d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
679d829674dSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
680d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
681d829674dSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
682d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
683d829674dSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
684d829674dSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
685d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
686d829674dSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
687d829674dSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
688d829674dSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
689d829674dSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
690d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
691d829674dSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
692d829674dSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
693d829674dSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
694d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
695d829674dSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
696d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
697d829674dSFrank Praznik 	0x81, 0x01,         /*      Input (Constant),               */
698d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
699d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
700d829674dSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
701d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
702d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
703d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
704d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
705d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
706d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
707d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
708d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
709d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
710d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
711d829674dSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
712d829674dSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
713d829674dSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
714d829674dSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
715d829674dSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
716d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
717d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
718d829674dSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
719d829674dSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
720fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
721fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
722d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
723d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
724d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
725d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
726d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
727d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
728d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
729d829674dSFrank Praznik 	0x95, 0x31,         /*      Report Count (51),              */
730d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
731d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
732d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
733d829674dSFrank Praznik 	0x95, 0x4D,         /*      Report Count (77),              */
734d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
735d829674dSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
736d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
737d829674dSFrank Praznik 	0x95, 0x8D,         /*      Report Count (141),             */
738d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
739d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
740d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
741d829674dSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
742d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
743d829674dSFrank Praznik 	0x95, 0xCD,         /*      Report Count (205),             */
744d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
745d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
746d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
747d829674dSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
748d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
749d829674dSFrank Praznik 	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
750d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
751d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
752d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
753d829674dSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
754d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
755d829674dSFrank Praznik 	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
756d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
757d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
758d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
759d829674dSFrank Praznik 	0x85, 0x16,         /*      Report ID (22),                 */
760d829674dSFrank Praznik 	0x09, 0x2A,         /*      Usage (2Ah),                    */
761d829674dSFrank Praznik 	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
762d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
763d829674dSFrank Praznik 	0x09, 0x2B,         /*      Usage (2Bh),                    */
764d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
765d829674dSFrank Praznik 	0x85, 0x17,         /*      Report ID (23),                 */
766d829674dSFrank Praznik 	0x09, 0x2C,         /*      Usage (2Ch),                    */
767d829674dSFrank Praznik 	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
768d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
769d829674dSFrank Praznik 	0x09, 0x2D,         /*      Usage (2Dh),                    */
770d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
771d829674dSFrank Praznik 	0x85, 0x18,         /*      Report ID (24),                 */
772d829674dSFrank Praznik 	0x09, 0x2E,         /*      Usage (2Eh),                    */
773d829674dSFrank Praznik 	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
774d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
775d829674dSFrank Praznik 	0x09, 0x2F,         /*      Usage (2Fh),                    */
776d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
777d829674dSFrank Praznik 	0x85, 0x19,         /*      Report ID (25),                 */
778d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
779d829674dSFrank Praznik 	0x96, 0x22, 0x02,   /*      Report Count (546),             */
780d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
781d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
782d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
783d829674dSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
784d829674dSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
785d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
786d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
787d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
788d829674dSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
789d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
790d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
791d829674dSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
792d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
793d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
794d829674dSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
795d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
796d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
797d829674dSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
798d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
799d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
800d829674dSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
801d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
802d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
803d829674dSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
804d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
805d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
806d829674dSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
807d829674dSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
808d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
809d829674dSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
810d829674dSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
811d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
812d829674dSFrank Praznik 	0xC0                /*  End Collection                      */
813d829674dSFrank Praznik };
814d829674dSFrank Praznik 
8151adf904eSPavel Machek static u8 ps3remote_rdesc[] = {
816078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
817078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
818078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
819078328daSJiri Kosina 
820078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
821078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
822078328daSJiri Kosina 
823ef916ef5SAntonio Ospite 	  /*
824ef916ef5SAntonio Ospite 	   * Ignore the 1st byte, maybe it is used for a controller
825ef916ef5SAntonio Ospite 	   * number but it's not needed for correct operation
826ef916ef5SAntonio Ospite 	   */
827078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
828078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
829078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
830078328daSJiri Kosina 
831ef916ef5SAntonio Ospite 	  /*
832ef916ef5SAntonio Ospite 	   * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
833ef916ef5SAntonio Ospite 	   * buttons multiple keypresses are allowed
834ef916ef5SAntonio Ospite 	   */
835078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
836078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
837078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
838078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
839078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
840078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
841078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
842078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
843078328daSJiri Kosina 
844078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
845078328daSJiri Kosina 
846078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
847078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
848078328daSJiri Kosina 
849078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
850078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
851078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
852078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
853078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
854078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
855078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
856078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
857078328daSJiri Kosina 	  0x80,              /* MInput  */
858078328daSJiri Kosina 
859ef916ef5SAntonio Ospite 	  /*
860ef916ef5SAntonio Ospite 	   * Ignore bytes from 6th to 11th, 6th to 10th are always constant at
861ef916ef5SAntonio Ospite 	   * 0xff and 11th is for press indication
862ef916ef5SAntonio Ospite 	   */
863078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
864078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
865078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
866078328daSJiri Kosina 
867078328daSJiri Kosina 	  /* 12th byte is for battery strength */
868078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
869078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
870078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
871078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
872078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
873078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
874078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
875078328daSJiri Kosina 
876078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
877078328daSJiri Kosina 
878078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
879078328daSJiri Kosina };
880078328daSJiri Kosina 
881078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
882078328daSJiri Kosina 	[0x01] = KEY_SELECT,
883078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
884078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
885078328daSJiri Kosina 	[0x04] = BTN_START,
886078328daSJiri Kosina 	[0x05] = KEY_UP,
887078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
888078328daSJiri Kosina 	[0x07] = KEY_DOWN,
889078328daSJiri Kosina 	[0x08] = KEY_LEFT,
890078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
891078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
892078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
893078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
894078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
895078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
896078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
897078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
898078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
899078328daSJiri Kosina 	[0x14] = KEY_ENTER,
900078328daSJiri Kosina };
901078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
902078328daSJiri Kosina 	[0x00] = KEY_1,
903078328daSJiri Kosina 	[0x01] = KEY_2,
904078328daSJiri Kosina 	[0x02] = KEY_3,
905078328daSJiri Kosina 	[0x03] = KEY_4,
906078328daSJiri Kosina 	[0x04] = KEY_5,
907078328daSJiri Kosina 	[0x05] = KEY_6,
908078328daSJiri Kosina 	[0x06] = KEY_7,
909078328daSJiri Kosina 	[0x07] = KEY_8,
910078328daSJiri Kosina 	[0x08] = KEY_9,
911078328daSJiri Kosina 	[0x09] = KEY_0,
912078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
913078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
914078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
915078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
916078328daSJiri Kosina 	[0x28] = KEY_TIME,
917078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
918078328daSJiri Kosina 	[0x31] = KEY_NEXT,
919078328daSJiri Kosina 	[0x32] = KEY_PLAY,
920078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
921078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
922078328daSJiri Kosina 	[0x38] = KEY_STOP,
923078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
924078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
925078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
926078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
927078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
928078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
929078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
930078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
931078328daSJiri Kosina 	[0x80] = KEY_BLUE,
932078328daSJiri Kosina 	[0x81] = KEY_RED,
933078328daSJiri Kosina 	[0x82] = KEY_GREEN,
934078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
935078328daSJiri Kosina };
936078328daSJiri Kosina 
937f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
938ad142b9eSFrank Praznik 	/*
939ad142b9eSFrank Praznik 	 * The controller has 4 remote buzzers, each with one LED and 5
940f04d5140SColin Leitner 	 * buttons.
941f04d5140SColin Leitner 	 *
942f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
943f04d5140SColin Leitner 	 *
944f04d5140SColin Leitner 	 * Key          Offset
945f04d5140SColin Leitner 	 * -------------------
946f04d5140SColin Leitner 	 * Buzz              1
947f04d5140SColin Leitner 	 * Blue              5
948f04d5140SColin Leitner 	 * Orange            4
949f04d5140SColin Leitner 	 * Green             3
950f04d5140SColin Leitner 	 * Yellow            2
951f04d5140SColin Leitner 	 *
952f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
953f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
954f04d5140SColin Leitner 	 */
955f04d5140SColin Leitner 	 [1] = BTN_TRIGGER_HAPPY1,
956f04d5140SColin Leitner 	 [2] = BTN_TRIGGER_HAPPY2,
957f04d5140SColin Leitner 	 [3] = BTN_TRIGGER_HAPPY3,
958f04d5140SColin Leitner 	 [4] = BTN_TRIGGER_HAPPY4,
959f04d5140SColin Leitner 	 [5] = BTN_TRIGGER_HAPPY5,
960f04d5140SColin Leitner 	 [6] = BTN_TRIGGER_HAPPY6,
961f04d5140SColin Leitner 	 [7] = BTN_TRIGGER_HAPPY7,
962f04d5140SColin Leitner 	 [8] = BTN_TRIGGER_HAPPY8,
963f04d5140SColin Leitner 	 [9] = BTN_TRIGGER_HAPPY9,
964f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
965f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
966f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
967f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
968f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
969f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
970f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
971f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
972f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
973f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
974f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
975f04d5140SColin Leitner };
976f04d5140SColin Leitner 
977d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
978d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
979d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
980d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
981d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
982d902f472SFrank Praznik };
983d902f472SFrank Praznik 
98455d3b664SFrank Praznik struct sixaxis_led {
9851adf904eSPavel Machek 	u8 time_enabled; /* the total time the led is active (0xff means forever) */
9861adf904eSPavel Machek 	u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
9871adf904eSPavel Machek 	u8 enabled;
9881adf904eSPavel Machek 	u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
9891adf904eSPavel Machek 	u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
99055d3b664SFrank Praznik } __packed;
99155d3b664SFrank Praznik 
99255d3b664SFrank Praznik struct sixaxis_rumble {
9931adf904eSPavel Machek 	u8 padding;
9941adf904eSPavel Machek 	u8 right_duration; /* Right motor duration (0xff means forever) */
9951adf904eSPavel Machek 	u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
9961adf904eSPavel Machek 	u8 left_duration;    /* Left motor duration (0xff means forever) */
9971adf904eSPavel Machek 	u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
99855d3b664SFrank Praznik } __packed;
99955d3b664SFrank Praznik 
100055d3b664SFrank Praznik struct sixaxis_output_report {
10011adf904eSPavel Machek 	u8 report_id;
100255d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
10031adf904eSPavel Machek 	u8 padding[4];
10041adf904eSPavel Machek 	u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
100555d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
100655d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
100755d3b664SFrank Praznik } __packed;
100855d3b664SFrank Praznik 
100955d3b664SFrank Praznik union sixaxis_output_report_01 {
101055d3b664SFrank Praznik 	struct sixaxis_output_report data;
10111adf904eSPavel Machek 	u8 buf[36];
101255d3b664SFrank Praznik };
101355d3b664SFrank Praznik 
1014c5e0c1c4SFrank Praznik struct motion_output_report_02 {
1015c5e0c1c4SFrank Praznik 	u8 type, zero;
1016c5e0c1c4SFrank Praznik 	u8 r, g, b;
1017c5e0c1c4SFrank Praznik 	u8 zero2;
1018c5e0c1c4SFrank Praznik 	u8 rumble;
1019c5e0c1c4SFrank Praznik };
1020c5e0c1c4SFrank Praznik 
10219b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37
10229b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32
10239b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78
10249b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7
102529b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
1026a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
102741d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
10289b2b5c9aSFrank Praznik 
10298b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
1030d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
10318025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
1032d2d782fcSFrank Praznik 
1033cc6e0bbbSJiri Kosina struct sony_sc {
1034d902f472SFrank Praznik 	spinlock_t lock;
1035d2d782fcSFrank Praznik 	struct list_head list_node;
10360a286ef2SSven Eckelmann 	struct hid_device *hdev;
103760781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
1038cc6e0bbbSJiri Kosina 	unsigned long quirks;
10390a286ef2SSven Eckelmann 	struct work_struct state_worker;
1040d8aaccdaSFrank Praznik 	void (*send_output_report)(struct sony_sc *);
1041297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
1042297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
10438025087aSFrank Praznik 	int device_id;
10441adf904eSPavel Machek 	u8 *output_report_dmabuf;
1045f04d5140SColin Leitner 
10469f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
10471adf904eSPavel Machek 	u8 left;
10481adf904eSPavel Machek 	u8 right;
10499f323b68SSven Eckelmann #endif
10509f323b68SSven Eckelmann 
10511adf904eSPavel Machek 	u8 mac_address[6];
10521adf904eSPavel Machek 	u8 worker_initialized;
1053*2a242932SFrank Praznik 	u8 defer_initialization;
10541adf904eSPavel Machek 	u8 cable_state;
10551adf904eSPavel Machek 	u8 battery_charging;
10561adf904eSPavel Machek 	u8 battery_capacity;
10571adf904eSPavel Machek 	u8 led_state[MAX_LEDS];
10581adf904eSPavel Machek 	u8 resume_led_state[MAX_LEDS];
10591adf904eSPavel Machek 	u8 led_delay_on[MAX_LEDS];
10601adf904eSPavel Machek 	u8 led_delay_off[MAX_LEDS];
10611adf904eSPavel Machek 	u8 led_count;
1062cc6e0bbbSJiri Kosina };
1063cc6e0bbbSJiri Kosina 
1064*2a242932SFrank Praznik static inline void sony_schedule_work(struct sony_sc *sc)
1065*2a242932SFrank Praznik {
1066*2a242932SFrank Praznik 	if (!sc->defer_initialization)
1067*2a242932SFrank Praznik 		schedule_work(&sc->state_worker);
1068*2a242932SFrank Praznik }
1069*2a242932SFrank Praznik 
10701adf904eSPavel Machek static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc,
1071c607fb8dSAntonio Ospite 			     unsigned int *rsize)
1072c607fb8dSAntonio Ospite {
1073c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
1074c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
1075c607fb8dSAntonio Ospite }
1076c607fb8dSAntonio Ospite 
1077c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
1078c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
1079c5e0c1c4SFrank Praznik {
1080c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
1081c5e0c1c4SFrank Praznik 	return motion_rdesc;
1082c5e0c1c4SFrank Praznik }
1083c5e0c1c4SFrank Praznik 
1084b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc,
1085b2723eb7SSimon Wood 			     unsigned int *rsize)
1086b2723eb7SSimon Wood {
1087b2723eb7SSimon Wood 	*rsize = sizeof(navigation_rdesc);
1088b2723eb7SSimon Wood 	return navigation_rdesc;
1089b2723eb7SSimon Wood }
1090b2723eb7SSimon Wood 
10911adf904eSPavel Machek static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc,
1092078328daSJiri Kosina 			     unsigned int *rsize)
1093078328daSJiri Kosina {
1094078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
1095078328daSJiri Kosina 	return ps3remote_rdesc;
1096078328daSJiri Kosina }
1097078328daSJiri Kosina 
1098078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
1099078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
1100078328daSJiri Kosina 			     unsigned long **bit, int *max)
1101078328daSJiri Kosina {
1102078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
1103078328daSJiri Kosina 
1104078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1105078328daSJiri Kosina 		return -1;
1106078328daSJiri Kosina 
1107078328daSJiri Kosina 	switch (usage->collection_index) {
1108078328daSJiri Kosina 	case 1:
1109078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
1110078328daSJiri Kosina 			return -1;
1111078328daSJiri Kosina 
1112078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
1113078328daSJiri Kosina 		if (!key)
1114078328daSJiri Kosina 			return -1;
1115078328daSJiri Kosina 		break;
1116078328daSJiri Kosina 	case 2:
1117078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1118078328daSJiri Kosina 			return -1;
1119078328daSJiri Kosina 
1120078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1121078328daSJiri Kosina 		if (!key)
1122078328daSJiri Kosina 			return -1;
1123078328daSJiri Kosina 		break;
1124078328daSJiri Kosina 	default:
1125078328daSJiri Kosina 		return -1;
1126078328daSJiri Kosina 	}
1127078328daSJiri Kosina 
1128078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1129078328daSJiri Kosina 	return 1;
1130078328daSJiri Kosina }
1131078328daSJiri Kosina 
11321adf904eSPavel Machek static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
113373e4008dSNikolai Kondrashov 		unsigned int *rsize)
1134cc6e0bbbSJiri Kosina {
1135cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1136cc6e0bbbSJiri Kosina 
113774500cc8SScott Moreau 	if (sc->quirks & SINO_LITE_CONTROLLER)
113874500cc8SScott Moreau 		return rdesc;
113974500cc8SScott Moreau 
114099d24902SFernando Luis Vázquez Cao 	/*
114199d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
114299d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
114399d24902SFernando Luis Vázquez Cao 	 */
114499d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
114599d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
114699d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
114799d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
114899d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
114999d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
115099d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1151a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
115299d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1153cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1154cc6e0bbbSJiri Kosina 	}
115561ab44beSSimon Wood 
1156ed19d8cfSFrank Praznik 	/*
1157ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1158ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1159ed19d8cfSFrank Praznik 	 * modified one.
1160ed19d8cfSFrank Praznik 	 */
1161b71b5578SFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1162ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1163ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1164ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1165b71b5578SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
1166d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1167d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1168d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1169ed19d8cfSFrank Praznik 	}
1170ed19d8cfSFrank Praznik 
1171c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1172c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1173078328daSJiri Kosina 
1174c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1175c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1176c5e0c1c4SFrank Praznik 
11774545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1178b2723eb7SSimon Wood 		return navigation_fixup(hdev, rdesc, rsize);
11794545ee0aSSimon Wood 
1180078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1181078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1182078328daSJiri Kosina 
118373e4008dSNikolai Kondrashov 	return rdesc;
1184cc6e0bbbSJiri Kosina }
1185cc6e0bbbSJiri Kosina 
11861adf904eSPavel Machek static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
1187d902f472SFrank Praznik {
11881adf904eSPavel Machek 	static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1189d902f472SFrank Praznik 	unsigned long flags;
119012e9a6d7SSimon Wood 	int offset;
11911adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1192d902f472SFrank Praznik 
1193ad142b9eSFrank Praznik 	/*
1194ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1195d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1196d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1197d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1198d902f472SFrank Praznik 	 */
119912e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
120012e9a6d7SSimon Wood 
120112e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1202d902f472SFrank Praznik 		battery_capacity = 100;
120312e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
12049fddd74aSFrank Praznik 		cable_state = 1;
1205d902f472SFrank Praznik 	} else {
12061adf904eSPavel Machek 		u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1207ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1208d902f472SFrank Praznik 		battery_charging = 0;
12099fddd74aSFrank Praznik 		cable_state = 0;
1210d902f472SFrank Praznik 	}
1211d902f472SFrank Praznik 
1212d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1213d902f472SFrank Praznik 	sc->cable_state = cable_state;
1214d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1215d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1216d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1217d902f472SFrank Praznik }
1218d902f472SFrank Praznik 
12191adf904eSPavel Machek static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1220d902f472SFrank Praznik {
1221e5606230SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1222e5606230SFrank Praznik 						struct hid_input, list);
1223e5606230SFrank Praznik 	struct input_dev *input_dev = hidinput->input;
1224d902f472SFrank Praznik 	unsigned long flags;
12256c5f860dSFrank Praznik 	int n, offset;
12261adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1227d902f472SFrank Praznik 
1228ad142b9eSFrank Praznik 	/*
1229ad142b9eSFrank Praznik 	 * Battery and touchpad data starts at byte 30 in the USB report and
12306c5f860dSFrank Praznik 	 * 32 in Bluetooth report.
12316c5f860dSFrank Praznik 	 */
12326c5f860dSFrank Praznik 	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
12336c5f860dSFrank Praznik 
1234ad142b9eSFrank Praznik 	/*
1235ad142b9eSFrank Praznik 	 * The lower 4 bits of byte 30 contain the battery level
1236d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1237d902f472SFrank Praznik 	 */
12386c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
12396c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1240d902f472SFrank Praznik 
1241ad142b9eSFrank Praznik 	/*
1242ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
12436c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
12446c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1245d902f472SFrank Praznik 	 */
12466c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1247d902f472SFrank Praznik 		battery_charging = 0;
1248d902f472SFrank Praznik 	else
1249d902f472SFrank Praznik 		battery_charging = 1;
1250d902f472SFrank Praznik 
12516c5f860dSFrank Praznik 	if (!cable_state)
12526c5f860dSFrank Praznik 		battery_capacity++;
1253d902f472SFrank Praznik 	if (battery_capacity > 10)
12546c5f860dSFrank Praznik 		battery_capacity = 10;
12556c5f860dSFrank Praznik 
1256d902f472SFrank Praznik 	battery_capacity *= 10;
1257d902f472SFrank Praznik 
1258d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1259d902f472SFrank Praznik 	sc->cable_state = cable_state;
1260d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1261d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1262d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1263e5606230SFrank Praznik 
12646c5f860dSFrank Praznik 	offset += 5;
12656c5f860dSFrank Praznik 
1266ad142b9eSFrank Praznik 	/*
1267ad142b9eSFrank Praznik 	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
12686c5f860dSFrank Praznik 	 * and 37 on Bluetooth.
1269e5606230SFrank Praznik 	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
1270e5606230SFrank Praznik 	 * indicator that is 0 when pressed and 1 when not pressed.
1271e5606230SFrank Praznik 	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1272e5606230SFrank Praznik 	 * The data for the second touch is in the same format and immediatly
1273e5606230SFrank Praznik 	 * follows the data for the first.
1274e5606230SFrank Praznik 	 */
1275e5606230SFrank Praznik 	for (n = 0; n < 2; n++) {
12761adf904eSPavel Machek 		u16 x, y;
1277e5606230SFrank Praznik 
1278e5606230SFrank Praznik 		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1279e5606230SFrank Praznik 		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1280e5606230SFrank Praznik 
1281e5606230SFrank Praznik 		input_mt_slot(input_dev, n);
1282e5606230SFrank Praznik 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
1283e5606230SFrank Praznik 					!(rd[offset] >> 7));
1284e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
1285e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
1286e5606230SFrank Praznik 
1287e5606230SFrank Praznik 		offset += 4;
1288e5606230SFrank Praznik 	}
1289d902f472SFrank Praznik }
1290d902f472SFrank Praznik 
1291c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
12921adf904eSPavel Machek 		u8 *rd, int size)
1293c9e4d877SSimon Wood {
1294c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1295c9e4d877SSimon Wood 
1296ad142b9eSFrank Praznik 	/*
1297ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1298c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1299c9e4d877SSimon Wood 	 */
1300fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
13018f5f0bc2SFrank Praznik 		/*
13028f5f0bc2SFrank Praznik 		 * When connected via Bluetooth the Sixaxis occasionally sends
13038f5f0bc2SFrank Praznik 		 * a report with the second byte 0xff and the rest zeroed.
13048f5f0bc2SFrank Praznik 		 *
13058f5f0bc2SFrank Praznik 		 * This report does not reflect the actual state of the
13068f5f0bc2SFrank Praznik 		 * controller must be ignored to avoid generating false input
13078f5f0bc2SFrank Praznik 		 * events.
13088f5f0bc2SFrank Praznik 		 */
13098f5f0bc2SFrank Praznik 		if (rd[1] == 0xff)
13108f5f0bc2SFrank Praznik 			return -EINVAL;
13118f5f0bc2SFrank Praznik 
1312c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1313c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1314c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1315c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1316d902f472SFrank Praznik 
1317d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
131812e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
131912e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
13204545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
13214545ee0aSSimon Wood 			size == 49) {
13224545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
132368330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
132468330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
132568330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
1326d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1327c9e4d877SSimon Wood 	}
1328c9e4d877SSimon Wood 
1329*2a242932SFrank Praznik 	if (sc->defer_initialization) {
1330*2a242932SFrank Praznik 		sc->defer_initialization = 0;
1331*2a242932SFrank Praznik 		sony_schedule_work(sc);
1332*2a242932SFrank Praznik 	}
1333*2a242932SFrank Praznik 
1334c9e4d877SSimon Wood 	return 0;
1335c9e4d877SSimon Wood }
1336c9e4d877SSimon Wood 
1337f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1338f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1339f04d5140SColin Leitner 			unsigned long **bit, int *max)
1340f04d5140SColin Leitner {
1341f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1342f04d5140SColin Leitner 
1343f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1344f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1345f04d5140SColin Leitner 
1346f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1347f04d5140SColin Leitner 			return -1;
1348f04d5140SColin Leitner 
1349f04d5140SColin Leitner 		switch (usage->collection_index) {
1350f04d5140SColin Leitner 		case 1:
1351f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1352f04d5140SColin Leitner 				return -1;
1353f04d5140SColin Leitner 
1354f04d5140SColin Leitner 			key = buzz_keymap[key];
1355f04d5140SColin Leitner 			if (!key)
1356f04d5140SColin Leitner 				return -1;
1357f04d5140SColin Leitner 			break;
1358f04d5140SColin Leitner 		default:
1359f04d5140SColin Leitner 			return -1;
1360f04d5140SColin Leitner 		}
1361f04d5140SColin Leitner 
1362f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1363f04d5140SColin Leitner 		return 1;
1364f04d5140SColin Leitner 	}
1365f04d5140SColin Leitner 
1366078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1367078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1368078328daSJiri Kosina 
13696f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
13706f498018SBenjamin Tissoires 	return 0;
1371f04d5140SColin Leitner }
1372f04d5140SColin Leitner 
1373ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count,
1374ce8efc3bSFrank Praznik 					int w, int h)
1375ce8efc3bSFrank Praznik {
1376ce8efc3bSFrank Praznik 	struct input_dev *input_dev = hi->input;
1377ce8efc3bSFrank Praznik 	int ret;
1378ce8efc3bSFrank Praznik 
1379ce8efc3bSFrank Praznik 	ret = input_mt_init_slots(input_dev, touch_count, 0);
1380ce8efc3bSFrank Praznik 	if (ret < 0)
1381ce8efc3bSFrank Praznik 		return ret;
1382ce8efc3bSFrank Praznik 
1383ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
1384ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
1385ce8efc3bSFrank Praznik 
1386ce8efc3bSFrank Praznik 	return 0;
1387ce8efc3bSFrank Praznik }
1388ce8efc3bSFrank Praznik 
13899154301aSDmitry Torokhov static int sony_input_configured(struct hid_device *hdev,
1390ce8efc3bSFrank Praznik 					struct hid_input *hidinput)
1391ce8efc3bSFrank Praznik {
1392ce8efc3bSFrank Praznik 	struct sony_sc *sc = hid_get_drvdata(hdev);
13939154301aSDmitry Torokhov 	int ret;
1394ce8efc3bSFrank Praznik 
1395ce8efc3bSFrank Praznik 	/*
1396ce8efc3bSFrank Praznik 	 * The Dualshock 4 touchpad supports 2 touches and has a
1397981c5b4aSFrank Praznik 	 * resolution of 1920x942 (44.86 dots/mm).
1398ce8efc3bSFrank Praznik 	 */
1399ce8efc3bSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER) {
14009154301aSDmitry Torokhov 		ret = sony_register_touchpad(hidinput, 2, 1920, 942);
14019154301aSDmitry Torokhov 		if (ret) {
1402ce8efc3bSFrank Praznik 			hid_err(sc->hdev,
14039154301aSDmitry Torokhov 				"Unable to initialize multi-touch slots: %d\n",
14049154301aSDmitry Torokhov 				ret);
14059154301aSDmitry Torokhov 			return ret;
1406ce8efc3bSFrank Praznik 		}
1407ce8efc3bSFrank Praznik 	}
1408ce8efc3bSFrank Praznik 
14099154301aSDmitry Torokhov 	return 0;
14109154301aSDmitry Torokhov }
14119154301aSDmitry Torokhov 
14125710fabfSAntonio Ospite /*
1413bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1414bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1415bd28ce00SJiri Slaby  * events.
1416bd28ce00SJiri Slaby  */
1417816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1418bd28ce00SJiri Slaby {
1419a85d67b5SAntonio Ospite 	const int buf_size =
1420a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
14211adf904eSPavel Machek 	u8 *buf;
1422bd28ce00SJiri Slaby 	int ret;
1423bd28ce00SJiri Slaby 
14242e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1425bd28ce00SJiri Slaby 	if (!buf)
1426bd28ce00SJiri Slaby 		return -ENOMEM;
1427bd28ce00SJiri Slaby 
1428a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1429a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1430a7de9b86SLauri Kasanen 	if (ret < 0) {
1431a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1432a7de9b86SLauri Kasanen 		goto out;
1433a7de9b86SLauri Kasanen 	}
1434f204828aSBenjamin Tissoires 
1435a7de9b86SLauri Kasanen 	/*
1436a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1437a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1438a7de9b86SLauri Kasanen 	 */
1439a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1440a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1441a7de9b86SLauri Kasanen 	if (ret < 0) {
1442a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1443a7de9b86SLauri Kasanen 		goto out;
1444a7de9b86SLauri Kasanen 	}
1445a7de9b86SLauri Kasanen 
1446a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
144719f4c2baSBenjamin Tissoires 	if (ret < 0) {
144819f4c2baSBenjamin Tissoires 		hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
144919f4c2baSBenjamin Tissoires 		ret = 0;
145019f4c2baSBenjamin Tissoires 	}
1451bd28ce00SJiri Slaby 
1452a7de9b86SLauri Kasanen out:
1453bd28ce00SJiri Slaby 	kfree(buf);
1454bd28ce00SJiri Slaby 
1455bd28ce00SJiri Slaby 	return ret;
1456bd28ce00SJiri Slaby }
1457bd28ce00SJiri Slaby 
1458816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1459f9ce7c28SBastien Nocera {
14601adf904eSPavel Machek 	static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
14611adf904eSPavel Machek 	u8 *buf;
14629b2b5c9aSFrank Praznik 	int ret;
14639b2b5c9aSFrank Praznik 
14649b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
14659b2b5c9aSFrank Praznik 	if (!buf)
14669b2b5c9aSFrank Praznik 		return -ENOMEM;
14679b2b5c9aSFrank Praznik 
14689b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1469b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
14709b2b5c9aSFrank Praznik 
14719b2b5c9aSFrank Praznik 	kfree(buf);
14729b2b5c9aSFrank Praznik 
14739b2b5c9aSFrank Praznik 	return ret;
1474f9ce7c28SBastien Nocera }
1475f9ce7c28SBastien Nocera 
1476ad142b9eSFrank Praznik /*
1477ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
147868330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
147968330d83SFrank Praznik  */
148068330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
148168330d83SFrank Praznik {
14821adf904eSPavel Machek 	u8 *buf;
14839b2b5c9aSFrank Praznik 	int ret;
148468330d83SFrank Praznik 
14859b2b5c9aSFrank Praznik 	buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);
14869b2b5c9aSFrank Praznik 	if (!buf)
14879b2b5c9aSFrank Praznik 		return -ENOMEM;
14889b2b5c9aSFrank Praznik 
14899b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,
149068330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
14919b2b5c9aSFrank Praznik 
14929b2b5c9aSFrank Praznik 	kfree(buf);
14939b2b5c9aSFrank Praznik 
14949b2b5c9aSFrank Praznik 	return ret;
1495bd28ce00SJiri Slaby }
1496bd28ce00SJiri Slaby 
1497221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
14988025087aSFrank Praznik {
14991adf904eSPavel Machek 	static const u8 sixaxis_leds[10][4] = {
15008025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
15018025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
15028025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
15038025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
15048025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
15058025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
15068025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
15078025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
15088025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
15098025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
15108025087aSFrank Praznik 	};
15118025087aSFrank Praznik 
1512221399b3SFrank Praznik 	int id = sc->device_id;
1513221399b3SFrank Praznik 
1514221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
15158025087aSFrank Praznik 
15168025087aSFrank Praznik 	if (id < 0)
15178025087aSFrank Praznik 		return;
15188025087aSFrank Praznik 
15198025087aSFrank Praznik 	id %= 10;
1520221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
15218025087aSFrank Praznik }
15228025087aSFrank Praznik 
1523221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
15248025087aSFrank Praznik {
15258025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
15261adf904eSPavel Machek 	static const u8 color_code[7][3] = {
15278025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
15288025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
15298025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
15308025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
15318025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
15328025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
15338025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
15348025087aSFrank Praznik 	};
15358025087aSFrank Praznik 
1536221399b3SFrank Praznik 	int id = sc->device_id;
1537221399b3SFrank Praznik 
1538221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
15398025087aSFrank Praznik 
15408025087aSFrank Praznik 	if (id < 0)
15418025087aSFrank Praznik 		return;
15428025087aSFrank Praznik 
15438025087aSFrank Praznik 	id %= 7;
1544221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
15458025087aSFrank Praznik }
15468025087aSFrank Praznik 
1547221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1548f04d5140SColin Leitner {
1549221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1550f04d5140SColin Leitner 	struct list_head *report_list =
1551f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1552f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1553f04d5140SColin Leitner 		struct hid_report, list);
15541adf904eSPavel Machek 	s32 *value = report->field[0]->value;
1555f04d5140SColin Leitner 
1556221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1557221399b3SFrank Praznik 
1558f04d5140SColin Leitner 	value[0] = 0x00;
1559221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1560221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1561221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1562221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1563f04d5140SColin Leitner 	value[5] = 0x00;
1564f04d5140SColin Leitner 	value[6] = 0x00;
1565f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1566f04d5140SColin Leitner }
1567f04d5140SColin Leitner 
1568221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
15690a286ef2SSven Eckelmann {
1570221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
1571*2a242932SFrank Praznik 		sony_schedule_work(sc);
1572221399b3SFrank Praznik 	else
1573221399b3SFrank Praznik 		buzz_set_leds(sc);
15740a286ef2SSven Eckelmann }
15750a286ef2SSven Eckelmann 
1576c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1577f04d5140SColin Leitner 				    enum led_brightness value)
1578f04d5140SColin Leitner {
1579f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1580ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1581f04d5140SColin Leitner 	struct sony_sc *drv_data;
1582f04d5140SColin Leitner 
1583f04d5140SColin Leitner 	int n;
1584b3ed458cSFrank Praznik 	int force_update;
1585f04d5140SColin Leitner 
1586f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
15872251b85fSSven Eckelmann 	if (!drv_data) {
1588f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1589f04d5140SColin Leitner 		return;
1590f04d5140SColin Leitner 	}
1591f04d5140SColin Leitner 
1592b3ed458cSFrank Praznik 	/*
1593b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1594b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1595b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1596b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1597b3ed458cSFrank Praznik 	 * stop the flashing later on.
1598b3ed458cSFrank Praznik 	 */
1599b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1600b3ed458cSFrank Praznik 
160160781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1602b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1603b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1604b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1605b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1606b3ed458cSFrank Praznik 
160760781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1608b3ed458cSFrank Praznik 
1609b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1610b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1611b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1612b3ed458cSFrank Praznik 
1613221399b3SFrank Praznik 			sony_set_leds(drv_data);
1614f04d5140SColin Leitner 			break;
1615f04d5140SColin Leitner 		}
1616f04d5140SColin Leitner 	}
1617f04d5140SColin Leitner }
1618f04d5140SColin Leitner 
1619c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1620f04d5140SColin Leitner {
1621f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1622ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1623f04d5140SColin Leitner 	struct sony_sc *drv_data;
1624f04d5140SColin Leitner 
1625f04d5140SColin Leitner 	int n;
1626f04d5140SColin Leitner 
1627f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
16282251b85fSSven Eckelmann 	if (!drv_data) {
1629f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1630f04d5140SColin Leitner 		return LED_OFF;
1631f04d5140SColin Leitner 	}
1632f04d5140SColin Leitner 
163360781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
16347db7504aSSimon Wood 		if (led == drv_data->leds[n])
16357db7504aSSimon Wood 			return drv_data->led_state[n];
1636f04d5140SColin Leitner 	}
1637f04d5140SColin Leitner 
16387db7504aSSimon Wood 	return LED_OFF;
1639f04d5140SColin Leitner }
1640f04d5140SColin Leitner 
1641b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1642b3ed458cSFrank Praznik 				unsigned long *delay_off)
1643b3ed458cSFrank Praznik {
1644b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1645ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1646b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1647b3ed458cSFrank Praznik 	int n;
16481adf904eSPavel Machek 	u8 new_on, new_off;
1649b3ed458cSFrank Praznik 
1650b3ed458cSFrank Praznik 	if (!drv_data) {
1651b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1652b3ed458cSFrank Praznik 		return -EINVAL;
1653b3ed458cSFrank Praznik 	}
1654b3ed458cSFrank Praznik 
1655b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1656b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1657b3ed458cSFrank Praznik 		*delay_on = 2550;
1658b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1659b3ed458cSFrank Praznik 		*delay_off = 2550;
1660b3ed458cSFrank Praznik 
1661b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1662b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1663b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1664b3ed458cSFrank Praznik 
1665b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1666b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1667b3ed458cSFrank Praznik 
1668b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1669b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1670b3ed458cSFrank Praznik 			break;
1671b3ed458cSFrank Praznik 	}
1672b3ed458cSFrank Praznik 
1673b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1674b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1675b3ed458cSFrank Praznik 		return -EINVAL;
1676b3ed458cSFrank Praznik 
1677b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1678b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1679b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1680b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1681b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
1682*2a242932SFrank Praznik 		sony_schedule_work(drv_data);
1683b3ed458cSFrank Praznik 	}
1684b3ed458cSFrank Praznik 
1685b3ed458cSFrank Praznik 	return 0;
1686b3ed458cSFrank Praznik }
1687b3ed458cSFrank Praznik 
1688fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
16890a286ef2SSven Eckelmann {
16900a286ef2SSven Eckelmann 	struct led_classdev *led;
16910a286ef2SSven Eckelmann 	int n;
16920a286ef2SSven Eckelmann 
1693fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
16940a286ef2SSven Eckelmann 
1695fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1696fa57a810SFrank Praznik 		led = sc->leds[n];
1697fa57a810SFrank Praznik 		sc->leds[n] = NULL;
16980a286ef2SSven Eckelmann 		if (!led)
16990a286ef2SSven Eckelmann 			continue;
17000a286ef2SSven Eckelmann 		led_classdev_unregister(led);
17010a286ef2SSven Eckelmann 		kfree(led);
17020a286ef2SSven Eckelmann 	}
170360781cf4SFrank Praznik 
1704fa57a810SFrank Praznik 	sc->led_count = 0;
17050a286ef2SSven Eckelmann }
17060a286ef2SSven Eckelmann 
1707fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1708f04d5140SColin Leitner {
1709fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
171040e32ee6SJiri Kosina 	int n, ret = 0;
1711b3ed458cSFrank Praznik 	int use_ds4_names;
171240e32ee6SJiri Kosina 	struct led_classdev *led;
171340e32ee6SJiri Kosina 	size_t name_sz;
171440e32ee6SJiri Kosina 	char *name;
17150a286ef2SSven Eckelmann 	size_t name_len;
17160a286ef2SSven Eckelmann 	const char *name_fmt;
1717b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1718b3ed458cSFrank Praznik 						  "global" };
17191adf904eSPavel Machek 	u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
17201adf904eSPavel Machek 	u8 use_hw_blink[MAX_LEDS] = { 0 };
1721f04d5140SColin Leitner 
1722fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1723f04d5140SColin Leitner 
1724fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1725fa57a810SFrank Praznik 		sc->led_count = 4;
1726b3ed458cSFrank Praznik 		use_ds4_names = 0;
17270a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
17280a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
17299446edb9SKees Cook 		/* Validate expected report characteristics. */
17309446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
17319446edb9SKees Cook 			return -ENODEV;
1732fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1733221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1734221399b3SFrank Praznik 		sc->led_state[3] = 1;
1735b3ed458cSFrank Praznik 		sc->led_count = 4;
1736b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1737b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1738b3ed458cSFrank Praznik 		use_ds4_names = 1;
173961ebca93SFrank Praznik 		name_len = 0;
174061ebca93SFrank Praznik 		name_fmt = "%s:%s";
1741c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1742c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1743c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1744c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1745c5e0c1c4SFrank Praznik 		name_len = 0;
1746c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
17474545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
17481adf904eSPavel Machek 		static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
17494545ee0aSSimon Wood 
17504545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
17514545ee0aSSimon Wood 		sc->led_count = 1;
17524545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
17534545ee0aSSimon Wood 		use_ds4_names = 0;
17544545ee0aSSimon Wood 		name_len = strlen("::sony#");
17554545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
175660781cf4SFrank Praznik 	} else {
1757221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1758fa57a810SFrank Praznik 		sc->led_count = 4;
1759b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1760b3ed458cSFrank Praznik 		use_ds4_names = 0;
176161ebca93SFrank Praznik 		name_len = strlen("::sony#");
176261ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
176360781cf4SFrank Praznik 	}
176460781cf4SFrank Praznik 
1765ad142b9eSFrank Praznik 	/*
1766ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1767f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1768ad142b9eSFrank Praznik 	 * LEDs to on
1769ad142b9eSFrank Praznik 	 */
1770221399b3SFrank Praznik 	sony_set_leds(sc);
1771f04d5140SColin Leitner 
17720a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1773f04d5140SColin Leitner 
1774fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
177561ebca93SFrank Praznik 
1776b3ed458cSFrank Praznik 		if (use_ds4_names)
1777b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
177861ebca93SFrank Praznik 
1779f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1780f04d5140SColin Leitner 		if (!led) {
1781f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
17828cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1783f04d5140SColin Leitner 			goto error_leds;
1784f04d5140SColin Leitner 		}
1785f04d5140SColin Leitner 
1786f04d5140SColin Leitner 		name = (void *)(&led[1]);
1787b3ed458cSFrank Praznik 		if (use_ds4_names)
1788b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1789b3ed458cSFrank Praznik 			ds4_name_str[n]);
179061ebca93SFrank Praznik 		else
17910a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1792f04d5140SColin Leitner 		led->name = name;
1793221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1794b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1795c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1796c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1797f04d5140SColin Leitner 
1798b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1799b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1800b3ed458cSFrank Praznik 
18018025087aSFrank Praznik 		sc->leds[n] = led;
18028025087aSFrank Praznik 
18038cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
18048cd5fcdaSJulia Lawall 		if (ret) {
1805f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
18068025087aSFrank Praznik 			sc->leds[n] = NULL;
1807f04d5140SColin Leitner 			kfree(led);
1808f04d5140SColin Leitner 			goto error_leds;
1809f04d5140SColin Leitner 		}
1810f04d5140SColin Leitner 	}
1811f04d5140SColin Leitner 
1812f04d5140SColin Leitner 	return ret;
1813f04d5140SColin Leitner 
1814f04d5140SColin Leitner error_leds:
1815fa57a810SFrank Praznik 	sony_leds_remove(sc);
1816f04d5140SColin Leitner 
1817f04d5140SColin Leitner 	return ret;
1818f04d5140SColin Leitner }
1819f04d5140SColin Leitner 
1820d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc)
1821a08c22c0SSven Eckelmann {
18229b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
182355d3b664SFrank Praznik 		.buf = {
1824a08c22c0SSven Eckelmann 			0x01,
1825ad07b7a6SScott Moreau 			0x01, 0xff, 0x00, 0xff, 0x00,
18260a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1827a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1828a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1829a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1830a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1831a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
183255d3b664SFrank Praznik 		}
1833a08c22c0SSven Eckelmann 	};
18349b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
18359b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
18369b2b5c9aSFrank Praznik 	int n;
18379b2b5c9aSFrank Praznik 
18389b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
18399b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
18409f323b68SSven Eckelmann 
18410a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
18429b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
18439b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
18440a286ef2SSven Eckelmann #endif
18450a286ef2SSven Eckelmann 
18469b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
18479b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
18489b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
18499b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
18509f323b68SSven Eckelmann 
185188f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
18529b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
18539b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
185488f6576fSSimon Wood 
1855b3ed458cSFrank Praznik 	/*
1856b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
1857b3ed458cSFrank Praznik 	 * corresponding light on the controller.
1858b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
1859b3ed458cSFrank Praznik 	 *
1860b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
1861b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
1862b3ed458cSFrank Praznik 	 * always off.
1863b3ed458cSFrank Praznik 	 */
1864b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
1865b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
18669b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
18679b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
1868b3ed458cSFrank Praznik 		}
1869b3ed458cSFrank Praznik 	}
1870b3ed458cSFrank Praznik 
18711adf904eSPavel Machek 	hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
18729b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
18739b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18749f323b68SSven Eckelmann }
18759f323b68SSven Eckelmann 
1876d8aaccdaSFrank Praznik static void dualshock4_send_output_report(struct sony_sc *sc)
18770bd88dd3SFrank Praznik {
18780da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
18791adf904eSPavel Machek 	u8 *buf = sc->output_report_dmabuf;
188048220237SFrank Praznik 	int offset;
18810da8ea65SFrank Praznik 
1882fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
18839b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x05_SIZE);
188448220237SFrank Praznik 		buf[0] = 0x05;
1885b3ed458cSFrank Praznik 		buf[1] = 0xFF;
188648220237SFrank Praznik 		offset = 4;
1887fdcf105dSFrank Praznik 	} else {
18889b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x11_SIZE);
1889fdcf105dSFrank Praznik 		buf[0] = 0x11;
1890824deff8SRostislav Pehlivanov 		buf[1] = 0x80;
1891fdcf105dSFrank Praznik 		buf[3] = 0x0F;
1892fdcf105dSFrank Praznik 		offset = 6;
1893fdcf105dSFrank Praznik 	}
18940bd88dd3SFrank Praznik 
18950bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
189648220237SFrank Praznik 	buf[offset++] = sc->right;
189748220237SFrank Praznik 	buf[offset++] = sc->left;
189848220237SFrank Praznik #else
189948220237SFrank Praznik 	offset += 2;
19000bd88dd3SFrank Praznik #endif
19010bd88dd3SFrank Praznik 
1902b3ed458cSFrank Praznik 	/* LED 3 is the global control */
1903b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
190448220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
190548220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
190648220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
1907b3ed458cSFrank Praznik 	} else {
1908b3ed458cSFrank Praznik 		offset += 3;
1909b3ed458cSFrank Praznik 	}
1910b3ed458cSFrank Praznik 
1911b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
1912b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
1913b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
191460781cf4SFrank Praznik 
1915fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
19169b2b5c9aSFrank Praznik 		hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);
1917fdcf105dSFrank Praznik 	else
19189b2b5c9aSFrank Praznik 		hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,
1919fdcf105dSFrank Praznik 				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
19200bd88dd3SFrank Praznik }
19210bd88dd3SFrank Praznik 
1922d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc)
1923c5e0c1c4SFrank Praznik {
1924c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1925c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
1926c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
1927c5e0c1c4SFrank Praznik 
192841d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
1929c5e0c1c4SFrank Praznik 
1930c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
1931c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
1932c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
1933c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
1934c5e0c1c4SFrank Praznik 
1935c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1936c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
1937c5e0c1c4SFrank Praznik #endif
1938c5e0c1c4SFrank Praznik 
19391adf904eSPavel Machek 	hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE);
1940c5e0c1c4SFrank Praznik }
1941c5e0c1c4SFrank Praznik 
1942decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc)
1943decd946cSFrank Praznik {
1944decd946cSFrank Praznik 	if (sc->send_output_report)
1945decd946cSFrank Praznik 		sc->send_output_report(sc);
1946decd946cSFrank Praznik }
1947decd946cSFrank Praznik 
1948d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work)
1949d8aaccdaSFrank Praznik {
1950d8aaccdaSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1951ef916ef5SAntonio Ospite 
1952d8aaccdaSFrank Praznik 	sc->send_output_report(sc);
1953d8aaccdaSFrank Praznik }
1954d8aaccdaSFrank Praznik 
19559b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
19569b2b5c9aSFrank Praznik {
19574545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
19584545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
19599b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
19609b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
19619b2b5c9aSFrank Praznik 				GFP_KERNEL);
19629b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
19639b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,
19649b2b5c9aSFrank Praznik 						GFP_KERNEL);
19659b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
19669b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
19679b2b5c9aSFrank Praznik 						GFP_KERNEL);
1968c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
196941d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
1970c5e0c1c4SFrank Praznik 						GFP_KERNEL);
19719b2b5c9aSFrank Praznik 	else
19729b2b5c9aSFrank Praznik 		return 0;
19739b2b5c9aSFrank Praznik 
19749b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
19759b2b5c9aSFrank Praznik 		return -ENOMEM;
19769b2b5c9aSFrank Praznik 
19779b2b5c9aSFrank Praznik 	return 0;
19789b2b5c9aSFrank Praznik }
19799b2b5c9aSFrank Praznik 
19800a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
19819f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
19829f323b68SSven Eckelmann 			    struct ff_effect *effect)
19839f323b68SSven Eckelmann {
1984a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
19859f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
1986a08c22c0SSven Eckelmann 
1987a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
1988a08c22c0SSven Eckelmann 		return 0;
1989a08c22c0SSven Eckelmann 
19909f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
19910bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
1992a08c22c0SSven Eckelmann 
1993*2a242932SFrank Praznik 	sony_schedule_work(sc);
19949f323b68SSven Eckelmann 	return 0;
1995a08c22c0SSven Eckelmann }
1996a08c22c0SSven Eckelmann 
1997fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1998a08c22c0SSven Eckelmann {
1999fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
2000a08c22c0SSven Eckelmann 						struct hid_input, list);
2001a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
2002a08c22c0SSven Eckelmann 
2003a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
2004a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
2005a08c22c0SSven Eckelmann }
2006a08c22c0SSven Eckelmann 
2007a08c22c0SSven Eckelmann #else
2008fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
2009a08c22c0SSven Eckelmann {
2010a08c22c0SSven Eckelmann 	return 0;
2011a08c22c0SSven Eckelmann }
20129f323b68SSven Eckelmann 
2013a08c22c0SSven Eckelmann #endif
2014a08c22c0SSven Eckelmann 
2015d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
2016d902f472SFrank Praznik 				     enum power_supply_property psp,
2017d902f472SFrank Praznik 				     union power_supply_propval *val)
2018c4e1ddf2SFrank Praznik {
2019297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
2020d902f472SFrank Praznik 	unsigned long flags;
2021d902f472SFrank Praznik 	int ret = 0;
2022d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
2023c4e1ddf2SFrank Praznik 
2024d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
2025d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
2026d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
2027d902f472SFrank Praznik 	cable_state = sc->cable_state;
2028d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
2029c4e1ddf2SFrank Praznik 
2030d902f472SFrank Praznik 	switch (psp) {
2031d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
2032d902f472SFrank Praznik 		val->intval = 1;
2033d902f472SFrank Praznik 		break;
2034d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
2035d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
2036d902f472SFrank Praznik 		break;
2037d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
2038d902f472SFrank Praznik 		val->intval = battery_capacity;
2039d902f472SFrank Praznik 		break;
2040d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
2041d902f472SFrank Praznik 		if (battery_charging)
2042d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
2043d902f472SFrank Praznik 		else
2044d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
2045d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
2046d902f472SFrank Praznik 			else
2047d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2048d902f472SFrank Praznik 		break;
2049d902f472SFrank Praznik 	default:
2050d902f472SFrank Praznik 		ret = -EINVAL;
2051d902f472SFrank Praznik 		break;
2052c4e1ddf2SFrank Praznik 	}
2053d902f472SFrank Praznik 	return ret;
2054d902f472SFrank Praznik }
2055d902f472SFrank Praznik 
20560f398230SFrank Praznik static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
2057d902f472SFrank Praznik {
20580f398230SFrank Praznik 	const char *battery_str_fmt = append_dev_id ?
20590f398230SFrank Praznik 		"sony_controller_battery_%pMR_%i" :
20600f398230SFrank Praznik 		"sony_controller_battery_%pMR";
2061297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
2062d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
2063d902f472SFrank Praznik 	int ret;
2064d902f472SFrank Praznik 
2065ad142b9eSFrank Praznik 	/*
2066ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
2067d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
2068d9a293a9SFrank Praznik 	 */
2069d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
2070d9a293a9SFrank Praznik 
2071297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
2072297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
2073297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
2074297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2075297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
20760f398230SFrank Praznik 	sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
20770f398230SFrank Praznik 					  sc->mac_address, sc->device_id);
2078297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2079d902f472SFrank Praznik 		return -ENOMEM;
2080d902f472SFrank Praznik 
2081297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
2082297d716fSKrzysztof Kozlowski 					    &psy_cfg);
2083297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
2084297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
2085d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
2086d902f472SFrank Praznik 		goto err_free;
2087d902f472SFrank Praznik 	}
2088d902f472SFrank Praznik 
2089297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
2090d902f472SFrank Praznik 	return 0;
2091d902f472SFrank Praznik 
2092d902f472SFrank Praznik err_free:
2093297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2094297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2095d902f472SFrank Praznik 	return ret;
2096d902f472SFrank Praznik }
2097d902f472SFrank Praznik 
2098d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
2099d902f472SFrank Praznik {
2100297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2101d902f472SFrank Praznik 		return;
2102d902f472SFrank Praznik 
2103297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
2104297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2105297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2106d902f472SFrank Praznik }
2107d902f472SFrank Praznik 
2108d2d782fcSFrank Praznik /*
2109d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
2110d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
2111d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
2112d2d782fcSFrank Praznik  * once.
21130f398230SFrank Praznik  *
21140f398230SFrank Praznik  * Some USB-only devices masquerade as Sixaxis controllers and all have the
21150f398230SFrank Praznik  * same dummy Bluetooth address, so a comparison of the connection type is
21160f398230SFrank Praznik  * required.  Devices are only rejected in the case where two devices have
21170f398230SFrank Praznik  * matching Bluetooth addresses on different bus types.
2118d2d782fcSFrank Praznik  */
21190f398230SFrank Praznik static inline int sony_compare_connection_type(struct sony_sc *sc0,
21200f398230SFrank Praznik 						struct sony_sc *sc1)
21210f398230SFrank Praznik {
21220f398230SFrank Praznik 	const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE);
21230f398230SFrank Praznik 	const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
21240f398230SFrank Praznik 
21250f398230SFrank Praznik 	return sc0_not_bt == sc1_not_bt;
21260f398230SFrank Praznik }
21270f398230SFrank Praznik 
2128d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
2129d2d782fcSFrank Praznik {
2130d2d782fcSFrank Praznik 	struct sony_sc *entry;
2131d2d782fcSFrank Praznik 	unsigned long flags;
2132d2d782fcSFrank Praznik 	int ret;
2133d2d782fcSFrank Praznik 
2134d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
2135d2d782fcSFrank Praznik 
2136d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
2137d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
2138d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
2139d2d782fcSFrank Praznik 		if (!ret) {
21400f398230SFrank Praznik 			if (sony_compare_connection_type(sc, entry)) {
21410f398230SFrank Praznik 				ret = 1;
21420f398230SFrank Praznik 			} else {
2143d2d782fcSFrank Praznik 				ret = -EEXIST;
21440f398230SFrank Praznik 				hid_info(sc->hdev,
21450f398230SFrank Praznik 				"controller with MAC address %pMR already connected\n",
2146d2d782fcSFrank Praznik 				sc->mac_address);
21470f398230SFrank Praznik 			}
2148d2d782fcSFrank Praznik 			goto unlock;
2149d2d782fcSFrank Praznik 		}
2150c4e1ddf2SFrank Praznik 	}
2151c4e1ddf2SFrank Praznik 
2152d2d782fcSFrank Praznik 	ret = 0;
2153d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
2154c4e1ddf2SFrank Praznik 
2155d2d782fcSFrank Praznik unlock:
2156d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2157d2d782fcSFrank Praznik 	return ret;
2158d2d782fcSFrank Praznik }
2159d2d782fcSFrank Praznik 
2160d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
2161d2d782fcSFrank Praznik {
2162d2d782fcSFrank Praznik 	unsigned long flags;
2163d2d782fcSFrank Praznik 
2164d2d782fcSFrank Praznik 	if (sc->list_node.next) {
2165d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
2166d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
2167d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2168d2d782fcSFrank Praznik 	}
2169d2d782fcSFrank Praznik }
2170d2d782fcSFrank Praznik 
2171d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
2172d2d782fcSFrank Praznik {
2173d2d782fcSFrank Praznik 	int ret;
2174d2d782fcSFrank Praznik 
2175d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2176d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2177d2d782fcSFrank Praznik 	if (ret != 17)
2178c4e1ddf2SFrank Praznik 		return -EINVAL;
2179d2d782fcSFrank Praznik 
2180d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2181d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2182d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2183d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2184d2d782fcSFrank Praznik 
2185d2d782fcSFrank Praznik 	if (ret != 6)
2186d2d782fcSFrank Praznik 		return -EINVAL;
2187d2d782fcSFrank Praznik 
2188d2d782fcSFrank Praznik 	return 0;
2189c4e1ddf2SFrank Praznik }
2190c4e1ddf2SFrank Praznik 
2191d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2192d2d782fcSFrank Praznik {
21931adf904eSPavel Machek 	u8 *buf = NULL;
2194d2d782fcSFrank Praznik 	int n, ret;
2195d2d782fcSFrank Praznik 
2196d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
219712e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
21984545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2199d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2200d2d782fcSFrank Praznik 		/*
2201d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2202d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2203d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2204d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2205d2d782fcSFrank Praznik 		 */
2206d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2207d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2208d2d782fcSFrank Praznik 			return 0;
2209d2d782fcSFrank Praznik 		}
2210d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
22119b2b5c9aSFrank Praznik 		buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);
22129b2b5c9aSFrank Praznik 		if (!buf)
22139b2b5c9aSFrank Praznik 			return -ENOMEM;
2214d2d782fcSFrank Praznik 
2215d2d782fcSFrank Praznik 		/*
2216d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2217d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2218d2d782fcSFrank Praznik 		 * offset 1.
2219d2d782fcSFrank Praznik 		 */
22209b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
22219b2b5c9aSFrank Praznik 				DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
22229b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2223d2d782fcSFrank Praznik 
22249b2b5c9aSFrank Praznik 		if (ret != DS4_REPORT_0x81_SIZE) {
2225d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
22269b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22279b2b5c9aSFrank Praznik 			goto out_free;
2228d2d782fcSFrank Praznik 		}
2229d2d782fcSFrank Praznik 
2230d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
22314545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
22324545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
22339b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
22349b2b5c9aSFrank Praznik 		if (!buf)
22359b2b5c9aSFrank Praznik 			return -ENOMEM;
2236d2d782fcSFrank Praznik 
2237d2d782fcSFrank Praznik 		/*
2238d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2239d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2240d2d782fcSFrank Praznik 		 * offset 4.
2241d2d782fcSFrank Praznik 		 */
22429b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
22439b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
22449b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2245d2d782fcSFrank Praznik 
22469b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2247d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
22489b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22499b2b5c9aSFrank Praznik 			goto out_free;
2250d2d782fcSFrank Praznik 		}
2251d2d782fcSFrank Praznik 
2252d2d782fcSFrank Praznik 		/*
2253d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2254d2d782fcSFrank Praznik 		 * be byte-swapped.
2255d2d782fcSFrank Praznik 		 */
2256d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2257d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2258d2d782fcSFrank Praznik 	} else {
2259d2d782fcSFrank Praznik 		return 0;
2260d2d782fcSFrank Praznik 	}
2261d2d782fcSFrank Praznik 
22629b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
22639b2b5c9aSFrank Praznik 
22649b2b5c9aSFrank Praznik out_free:
22659b2b5c9aSFrank Praznik 
22669b2b5c9aSFrank Praznik 	kfree(buf);
22679b2b5c9aSFrank Praznik 
22689b2b5c9aSFrank Praznik 	return ret;
2269d2d782fcSFrank Praznik }
2270d2d782fcSFrank Praznik 
22718025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
22728025087aSFrank Praznik {
22738025087aSFrank Praznik 	int ret;
22748025087aSFrank Praznik 
22758025087aSFrank Praznik 	/*
22768025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
22778025087aSFrank Praznik 	 * All others are set to -1.
22788025087aSFrank Praznik 	 */
22798025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
22808025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
22818025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
22828025087aSFrank Praznik 					GFP_KERNEL);
22838025087aSFrank Praznik 		if (ret < 0) {
22848025087aSFrank Praznik 			sc->device_id = -1;
22858025087aSFrank Praznik 			return ret;
22868025087aSFrank Praznik 		}
22878025087aSFrank Praznik 		sc->device_id = ret;
22888025087aSFrank Praznik 	} else {
22898025087aSFrank Praznik 		sc->device_id = -1;
22908025087aSFrank Praznik 	}
22918025087aSFrank Praznik 
22928025087aSFrank Praznik 	return 0;
22938025087aSFrank Praznik }
22948025087aSFrank Praznik 
22958025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
22968025087aSFrank Praznik {
22978025087aSFrank Praznik 	if (sc->device_id >= 0) {
22988025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
22998025087aSFrank Praznik 		sc->device_id = -1;
23008025087aSFrank Praznik 	}
23018025087aSFrank Praznik }
23028025087aSFrank Praznik 
2303d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc,
2304d8aaccdaSFrank Praznik 				void (*send_output_report)(struct sony_sc *))
230546262047SFrank Praznik {
2306d8aaccdaSFrank Praznik 	sc->send_output_report = send_output_report;
2307d8aaccdaSFrank Praznik 
230846262047SFrank Praznik 	if (!sc->worker_initialized)
2309d8aaccdaSFrank Praznik 		INIT_WORK(&sc->state_worker, sony_state_worker);
231046262047SFrank Praznik 
231146262047SFrank Praznik 	sc->worker_initialized = 1;
231246262047SFrank Praznik }
231346262047SFrank Praznik 
231446262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
231546262047SFrank Praznik {
231646262047SFrank Praznik 	if (sc->worker_initialized)
231746262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
231846262047SFrank Praznik }
2319d2d782fcSFrank Praznik 
2320bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2321bd28ce00SJiri Slaby {
2322bd28ce00SJiri Slaby 	int ret;
23230f398230SFrank Praznik 	int append_dev_id;
2324cc6e0bbbSJiri Kosina 	unsigned long quirks = id->driver_data;
2325cc6e0bbbSJiri Kosina 	struct sony_sc *sc;
2326f04d5140SColin Leitner 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2327cc6e0bbbSJiri Kosina 
2328abf832bfSBenjamin Tissoires 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2329cc6e0bbbSJiri Kosina 	if (sc == NULL) {
23304291ee30SJoe Perches 		hid_err(hdev, "can't alloc sony descriptor\n");
2331cc6e0bbbSJiri Kosina 		return -ENOMEM;
2332cc6e0bbbSJiri Kosina 	}
2333cc6e0bbbSJiri Kosina 
2334b94993f6SFrank Praznik 	spin_lock_init(&sc->lock);
2335b94993f6SFrank Praznik 
2336cc6e0bbbSJiri Kosina 	sc->quirks = quirks;
2337cc6e0bbbSJiri Kosina 	hid_set_drvdata(hdev, sc);
23380a286ef2SSven Eckelmann 	sc->hdev = hdev;
2339bd28ce00SJiri Slaby 
2340bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
2341bd28ce00SJiri Slaby 	if (ret) {
23424291ee30SJoe Perches 		hid_err(hdev, "parse failed\n");
2343abf832bfSBenjamin Tissoires 		return ret;
2344bd28ce00SJiri Slaby 	}
2345bd28ce00SJiri Slaby 
2346f04d5140SColin Leitner 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2347f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
234850764650SAntonio Ospite 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2349f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2350f04d5140SColin Leitner 
2351f04d5140SColin Leitner 	ret = hid_hw_start(hdev, connect_mask);
2352bd28ce00SJiri Slaby 	if (ret) {
23534291ee30SJoe Perches 		hid_err(hdev, "hw start failed\n");
2354abf832bfSBenjamin Tissoires 		return ret;
2355bd28ce00SJiri Slaby 	}
2356bd28ce00SJiri Slaby 
23578025087aSFrank Praznik 	ret = sony_set_device_id(sc);
23588025087aSFrank Praznik 	if (ret < 0) {
23598025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
23608025087aSFrank Praznik 		goto err_stop;
23618025087aSFrank Praznik 	}
23628025087aSFrank Praznik 
2363131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2364131a8a9aSFrank Praznik 	if (ret < 0) {
2365131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2366131a8a9aSFrank Praznik 		goto err_stop;
2367131a8a9aSFrank Praznik 	}
2368131a8a9aSFrank Praznik 
23694545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
23704545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2371e534a935SBenjamin Tissoires 		/*
2372e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2373e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2374e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2375e534a935SBenjamin Tissoires 		 *
2376e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2377e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2378e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2379e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
2380*2a242932SFrank Praznik 		 *
2381*2a242932SFrank Praznik 		 * Additionally, the Sixaxis on USB isn't properly initialized
2382*2a242932SFrank Praznik 		 * until the PS logo button is pressed and as such won't retain
2383*2a242932SFrank Praznik 		 * any state set by an output report, so the initial
2384*2a242932SFrank Praznik 		 * configuration report is deferred until the first input
2385*2a242932SFrank Praznik 		 * report arrives.
2386e534a935SBenjamin Tissoires 		 */
2387e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2388e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
2389*2a242932SFrank Praznik 		sc->defer_initialization = 1;
2390816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
2391d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
23924545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
23934545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
23942078b9bbSFrank Praznik 		/*
23952078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
23962078b9bbSFrank Praznik 		 * when connected via Bluetooth.
23972078b9bbSFrank Praznik 		 */
23982078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2399816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
2400d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
2401fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
240268330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
24032078b9bbSFrank Praznik 			/*
24042078b9bbSFrank Praznik 			 * The DualShock 4 wants output reports sent on the ctrl
24052078b9bbSFrank Praznik 			 * endpoint when connected via Bluetooth.
24062078b9bbSFrank Praznik 			 */
24072078b9bbSFrank Praznik 			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
240868330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
240968330d83SFrank Praznik 			if (ret < 0) {
241068330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
241168330d83SFrank Praznik 				goto err_stop;
241268330d83SFrank Praznik 			}
241368330d83SFrank Praznik 		}
2414c4e1ddf2SFrank Praznik 
2415d8aaccdaSFrank Praznik 		sony_init_output_report(sc, dualshock4_send_output_report);
2416c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2417d8aaccdaSFrank Praznik 		sony_init_output_report(sc, motion_send_output_report);
24180bd88dd3SFrank Praznik 	} else {
24190bd88dd3SFrank Praznik 		ret = 0;
24200bd88dd3SFrank Praznik 	}
2421f9ce7c28SBastien Nocera 
24224dfdc464SJiri Kosina 	if (ret < 0)
2423bd28ce00SJiri Slaby 		goto err_stop;
2424bd28ce00SJiri Slaby 
24250f398230SFrank Praznik 	ret = append_dev_id = sony_check_add(sc);
2426d2d782fcSFrank Praznik 	if (ret < 0)
2427d2d782fcSFrank Praznik 		goto err_stop;
2428d2d782fcSFrank Praznik 
24290a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2430fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
24310a286ef2SSven Eckelmann 		if (ret < 0)
24320a286ef2SSven Eckelmann 			goto err_stop;
24330a286ef2SSven Eckelmann 	}
24340a286ef2SSven Eckelmann 
2435d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
24360f398230SFrank Praznik 		ret = sony_battery_probe(sc, append_dev_id);
2437a08c22c0SSven Eckelmann 		if (ret < 0)
2438a08c22c0SSven Eckelmann 			goto err_stop;
2439a08c22c0SSven Eckelmann 
2440d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2441d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2442d902f472SFrank Praznik 		if (ret < 0) {
2443d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2444d902f472SFrank Praznik 			goto err_stop;
2445d902f472SFrank Praznik 		}
2446d902f472SFrank Praznik 	}
2447d902f472SFrank Praznik 
2448c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2449fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2450d902f472SFrank Praznik 		if (ret < 0)
2451d902f472SFrank Praznik 			goto err_close;
24525f5750d2SFrank Praznik 	}
2453bd28ce00SJiri Slaby 
2454f425458eSH Hartley Sweeten 	return 0;
2455d902f472SFrank Praznik err_close:
2456d902f472SFrank Praznik 	hid_hw_close(hdev);
2457bd28ce00SJiri Slaby err_stop:
24580a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2459fa57a810SFrank Praznik 		sony_leds_remove(sc);
2460d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2461d902f472SFrank Praznik 		sony_battery_remove(sc);
246246262047SFrank Praznik 	sony_cancel_work_sync(sc);
24639b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2464d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
24658025087aSFrank Praznik 	sony_release_device_id(sc);
2466bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2467bd28ce00SJiri Slaby 	return ret;
2468bd28ce00SJiri Slaby }
2469bd28ce00SJiri Slaby 
2470bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2471bd28ce00SJiri Slaby {
2472bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2473bd28ce00SJiri Slaby 
24740a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2475fa57a810SFrank Praznik 		sony_leds_remove(sc);
2476bd28ce00SJiri Slaby 
2477d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2478d902f472SFrank Praznik 		hid_hw_close(hdev);
2479d902f472SFrank Praznik 		sony_battery_remove(sc);
2480d902f472SFrank Praznik 	}
2481d902f472SFrank Praznik 
248246262047SFrank Praznik 	sony_cancel_work_sync(sc);
24839f323b68SSven Eckelmann 
24849b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
24859b2b5c9aSFrank Praznik 
2486d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2487bd28ce00SJiri Slaby 
24888025087aSFrank Praznik 	sony_release_device_id(sc);
24898025087aSFrank Praznik 
2490bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2491bd28ce00SJiri Slaby }
2492bd28ce00SJiri Slaby 
2493decd946cSFrank Praznik #ifdef CONFIG_PM
2494decd946cSFrank Praznik 
2495decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2496decd946cSFrank Praznik {
2497decd946cSFrank Praznik 	/*
2498decd946cSFrank Praznik 	 * On suspend save the current LED state,
2499decd946cSFrank Praznik 	 * stop running force-feedback and blank the LEDS.
2500decd946cSFrank Praznik 	 */
2501decd946cSFrank Praznik 	if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
2502decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2503decd946cSFrank Praznik 
2504decd946cSFrank Praznik #ifdef CONFIG_SONY_FF
2505decd946cSFrank Praznik 		sc->left = sc->right = 0;
2506decd946cSFrank Praznik #endif
2507decd946cSFrank Praznik 
2508decd946cSFrank Praznik 		memcpy(sc->resume_led_state, sc->led_state,
2509decd946cSFrank Praznik 			sizeof(sc->resume_led_state));
2510decd946cSFrank Praznik 		memset(sc->led_state, 0, sizeof(sc->led_state));
2511decd946cSFrank Praznik 
2512decd946cSFrank Praznik 		sony_send_output_report(sc);
2513decd946cSFrank Praznik 	}
2514decd946cSFrank Praznik 
2515decd946cSFrank Praznik 	return 0;
2516decd946cSFrank Praznik }
2517decd946cSFrank Praznik 
2518decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev)
2519decd946cSFrank Praznik {
2520decd946cSFrank Praznik 	/* Restore the state of controller LEDs on resume */
2521decd946cSFrank Praznik 	if (SONY_LED_SUPPORT) {
2522decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2523decd946cSFrank Praznik 
2524decd946cSFrank Praznik 		memcpy(sc->led_state, sc->resume_led_state,
2525decd946cSFrank Praznik 			sizeof(sc->led_state));
2526decd946cSFrank Praznik 
2527decd946cSFrank Praznik 		/*
2528decd946cSFrank Praznik 		 * The Sixaxis and navigation controllers on USB need to be
2529decd946cSFrank Praznik 		 * reinitialized on resume or they won't behave properly.
2530decd946cSFrank Praznik 		 */
2531decd946cSFrank Praznik 		if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
2532*2a242932SFrank Praznik 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2533decd946cSFrank Praznik 			sixaxis_set_operational_usb(sc->hdev);
2534*2a242932SFrank Praznik 			sc->defer_initialization = 1;
2535*2a242932SFrank Praznik 		}
2536decd946cSFrank Praznik 
2537decd946cSFrank Praznik 		sony_set_leds(sc);
2538decd946cSFrank Praznik 	}
2539decd946cSFrank Praznik 
2540decd946cSFrank Praznik 	return 0;
2541decd946cSFrank Praznik }
2542decd946cSFrank Praznik 
2543decd946cSFrank Praznik #endif
2544decd946cSFrank Praznik 
2545bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2546bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2547bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2548bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
25494545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
25506eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
25514545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2552c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2553b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2554a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2555b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2556bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2557bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2558bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2559bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2560bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2561bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2562ef916ef5SAntonio Ospite 	/*
2563ef916ef5SAntonio Ospite 	 * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2564ef916ef5SAntonio Ospite 	 * Logitech joystick from the device descriptor.
2565ef916ef5SAntonio Ospite 	 */
2566bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2567bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2568bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2569bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2570bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2571bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2572bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2573bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2574bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2575bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
257668a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
257768a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
257868a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
25790bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
25800bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
25818ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
25820bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
25838ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
258474500cc8SScott Moreau 	/* Nyko Core Controller for PS3 */
258574500cc8SScott Moreau 	{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
258674500cc8SScott Moreau 		.driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
2587bd28ce00SJiri Slaby 	{ }
2588bd28ce00SJiri Slaby };
2589bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2590bd28ce00SJiri Slaby 
2591bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2592bd28ce00SJiri Slaby 	.name             = "sony",
2593bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2594bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2595ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2596bd28ce00SJiri Slaby 	.probe            = sony_probe,
2597bd28ce00SJiri Slaby 	.remove           = sony_remove,
2598bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2599decd946cSFrank Praznik 	.raw_event        = sony_raw_event,
2600decd946cSFrank Praznik 
2601decd946cSFrank Praznik #ifdef CONFIG_PM
2602decd946cSFrank Praznik 	.suspend          = sony_suspend,
2603decd946cSFrank Praznik 	.resume	          = sony_resume,
2604decd946cSFrank Praznik 	.reset_resume     = sony_resume,
2605decd946cSFrank Praznik #endif
2606bd28ce00SJiri Slaby };
26078025087aSFrank Praznik 
26088025087aSFrank Praznik static int __init sony_init(void)
26098025087aSFrank Praznik {
26108025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
26118025087aSFrank Praznik 
26128025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
26138025087aSFrank Praznik }
26148025087aSFrank Praznik 
26158025087aSFrank Praznik static void __exit sony_exit(void)
26168025087aSFrank Praznik {
26178025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
26188025087aSFrank Praznik 
26198025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
26206c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
26218025087aSFrank Praznik }
26228025087aSFrank Praznik module_init(sony_init);
26238025087aSFrank Praznik module_exit(sony_exit);
2624bd28ce00SJiri Slaby 
2625bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2626