xref: /linux/drivers/hid/hid-sony.c (revision 405182c2459fe2de4a3994ef39e866993e0e61d1)
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>
11c4425c8fSFrank Praznik  *  Copyright (c) 2014-2016 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>
3949b9ca6cSRoderick Colenbrander #include <linux/crc32.h>
4049b9ca6cSRoderick Colenbrander #include <asm/unaligned.h>
41bd28ce00SJiri Slaby 
42bd28ce00SJiri Slaby #include "hid-ids.h"
43bd28ce00SJiri Slaby 
44f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT       BIT(0)
45f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB    BIT(1)
46f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT     BIT(2)
47f1c458caSSven Eckelmann #define BUZZ_CONTROLLER           BIT(3)
48f1c458caSSven Eckelmann #define PS3REMOTE                 BIT(4)
498ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5)
508ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
51b3bca326SSimon Wood #define MOTION_CONTROLLER_USB     BIT(7)
52b3bca326SSimon Wood #define MOTION_CONTROLLER_BT      BIT(8)
534545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9)
544545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT  BIT(10)
5574500cc8SScott Moreau #define SINO_LITE_CONTROLLER      BIT(11)
564ba1eeebSMikko Perttunen #define FUTUREMAX_DANCE_MAT       BIT(12)
57cc6e0bbbSJiri Kosina 
58fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
59b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
604545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\
614545ee0aSSimon Wood 				NAVIGATION_CONTROLLER_BT)
6268330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
6368330d83SFrank Praznik 				DUALSHOCK4_CONTROLLER_BT)
64fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
654545ee0aSSimon Wood 				DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
664545ee0aSSimon Wood 				NAVIGATION_CONTROLLER)
6712e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
684545ee0aSSimon Wood 				MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
69c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
70c5e0c1c4SFrank Praznik 				MOTION_CONTROLLER)
710f398230SFrank Praznik #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\
720f398230SFrank Praznik 			MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT)
7360781cf4SFrank Praznik 
7460781cf4SFrank Praznik #define MAX_LEDS 4
750a286ef2SSven Eckelmann 
764c3e8298SFrank Praznik /*
774c3e8298SFrank Praznik  * The Sixaxis reports both digital and analog values for each button on the
784c3e8298SFrank Praznik  * controller except for Start, Select and the PS button.  The controller ends
794c3e8298SFrank Praznik  * up reporting 27 axes which causes them to spill over into the multi-touch
804c3e8298SFrank Praznik  * axis values.  Additionally, the controller only has 20 actual, physical axes
814c3e8298SFrank Praznik  * so there are several unused axes in between the used ones.
824c3e8298SFrank Praznik  */
831adf904eSPavel Machek static u8 sixaxis_rdesc[] = {
84fb705a6dSAntonio Ospite 	0x05, 0x01,         /*  Usage Page (Desktop),               */
854c3e8298SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
86fb705a6dSAntonio Ospite 	0xA1, 0x01,         /*  Collection (Application),           */
87fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
88fb705a6dSAntonio Ospite 	0x85, 0x01,         /*          Report ID (1),              */
89fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
90fb705a6dSAntonio Ospite 	0x95, 0x01,         /*          Report Count (1),           */
91fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
92fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
93fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
94fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
95fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
96fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
97fb705a6dSAntonio Ospite 	0x25, 0x01,         /*          Logical Maximum (1),        */
98fb705a6dSAntonio Ospite 	0x35, 0x00,         /*          Physical Minimum (0),       */
99fb705a6dSAntonio Ospite 	0x45, 0x01,         /*          Physical Maximum (1),       */
100fb705a6dSAntonio Ospite 	0x05, 0x09,         /*          Usage Page (Button),        */
101fb705a6dSAntonio Ospite 	0x19, 0x01,         /*          Usage Minimum (01h),        */
102fb705a6dSAntonio Ospite 	0x29, 0x13,         /*          Usage Maximum (13h),        */
103fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
104fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
105fb705a6dSAntonio Ospite 	0x95, 0x0D,         /*          Report Count (13),          */
106fb705a6dSAntonio Ospite 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
107fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
108fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
109fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
110fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
111fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
112fb705a6dSAntonio Ospite 	0xA1, 0x00,         /*          Collection (Physical),      */
113fb705a6dSAntonio Ospite 	0x75, 0x08,         /*              Report Size (8),        */
114fb705a6dSAntonio Ospite 	0x95, 0x04,         /*              Report Count (4),       */
115fb705a6dSAntonio Ospite 	0x35, 0x00,         /*              Physical Minimum (0),   */
116fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
117fb705a6dSAntonio Ospite 	0x09, 0x30,         /*              Usage (X),              */
118fb705a6dSAntonio Ospite 	0x09, 0x31,         /*              Usage (Y),              */
119fb705a6dSAntonio Ospite 	0x09, 0x32,         /*              Usage (Z),              */
120fb705a6dSAntonio Ospite 	0x09, 0x35,         /*              Usage (Rz),             */
121fb705a6dSAntonio Ospite 	0x81, 0x02,         /*              Input (Variable),       */
122fb705a6dSAntonio Ospite 	0xC0,               /*          End Collection,             */
123fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
124fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
125fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
126fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
127fb705a6dSAntonio Ospite 	0x95, 0x0C,         /*          Report Count (12),          */
128fb705a6dSAntonio Ospite 	0x81, 0x01,         /*          Input (Constant),           */
129fb705a6dSAntonio Ospite 	0x75, 0x10,         /*          Report Size (16),           */
130fb705a6dSAntonio Ospite 	0x95, 0x04,         /*          Report Count (4),           */
131fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
132fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
133fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
134fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
135fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
136fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
137fb705a6dSAntonio Ospite 	0x85, 0x02,         /*          Report ID (2),              */
138fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
139fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
140fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
141fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
142fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
143fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
144fb705a6dSAntonio Ospite 	0x85, 0xEE,         /*          Report ID (238),            */
145fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
146fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
147fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
148fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
149fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
150fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
151fb705a6dSAntonio Ospite 	0x85, 0xEF,         /*          Report ID (239),            */
152fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
153fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
154fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
155fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
156fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
157fb705a6dSAntonio Ospite 	0xC0                /*  End Collection                      */
158e57a67daSMauro Carvalho Chehab };
159e57a67daSMauro Carvalho Chehab 
160c5e0c1c4SFrank Praznik /* PS/3 Motion controller */
1611adf904eSPavel Machek static u8 motion_rdesc[] = {
162c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
163c5e0c1c4SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
164c5e0c1c4SFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
165c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
166c5e0c1c4SFrank Praznik 	0x85, 0x01,         /*          Report ID (1),              */
167c5e0c1c4SFrank Praznik 	0x75, 0x01,         /*          Report Size (1),            */
1688b2513c3SSimon Wood 	0x95, 0x15,         /*          Report Count (21),          */
169c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
170c5e0c1c4SFrank Praznik 	0x25, 0x01,         /*          Logical Maximum (1),        */
171c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*          Physical Minimum (0),       */
172c5e0c1c4SFrank Praznik 	0x45, 0x01,         /*          Physical Maximum (1),       */
173c5e0c1c4SFrank Praznik 	0x05, 0x09,         /*          Usage Page (Button),        */
174c5e0c1c4SFrank Praznik 	0x19, 0x01,         /*          Usage Minimum (01h),        */
1758b2513c3SSimon Wood 	0x29, 0x15,         /*          Usage Maximum (15h),        */
1768b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           * Buttons */
1778b2513c3SSimon Wood 	0x95, 0x0B,         /*          Report Count (11),          */
178c5e0c1c4SFrank Praznik 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1798b2513c3SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), * Padding */
180c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
181c5e0c1c4SFrank Praznik 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
182c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
183c5e0c1c4SFrank Praznik 	0xA1, 0x00,         /*          Collection (Physical),      */
184c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*              Report Size (8),        */
1858b2513c3SSimon Wood 	0x95, 0x01,         /*              Report Count (1),       */
186c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*              Physical Minimum (0),   */
187c5e0c1c4SFrank Praznik 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
188c5e0c1c4SFrank Praznik 	0x09, 0x30,         /*              Usage (X),              */
1898b2513c3SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       * Trigger */
190c5e0c1c4SFrank Praznik 	0xC0,               /*          End Collection,             */
1918b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1928b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
1938b2513c3SSimon Wood 	0x95, 0x07,         /*          Report Count (7),           * skip 7 bytes */
1948b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
195c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
196c5e0c1c4SFrank Praznik 	0x75, 0x10,         /*          Report Size (16),           */
1978b2513c3SSimon Wood 	0x46, 0xFF, 0xFF,   /*          Physical Maximum (65535),   */
1988b2513c3SSimon Wood 	0x27, 0xFF, 0xFF, 0x00, 0x00, /*      Logical Maximum (65535),    */
1998b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Accels */
2008b2513c3SSimon Wood 	0x09, 0x33,         /*              Usage (rX),             */
2018b2513c3SSimon Wood 	0x09, 0x34,         /*              Usage (rY),             */
2028b2513c3SSimon Wood 	0x09, 0x35,         /*              Usage (rZ),             */
203c5e0c1c4SFrank Praznik 	0x81, 0x02,         /*          Input (Variable),           */
2048b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2058b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Accels 2nd frame */
2068b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2078b2513c3SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
2088b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2098b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Gyros */
2108b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2118b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2128b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Gyros 2nd frame */
2138b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2148b2513c3SSimon Wood 	0x75, 0x0C,         /*          Report Size (12),           */
2158b2513c3SSimon Wood 	0x46, 0xFF, 0x0F,   /*          Physical Maximum (4095),    */
2168b2513c3SSimon Wood 	0x26, 0xFF, 0x0F,   /*          Logical Maximum (4095),     */
2178b2513c3SSimon Wood 	0x95, 0x04,         /*          Report Count (4),           * Skip Temp and Magnetometers */
2188b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2198b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2208b2513c3SSimon Wood 	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
2218b2513c3SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
2228b2513c3SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           * Skip Timestamp and Extension Bytes */
2238b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2248b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2258b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2268b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2278b2513c3SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
2288b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2298b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2308b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2318b2513c3SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
232c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
233c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
234c5e0c1c4SFrank Praznik 	0x85, 0x02,         /*          Report ID (2),              */
235c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
236c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
237c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
238c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
239c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
240c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
241c5e0c1c4SFrank Praznik 	0x85, 0xEE,         /*          Report ID (238),            */
242c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
243c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
244c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
245c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
246c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
247c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
248c5e0c1c4SFrank Praznik 	0x85, 0xEF,         /*          Report ID (239),            */
249c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
250c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
251c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
252c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
253c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
254c5e0c1c4SFrank Praznik 	0xC0                /*  End Collection                      */
255c5e0c1c4SFrank Praznik };
256c5e0c1c4SFrank Praznik 
257b2723eb7SSimon Wood /* PS/3 Navigation controller */
2581adf904eSPavel Machek static u8 navigation_rdesc[] = {
259b2723eb7SSimon Wood 	0x05, 0x01,         /*  Usage Page (Desktop),               */
260d542176fSAntonio Ospite 	0x09, 0x04,         /*  Usage (Joystick),                   */
261b2723eb7SSimon Wood 	0xA1, 0x01,         /*  Collection (Application),           */
262b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
263b2723eb7SSimon Wood 	0x85, 0x01,         /*          Report ID (1),              */
264b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
265b2723eb7SSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
266b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
267b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
268b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
269b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
270b2723eb7SSimon Wood 	0x95, 0x13,         /*          Report Count (19),          */
271b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
272b2723eb7SSimon Wood 	0x25, 0x01,         /*          Logical Maximum (1),        */
273b2723eb7SSimon Wood 	0x35, 0x00,         /*          Physical Minimum (0),       */
274b2723eb7SSimon Wood 	0x45, 0x01,         /*          Physical Maximum (1),       */
275b2723eb7SSimon Wood 	0x05, 0x09,         /*          Usage Page (Button),        */
276b2723eb7SSimon Wood 	0x19, 0x01,         /*          Usage Minimum (01h),        */
277b2723eb7SSimon Wood 	0x29, 0x13,         /*          Usage Maximum (13h),        */
278b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
279b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
280b2723eb7SSimon Wood 	0x95, 0x0D,         /*          Report Count (13),          */
281b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
282b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
283b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
284b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
285b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
286b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
287b2723eb7SSimon Wood 	0xA1, 0x00,         /*          Collection (Physical),      */
288b2723eb7SSimon Wood 	0x75, 0x08,         /*              Report Size (8),        */
289b2723eb7SSimon Wood 	0x95, 0x02,         /*              Report Count (2),       */
290b2723eb7SSimon Wood 	0x35, 0x00,         /*              Physical Minimum (0),   */
291b2723eb7SSimon Wood 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
292b2723eb7SSimon Wood 	0x09, 0x30,         /*              Usage (X),              */
293b2723eb7SSimon Wood 	0x09, 0x31,         /*              Usage (Y),              */
294b2723eb7SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       */
295b2723eb7SSimon Wood 	0xC0,               /*          End Collection,             */
296b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
297b2723eb7SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           */
298b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
299b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
300b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
301b2723eb7SSimon Wood 	0x95, 0x05,         /*          Report Count (5),           */
302b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
303b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
304b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3052259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3062259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3072259b5bbSSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
3082259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3092259b5bbSSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
3102259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3112259b5bbSSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3122259b5bbSSimon Wood 	0x95, 0x1E,         /*          Report Count (24),          */
313b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
314b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
315b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
316b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
317b2723eb7SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
318b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
319b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
320b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
321b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
322b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
323b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
324b2723eb7SSimon Wood 	0x85, 0x02,         /*          Report ID (2),              */
325b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
326b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
327b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
328b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
329b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
330b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
331b2723eb7SSimon Wood 	0x85, 0xEE,         /*          Report ID (238),            */
332b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
333b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
334b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
335b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
336b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
337b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
338b2723eb7SSimon Wood 	0x85, 0xEF,         /*          Report ID (239),            */
339b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
340b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
341b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
342b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
343b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
344b2723eb7SSimon Wood 	0xC0                /*  End Collection                      */
345b2723eb7SSimon Wood };
346c5e0c1c4SFrank Praznik 
347ad142b9eSFrank Praznik /*
348ad142b9eSFrank Praznik  * The default descriptor doesn't provide mapping for the accelerometers
34958d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
35058d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
35158d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
35258d7027bSFrank Praznik  */
353ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
35458d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
35558d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
35658d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
35758d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
35858d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
35958d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
36058d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
36158d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
36258d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36358d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
36458d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
36558d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
36658d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
36758d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
36858d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36958d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
37058d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
37158d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
37258d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
37358d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
37458d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
37558d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
37658d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
37758d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
37858d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
379ac797b95SRoderick Colenbrander 	0x29, 0x0D,         /*      Usage Maximum (0Dh),            */
38058d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
38158d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
38258d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
38358d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
38458d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
38558d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
38658d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
38758d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
38858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
38958d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
390fb291cbdSFrank Praznik 	0x25, 0x3F,         /*      Logical Maximum (63),           */
39158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39258d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
39358d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
39458d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
39558d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
39658d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
39758d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
39858d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
39958d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40058d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
40158d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
40258d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40358d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40458d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
40558d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
40658d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
40758d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
408bdae9e0eSRoderick Colenbrander 	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
40958d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
41058d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
41158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41258d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
41358d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
414bdae9e0eSRoderick Colenbrander 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
415bdae9e0eSRoderick Colenbrander 	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
41658d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
41758d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41858d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
41958d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
42058d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
421fb291cbdSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
42258d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
42358d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
42458d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
42558d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
42658d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
42758d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
42858d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
42958d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
43058d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
43158d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
43258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43358d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
43458d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
43558d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
43658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43758d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
43858d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
43958d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
44058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44158d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
44258d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
44358d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
44458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44558d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
44658d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
44758d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
44858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44958d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
45058d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
45158d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
45258d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
45358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45458d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
45558d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
45658d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
45758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45858d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
45958d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
46058d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
46158d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
46258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46358d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
46458d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
46558d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
46658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46758d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
46858d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
46958d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
47058d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
47158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47258d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
47358d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
47458d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
47558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47658d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
47758d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
47858d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
47958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48058d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
48158d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
48258d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
48358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48458d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
48558d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
48658d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
48758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48858d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
48958d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
49058d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
49158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49258d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
49358d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
49458d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
49558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49658d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
49758d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
49858d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
49958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50058d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
50158d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
50258d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
50358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50458d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
50558d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
50658d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
50758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50858d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
50958d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
51058d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
51158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51258d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
51358d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
51458d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51658d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
51758d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
51858d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52058d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
52158d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
52258d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
52358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52458d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
52558d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
52658d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
52758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52858d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
52958d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
53058d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
53158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53258d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
53358d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
53458d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
53558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53658d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
53758d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
53858d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
53958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54058d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
54158d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
54258d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
54358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54458d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
54558d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
54658d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54858d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
54958d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
55058d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
55158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55258d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
55358d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
55458d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55658d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
55758d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
55858d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56058d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
56158d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
56258d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
56358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56458d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
56558d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
56658d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56858d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
56958d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
57058d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
57158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57258d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
57358d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
57458d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
57558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57658d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
57758d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
57858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
57958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58058d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
58158d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
58258d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58458d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
58558d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
58658d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58858d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
58958d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
59058d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
59158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59258d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
59358d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
59458d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
59558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59658d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
59758d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
59858d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
59958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
60058d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
60158d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
60258d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
60358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
60458d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
605ed19d8cfSFrank Praznik };
606ed19d8cfSFrank Praznik 
607ad142b9eSFrank Praznik /*
608ad142b9eSFrank Praznik  * The default behavior of the Dualshock 4 is to send reports using report
609077147a3SFrank Praznik  * type 1 when running over Bluetooth. However, when feature report 2 is
610077147a3SFrank Praznik  * requested during the controller initialization it starts sending input
611077147a3SFrank Praznik  * reports in report 17.  Since report 17 is undefined in the default HID
612d829674dSFrank Praznik  * descriptor the button and axis definitions must be moved to report 17 or
613077147a3SFrank Praznik  * the HID layer won't process the received input.
614d829674dSFrank Praznik  */
615d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = {
616d829674dSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
617d829674dSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
618d829674dSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
619d829674dSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
620d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
621d829674dSFrank Praznik 	0x95, 0x0A,         /*      Report Count (9),               */
622d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
623d829674dSFrank Praznik 	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
624d829674dSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
625d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
626d829674dSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
627d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
628d829674dSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
629d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
630d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
631d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
632d829674dSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
633d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
634d829674dSFrank Praznik 	0x95, 0x28,         /*      Report Count (40),              */
635d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
636d829674dSFrank Praznik 	0x85, 0x06,         /*      Report ID (6),                  */
637d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
638d829674dSFrank Praznik 	0x95, 0x34,         /*      Report Count (52),              */
639d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
640d829674dSFrank Praznik 	0x85, 0x07,         /*      Report ID (7),                  */
641d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
642d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
643d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
644d829674dSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
645d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
646d829674dSFrank Praznik 	0x95, 0x2F,         /*      Report Count (47),              */
647d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
648d829674dSFrank Praznik 	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
649d829674dSFrank Praznik 	0x85, 0x03,         /*      Report ID (3),                  */
650d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
651d829674dSFrank Praznik 	0x95, 0x26,         /*      Report Count (38),              */
652d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
653d829674dSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
654d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
655d829674dSFrank Praznik 	0x95, 0x2E,         /*      Report Count (46),              */
656d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
657d829674dSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
658d829674dSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
659d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
660d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
661d829674dSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
662d829674dSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
663d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
664d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
665d829674dSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
666d829674dSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
667d829674dSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
668d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
669d829674dSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
670d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
671d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
672d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
673d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
674d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
675d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
676d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
677d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
678d829674dSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
679d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
680d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
681d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
682d829674dSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
683d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
684d829674dSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
685d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
686d829674dSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
687d829674dSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
688d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
689d829674dSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
690d829674dSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
691d829674dSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
692ac797b95SRoderick Colenbrander 	0x29, 0x0D,         /*      Usage Maximum (0Dh),            */
693d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
694d829674dSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
695d829674dSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
696d829674dSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
697d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
698d829674dSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
699d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
700d829674dSFrank Praznik 	0x81, 0x01,         /*      Input (Constant),               */
701d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
702d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
703d829674dSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
704d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
705d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
706d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
707d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
708d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
709d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
710d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
711d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
712d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
713d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
714d829674dSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
715d829674dSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
716d829674dSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
717bdae9e0eSRoderick Colenbrander 	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
718d829674dSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
719d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
720d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
721d829674dSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
722d829674dSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
723bdae9e0eSRoderick Colenbrander 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
724bdae9e0eSRoderick Colenbrander 	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
725d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
726d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
727d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
728d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
729d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
730d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
731d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
732d829674dSFrank Praznik 	0x95, 0x31,         /*      Report Count (51),              */
733d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
734d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
735d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
736d829674dSFrank Praznik 	0x95, 0x4D,         /*      Report Count (77),              */
737d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
738d829674dSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
739d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
740d829674dSFrank Praznik 	0x95, 0x8D,         /*      Report Count (141),             */
741d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
742d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
743d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
744d829674dSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
745d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
746d829674dSFrank Praznik 	0x95, 0xCD,         /*      Report Count (205),             */
747d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
748d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
749d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
750d829674dSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
751d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
752d829674dSFrank Praznik 	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
753d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
754d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
755d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
756d829674dSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
757d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
758d829674dSFrank Praznik 	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
759d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
760d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
761d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
762d829674dSFrank Praznik 	0x85, 0x16,         /*      Report ID (22),                 */
763d829674dSFrank Praznik 	0x09, 0x2A,         /*      Usage (2Ah),                    */
764d829674dSFrank Praznik 	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
765d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
766d829674dSFrank Praznik 	0x09, 0x2B,         /*      Usage (2Bh),                    */
767d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
768d829674dSFrank Praznik 	0x85, 0x17,         /*      Report ID (23),                 */
769d829674dSFrank Praznik 	0x09, 0x2C,         /*      Usage (2Ch),                    */
770d829674dSFrank Praznik 	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
771d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
772d829674dSFrank Praznik 	0x09, 0x2D,         /*      Usage (2Dh),                    */
773d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
774d829674dSFrank Praznik 	0x85, 0x18,         /*      Report ID (24),                 */
775d829674dSFrank Praznik 	0x09, 0x2E,         /*      Usage (2Eh),                    */
776d829674dSFrank Praznik 	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
777d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
778d829674dSFrank Praznik 	0x09, 0x2F,         /*      Usage (2Fh),                    */
779d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
780d829674dSFrank Praznik 	0x85, 0x19,         /*      Report ID (25),                 */
781d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
782d829674dSFrank Praznik 	0x96, 0x22, 0x02,   /*      Report Count (546),             */
783d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
784d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
785d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
786d829674dSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
787d829674dSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
788d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
789d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
790d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
791d829674dSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
792d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
793d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
794d829674dSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
795d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
796d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
797d829674dSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
798d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
799d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
800d829674dSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
801d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
802d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
803d829674dSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
804d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
805d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
806d829674dSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
807d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
808d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
809d829674dSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
810d829674dSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
811d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
812d829674dSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
813d829674dSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
814d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
815d829674dSFrank Praznik 	0xC0                /*  End Collection                      */
816d829674dSFrank Praznik };
817d829674dSFrank Praznik 
8181adf904eSPavel Machek static u8 ps3remote_rdesc[] = {
819078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
820078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
821078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
822078328daSJiri Kosina 
823078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
824078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
825078328daSJiri Kosina 
826ef916ef5SAntonio Ospite 	  /*
827ef916ef5SAntonio Ospite 	   * Ignore the 1st byte, maybe it is used for a controller
828ef916ef5SAntonio Ospite 	   * number but it's not needed for correct operation
829ef916ef5SAntonio Ospite 	   */
830078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
831078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
832078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
833078328daSJiri Kosina 
834ef916ef5SAntonio Ospite 	  /*
835ef916ef5SAntonio Ospite 	   * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
836ef916ef5SAntonio Ospite 	   * buttons multiple keypresses are allowed
837ef916ef5SAntonio Ospite 	   */
838078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
839078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
840078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
841078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
842078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
843078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
844078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
845078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
846078328daSJiri Kosina 
847078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
848078328daSJiri Kosina 
849078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
850078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
851078328daSJiri Kosina 
852078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
853078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
854078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
855078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
856078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
857078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
858078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
859078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
860078328daSJiri Kosina 	  0x80,              /* MInput  */
861078328daSJiri Kosina 
862ef916ef5SAntonio Ospite 	  /*
863ef916ef5SAntonio Ospite 	   * Ignore bytes from 6th to 11th, 6th to 10th are always constant at
864ef916ef5SAntonio Ospite 	   * 0xff and 11th is for press indication
865ef916ef5SAntonio Ospite 	   */
866078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
867078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
868078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
869078328daSJiri Kosina 
870078328daSJiri Kosina 	  /* 12th byte is for battery strength */
871078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
872078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
873078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
874078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
875078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
876078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
877078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
878078328daSJiri Kosina 
879078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
880078328daSJiri Kosina 
881078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
882078328daSJiri Kosina };
883078328daSJiri Kosina 
884078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
885078328daSJiri Kosina 	[0x01] = KEY_SELECT,
886078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
887078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
888078328daSJiri Kosina 	[0x04] = BTN_START,
889078328daSJiri Kosina 	[0x05] = KEY_UP,
890078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
891078328daSJiri Kosina 	[0x07] = KEY_DOWN,
892078328daSJiri Kosina 	[0x08] = KEY_LEFT,
893078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
894078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
895078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
896078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
897078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
898078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
899078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
900078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
901078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
902078328daSJiri Kosina 	[0x14] = KEY_ENTER,
903078328daSJiri Kosina };
904078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
905078328daSJiri Kosina 	[0x00] = KEY_1,
906078328daSJiri Kosina 	[0x01] = KEY_2,
907078328daSJiri Kosina 	[0x02] = KEY_3,
908078328daSJiri Kosina 	[0x03] = KEY_4,
909078328daSJiri Kosina 	[0x04] = KEY_5,
910078328daSJiri Kosina 	[0x05] = KEY_6,
911078328daSJiri Kosina 	[0x06] = KEY_7,
912078328daSJiri Kosina 	[0x07] = KEY_8,
913078328daSJiri Kosina 	[0x08] = KEY_9,
914078328daSJiri Kosina 	[0x09] = KEY_0,
915078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
916078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
917078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
918078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
919078328daSJiri Kosina 	[0x28] = KEY_TIME,
920078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
921078328daSJiri Kosina 	[0x31] = KEY_NEXT,
922078328daSJiri Kosina 	[0x32] = KEY_PLAY,
923078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
924078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
925078328daSJiri Kosina 	[0x38] = KEY_STOP,
926078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
927078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
928078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
929078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
930078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
931078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
932078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
933078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
934078328daSJiri Kosina 	[0x80] = KEY_BLUE,
935078328daSJiri Kosina 	[0x81] = KEY_RED,
936078328daSJiri Kosina 	[0x82] = KEY_GREEN,
937078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
938078328daSJiri Kosina };
939078328daSJiri Kosina 
940f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
941ad142b9eSFrank Praznik 	/*
942ad142b9eSFrank Praznik 	 * The controller has 4 remote buzzers, each with one LED and 5
943f04d5140SColin Leitner 	 * buttons.
944f04d5140SColin Leitner 	 *
945f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
946f04d5140SColin Leitner 	 *
947f04d5140SColin Leitner 	 * Key          Offset
948f04d5140SColin Leitner 	 * -------------------
949f04d5140SColin Leitner 	 * Buzz              1
950f04d5140SColin Leitner 	 * Blue              5
951f04d5140SColin Leitner 	 * Orange            4
952f04d5140SColin Leitner 	 * Green             3
953f04d5140SColin Leitner 	 * Yellow            2
954f04d5140SColin Leitner 	 *
955f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
956f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
957f04d5140SColin Leitner 	 */
958f04d5140SColin Leitner 	 [1] = BTN_TRIGGER_HAPPY1,
959f04d5140SColin Leitner 	 [2] = BTN_TRIGGER_HAPPY2,
960f04d5140SColin Leitner 	 [3] = BTN_TRIGGER_HAPPY3,
961f04d5140SColin Leitner 	 [4] = BTN_TRIGGER_HAPPY4,
962f04d5140SColin Leitner 	 [5] = BTN_TRIGGER_HAPPY5,
963f04d5140SColin Leitner 	 [6] = BTN_TRIGGER_HAPPY6,
964f04d5140SColin Leitner 	 [7] = BTN_TRIGGER_HAPPY7,
965f04d5140SColin Leitner 	 [8] = BTN_TRIGGER_HAPPY8,
966f04d5140SColin Leitner 	 [9] = BTN_TRIGGER_HAPPY9,
967f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
968f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
969f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
970f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
971f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
972f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
973f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
974f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
975f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
976f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
977f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
978f04d5140SColin Leitner };
979f04d5140SColin Leitner 
9809131f8ccSRoderick Colenbrander static const unsigned int ds4_absmap[] = {
9819131f8ccSRoderick Colenbrander 	[0x30] = ABS_X,
9829131f8ccSRoderick Colenbrander 	[0x31] = ABS_Y,
9839131f8ccSRoderick Colenbrander 	[0x32] = ABS_RX, /* right stick X */
9849131f8ccSRoderick Colenbrander 	[0x33] = ABS_Z, /* L2 */
9859131f8ccSRoderick Colenbrander 	[0x34] = ABS_RZ, /* R2 */
9869131f8ccSRoderick Colenbrander 	[0x35] = ABS_RY, /* right stick Y */
9879131f8ccSRoderick Colenbrander };
9889131f8ccSRoderick Colenbrander 
9899131f8ccSRoderick Colenbrander static const unsigned int ds4_keymap[] = {
9909131f8ccSRoderick Colenbrander 	[0x1] = BTN_WEST, /* Square */
9919131f8ccSRoderick Colenbrander 	[0x2] = BTN_SOUTH, /* Cross */
9929131f8ccSRoderick Colenbrander 	[0x3] = BTN_EAST, /* Circle */
9939131f8ccSRoderick Colenbrander 	[0x4] = BTN_NORTH, /* Triangle */
9949131f8ccSRoderick Colenbrander 	[0x5] = BTN_TL, /* L1 */
9959131f8ccSRoderick Colenbrander 	[0x6] = BTN_TR, /* R1 */
9969131f8ccSRoderick Colenbrander 	[0x7] = BTN_TL2, /* L2 */
9979131f8ccSRoderick Colenbrander 	[0x8] = BTN_TR2, /* R2 */
9989131f8ccSRoderick Colenbrander 	[0x9] = BTN_SELECT, /* Share */
9999131f8ccSRoderick Colenbrander 	[0xa] = BTN_START, /* Options */
10009131f8ccSRoderick Colenbrander 	[0xb] = BTN_THUMBL, /* L3 */
10019131f8ccSRoderick Colenbrander 	[0xc] = BTN_THUMBR, /* R3 */
10029131f8ccSRoderick Colenbrander 	[0xd] = BTN_MODE, /* PS */
10039131f8ccSRoderick Colenbrander };
10049131f8ccSRoderick Colenbrander 
10059131f8ccSRoderick Colenbrander 
1006d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
1007d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
1008d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
1009d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
1010d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
1011d902f472SFrank Praznik };
1012d902f472SFrank Praznik 
101355d3b664SFrank Praznik struct sixaxis_led {
10141adf904eSPavel Machek 	u8 time_enabled; /* the total time the led is active (0xff means forever) */
10151adf904eSPavel Machek 	u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
10161adf904eSPavel Machek 	u8 enabled;
10171adf904eSPavel Machek 	u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
10181adf904eSPavel Machek 	u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
101955d3b664SFrank Praznik } __packed;
102055d3b664SFrank Praznik 
102155d3b664SFrank Praznik struct sixaxis_rumble {
10221adf904eSPavel Machek 	u8 padding;
10231adf904eSPavel Machek 	u8 right_duration; /* Right motor duration (0xff means forever) */
10241adf904eSPavel Machek 	u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
10251adf904eSPavel Machek 	u8 left_duration;    /* Left motor duration (0xff means forever) */
10261adf904eSPavel Machek 	u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
102755d3b664SFrank Praznik } __packed;
102855d3b664SFrank Praznik 
102955d3b664SFrank Praznik struct sixaxis_output_report {
10301adf904eSPavel Machek 	u8 report_id;
103155d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
10321adf904eSPavel Machek 	u8 padding[4];
10331adf904eSPavel Machek 	u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
103455d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
103555d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
103655d3b664SFrank Praznik } __packed;
103755d3b664SFrank Praznik 
103855d3b664SFrank Praznik union sixaxis_output_report_01 {
103955d3b664SFrank Praznik 	struct sixaxis_output_report data;
10401adf904eSPavel Machek 	u8 buf[36];
104155d3b664SFrank Praznik };
104255d3b664SFrank Praznik 
1043c5e0c1c4SFrank Praznik struct motion_output_report_02 {
1044c5e0c1c4SFrank Praznik 	u8 type, zero;
1045c5e0c1c4SFrank Praznik 	u8 r, g, b;
1046c5e0c1c4SFrank Praznik 	u8 zero2;
1047c5e0c1c4SFrank Praznik 	u8 rumble;
1048c5e0c1c4SFrank Praznik };
1049c5e0c1c4SFrank Praznik 
10502c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x02_SIZE 37
10512c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x81_SIZE 7
105249b9ca6cSRoderick Colenbrander #define DS4_INPUT_REPORT_0x11_SIZE 78
10532c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x05_SIZE 32
10542c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x11_SIZE 78
105529b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
1056a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
105741d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
10589b2b5c9aSFrank Praznik 
1059cdc1c021SRoderick Colenbrander /* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an
1060cdc1c021SRoderick Colenbrander  * additional +2.
1061cdc1c021SRoderick Colenbrander  */
1062ac797b95SRoderick Colenbrander #define DS4_INPUT_REPORT_BUTTON_OFFSET    5
1063cdc1c021SRoderick Colenbrander #define DS4_INPUT_REPORT_BATTERY_OFFSET  30
1064cdc1c021SRoderick Colenbrander #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33
1065cdc1c021SRoderick Colenbrander 
1066ac797b95SRoderick Colenbrander #define DS4_TOUCHPAD_SUFFIX " Touchpad"
1067ac797b95SRoderick Colenbrander 
10688b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
1069d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
10708025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
1071d2d782fcSFrank Praznik 
1072cc6e0bbbSJiri Kosina struct sony_sc {
1073d902f472SFrank Praznik 	spinlock_t lock;
1074d2d782fcSFrank Praznik 	struct list_head list_node;
10750a286ef2SSven Eckelmann 	struct hid_device *hdev;
1076ac797b95SRoderick Colenbrander 	struct input_dev *touchpad;
107760781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
1078cc6e0bbbSJiri Kosina 	unsigned long quirks;
10790a286ef2SSven Eckelmann 	struct work_struct state_worker;
1080d8aaccdaSFrank Praznik 	void (*send_output_report)(struct sony_sc *);
1081297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
1082297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
10838025087aSFrank Praznik 	int device_id;
10841adf904eSPavel Machek 	u8 *output_report_dmabuf;
1085f04d5140SColin Leitner 
10869f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
10871adf904eSPavel Machek 	u8 left;
10881adf904eSPavel Machek 	u8 right;
10899f323b68SSven Eckelmann #endif
10909f323b68SSven Eckelmann 
10911adf904eSPavel Machek 	u8 mac_address[6];
10921adf904eSPavel Machek 	u8 worker_initialized;
10932a242932SFrank Praznik 	u8 defer_initialization;
10941adf904eSPavel Machek 	u8 cable_state;
10951adf904eSPavel Machek 	u8 battery_charging;
10961adf904eSPavel Machek 	u8 battery_capacity;
10971adf904eSPavel Machek 	u8 led_state[MAX_LEDS];
10981adf904eSPavel Machek 	u8 resume_led_state[MAX_LEDS];
10991adf904eSPavel Machek 	u8 led_delay_on[MAX_LEDS];
11001adf904eSPavel Machek 	u8 led_delay_off[MAX_LEDS];
11011adf904eSPavel Machek 	u8 led_count;
1102*405182c2SRoderick Colenbrander 	bool ds4_dongle_connected;
1103cc6e0bbbSJiri Kosina };
1104cc6e0bbbSJiri Kosina 
1105*405182c2SRoderick Colenbrander static void sony_set_leds(struct sony_sc *sc);
1106*405182c2SRoderick Colenbrander 
11072a242932SFrank Praznik static inline void sony_schedule_work(struct sony_sc *sc)
11082a242932SFrank Praznik {
11092a242932SFrank Praznik 	if (!sc->defer_initialization)
11102a242932SFrank Praznik 		schedule_work(&sc->state_worker);
11112a242932SFrank Praznik }
11122a242932SFrank Praznik 
11131adf904eSPavel Machek static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc,
1114c607fb8dSAntonio Ospite 			     unsigned int *rsize)
1115c607fb8dSAntonio Ospite {
1116c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
1117c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
1118c607fb8dSAntonio Ospite }
1119c607fb8dSAntonio Ospite 
1120c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
1121c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
1122c5e0c1c4SFrank Praznik {
1123c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
1124c5e0c1c4SFrank Praznik 	return motion_rdesc;
1125c5e0c1c4SFrank Praznik }
1126c5e0c1c4SFrank Praznik 
1127b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc,
1128b2723eb7SSimon Wood 			     unsigned int *rsize)
1129b2723eb7SSimon Wood {
1130b2723eb7SSimon Wood 	*rsize = sizeof(navigation_rdesc);
1131b2723eb7SSimon Wood 	return navigation_rdesc;
1132b2723eb7SSimon Wood }
1133b2723eb7SSimon Wood 
11341adf904eSPavel Machek static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc,
1135078328daSJiri Kosina 			     unsigned int *rsize)
1136078328daSJiri Kosina {
1137078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
1138078328daSJiri Kosina 	return ps3remote_rdesc;
1139078328daSJiri Kosina }
1140078328daSJiri Kosina 
1141078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
1142078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
1143078328daSJiri Kosina 			     unsigned long **bit, int *max)
1144078328daSJiri Kosina {
1145078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
1146078328daSJiri Kosina 
1147078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1148078328daSJiri Kosina 		return -1;
1149078328daSJiri Kosina 
1150078328daSJiri Kosina 	switch (usage->collection_index) {
1151078328daSJiri Kosina 	case 1:
1152078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
1153078328daSJiri Kosina 			return -1;
1154078328daSJiri Kosina 
1155078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
1156078328daSJiri Kosina 		if (!key)
1157078328daSJiri Kosina 			return -1;
1158078328daSJiri Kosina 		break;
1159078328daSJiri Kosina 	case 2:
1160078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1161078328daSJiri Kosina 			return -1;
1162078328daSJiri Kosina 
1163078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1164078328daSJiri Kosina 		if (!key)
1165078328daSJiri Kosina 			return -1;
1166078328daSJiri Kosina 		break;
1167078328daSJiri Kosina 	default:
1168078328daSJiri Kosina 		return -1;
1169078328daSJiri Kosina 	}
1170078328daSJiri Kosina 
1171078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1172078328daSJiri Kosina 	return 1;
1173078328daSJiri Kosina }
1174078328daSJiri Kosina 
11759131f8ccSRoderick Colenbrander static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi,
11769131f8ccSRoderick Colenbrander 		       struct hid_field *field, struct hid_usage *usage,
11779131f8ccSRoderick Colenbrander 		       unsigned long **bit, int *max)
11789131f8ccSRoderick Colenbrander {
11799131f8ccSRoderick Colenbrander 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
11809131f8ccSRoderick Colenbrander 		unsigned int key = usage->hid & HID_USAGE;
11819131f8ccSRoderick Colenbrander 
11829131f8ccSRoderick Colenbrander 		if (key >= ARRAY_SIZE(ds4_keymap))
11839131f8ccSRoderick Colenbrander 			return -1;
11849131f8ccSRoderick Colenbrander 
11859131f8ccSRoderick Colenbrander 		key = ds4_keymap[key];
11869131f8ccSRoderick Colenbrander 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
11879131f8ccSRoderick Colenbrander 		return 1;
11889131f8ccSRoderick Colenbrander 	} else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
11899131f8ccSRoderick Colenbrander 		unsigned int abs = usage->hid & HID_USAGE;
11909131f8ccSRoderick Colenbrander 
11919131f8ccSRoderick Colenbrander 		/* Let the HID parser deal with the HAT. */
11929131f8ccSRoderick Colenbrander 		if (usage->hid == HID_GD_HATSWITCH)
11939131f8ccSRoderick Colenbrander 			return 0;
11949131f8ccSRoderick Colenbrander 
11959131f8ccSRoderick Colenbrander 		if (abs >= ARRAY_SIZE(ds4_absmap))
11969131f8ccSRoderick Colenbrander 			return -1;
11979131f8ccSRoderick Colenbrander 
11989131f8ccSRoderick Colenbrander 		abs = ds4_absmap[abs];
11999131f8ccSRoderick Colenbrander 		hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
12009131f8ccSRoderick Colenbrander 		return 1;
12019131f8ccSRoderick Colenbrander 	}
12029131f8ccSRoderick Colenbrander 
12039131f8ccSRoderick Colenbrander 	return 0;
12049131f8ccSRoderick Colenbrander }
12059131f8ccSRoderick Colenbrander 
12061adf904eSPavel Machek static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
120773e4008dSNikolai Kondrashov 		unsigned int *rsize)
1208cc6e0bbbSJiri Kosina {
1209cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1210cc6e0bbbSJiri Kosina 
12114ba1eeebSMikko Perttunen 	if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
121274500cc8SScott Moreau 		return rdesc;
121374500cc8SScott Moreau 
121499d24902SFernando Luis Vázquez Cao 	/*
121599d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
121699d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
121799d24902SFernando Luis Vázquez Cao 	 */
121899d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
121999d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
122099d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
122199d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
122299d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
122399d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
122499d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1225a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
122699d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1227cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1228cc6e0bbbSJiri Kosina 	}
122961ab44beSSimon Wood 
1230ed19d8cfSFrank Praznik 	/*
1231ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1232ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1233ed19d8cfSFrank Praznik 	 * modified one.
1234ed19d8cfSFrank Praznik 	 */
1235b71b5578SFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1236ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1237ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1238ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1239b71b5578SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
1240d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1241d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1242d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1243ed19d8cfSFrank Praznik 	}
1244ed19d8cfSFrank Praznik 
1245c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1246c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1247078328daSJiri Kosina 
1248c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1249c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1250c5e0c1c4SFrank Praznik 
12514545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1252b2723eb7SSimon Wood 		return navigation_fixup(hdev, rdesc, rsize);
12534545ee0aSSimon Wood 
1254078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1255078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1256078328daSJiri Kosina 
125773e4008dSNikolai Kondrashov 	return rdesc;
1258cc6e0bbbSJiri Kosina }
1259cc6e0bbbSJiri Kosina 
12601adf904eSPavel Machek static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
1261d902f472SFrank Praznik {
12621adf904eSPavel Machek 	static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1263d902f472SFrank Praznik 	unsigned long flags;
126412e9a6d7SSimon Wood 	int offset;
12651adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1266d902f472SFrank Praznik 
1267ad142b9eSFrank Praznik 	/*
1268ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1269d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1270d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1271d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1272d902f472SFrank Praznik 	 */
127312e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
127412e9a6d7SSimon Wood 
127512e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1276d902f472SFrank Praznik 		battery_capacity = 100;
127712e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
12789fddd74aSFrank Praznik 		cable_state = 1;
1279d902f472SFrank Praznik 	} else {
12801adf904eSPavel Machek 		u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1281ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1282d902f472SFrank Praznik 		battery_charging = 0;
12839fddd74aSFrank Praznik 		cable_state = 0;
1284d902f472SFrank Praznik 	}
1285d902f472SFrank Praznik 
1286d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1287d902f472SFrank Praznik 	sc->cable_state = cable_state;
1288d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1289d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1290d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1291d902f472SFrank Praznik }
1292d902f472SFrank Praznik 
12931adf904eSPavel Machek static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1294d902f472SFrank Praznik {
1295d902f472SFrank Praznik 	unsigned long flags;
1296cdc1c021SRoderick Colenbrander 	int n, m, offset, num_touch_data, max_touch_data;
12971adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1298d902f472SFrank Praznik 
1299cdc1c021SRoderick Colenbrander 	/* When using Bluetooth the header is 2 bytes longer, so skip these. */
1300cdc1c021SRoderick Colenbrander 	int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2;
13016c5f860dSFrank Praznik 
1302ac797b95SRoderick Colenbrander 	/* Second bit of third button byte is for the touchpad button. */
1303ac797b95SRoderick Colenbrander 	offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET;
1304ac797b95SRoderick Colenbrander 	input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2);
1305ac797b95SRoderick Colenbrander 
1306ad142b9eSFrank Praznik 	/*
1307cdc1c021SRoderick Colenbrander 	 * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level
1308d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1309d902f472SFrank Praznik 	 */
1310cdc1c021SRoderick Colenbrander 	offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET;
13116c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
13126c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1313d902f472SFrank Praznik 
1314ad142b9eSFrank Praznik 	/*
1315ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
13166c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
13176c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1318d902f472SFrank Praznik 	 */
13196c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1320d902f472SFrank Praznik 		battery_charging = 0;
1321d902f472SFrank Praznik 	else
1322d902f472SFrank Praznik 		battery_charging = 1;
1323d902f472SFrank Praznik 
13246c5f860dSFrank Praznik 	if (!cable_state)
13256c5f860dSFrank Praznik 		battery_capacity++;
1326d902f472SFrank Praznik 	if (battery_capacity > 10)
13276c5f860dSFrank Praznik 		battery_capacity = 10;
13286c5f860dSFrank Praznik 
1329d902f472SFrank Praznik 	battery_capacity *= 10;
1330d902f472SFrank Praznik 
1331d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1332d902f472SFrank Praznik 	sc->cable_state = cable_state;
1333d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1334d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1335d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1336e5606230SFrank Praznik 
1337cdc1c021SRoderick Colenbrander 	/*
1338cdc1c021SRoderick Colenbrander 	 * The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB
1339cdc1c021SRoderick Colenbrander 	 * and 35 on Bluetooth.
1340cdc1c021SRoderick Colenbrander 	 * The first byte indicates the number of touch data in the report.
1341cdc1c021SRoderick Colenbrander 	 * Trackpad data starts 2 bytes later (e.g. 35 for USB).
1342cdc1c021SRoderick Colenbrander 	 */
1343cdc1c021SRoderick Colenbrander 	offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET;
1344cdc1c021SRoderick Colenbrander 	max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4;
1345cdc1c021SRoderick Colenbrander 	if (rd[offset] > 0 && rd[offset] <= max_touch_data)
1346cdc1c021SRoderick Colenbrander 		num_touch_data = rd[offset];
1347cdc1c021SRoderick Colenbrander 	else
1348cdc1c021SRoderick Colenbrander 		num_touch_data = 1;
1349cdc1c021SRoderick Colenbrander 	offset += 1;
1350cdc1c021SRoderick Colenbrander 
1351cdc1c021SRoderick Colenbrander 	for (m = 0; m < num_touch_data; m++) {
1352cdc1c021SRoderick Colenbrander 		/* Skip past timestamp */
1353cdc1c021SRoderick Colenbrander 		offset += 1;
13546c5f860dSFrank Praznik 
1355ad142b9eSFrank Praznik 		/*
1356cdc1c021SRoderick Colenbrander 		 * The first 7 bits of the first byte is a counter and bit 8 is
1357cdc1c021SRoderick Colenbrander 		 * a touch indicator that is 0 when pressed and 1 when not
1358cdc1c021SRoderick Colenbrander 		 * pressed.
1359e5606230SFrank Praznik 		 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1360cdc1c021SRoderick Colenbrander 		 * The data for the second touch is in the same format and
1361cdc1c021SRoderick Colenbrander 		 * immediately follows the data for the first.
1362e5606230SFrank Praznik 		 */
1363e5606230SFrank Praznik 		for (n = 0; n < 2; n++) {
13641adf904eSPavel Machek 			u16 x, y;
1365cdc1c021SRoderick Colenbrander 			bool active;
1366e5606230SFrank Praznik 
1367e5606230SFrank Praznik 			x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1368e5606230SFrank Praznik 			y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1369e5606230SFrank Praznik 
1370cdc1c021SRoderick Colenbrander 			active = !(rd[offset] >> 7);
1371ac797b95SRoderick Colenbrander 			input_mt_slot(sc->touchpad, n);
1372ac797b95SRoderick Colenbrander 			input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active);
1373cdc1c021SRoderick Colenbrander 
1374cdc1c021SRoderick Colenbrander 			if (active) {
1375ac797b95SRoderick Colenbrander 				input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x);
1376ac797b95SRoderick Colenbrander 				input_report_abs(sc->touchpad, ABS_MT_POSITION_Y, y);
1377cdc1c021SRoderick Colenbrander 			}
1378e5606230SFrank Praznik 
1379e5606230SFrank Praznik 			offset += 4;
1380e5606230SFrank Praznik 		}
1381ac797b95SRoderick Colenbrander 		input_mt_sync_frame(sc->touchpad);
1382ac797b95SRoderick Colenbrander 		input_sync(sc->touchpad);
1383cdc1c021SRoderick Colenbrander 	}
1384d902f472SFrank Praznik }
1385d902f472SFrank Praznik 
1386c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
13871adf904eSPavel Machek 		u8 *rd, int size)
1388c9e4d877SSimon Wood {
1389c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1390c9e4d877SSimon Wood 
1391ad142b9eSFrank Praznik 	/*
1392ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1393c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1394c9e4d877SSimon Wood 	 */
1395fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
13968f5f0bc2SFrank Praznik 		/*
13978f5f0bc2SFrank Praznik 		 * When connected via Bluetooth the Sixaxis occasionally sends
13988f5f0bc2SFrank Praznik 		 * a report with the second byte 0xff and the rest zeroed.
13998f5f0bc2SFrank Praznik 		 *
14008f5f0bc2SFrank Praznik 		 * This report does not reflect the actual state of the
14018f5f0bc2SFrank Praznik 		 * controller must be ignored to avoid generating false input
14028f5f0bc2SFrank Praznik 		 * events.
14038f5f0bc2SFrank Praznik 		 */
14048f5f0bc2SFrank Praznik 		if (rd[1] == 0xff)
14058f5f0bc2SFrank Praznik 			return -EINVAL;
14068f5f0bc2SFrank Praznik 
1407c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1408c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1409c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1410c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1411d902f472SFrank Praznik 
1412d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
141312e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
141412e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
14154545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
14164545ee0aSSimon Wood 			size == 49) {
14174545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
141868330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
141968330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
142068330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
142149b9ca6cSRoderick Colenbrander 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
142249b9ca6cSRoderick Colenbrander 			/* CRC check */
142349b9ca6cSRoderick Colenbrander 			u8 bthdr = 0xA1;
142449b9ca6cSRoderick Colenbrander 			u32 crc;
142549b9ca6cSRoderick Colenbrander 			u32 report_crc;
142649b9ca6cSRoderick Colenbrander 
142749b9ca6cSRoderick Colenbrander 			crc = crc32_le(0xFFFFFFFF, &bthdr, 1);
142849b9ca6cSRoderick Colenbrander 			crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4);
142949b9ca6cSRoderick Colenbrander 			report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]);
143049b9ca6cSRoderick Colenbrander 			if (crc != report_crc) {
143149b9ca6cSRoderick Colenbrander 				hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n",
143249b9ca6cSRoderick Colenbrander 					report_crc, crc);
143349b9ca6cSRoderick Colenbrander 				return -EILSEQ;
143449b9ca6cSRoderick Colenbrander 			}
143549b9ca6cSRoderick Colenbrander 		}
1436*405182c2SRoderick Colenbrander 
1437*405182c2SRoderick Colenbrander 		/*
1438*405182c2SRoderick Colenbrander 		 * In the case of a DS4 USB dongle, bit[2] of byte 31 indicates
1439*405182c2SRoderick Colenbrander 		 * if a DS4 is actually connected (indicated by '0').
1440*405182c2SRoderick Colenbrander 		 * For non-dongle, this bit is always 0 (connected).
1441*405182c2SRoderick Colenbrander 		 */
1442*405182c2SRoderick Colenbrander 		if (sc->hdev->vendor == USB_VENDOR_ID_SONY &&
1443*405182c2SRoderick Colenbrander 		    sc->hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) {
1444*405182c2SRoderick Colenbrander 			bool connected = (rd[31] & 0x04) ? false : true;
1445*405182c2SRoderick Colenbrander 
1446*405182c2SRoderick Colenbrander 			if (!sc->ds4_dongle_connected && connected) {
1447*405182c2SRoderick Colenbrander 				hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected\n");
1448*405182c2SRoderick Colenbrander 				sony_set_leds(sc);
1449*405182c2SRoderick Colenbrander 				sc->ds4_dongle_connected = true;
1450*405182c2SRoderick Colenbrander 			} else if (sc->ds4_dongle_connected && !connected) {
1451*405182c2SRoderick Colenbrander 				hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected\n");
1452*405182c2SRoderick Colenbrander 				sc->ds4_dongle_connected = false;
1453*405182c2SRoderick Colenbrander 				/* Return 0, so hidraw can get the report. */
1454*405182c2SRoderick Colenbrander 				return 0;
1455*405182c2SRoderick Colenbrander 			} else if (!sc->ds4_dongle_connected) {
1456*405182c2SRoderick Colenbrander 				/* Return 0, so hidraw can get the report. */
1457*405182c2SRoderick Colenbrander 				return 0;
1458*405182c2SRoderick Colenbrander 			}
1459*405182c2SRoderick Colenbrander 		}
1460*405182c2SRoderick Colenbrander 
1461d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1462c9e4d877SSimon Wood 	}
1463c9e4d877SSimon Wood 
14642a242932SFrank Praznik 	if (sc->defer_initialization) {
14652a242932SFrank Praznik 		sc->defer_initialization = 0;
14662a242932SFrank Praznik 		sony_schedule_work(sc);
14672a242932SFrank Praznik 	}
14682a242932SFrank Praznik 
1469c9e4d877SSimon Wood 	return 0;
1470c9e4d877SSimon Wood }
1471c9e4d877SSimon Wood 
1472f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1473f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1474f04d5140SColin Leitner 			unsigned long **bit, int *max)
1475f04d5140SColin Leitner {
1476f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1477f04d5140SColin Leitner 
1478f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1479f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1480f04d5140SColin Leitner 
1481f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1482f04d5140SColin Leitner 			return -1;
1483f04d5140SColin Leitner 
1484f04d5140SColin Leitner 		switch (usage->collection_index) {
1485f04d5140SColin Leitner 		case 1:
1486f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1487f04d5140SColin Leitner 				return -1;
1488f04d5140SColin Leitner 
1489f04d5140SColin Leitner 			key = buzz_keymap[key];
1490f04d5140SColin Leitner 			if (!key)
1491f04d5140SColin Leitner 				return -1;
1492f04d5140SColin Leitner 			break;
1493f04d5140SColin Leitner 		default:
1494f04d5140SColin Leitner 			return -1;
1495f04d5140SColin Leitner 		}
1496f04d5140SColin Leitner 
1497f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1498f04d5140SColin Leitner 		return 1;
1499f04d5140SColin Leitner 	}
1500f04d5140SColin Leitner 
1501078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1502078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1503078328daSJiri Kosina 
15049131f8ccSRoderick Colenbrander 
15059131f8ccSRoderick Colenbrander 	if (sc->quirks & DUALSHOCK4_CONTROLLER)
15069131f8ccSRoderick Colenbrander 		return ds4_mapping(hdev, hi, field, usage, bit, max);
15079131f8ccSRoderick Colenbrander 
15086f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
15096f498018SBenjamin Tissoires 	return 0;
1510f04d5140SColin Leitner }
1511f04d5140SColin Leitner 
1512ac797b95SRoderick Colenbrander static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
1513ce8efc3bSFrank Praznik 					int w, int h)
1514ce8efc3bSFrank Praznik {
1515ac797b95SRoderick Colenbrander 	size_t name_sz;
1516ac797b95SRoderick Colenbrander 	char *name;
1517ce8efc3bSFrank Praznik 	int ret;
1518ce8efc3bSFrank Praznik 
1519ac797b95SRoderick Colenbrander 	sc->touchpad = input_allocate_device();
1520ac797b95SRoderick Colenbrander 	if (!sc->touchpad)
1521ac797b95SRoderick Colenbrander 		return -ENOMEM;
1522ce8efc3bSFrank Praznik 
1523ac797b95SRoderick Colenbrander 	input_set_drvdata(sc->touchpad, sc);
1524ac797b95SRoderick Colenbrander 	sc->touchpad->dev.parent = &sc->hdev->dev;
1525ac797b95SRoderick Colenbrander 	sc->touchpad->phys = sc->hdev->phys;
1526ac797b95SRoderick Colenbrander 	sc->touchpad->uniq = sc->hdev->uniq;
1527ac797b95SRoderick Colenbrander 	sc->touchpad->id.bustype = sc->hdev->bus;
1528ac797b95SRoderick Colenbrander 	sc->touchpad->id.vendor = sc->hdev->vendor;
1529ac797b95SRoderick Colenbrander 	sc->touchpad->id.product = sc->hdev->product;
1530ac797b95SRoderick Colenbrander 	sc->touchpad->id.version = sc->hdev->version;
1531ac797b95SRoderick Colenbrander 
1532ac797b95SRoderick Colenbrander 	/* Append a suffix to the controller name as there are various
1533ac797b95SRoderick Colenbrander 	 * DS4 compatible non-Sony devices with different names.
1534ac797b95SRoderick Colenbrander 	 */
1535ac797b95SRoderick Colenbrander 	name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX);
1536ac797b95SRoderick Colenbrander 	name = kzalloc(name_sz, GFP_KERNEL);
1537ac797b95SRoderick Colenbrander 	if (!name) {
1538ac797b95SRoderick Colenbrander 		ret = -ENOMEM;
1539ac797b95SRoderick Colenbrander 		goto err;
1540ac797b95SRoderick Colenbrander 	}
1541ac797b95SRoderick Colenbrander 	snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name);
1542ac797b95SRoderick Colenbrander 	sc->touchpad->name = name;
1543ac797b95SRoderick Colenbrander 
1544ac797b95SRoderick Colenbrander 	ret = input_mt_init_slots(sc->touchpad, touch_count, 0);
1545ac797b95SRoderick Colenbrander 	if (ret < 0)
1546ac797b95SRoderick Colenbrander 		goto err;
1547ac797b95SRoderick Colenbrander 
1548ac797b95SRoderick Colenbrander 	/* We map the button underneath the touchpad to BTN_LEFT. */
1549ac797b95SRoderick Colenbrander 	__set_bit(EV_KEY, sc->touchpad->evbit);
1550ac797b95SRoderick Colenbrander 	__set_bit(BTN_LEFT, sc->touchpad->keybit);
1551ac797b95SRoderick Colenbrander 	__set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit);
1552ac797b95SRoderick Colenbrander 
1553ac797b95SRoderick Colenbrander 	input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0);
1554ac797b95SRoderick Colenbrander 	input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0);
1555ac797b95SRoderick Colenbrander 
1556ac797b95SRoderick Colenbrander 	ret = input_register_device(sc->touchpad);
1557ac797b95SRoderick Colenbrander 	if (ret < 0)
1558ac797b95SRoderick Colenbrander 		goto err;
1559ce8efc3bSFrank Praznik 
1560ce8efc3bSFrank Praznik 	return 0;
1561ac797b95SRoderick Colenbrander 
1562ac797b95SRoderick Colenbrander err:
1563ac797b95SRoderick Colenbrander 	kfree(sc->touchpad->name);
1564ac797b95SRoderick Colenbrander 	sc->touchpad->name = NULL;
1565ac797b95SRoderick Colenbrander 
1566ac797b95SRoderick Colenbrander 	input_free_device(sc->touchpad);
1567ac797b95SRoderick Colenbrander 	sc->touchpad = NULL;
1568ac797b95SRoderick Colenbrander 
1569ac797b95SRoderick Colenbrander 	return ret;
1570ce8efc3bSFrank Praznik }
1571ce8efc3bSFrank Praznik 
1572ac797b95SRoderick Colenbrander static void sony_unregister_touchpad(struct sony_sc *sc)
1573ac797b95SRoderick Colenbrander {
1574ac797b95SRoderick Colenbrander 	if (!sc->touchpad)
1575ac797b95SRoderick Colenbrander 		return;
1576ac797b95SRoderick Colenbrander 
1577ac797b95SRoderick Colenbrander 	kfree(sc->touchpad->name);
1578ac797b95SRoderick Colenbrander 	sc->touchpad->name = NULL;
1579ac797b95SRoderick Colenbrander 
1580ac797b95SRoderick Colenbrander 	input_unregister_device(sc->touchpad);
1581ac797b95SRoderick Colenbrander 	sc->touchpad = NULL;
1582ac797b95SRoderick Colenbrander }
15839154301aSDmitry Torokhov 
15845710fabfSAntonio Ospite /*
1585bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1586bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1587bd28ce00SJiri Slaby  * events.
1588bd28ce00SJiri Slaby  */
1589816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1590bd28ce00SJiri Slaby {
1591a85d67b5SAntonio Ospite 	const int buf_size =
1592a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
15931adf904eSPavel Machek 	u8 *buf;
1594bd28ce00SJiri Slaby 	int ret;
1595bd28ce00SJiri Slaby 
15962e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1597bd28ce00SJiri Slaby 	if (!buf)
1598bd28ce00SJiri Slaby 		return -ENOMEM;
1599bd28ce00SJiri Slaby 
1600a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1601a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1602a7de9b86SLauri Kasanen 	if (ret < 0) {
1603a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1604a7de9b86SLauri Kasanen 		goto out;
1605a7de9b86SLauri Kasanen 	}
1606f204828aSBenjamin Tissoires 
1607a7de9b86SLauri Kasanen 	/*
1608a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1609a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1610a7de9b86SLauri Kasanen 	 */
1611a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1612a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1613a7de9b86SLauri Kasanen 	if (ret < 0) {
1614a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1615a7de9b86SLauri Kasanen 		goto out;
1616a7de9b86SLauri Kasanen 	}
1617a7de9b86SLauri Kasanen 
1618a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
161919f4c2baSBenjamin Tissoires 	if (ret < 0) {
162019f4c2baSBenjamin Tissoires 		hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
162119f4c2baSBenjamin Tissoires 		ret = 0;
162219f4c2baSBenjamin Tissoires 	}
1623bd28ce00SJiri Slaby 
1624a7de9b86SLauri Kasanen out:
1625bd28ce00SJiri Slaby 	kfree(buf);
1626bd28ce00SJiri Slaby 
1627bd28ce00SJiri Slaby 	return ret;
1628bd28ce00SJiri Slaby }
1629bd28ce00SJiri Slaby 
1630816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1631f9ce7c28SBastien Nocera {
16321adf904eSPavel Machek 	static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
16331adf904eSPavel Machek 	u8 *buf;
16349b2b5c9aSFrank Praznik 	int ret;
16359b2b5c9aSFrank Praznik 
16369b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
16379b2b5c9aSFrank Praznik 	if (!buf)
16389b2b5c9aSFrank Praznik 		return -ENOMEM;
16399b2b5c9aSFrank Praznik 
16409b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1641b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
16429b2b5c9aSFrank Praznik 
16439b2b5c9aSFrank Praznik 	kfree(buf);
16449b2b5c9aSFrank Praznik 
16459b2b5c9aSFrank Praznik 	return ret;
1646f9ce7c28SBastien Nocera }
1647f9ce7c28SBastien Nocera 
1648ad142b9eSFrank Praznik /*
1649ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
165068330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
165168330d83SFrank Praznik  */
165268330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
165368330d83SFrank Praznik {
16541adf904eSPavel Machek 	u8 *buf;
16559b2b5c9aSFrank Praznik 	int ret;
165668330d83SFrank Praznik 
16572c159de0SRoderick Colenbrander 	buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);
16589b2b5c9aSFrank Praznik 	if (!buf)
16599b2b5c9aSFrank Praznik 		return -ENOMEM;
16609b2b5c9aSFrank Praznik 
16612c159de0SRoderick Colenbrander 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE,
166268330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
16639b2b5c9aSFrank Praznik 
16649b2b5c9aSFrank Praznik 	kfree(buf);
16659b2b5c9aSFrank Praznik 
16669b2b5c9aSFrank Praznik 	return ret;
1667bd28ce00SJiri Slaby }
1668bd28ce00SJiri Slaby 
1669221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
16708025087aSFrank Praznik {
16711adf904eSPavel Machek 	static const u8 sixaxis_leds[10][4] = {
16728025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
16738025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
16748025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
16758025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
16768025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
16778025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
16788025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
16798025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
16808025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
16818025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
16828025087aSFrank Praznik 	};
16838025087aSFrank Praznik 
1684221399b3SFrank Praznik 	int id = sc->device_id;
1685221399b3SFrank Praznik 
1686221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
16878025087aSFrank Praznik 
16888025087aSFrank Praznik 	if (id < 0)
16898025087aSFrank Praznik 		return;
16908025087aSFrank Praznik 
16918025087aSFrank Praznik 	id %= 10;
1692221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
16938025087aSFrank Praznik }
16948025087aSFrank Praznik 
1695221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
16968025087aSFrank Praznik {
16978025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
16981adf904eSPavel Machek 	static const u8 color_code[7][3] = {
16998025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
17008025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
17018025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
17028025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
17038025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
17048025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
17058025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
17068025087aSFrank Praznik 	};
17078025087aSFrank Praznik 
1708221399b3SFrank Praznik 	int id = sc->device_id;
1709221399b3SFrank Praznik 
1710221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
17118025087aSFrank Praznik 
17128025087aSFrank Praznik 	if (id < 0)
17138025087aSFrank Praznik 		return;
17148025087aSFrank Praznik 
17158025087aSFrank Praznik 	id %= 7;
1716221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
17178025087aSFrank Praznik }
17188025087aSFrank Praznik 
1719221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1720f04d5140SColin Leitner {
1721221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1722f04d5140SColin Leitner 	struct list_head *report_list =
1723f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1724f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1725f04d5140SColin Leitner 		struct hid_report, list);
17261adf904eSPavel Machek 	s32 *value = report->field[0]->value;
1727f04d5140SColin Leitner 
1728221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1729221399b3SFrank Praznik 
1730f04d5140SColin Leitner 	value[0] = 0x00;
1731221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1732221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1733221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1734221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1735f04d5140SColin Leitner 	value[5] = 0x00;
1736f04d5140SColin Leitner 	value[6] = 0x00;
1737f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1738f04d5140SColin Leitner }
1739f04d5140SColin Leitner 
1740221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
17410a286ef2SSven Eckelmann {
1742221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
17432a242932SFrank Praznik 		sony_schedule_work(sc);
1744221399b3SFrank Praznik 	else
1745221399b3SFrank Praznik 		buzz_set_leds(sc);
17460a286ef2SSven Eckelmann }
17470a286ef2SSven Eckelmann 
1748c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1749f04d5140SColin Leitner 				    enum led_brightness value)
1750f04d5140SColin Leitner {
1751f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1752ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1753f04d5140SColin Leitner 	struct sony_sc *drv_data;
1754f04d5140SColin Leitner 
1755f04d5140SColin Leitner 	int n;
1756b3ed458cSFrank Praznik 	int force_update;
1757f04d5140SColin Leitner 
1758f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
17592251b85fSSven Eckelmann 	if (!drv_data) {
1760f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1761f04d5140SColin Leitner 		return;
1762f04d5140SColin Leitner 	}
1763f04d5140SColin Leitner 
1764b3ed458cSFrank Praznik 	/*
1765b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1766b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1767b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1768b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1769b3ed458cSFrank Praznik 	 * stop the flashing later on.
1770b3ed458cSFrank Praznik 	 */
1771b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1772b3ed458cSFrank Praznik 
177360781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1774b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1775b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1776b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1777b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1778b3ed458cSFrank Praznik 
177960781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1780b3ed458cSFrank Praznik 
1781b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1782b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1783b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1784b3ed458cSFrank Praznik 
1785221399b3SFrank Praznik 			sony_set_leds(drv_data);
1786f04d5140SColin Leitner 			break;
1787f04d5140SColin Leitner 		}
1788f04d5140SColin Leitner 	}
1789f04d5140SColin Leitner }
1790f04d5140SColin Leitner 
1791c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1792f04d5140SColin Leitner {
1793f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1794ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1795f04d5140SColin Leitner 	struct sony_sc *drv_data;
1796f04d5140SColin Leitner 
1797f04d5140SColin Leitner 	int n;
1798f04d5140SColin Leitner 
1799f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
18002251b85fSSven Eckelmann 	if (!drv_data) {
1801f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1802f04d5140SColin Leitner 		return LED_OFF;
1803f04d5140SColin Leitner 	}
1804f04d5140SColin Leitner 
180560781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
18067db7504aSSimon Wood 		if (led == drv_data->leds[n])
18077db7504aSSimon Wood 			return drv_data->led_state[n];
1808f04d5140SColin Leitner 	}
1809f04d5140SColin Leitner 
18107db7504aSSimon Wood 	return LED_OFF;
1811f04d5140SColin Leitner }
1812f04d5140SColin Leitner 
1813b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1814b3ed458cSFrank Praznik 				unsigned long *delay_off)
1815b3ed458cSFrank Praznik {
1816b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1817ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1818b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1819b3ed458cSFrank Praznik 	int n;
18201adf904eSPavel Machek 	u8 new_on, new_off;
1821b3ed458cSFrank Praznik 
1822b3ed458cSFrank Praznik 	if (!drv_data) {
1823b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1824b3ed458cSFrank Praznik 		return -EINVAL;
1825b3ed458cSFrank Praznik 	}
1826b3ed458cSFrank Praznik 
1827b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1828b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1829b3ed458cSFrank Praznik 		*delay_on = 2550;
1830b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1831b3ed458cSFrank Praznik 		*delay_off = 2550;
1832b3ed458cSFrank Praznik 
1833b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1834b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1835b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1836b3ed458cSFrank Praznik 
1837b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1838b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1839b3ed458cSFrank Praznik 
1840b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1841b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1842b3ed458cSFrank Praznik 			break;
1843b3ed458cSFrank Praznik 	}
1844b3ed458cSFrank Praznik 
1845b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1846b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1847b3ed458cSFrank Praznik 		return -EINVAL;
1848b3ed458cSFrank Praznik 
1849b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1850b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1851b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1852b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1853b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
18542a242932SFrank Praznik 		sony_schedule_work(drv_data);
1855b3ed458cSFrank Praznik 	}
1856b3ed458cSFrank Praznik 
1857b3ed458cSFrank Praznik 	return 0;
1858b3ed458cSFrank Praznik }
1859b3ed458cSFrank Praznik 
1860fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
18610a286ef2SSven Eckelmann {
18620a286ef2SSven Eckelmann 	struct led_classdev *led;
18630a286ef2SSven Eckelmann 	int n;
18640a286ef2SSven Eckelmann 
1865fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
18660a286ef2SSven Eckelmann 
1867fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1868fa57a810SFrank Praznik 		led = sc->leds[n];
1869fa57a810SFrank Praznik 		sc->leds[n] = NULL;
18700a286ef2SSven Eckelmann 		if (!led)
18710a286ef2SSven Eckelmann 			continue;
18720a286ef2SSven Eckelmann 		led_classdev_unregister(led);
18730a286ef2SSven Eckelmann 		kfree(led);
18740a286ef2SSven Eckelmann 	}
187560781cf4SFrank Praznik 
1876fa57a810SFrank Praznik 	sc->led_count = 0;
18770a286ef2SSven Eckelmann }
18780a286ef2SSven Eckelmann 
1879fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1880f04d5140SColin Leitner {
1881fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
188240e32ee6SJiri Kosina 	int n, ret = 0;
1883b3ed458cSFrank Praznik 	int use_ds4_names;
188440e32ee6SJiri Kosina 	struct led_classdev *led;
188540e32ee6SJiri Kosina 	size_t name_sz;
188640e32ee6SJiri Kosina 	char *name;
18870a286ef2SSven Eckelmann 	size_t name_len;
18880a286ef2SSven Eckelmann 	const char *name_fmt;
1889b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1890b3ed458cSFrank Praznik 						  "global" };
18911adf904eSPavel Machek 	u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
18921adf904eSPavel Machek 	u8 use_hw_blink[MAX_LEDS] = { 0 };
1893f04d5140SColin Leitner 
1894fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1895f04d5140SColin Leitner 
1896fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1897fa57a810SFrank Praznik 		sc->led_count = 4;
1898b3ed458cSFrank Praznik 		use_ds4_names = 0;
18990a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
19000a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
19019446edb9SKees Cook 		/* Validate expected report characteristics. */
19029446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
19039446edb9SKees Cook 			return -ENODEV;
1904fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1905221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1906221399b3SFrank Praznik 		sc->led_state[3] = 1;
1907b3ed458cSFrank Praznik 		sc->led_count = 4;
1908b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1909b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1910b3ed458cSFrank Praznik 		use_ds4_names = 1;
191161ebca93SFrank Praznik 		name_len = 0;
191261ebca93SFrank Praznik 		name_fmt = "%s:%s";
1913c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1914c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1915c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1916c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1917c5e0c1c4SFrank Praznik 		name_len = 0;
1918c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
19194545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
19201adf904eSPavel Machek 		static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
19214545ee0aSSimon Wood 
19224545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
19234545ee0aSSimon Wood 		sc->led_count = 1;
19244545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
19254545ee0aSSimon Wood 		use_ds4_names = 0;
19264545ee0aSSimon Wood 		name_len = strlen("::sony#");
19274545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
192860781cf4SFrank Praznik 	} else {
1929221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1930fa57a810SFrank Praznik 		sc->led_count = 4;
1931b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1932b3ed458cSFrank Praznik 		use_ds4_names = 0;
193361ebca93SFrank Praznik 		name_len = strlen("::sony#");
193461ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
193560781cf4SFrank Praznik 	}
193660781cf4SFrank Praznik 
1937ad142b9eSFrank Praznik 	/*
1938ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1939f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1940ad142b9eSFrank Praznik 	 * LEDs to on
1941ad142b9eSFrank Praznik 	 */
1942221399b3SFrank Praznik 	sony_set_leds(sc);
1943f04d5140SColin Leitner 
19440a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1945f04d5140SColin Leitner 
1946fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
194761ebca93SFrank Praznik 
1948b3ed458cSFrank Praznik 		if (use_ds4_names)
1949b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
195061ebca93SFrank Praznik 
1951f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1952f04d5140SColin Leitner 		if (!led) {
1953f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
19548cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1955f04d5140SColin Leitner 			goto error_leds;
1956f04d5140SColin Leitner 		}
1957f04d5140SColin Leitner 
1958f04d5140SColin Leitner 		name = (void *)(&led[1]);
1959b3ed458cSFrank Praznik 		if (use_ds4_names)
1960b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1961b3ed458cSFrank Praznik 			ds4_name_str[n]);
196261ebca93SFrank Praznik 		else
19630a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1964f04d5140SColin Leitner 		led->name = name;
1965221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1966b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1967c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1968c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1969f04d5140SColin Leitner 
1970b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1971b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1972b3ed458cSFrank Praznik 
19738025087aSFrank Praznik 		sc->leds[n] = led;
19748025087aSFrank Praznik 
19758cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
19768cd5fcdaSJulia Lawall 		if (ret) {
1977f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
19788025087aSFrank Praznik 			sc->leds[n] = NULL;
1979f04d5140SColin Leitner 			kfree(led);
1980f04d5140SColin Leitner 			goto error_leds;
1981f04d5140SColin Leitner 		}
1982f04d5140SColin Leitner 	}
1983f04d5140SColin Leitner 
1984f04d5140SColin Leitner 	return ret;
1985f04d5140SColin Leitner 
1986f04d5140SColin Leitner error_leds:
1987fa57a810SFrank Praznik 	sony_leds_remove(sc);
1988f04d5140SColin Leitner 
1989f04d5140SColin Leitner 	return ret;
1990f04d5140SColin Leitner }
1991f04d5140SColin Leitner 
1992d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc)
1993a08c22c0SSven Eckelmann {
19949b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
199555d3b664SFrank Praznik 		.buf = {
1996a08c22c0SSven Eckelmann 			0x01,
1997ad07b7a6SScott Moreau 			0x01, 0xff, 0x00, 0xff, 0x00,
19980a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1999a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
2000a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
2001a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
2002a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
2003a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
200455d3b664SFrank Praznik 		}
2005a08c22c0SSven Eckelmann 	};
20069b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
20079b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
20089b2b5c9aSFrank Praznik 	int n;
20099b2b5c9aSFrank Praznik 
20109b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
20119b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
20129f323b68SSven Eckelmann 
20130a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
20149b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
20159b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
20160a286ef2SSven Eckelmann #endif
20170a286ef2SSven Eckelmann 
20189b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
20199b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
20209b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
20219b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
20229f323b68SSven Eckelmann 
202388f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
20249b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
20259b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
202688f6576fSSimon Wood 
2027b3ed458cSFrank Praznik 	/*
2028b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
2029b3ed458cSFrank Praznik 	 * corresponding light on the controller.
2030b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
2031b3ed458cSFrank Praznik 	 *
2032b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
2033b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
2034b3ed458cSFrank Praznik 	 * always off.
2035b3ed458cSFrank Praznik 	 */
2036b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
2037b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
20389b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
20399b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
2040b3ed458cSFrank Praznik 		}
2041b3ed458cSFrank Praznik 	}
2042b3ed458cSFrank Praznik 
20431adf904eSPavel Machek 	hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
20449b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
20459b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
20469f323b68SSven Eckelmann }
20479f323b68SSven Eckelmann 
2048d8aaccdaSFrank Praznik static void dualshock4_send_output_report(struct sony_sc *sc)
20490bd88dd3SFrank Praznik {
20500da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
20511adf904eSPavel Machek 	u8 *buf = sc->output_report_dmabuf;
205248220237SFrank Praznik 	int offset;
20530da8ea65SFrank Praznik 
2054c4425c8fSFrank Praznik 	/*
2055c4425c8fSFrank Praznik 	 * NOTE: The buf[1] field of the Bluetooth report controls
2056c4425c8fSFrank Praznik 	 * the Dualshock 4 reporting rate.
2057c4425c8fSFrank Praznik 	 *
2058c4425c8fSFrank Praznik 	 * Known values include:
2059c4425c8fSFrank Praznik 	 *
2060c4425c8fSFrank Praznik 	 * 0x80 - 1000hz (full speed)
2061c4425c8fSFrank Praznik 	 * 0xA0 - 31hz
2062c4425c8fSFrank Praznik 	 * 0xB0 - 20hz
2063c4425c8fSFrank Praznik 	 * 0xD0 - 66hz
2064c4425c8fSFrank Praznik 	 */
2065fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
20662c159de0SRoderick Colenbrander 		memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE);
206748220237SFrank Praznik 		buf[0] = 0x05;
2068b3ed458cSFrank Praznik 		buf[1] = 0xFF;
206948220237SFrank Praznik 		offset = 4;
2070fdcf105dSFrank Praznik 	} else {
20712c159de0SRoderick Colenbrander 		memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE);
2072fdcf105dSFrank Praznik 		buf[0] = 0x11;
2073e7ef53adSRoderick Colenbrander 		buf[1] = 0xC0; /* HID + CRC */
2074fdcf105dSFrank Praznik 		buf[3] = 0x0F;
2075fdcf105dSFrank Praznik 		offset = 6;
2076fdcf105dSFrank Praznik 	}
20770bd88dd3SFrank Praznik 
20780bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
207948220237SFrank Praznik 	buf[offset++] = sc->right;
208048220237SFrank Praznik 	buf[offset++] = sc->left;
208148220237SFrank Praznik #else
208248220237SFrank Praznik 	offset += 2;
20830bd88dd3SFrank Praznik #endif
20840bd88dd3SFrank Praznik 
2085b3ed458cSFrank Praznik 	/* LED 3 is the global control */
2086b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
208748220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
208848220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
208948220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
2090b3ed458cSFrank Praznik 	} else {
2091b3ed458cSFrank Praznik 		offset += 3;
2092b3ed458cSFrank Praznik 	}
2093b3ed458cSFrank Praznik 
2094b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
2095b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
2096b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
209760781cf4SFrank Praznik 
2098fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
20992c159de0SRoderick Colenbrander 		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE);
2100e7ef53adSRoderick Colenbrander 	else {
2101e7ef53adSRoderick Colenbrander 		/* CRC generation */
2102e7ef53adSRoderick Colenbrander 		u8 bthdr = 0xA2;
2103e7ef53adSRoderick Colenbrander 		u32 crc;
2104e7ef53adSRoderick Colenbrander 
2105e7ef53adSRoderick Colenbrander 		crc = crc32_le(0xFFFFFFFF, &bthdr, 1);
2106e7ef53adSRoderick Colenbrander 		crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4);
2107e7ef53adSRoderick Colenbrander 		put_unaligned_le32(crc, &buf[74]);
2108e7ef53adSRoderick Colenbrander 		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE);
2109e7ef53adSRoderick Colenbrander 	}
21100bd88dd3SFrank Praznik }
21110bd88dd3SFrank Praznik 
2112d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc)
2113c5e0c1c4SFrank Praznik {
2114c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
2115c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
2116c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
2117c5e0c1c4SFrank Praznik 
211841d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
2119c5e0c1c4SFrank Praznik 
2120c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
2121c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
2122c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
2123c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
2124c5e0c1c4SFrank Praznik 
2125c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
2126c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
2127c5e0c1c4SFrank Praznik #endif
2128c5e0c1c4SFrank Praznik 
21291adf904eSPavel Machek 	hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE);
2130c5e0c1c4SFrank Praznik }
2131c5e0c1c4SFrank Praznik 
2132decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc)
2133decd946cSFrank Praznik {
2134decd946cSFrank Praznik 	if (sc->send_output_report)
2135decd946cSFrank Praznik 		sc->send_output_report(sc);
2136decd946cSFrank Praznik }
2137decd946cSFrank Praznik 
2138d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work)
2139d8aaccdaSFrank Praznik {
2140d8aaccdaSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
2141ef916ef5SAntonio Ospite 
2142d8aaccdaSFrank Praznik 	sc->send_output_report(sc);
2143d8aaccdaSFrank Praznik }
2144d8aaccdaSFrank Praznik 
21459b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
21469b2b5c9aSFrank Praznik {
21474545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
21484545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
21499b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
21509b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
21519b2b5c9aSFrank Praznik 				GFP_KERNEL);
21529b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
21532c159de0SRoderick Colenbrander 		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE,
21549b2b5c9aSFrank Praznik 						GFP_KERNEL);
21559b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
21562c159de0SRoderick Colenbrander 		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE,
21579b2b5c9aSFrank Praznik 						GFP_KERNEL);
2158c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
215941d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
2160c5e0c1c4SFrank Praznik 						GFP_KERNEL);
21619b2b5c9aSFrank Praznik 	else
21629b2b5c9aSFrank Praznik 		return 0;
21639b2b5c9aSFrank Praznik 
21649b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
21659b2b5c9aSFrank Praznik 		return -ENOMEM;
21669b2b5c9aSFrank Praznik 
21679b2b5c9aSFrank Praznik 	return 0;
21689b2b5c9aSFrank Praznik }
21699b2b5c9aSFrank Praznik 
21700a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
21719f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
21729f323b68SSven Eckelmann 			    struct ff_effect *effect)
21739f323b68SSven Eckelmann {
2174a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
21759f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
2176a08c22c0SSven Eckelmann 
2177a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
2178a08c22c0SSven Eckelmann 		return 0;
2179a08c22c0SSven Eckelmann 
21809f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
21810bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
2182a08c22c0SSven Eckelmann 
21832a242932SFrank Praznik 	sony_schedule_work(sc);
21849f323b68SSven Eckelmann 	return 0;
2185a08c22c0SSven Eckelmann }
2186a08c22c0SSven Eckelmann 
2187fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
2188a08c22c0SSven Eckelmann {
2189fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
2190a08c22c0SSven Eckelmann 						struct hid_input, list);
2191a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
2192a08c22c0SSven Eckelmann 
2193a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
2194a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
2195a08c22c0SSven Eckelmann }
2196a08c22c0SSven Eckelmann 
2197a08c22c0SSven Eckelmann #else
2198fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
2199a08c22c0SSven Eckelmann {
2200a08c22c0SSven Eckelmann 	return 0;
2201a08c22c0SSven Eckelmann }
22029f323b68SSven Eckelmann 
2203a08c22c0SSven Eckelmann #endif
2204a08c22c0SSven Eckelmann 
2205d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
2206d902f472SFrank Praznik 				     enum power_supply_property psp,
2207d902f472SFrank Praznik 				     union power_supply_propval *val)
2208c4e1ddf2SFrank Praznik {
2209297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
2210d902f472SFrank Praznik 	unsigned long flags;
2211d902f472SFrank Praznik 	int ret = 0;
2212d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
2213c4e1ddf2SFrank Praznik 
2214d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
2215d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
2216d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
2217d902f472SFrank Praznik 	cable_state = sc->cable_state;
2218d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
2219c4e1ddf2SFrank Praznik 
2220d902f472SFrank Praznik 	switch (psp) {
2221d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
2222d902f472SFrank Praznik 		val->intval = 1;
2223d902f472SFrank Praznik 		break;
2224d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
2225d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
2226d902f472SFrank Praznik 		break;
2227d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
2228d902f472SFrank Praznik 		val->intval = battery_capacity;
2229d902f472SFrank Praznik 		break;
2230d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
2231d902f472SFrank Praznik 		if (battery_charging)
2232d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
2233d902f472SFrank Praznik 		else
2234d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
2235d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
2236d902f472SFrank Praznik 			else
2237d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2238d902f472SFrank Praznik 		break;
2239d902f472SFrank Praznik 	default:
2240d902f472SFrank Praznik 		ret = -EINVAL;
2241d902f472SFrank Praznik 		break;
2242c4e1ddf2SFrank Praznik 	}
2243d902f472SFrank Praznik 	return ret;
2244d902f472SFrank Praznik }
2245d902f472SFrank Praznik 
22460f398230SFrank Praznik static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
2247d902f472SFrank Praznik {
22480f398230SFrank Praznik 	const char *battery_str_fmt = append_dev_id ?
22490f398230SFrank Praznik 		"sony_controller_battery_%pMR_%i" :
22500f398230SFrank Praznik 		"sony_controller_battery_%pMR";
2251297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
2252d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
2253d902f472SFrank Praznik 	int ret;
2254d902f472SFrank Praznik 
2255ad142b9eSFrank Praznik 	/*
2256ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
2257d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
2258d9a293a9SFrank Praznik 	 */
2259d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
2260d9a293a9SFrank Praznik 
2261297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
2262297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
2263297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
2264297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2265297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
22660f398230SFrank Praznik 	sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
22670f398230SFrank Praznik 					  sc->mac_address, sc->device_id);
2268297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2269d902f472SFrank Praznik 		return -ENOMEM;
2270d902f472SFrank Praznik 
2271297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
2272297d716fSKrzysztof Kozlowski 					    &psy_cfg);
2273297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
2274297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
2275d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
2276d902f472SFrank Praznik 		goto err_free;
2277d902f472SFrank Praznik 	}
2278d902f472SFrank Praznik 
2279297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
2280d902f472SFrank Praznik 	return 0;
2281d902f472SFrank Praznik 
2282d902f472SFrank Praznik err_free:
2283297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2284297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2285d902f472SFrank Praznik 	return ret;
2286d902f472SFrank Praznik }
2287d902f472SFrank Praznik 
2288d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
2289d902f472SFrank Praznik {
2290297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2291d902f472SFrank Praznik 		return;
2292d902f472SFrank Praznik 
2293297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
2294297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2295297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2296d902f472SFrank Praznik }
2297d902f472SFrank Praznik 
2298d2d782fcSFrank Praznik /*
2299d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
2300d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
2301d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
2302d2d782fcSFrank Praznik  * once.
23030f398230SFrank Praznik  *
23040f398230SFrank Praznik  * Some USB-only devices masquerade as Sixaxis controllers and all have the
23050f398230SFrank Praznik  * same dummy Bluetooth address, so a comparison of the connection type is
23060f398230SFrank Praznik  * required.  Devices are only rejected in the case where two devices have
23070f398230SFrank Praznik  * matching Bluetooth addresses on different bus types.
2308d2d782fcSFrank Praznik  */
23090f398230SFrank Praznik static inline int sony_compare_connection_type(struct sony_sc *sc0,
23100f398230SFrank Praznik 						struct sony_sc *sc1)
23110f398230SFrank Praznik {
23120f398230SFrank Praznik 	const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE);
23130f398230SFrank Praznik 	const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
23140f398230SFrank Praznik 
23150f398230SFrank Praznik 	return sc0_not_bt == sc1_not_bt;
23160f398230SFrank Praznik }
23170f398230SFrank Praznik 
2318d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
2319d2d782fcSFrank Praznik {
2320d2d782fcSFrank Praznik 	struct sony_sc *entry;
2321d2d782fcSFrank Praznik 	unsigned long flags;
2322d2d782fcSFrank Praznik 	int ret;
2323d2d782fcSFrank Praznik 
2324d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
2325d2d782fcSFrank Praznik 
2326d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
2327d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
2328d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
2329d2d782fcSFrank Praznik 		if (!ret) {
23300f398230SFrank Praznik 			if (sony_compare_connection_type(sc, entry)) {
23310f398230SFrank Praznik 				ret = 1;
23320f398230SFrank Praznik 			} else {
2333d2d782fcSFrank Praznik 				ret = -EEXIST;
23340f398230SFrank Praznik 				hid_info(sc->hdev,
23350f398230SFrank Praznik 				"controller with MAC address %pMR already connected\n",
2336d2d782fcSFrank Praznik 				sc->mac_address);
23370f398230SFrank Praznik 			}
2338d2d782fcSFrank Praznik 			goto unlock;
2339d2d782fcSFrank Praznik 		}
2340c4e1ddf2SFrank Praznik 	}
2341c4e1ddf2SFrank Praznik 
2342d2d782fcSFrank Praznik 	ret = 0;
2343d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
2344c4e1ddf2SFrank Praznik 
2345d2d782fcSFrank Praznik unlock:
2346d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2347d2d782fcSFrank Praznik 	return ret;
2348d2d782fcSFrank Praznik }
2349d2d782fcSFrank Praznik 
2350d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
2351d2d782fcSFrank Praznik {
2352d2d782fcSFrank Praznik 	unsigned long flags;
2353d2d782fcSFrank Praznik 
2354d2d782fcSFrank Praznik 	if (sc->list_node.next) {
2355d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
2356d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
2357d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2358d2d782fcSFrank Praznik 	}
2359d2d782fcSFrank Praznik }
2360d2d782fcSFrank Praznik 
2361d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
2362d2d782fcSFrank Praznik {
2363d2d782fcSFrank Praznik 	int ret;
2364d2d782fcSFrank Praznik 
2365d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2366d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2367d2d782fcSFrank Praznik 	if (ret != 17)
2368c4e1ddf2SFrank Praznik 		return -EINVAL;
2369d2d782fcSFrank Praznik 
2370d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2371d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2372d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2373d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2374d2d782fcSFrank Praznik 
2375d2d782fcSFrank Praznik 	if (ret != 6)
2376d2d782fcSFrank Praznik 		return -EINVAL;
2377d2d782fcSFrank Praznik 
2378d2d782fcSFrank Praznik 	return 0;
2379c4e1ddf2SFrank Praznik }
2380c4e1ddf2SFrank Praznik 
2381d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2382d2d782fcSFrank Praznik {
23831adf904eSPavel Machek 	u8 *buf = NULL;
2384d2d782fcSFrank Praznik 	int n, ret;
2385d2d782fcSFrank Praznik 
2386d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
238712e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
23884545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2389d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2390d2d782fcSFrank Praznik 		/*
2391d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2392d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2393d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2394d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2395d2d782fcSFrank Praznik 		 */
2396d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2397d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2398d2d782fcSFrank Praznik 			return 0;
2399d2d782fcSFrank Praznik 		}
2400d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
24012c159de0SRoderick Colenbrander 		buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL);
24029b2b5c9aSFrank Praznik 		if (!buf)
24039b2b5c9aSFrank Praznik 			return -ENOMEM;
2404d2d782fcSFrank Praznik 
2405d2d782fcSFrank Praznik 		/*
2406d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2407d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2408d2d782fcSFrank Praznik 		 * offset 1.
2409d2d782fcSFrank Praznik 		 */
24109b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
24112c159de0SRoderick Colenbrander 				DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
24129b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2413d2d782fcSFrank Praznik 
24142c159de0SRoderick Colenbrander 		if (ret != DS4_FEATURE_REPORT_0x81_SIZE) {
2415d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
24169b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
24179b2b5c9aSFrank Praznik 			goto out_free;
2418d2d782fcSFrank Praznik 		}
2419d2d782fcSFrank Praznik 
2420d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
2421c70d5f70SRoderick Colenbrander 
2422c70d5f70SRoderick Colenbrander 		snprintf(sc->hdev->uniq, sizeof(sc->hdev->uniq),
2423c70d5f70SRoderick Colenbrander 			"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2424c70d5f70SRoderick Colenbrander 			sc->mac_address[5], sc->mac_address[4],
2425c70d5f70SRoderick Colenbrander 			sc->mac_address[3], sc->mac_address[2],
2426c70d5f70SRoderick Colenbrander 			sc->mac_address[1], sc->mac_address[0]);
24274545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
24284545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
24299b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
24309b2b5c9aSFrank Praznik 		if (!buf)
24319b2b5c9aSFrank Praznik 			return -ENOMEM;
2432d2d782fcSFrank Praznik 
2433d2d782fcSFrank Praznik 		/*
2434d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2435d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2436d2d782fcSFrank Praznik 		 * offset 4.
2437d2d782fcSFrank Praznik 		 */
24389b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
24399b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
24409b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2441d2d782fcSFrank Praznik 
24429b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2443d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
24449b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
24459b2b5c9aSFrank Praznik 			goto out_free;
2446d2d782fcSFrank Praznik 		}
2447d2d782fcSFrank Praznik 
2448d2d782fcSFrank Praznik 		/*
2449d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2450d2d782fcSFrank Praznik 		 * be byte-swapped.
2451d2d782fcSFrank Praznik 		 */
2452d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2453d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2454d2d782fcSFrank Praznik 	} else {
2455d2d782fcSFrank Praznik 		return 0;
2456d2d782fcSFrank Praznik 	}
2457d2d782fcSFrank Praznik 
24589b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
24599b2b5c9aSFrank Praznik 
24609b2b5c9aSFrank Praznik out_free:
24619b2b5c9aSFrank Praznik 
24629b2b5c9aSFrank Praznik 	kfree(buf);
24639b2b5c9aSFrank Praznik 
24649b2b5c9aSFrank Praznik 	return ret;
2465d2d782fcSFrank Praznik }
2466d2d782fcSFrank Praznik 
24678025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
24688025087aSFrank Praznik {
24698025087aSFrank Praznik 	int ret;
24708025087aSFrank Praznik 
24718025087aSFrank Praznik 	/*
24728025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
24738025087aSFrank Praznik 	 * All others are set to -1.
24748025087aSFrank Praznik 	 */
24758025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
24768025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
24778025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
24788025087aSFrank Praznik 					GFP_KERNEL);
24798025087aSFrank Praznik 		if (ret < 0) {
24808025087aSFrank Praznik 			sc->device_id = -1;
24818025087aSFrank Praznik 			return ret;
24828025087aSFrank Praznik 		}
24838025087aSFrank Praznik 		sc->device_id = ret;
24848025087aSFrank Praznik 	} else {
24858025087aSFrank Praznik 		sc->device_id = -1;
24868025087aSFrank Praznik 	}
24878025087aSFrank Praznik 
24888025087aSFrank Praznik 	return 0;
24898025087aSFrank Praznik }
24908025087aSFrank Praznik 
24918025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
24928025087aSFrank Praznik {
24938025087aSFrank Praznik 	if (sc->device_id >= 0) {
24948025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
24958025087aSFrank Praznik 		sc->device_id = -1;
24968025087aSFrank Praznik 	}
24978025087aSFrank Praznik }
24988025087aSFrank Praznik 
2499d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc,
2500d8aaccdaSFrank Praznik 				void (*send_output_report)(struct sony_sc *))
250146262047SFrank Praznik {
2502d8aaccdaSFrank Praznik 	sc->send_output_report = send_output_report;
2503d8aaccdaSFrank Praznik 
250446262047SFrank Praznik 	if (!sc->worker_initialized)
2505d8aaccdaSFrank Praznik 		INIT_WORK(&sc->state_worker, sony_state_worker);
250646262047SFrank Praznik 
250746262047SFrank Praznik 	sc->worker_initialized = 1;
250846262047SFrank Praznik }
250946262047SFrank Praznik 
251046262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
251146262047SFrank Praznik {
251246262047SFrank Praznik 	if (sc->worker_initialized)
251346262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
251446262047SFrank Praznik }
2515d2d782fcSFrank Praznik 
2516e1bc84d0SRoderick Colenbrander static int sony_input_configured(struct hid_device *hdev,
2517e1bc84d0SRoderick Colenbrander 					struct hid_input *hidinput)
2518bd28ce00SJiri Slaby {
2519e1bc84d0SRoderick Colenbrander 	struct sony_sc *sc = hid_get_drvdata(hdev);
25200f398230SFrank Praznik 	int append_dev_id;
2521e1bc84d0SRoderick Colenbrander 	int ret;
2522bd28ce00SJiri Slaby 
25238025087aSFrank Praznik 	ret = sony_set_device_id(sc);
25248025087aSFrank Praznik 	if (ret < 0) {
25258025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
25268025087aSFrank Praznik 		goto err_stop;
25278025087aSFrank Praznik 	}
25288025087aSFrank Praznik 
2529131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2530131a8a9aSFrank Praznik 	if (ret < 0) {
2531131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2532131a8a9aSFrank Praznik 		goto err_stop;
2533131a8a9aSFrank Praznik 	}
2534131a8a9aSFrank Praznik 
25354545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
25364545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2537e534a935SBenjamin Tissoires 		/*
2538e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2539e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2540e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2541e534a935SBenjamin Tissoires 		 *
2542e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2543e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2544e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2545e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
25462a242932SFrank Praznik 		 *
25472a242932SFrank Praznik 		 * Additionally, the Sixaxis on USB isn't properly initialized
25482a242932SFrank Praznik 		 * until the PS logo button is pressed and as such won't retain
25492a242932SFrank Praznik 		 * any state set by an output report, so the initial
25502a242932SFrank Praznik 		 * configuration report is deferred until the first input
25512a242932SFrank Praznik 		 * report arrives.
2552e534a935SBenjamin Tissoires 		 */
2553e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2554e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
25552a242932SFrank Praznik 		sc->defer_initialization = 1;
2556816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
2557d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
25584545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
25594545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
25602078b9bbSFrank Praznik 		/*
25612078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
25622078b9bbSFrank Praznik 		 * when connected via Bluetooth.
25632078b9bbSFrank Praznik 		 */
25642078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2565816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
2566d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
2567fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
256868330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
256968330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
257068330d83SFrank Praznik 			if (ret < 0) {
257168330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
257268330d83SFrank Praznik 				goto err_stop;
257368330d83SFrank Praznik 			}
257468330d83SFrank Praznik 		}
2575c4e1ddf2SFrank Praznik 
2576e1bc84d0SRoderick Colenbrander 		/*
2577e1bc84d0SRoderick Colenbrander 		 * The Dualshock 4 touchpad supports 2 touches and has a
2578e1bc84d0SRoderick Colenbrander 		 * resolution of 1920x942 (44.86 dots/mm).
2579e1bc84d0SRoderick Colenbrander 		 */
2580ac797b95SRoderick Colenbrander 		ret = sony_register_touchpad(sc, 2, 1920, 942);
2581e1bc84d0SRoderick Colenbrander 		if (ret) {
2582e1bc84d0SRoderick Colenbrander 			hid_err(sc->hdev,
2583e1bc84d0SRoderick Colenbrander 			"Unable to initialize multi-touch slots: %d\n",
2584e1bc84d0SRoderick Colenbrander 			ret);
25852b6579d4SRoderick Colenbrander 			goto err_stop;
2586e1bc84d0SRoderick Colenbrander 		}
2587e1bc84d0SRoderick Colenbrander 
2588d8aaccdaSFrank Praznik 		sony_init_output_report(sc, dualshock4_send_output_report);
2589c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2590d8aaccdaSFrank Praznik 		sony_init_output_report(sc, motion_send_output_report);
25910bd88dd3SFrank Praznik 	} else {
25920bd88dd3SFrank Praznik 		ret = 0;
25930bd88dd3SFrank Praznik 	}
2594f9ce7c28SBastien Nocera 
25954dfdc464SJiri Kosina 	if (ret < 0)
2596bd28ce00SJiri Slaby 		goto err_stop;
2597bd28ce00SJiri Slaby 
25980f398230SFrank Praznik 	ret = append_dev_id = sony_check_add(sc);
2599d2d782fcSFrank Praznik 	if (ret < 0)
2600d2d782fcSFrank Praznik 		goto err_stop;
2601d2d782fcSFrank Praznik 
26020a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2603fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
26040a286ef2SSven Eckelmann 		if (ret < 0)
26050a286ef2SSven Eckelmann 			goto err_stop;
26060a286ef2SSven Eckelmann 	}
26070a286ef2SSven Eckelmann 
2608d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
26090f398230SFrank Praznik 		ret = sony_battery_probe(sc, append_dev_id);
2610a08c22c0SSven Eckelmann 		if (ret < 0)
2611a08c22c0SSven Eckelmann 			goto err_stop;
2612a08c22c0SSven Eckelmann 
2613d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2614d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2615d902f472SFrank Praznik 		if (ret < 0) {
2616d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2617d902f472SFrank Praznik 			goto err_stop;
2618d902f472SFrank Praznik 		}
2619d902f472SFrank Praznik 	}
2620d902f472SFrank Praznik 
2621c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2622fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2623d902f472SFrank Praznik 		if (ret < 0)
2624d902f472SFrank Praznik 			goto err_close;
26255f5750d2SFrank Praznik 	}
2626bd28ce00SJiri Slaby 
2627f425458eSH Hartley Sweeten 	return 0;
2628d902f472SFrank Praznik err_close:
2629d902f472SFrank Praznik 	hid_hw_close(hdev);
2630bd28ce00SJiri Slaby err_stop:
26310a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2632fa57a810SFrank Praznik 		sony_leds_remove(sc);
2633d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2634d902f472SFrank Praznik 		sony_battery_remove(sc);
263546262047SFrank Praznik 	sony_cancel_work_sync(sc);
26369b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2637d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
26388025087aSFrank Praznik 	sony_release_device_id(sc);
2639bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2640bd28ce00SJiri Slaby 	return ret;
2641bd28ce00SJiri Slaby }
2642bd28ce00SJiri Slaby 
2643e1bc84d0SRoderick Colenbrander static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2644e1bc84d0SRoderick Colenbrander {
2645e1bc84d0SRoderick Colenbrander 	int ret;
2646e1bc84d0SRoderick Colenbrander 	unsigned long quirks = id->driver_data;
2647e1bc84d0SRoderick Colenbrander 	struct sony_sc *sc;
2648e1bc84d0SRoderick Colenbrander 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2649e1bc84d0SRoderick Colenbrander 
2650e1bc84d0SRoderick Colenbrander 	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
2651e1bc84d0SRoderick Colenbrander 		quirks |= FUTUREMAX_DANCE_MAT;
2652e1bc84d0SRoderick Colenbrander 
2653e1bc84d0SRoderick Colenbrander 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2654e1bc84d0SRoderick Colenbrander 	if (sc == NULL) {
2655e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "can't alloc sony descriptor\n");
2656e1bc84d0SRoderick Colenbrander 		return -ENOMEM;
2657e1bc84d0SRoderick Colenbrander 	}
2658e1bc84d0SRoderick Colenbrander 
2659e1bc84d0SRoderick Colenbrander 	spin_lock_init(&sc->lock);
2660e1bc84d0SRoderick Colenbrander 
2661e1bc84d0SRoderick Colenbrander 	sc->quirks = quirks;
2662e1bc84d0SRoderick Colenbrander 	hid_set_drvdata(hdev, sc);
2663e1bc84d0SRoderick Colenbrander 	sc->hdev = hdev;
2664e1bc84d0SRoderick Colenbrander 
2665e1bc84d0SRoderick Colenbrander 	ret = hid_parse(hdev);
2666e1bc84d0SRoderick Colenbrander 	if (ret) {
2667e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "parse failed\n");
2668e1bc84d0SRoderick Colenbrander 		return ret;
2669e1bc84d0SRoderick Colenbrander 	}
2670e1bc84d0SRoderick Colenbrander 
2671e1bc84d0SRoderick Colenbrander 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2672e1bc84d0SRoderick Colenbrander 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2673e1bc84d0SRoderick Colenbrander 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2674e1bc84d0SRoderick Colenbrander 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2675e1bc84d0SRoderick Colenbrander 
26769131f8ccSRoderick Colenbrander 	/* Patch the hw version on DS4 compatible devices, so applications can
26779131f8ccSRoderick Colenbrander 	 * distinguish between the default HID mappings and the mappings defined
26789131f8ccSRoderick Colenbrander 	 * by the Linux game controller spec. This is important for the SDL2
26799131f8ccSRoderick Colenbrander 	 * library, which has a game controller database, which uses device ids
26809131f8ccSRoderick Colenbrander 	 * in combination with version as a key.
26819131f8ccSRoderick Colenbrander 	 */
26829131f8ccSRoderick Colenbrander 	if (sc->quirks & DUALSHOCK4_CONTROLLER)
26839131f8ccSRoderick Colenbrander 		hdev->version |= 0x8000;
26849131f8ccSRoderick Colenbrander 
2685e1bc84d0SRoderick Colenbrander 	ret = hid_hw_start(hdev, connect_mask);
2686e1bc84d0SRoderick Colenbrander 	if (ret) {
2687e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "hw start failed\n");
2688e1bc84d0SRoderick Colenbrander 		return ret;
2689e1bc84d0SRoderick Colenbrander 	}
2690e1bc84d0SRoderick Colenbrander 
26914f967f6dSRoderick Colenbrander 	/* sony_input_configured can fail, but this doesn't result
26924f967f6dSRoderick Colenbrander 	 * in hid_hw_start failures (intended). Check whether
26934f967f6dSRoderick Colenbrander 	 * the HID layer claimed the device else fail.
26944f967f6dSRoderick Colenbrander 	 * We don't know the actual reason for the failure, most
26954f967f6dSRoderick Colenbrander 	 * likely it is due to EEXIST in case of double connection
26964f967f6dSRoderick Colenbrander 	 * of USB and Bluetooth, but could have been due to ENOMEM
26974f967f6dSRoderick Colenbrander 	 * or other reasons as well.
26984f967f6dSRoderick Colenbrander 	 */
26994f967f6dSRoderick Colenbrander 	if (!(hdev->claimed & HID_CLAIMED_INPUT)) {
27004f967f6dSRoderick Colenbrander 		hid_err(hdev, "failed to claim input\n");
27014f967f6dSRoderick Colenbrander 		return -ENODEV;
27024f967f6dSRoderick Colenbrander 	}
27034f967f6dSRoderick Colenbrander 
2704e1bc84d0SRoderick Colenbrander 	return ret;
2705e1bc84d0SRoderick Colenbrander }
2706e1bc84d0SRoderick Colenbrander 
2707bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2708bd28ce00SJiri Slaby {
2709bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2710bd28ce00SJiri Slaby 
2711ac797b95SRoderick Colenbrander 	hid_hw_close(hdev);
2712ac797b95SRoderick Colenbrander 
27130a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2714fa57a810SFrank Praznik 		sony_leds_remove(sc);
2715bd28ce00SJiri Slaby 
2716ac797b95SRoderick Colenbrander 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2717d902f472SFrank Praznik 		sony_battery_remove(sc);
2718ac797b95SRoderick Colenbrander 
2719ac797b95SRoderick Colenbrander 	if (sc->touchpad)
2720ac797b95SRoderick Colenbrander 		sony_unregister_touchpad(sc);
2721d902f472SFrank Praznik 
272246262047SFrank Praznik 	sony_cancel_work_sync(sc);
27239f323b68SSven Eckelmann 
27249b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
27259b2b5c9aSFrank Praznik 
2726d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2727bd28ce00SJiri Slaby 
27288025087aSFrank Praznik 	sony_release_device_id(sc);
27298025087aSFrank Praznik 
2730bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2731bd28ce00SJiri Slaby }
2732bd28ce00SJiri Slaby 
2733decd946cSFrank Praznik #ifdef CONFIG_PM
2734decd946cSFrank Praznik 
2735decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2736decd946cSFrank Praznik {
2737decd946cSFrank Praznik 	/*
2738decd946cSFrank Praznik 	 * On suspend save the current LED state,
2739decd946cSFrank Praznik 	 * stop running force-feedback and blank the LEDS.
2740decd946cSFrank Praznik 	 */
2741decd946cSFrank Praznik 	if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
2742decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2743decd946cSFrank Praznik 
2744decd946cSFrank Praznik #ifdef CONFIG_SONY_FF
2745decd946cSFrank Praznik 		sc->left = sc->right = 0;
2746decd946cSFrank Praznik #endif
2747decd946cSFrank Praznik 
2748decd946cSFrank Praznik 		memcpy(sc->resume_led_state, sc->led_state,
2749decd946cSFrank Praznik 			sizeof(sc->resume_led_state));
2750decd946cSFrank Praznik 		memset(sc->led_state, 0, sizeof(sc->led_state));
2751decd946cSFrank Praznik 
2752decd946cSFrank Praznik 		sony_send_output_report(sc);
2753decd946cSFrank Praznik 	}
2754decd946cSFrank Praznik 
2755decd946cSFrank Praznik 	return 0;
2756decd946cSFrank Praznik }
2757decd946cSFrank Praznik 
2758decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev)
2759decd946cSFrank Praznik {
2760decd946cSFrank Praznik 	/* Restore the state of controller LEDs on resume */
2761decd946cSFrank Praznik 	if (SONY_LED_SUPPORT) {
2762decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2763decd946cSFrank Praznik 
2764decd946cSFrank Praznik 		memcpy(sc->led_state, sc->resume_led_state,
2765decd946cSFrank Praznik 			sizeof(sc->led_state));
2766decd946cSFrank Praznik 
2767decd946cSFrank Praznik 		/*
2768decd946cSFrank Praznik 		 * The Sixaxis and navigation controllers on USB need to be
2769decd946cSFrank Praznik 		 * reinitialized on resume or they won't behave properly.
2770decd946cSFrank Praznik 		 */
2771decd946cSFrank Praznik 		if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
27722a242932SFrank Praznik 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2773decd946cSFrank Praznik 			sixaxis_set_operational_usb(sc->hdev);
27742a242932SFrank Praznik 			sc->defer_initialization = 1;
27752a242932SFrank Praznik 		}
2776decd946cSFrank Praznik 
2777decd946cSFrank Praznik 		sony_set_leds(sc);
2778decd946cSFrank Praznik 	}
2779decd946cSFrank Praznik 
2780decd946cSFrank Praznik 	return 0;
2781decd946cSFrank Praznik }
2782decd946cSFrank Praznik 
2783decd946cSFrank Praznik #endif
2784decd946cSFrank Praznik 
2785bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2786bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2787bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2788bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
27894545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
27906eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
27914545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2792c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2793b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2794a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2795b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2796bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2797bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2798bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2799bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2800bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2801bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2802ef916ef5SAntonio Ospite 	/*
2803ef916ef5SAntonio Ospite 	 * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2804ef916ef5SAntonio Ospite 	 * Logitech joystick from the device descriptor.
2805ef916ef5SAntonio Ospite 	 */
2806bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2807bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2808bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2809bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2810bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2811bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2812bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2813bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2814bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2815bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
281668a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
281768a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
281868a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
28190bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
28200bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
28218ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
28220bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
28238ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
2824cf1015d6SRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
2825cf1015d6SRoderick Colenbrander 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
2826cf1015d6SRoderick Colenbrander 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
2827cf1015d6SRoderick Colenbrander 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
2828de66a1a0SRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE),
2829de66a1a0SRoderick Colenbrander 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
283074500cc8SScott Moreau 	/* Nyko Core Controller for PS3 */
283174500cc8SScott Moreau 	{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
283274500cc8SScott Moreau 		.driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
2833bd28ce00SJiri Slaby 	{ }
2834bd28ce00SJiri Slaby };
2835bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2836bd28ce00SJiri Slaby 
2837bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2838bd28ce00SJiri Slaby 	.name             = "sony",
2839bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2840bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2841ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2842bd28ce00SJiri Slaby 	.probe            = sony_probe,
2843bd28ce00SJiri Slaby 	.remove           = sony_remove,
2844bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2845decd946cSFrank Praznik 	.raw_event        = sony_raw_event,
2846decd946cSFrank Praznik 
2847decd946cSFrank Praznik #ifdef CONFIG_PM
2848decd946cSFrank Praznik 	.suspend          = sony_suspend,
2849decd946cSFrank Praznik 	.resume	          = sony_resume,
2850decd946cSFrank Praznik 	.reset_resume     = sony_resume,
2851decd946cSFrank Praznik #endif
2852bd28ce00SJiri Slaby };
28538025087aSFrank Praznik 
28548025087aSFrank Praznik static int __init sony_init(void)
28558025087aSFrank Praznik {
28568025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
28578025087aSFrank Praznik 
28588025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
28598025087aSFrank Praznik }
28608025087aSFrank Praznik 
28618025087aSFrank Praznik static void __exit sony_exit(void)
28628025087aSFrank Praznik {
28638025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
28648025087aSFrank Praznik 
28658025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
28666c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
28678025087aSFrank Praznik }
28688025087aSFrank Praznik module_init(sony_init);
28698025087aSFrank Praznik module_exit(sony_exit);
2870bd28ce00SJiri Slaby 
2871bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2872