xref: /linux/drivers/hid/hid-sony.c (revision cf1015d65d7c8a5504a4c03afb60fb86bff0f032)
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),            */
37958d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
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),            */
692d829674dSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
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 
980d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
981d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
982d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
983d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
984d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
985d902f472SFrank Praznik };
986d902f472SFrank Praznik 
98755d3b664SFrank Praznik struct sixaxis_led {
9881adf904eSPavel Machek 	u8 time_enabled; /* the total time the led is active (0xff means forever) */
9891adf904eSPavel Machek 	u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
9901adf904eSPavel Machek 	u8 enabled;
9911adf904eSPavel Machek 	u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
9921adf904eSPavel Machek 	u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
99355d3b664SFrank Praznik } __packed;
99455d3b664SFrank Praznik 
99555d3b664SFrank Praznik struct sixaxis_rumble {
9961adf904eSPavel Machek 	u8 padding;
9971adf904eSPavel Machek 	u8 right_duration; /* Right motor duration (0xff means forever) */
9981adf904eSPavel Machek 	u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
9991adf904eSPavel Machek 	u8 left_duration;    /* Left motor duration (0xff means forever) */
10001adf904eSPavel Machek 	u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
100155d3b664SFrank Praznik } __packed;
100255d3b664SFrank Praznik 
100355d3b664SFrank Praznik struct sixaxis_output_report {
10041adf904eSPavel Machek 	u8 report_id;
100555d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
10061adf904eSPavel Machek 	u8 padding[4];
10071adf904eSPavel Machek 	u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
100855d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
100955d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
101055d3b664SFrank Praznik } __packed;
101155d3b664SFrank Praznik 
101255d3b664SFrank Praznik union sixaxis_output_report_01 {
101355d3b664SFrank Praznik 	struct sixaxis_output_report data;
10141adf904eSPavel Machek 	u8 buf[36];
101555d3b664SFrank Praznik };
101655d3b664SFrank Praznik 
1017c5e0c1c4SFrank Praznik struct motion_output_report_02 {
1018c5e0c1c4SFrank Praznik 	u8 type, zero;
1019c5e0c1c4SFrank Praznik 	u8 r, g, b;
1020c5e0c1c4SFrank Praznik 	u8 zero2;
1021c5e0c1c4SFrank Praznik 	u8 rumble;
1022c5e0c1c4SFrank Praznik };
1023c5e0c1c4SFrank Praznik 
10242c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x02_SIZE 37
10252c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x81_SIZE 7
102649b9ca6cSRoderick Colenbrander #define DS4_INPUT_REPORT_0x11_SIZE 78
10272c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x05_SIZE 32
10282c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x11_SIZE 78
102929b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
1030a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
103141d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
10329b2b5c9aSFrank Praznik 
1033cdc1c021SRoderick Colenbrander /* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an
1034cdc1c021SRoderick Colenbrander  * additional +2.
1035cdc1c021SRoderick Colenbrander  */
1036cdc1c021SRoderick Colenbrander #define DS4_INPUT_REPORT_BATTERY_OFFSET  30
1037cdc1c021SRoderick Colenbrander #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33
1038cdc1c021SRoderick Colenbrander 
10398b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
1040d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
10418025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
1042d2d782fcSFrank Praznik 
1043cc6e0bbbSJiri Kosina struct sony_sc {
1044d902f472SFrank Praznik 	spinlock_t lock;
1045d2d782fcSFrank Praznik 	struct list_head list_node;
10460a286ef2SSven Eckelmann 	struct hid_device *hdev;
104760781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
1048cc6e0bbbSJiri Kosina 	unsigned long quirks;
10490a286ef2SSven Eckelmann 	struct work_struct state_worker;
1050d8aaccdaSFrank Praznik 	void (*send_output_report)(struct sony_sc *);
1051297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
1052297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
10538025087aSFrank Praznik 	int device_id;
10541adf904eSPavel Machek 	u8 *output_report_dmabuf;
1055f04d5140SColin Leitner 
10569f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
10571adf904eSPavel Machek 	u8 left;
10581adf904eSPavel Machek 	u8 right;
10599f323b68SSven Eckelmann #endif
10609f323b68SSven Eckelmann 
10611adf904eSPavel Machek 	u8 mac_address[6];
10621adf904eSPavel Machek 	u8 worker_initialized;
10632a242932SFrank Praznik 	u8 defer_initialization;
10641adf904eSPavel Machek 	u8 cable_state;
10651adf904eSPavel Machek 	u8 battery_charging;
10661adf904eSPavel Machek 	u8 battery_capacity;
10671adf904eSPavel Machek 	u8 led_state[MAX_LEDS];
10681adf904eSPavel Machek 	u8 resume_led_state[MAX_LEDS];
10691adf904eSPavel Machek 	u8 led_delay_on[MAX_LEDS];
10701adf904eSPavel Machek 	u8 led_delay_off[MAX_LEDS];
10711adf904eSPavel Machek 	u8 led_count;
1072cc6e0bbbSJiri Kosina };
1073cc6e0bbbSJiri Kosina 
10742a242932SFrank Praznik static inline void sony_schedule_work(struct sony_sc *sc)
10752a242932SFrank Praznik {
10762a242932SFrank Praznik 	if (!sc->defer_initialization)
10772a242932SFrank Praznik 		schedule_work(&sc->state_worker);
10782a242932SFrank Praznik }
10792a242932SFrank Praznik 
10801adf904eSPavel Machek static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc,
1081c607fb8dSAntonio Ospite 			     unsigned int *rsize)
1082c607fb8dSAntonio Ospite {
1083c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
1084c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
1085c607fb8dSAntonio Ospite }
1086c607fb8dSAntonio Ospite 
1087c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
1088c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
1089c5e0c1c4SFrank Praznik {
1090c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
1091c5e0c1c4SFrank Praznik 	return motion_rdesc;
1092c5e0c1c4SFrank Praznik }
1093c5e0c1c4SFrank Praznik 
1094b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc,
1095b2723eb7SSimon Wood 			     unsigned int *rsize)
1096b2723eb7SSimon Wood {
1097b2723eb7SSimon Wood 	*rsize = sizeof(navigation_rdesc);
1098b2723eb7SSimon Wood 	return navigation_rdesc;
1099b2723eb7SSimon Wood }
1100b2723eb7SSimon Wood 
11011adf904eSPavel Machek static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc,
1102078328daSJiri Kosina 			     unsigned int *rsize)
1103078328daSJiri Kosina {
1104078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
1105078328daSJiri Kosina 	return ps3remote_rdesc;
1106078328daSJiri Kosina }
1107078328daSJiri Kosina 
1108078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
1109078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
1110078328daSJiri Kosina 			     unsigned long **bit, int *max)
1111078328daSJiri Kosina {
1112078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
1113078328daSJiri Kosina 
1114078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1115078328daSJiri Kosina 		return -1;
1116078328daSJiri Kosina 
1117078328daSJiri Kosina 	switch (usage->collection_index) {
1118078328daSJiri Kosina 	case 1:
1119078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
1120078328daSJiri Kosina 			return -1;
1121078328daSJiri Kosina 
1122078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
1123078328daSJiri Kosina 		if (!key)
1124078328daSJiri Kosina 			return -1;
1125078328daSJiri Kosina 		break;
1126078328daSJiri Kosina 	case 2:
1127078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1128078328daSJiri Kosina 			return -1;
1129078328daSJiri Kosina 
1130078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1131078328daSJiri Kosina 		if (!key)
1132078328daSJiri Kosina 			return -1;
1133078328daSJiri Kosina 		break;
1134078328daSJiri Kosina 	default:
1135078328daSJiri Kosina 		return -1;
1136078328daSJiri Kosina 	}
1137078328daSJiri Kosina 
1138078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1139078328daSJiri Kosina 	return 1;
1140078328daSJiri Kosina }
1141078328daSJiri Kosina 
11421adf904eSPavel Machek static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
114373e4008dSNikolai Kondrashov 		unsigned int *rsize)
1144cc6e0bbbSJiri Kosina {
1145cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1146cc6e0bbbSJiri Kosina 
11474ba1eeebSMikko Perttunen 	if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
114874500cc8SScott Moreau 		return rdesc;
114974500cc8SScott Moreau 
115099d24902SFernando Luis Vázquez Cao 	/*
115199d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
115299d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
115399d24902SFernando Luis Vázquez Cao 	 */
115499d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
115599d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
115699d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
115799d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
115899d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
115999d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
116099d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1161a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
116299d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1163cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1164cc6e0bbbSJiri Kosina 	}
116561ab44beSSimon Wood 
1166ed19d8cfSFrank Praznik 	/*
1167ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1168ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1169ed19d8cfSFrank Praznik 	 * modified one.
1170ed19d8cfSFrank Praznik 	 */
1171b71b5578SFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1172ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1173ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1174ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1175b71b5578SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
1176d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1177d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1178d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1179ed19d8cfSFrank Praznik 	}
1180ed19d8cfSFrank Praznik 
1181c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1182c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1183078328daSJiri Kosina 
1184c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1185c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1186c5e0c1c4SFrank Praznik 
11874545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1188b2723eb7SSimon Wood 		return navigation_fixup(hdev, rdesc, rsize);
11894545ee0aSSimon Wood 
1190078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1191078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1192078328daSJiri Kosina 
119373e4008dSNikolai Kondrashov 	return rdesc;
1194cc6e0bbbSJiri Kosina }
1195cc6e0bbbSJiri Kosina 
11961adf904eSPavel Machek static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
1197d902f472SFrank Praznik {
11981adf904eSPavel Machek 	static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1199d902f472SFrank Praznik 	unsigned long flags;
120012e9a6d7SSimon Wood 	int offset;
12011adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1202d902f472SFrank Praznik 
1203ad142b9eSFrank Praznik 	/*
1204ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1205d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1206d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1207d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1208d902f472SFrank Praznik 	 */
120912e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
121012e9a6d7SSimon Wood 
121112e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1212d902f472SFrank Praznik 		battery_capacity = 100;
121312e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
12149fddd74aSFrank Praznik 		cable_state = 1;
1215d902f472SFrank Praznik 	} else {
12161adf904eSPavel Machek 		u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1217ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1218d902f472SFrank Praznik 		battery_charging = 0;
12199fddd74aSFrank Praznik 		cable_state = 0;
1220d902f472SFrank Praznik 	}
1221d902f472SFrank Praznik 
1222d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1223d902f472SFrank Praznik 	sc->cable_state = cable_state;
1224d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1225d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1226d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1227d902f472SFrank Praznik }
1228d902f472SFrank Praznik 
12291adf904eSPavel Machek static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1230d902f472SFrank Praznik {
1231e5606230SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1232e5606230SFrank Praznik 						struct hid_input, list);
1233e5606230SFrank Praznik 	struct input_dev *input_dev = hidinput->input;
1234d902f472SFrank Praznik 	unsigned long flags;
1235cdc1c021SRoderick Colenbrander 	int n, m, offset, num_touch_data, max_touch_data;
12361adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1237d902f472SFrank Praznik 
1238cdc1c021SRoderick Colenbrander 	/* When using Bluetooth the header is 2 bytes longer, so skip these. */
1239cdc1c021SRoderick Colenbrander 	int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2;
12406c5f860dSFrank Praznik 
1241ad142b9eSFrank Praznik 	/*
1242cdc1c021SRoderick Colenbrander 	 * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level
1243d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1244d902f472SFrank Praznik 	 */
1245cdc1c021SRoderick Colenbrander 	offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET;
12466c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
12476c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1248d902f472SFrank Praznik 
1249ad142b9eSFrank Praznik 	/*
1250ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
12516c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
12526c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1253d902f472SFrank Praznik 	 */
12546c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1255d902f472SFrank Praznik 		battery_charging = 0;
1256d902f472SFrank Praznik 	else
1257d902f472SFrank Praznik 		battery_charging = 1;
1258d902f472SFrank Praznik 
12596c5f860dSFrank Praznik 	if (!cable_state)
12606c5f860dSFrank Praznik 		battery_capacity++;
1261d902f472SFrank Praznik 	if (battery_capacity > 10)
12626c5f860dSFrank Praznik 		battery_capacity = 10;
12636c5f860dSFrank Praznik 
1264d902f472SFrank Praznik 	battery_capacity *= 10;
1265d902f472SFrank Praznik 
1266d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1267d902f472SFrank Praznik 	sc->cable_state = cable_state;
1268d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1269d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1270d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1271e5606230SFrank Praznik 
1272cdc1c021SRoderick Colenbrander 	/*
1273cdc1c021SRoderick Colenbrander 	 * The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB
1274cdc1c021SRoderick Colenbrander 	 * and 35 on Bluetooth.
1275cdc1c021SRoderick Colenbrander 	 * The first byte indicates the number of touch data in the report.
1276cdc1c021SRoderick Colenbrander 	 * Trackpad data starts 2 bytes later (e.g. 35 for USB).
1277cdc1c021SRoderick Colenbrander 	 */
1278cdc1c021SRoderick Colenbrander 	offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET;
1279cdc1c021SRoderick Colenbrander 	max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4;
1280cdc1c021SRoderick Colenbrander 	if (rd[offset] > 0 && rd[offset] <= max_touch_data)
1281cdc1c021SRoderick Colenbrander 		num_touch_data = rd[offset];
1282cdc1c021SRoderick Colenbrander 	else
1283cdc1c021SRoderick Colenbrander 		num_touch_data = 1;
1284cdc1c021SRoderick Colenbrander 	offset += 1;
1285cdc1c021SRoderick Colenbrander 
1286cdc1c021SRoderick Colenbrander 	for (m = 0; m < num_touch_data; m++) {
1287cdc1c021SRoderick Colenbrander 		/* Skip past timestamp */
1288cdc1c021SRoderick Colenbrander 		offset += 1;
12896c5f860dSFrank Praznik 
1290ad142b9eSFrank Praznik 		/*
1291cdc1c021SRoderick Colenbrander 		 * The first 7 bits of the first byte is a counter and bit 8 is
1292cdc1c021SRoderick Colenbrander 		 * a touch indicator that is 0 when pressed and 1 when not
1293cdc1c021SRoderick Colenbrander 		 * pressed.
1294e5606230SFrank Praznik 		 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1295cdc1c021SRoderick Colenbrander 		 * The data for the second touch is in the same format and
1296cdc1c021SRoderick Colenbrander 		 * immediately follows the data for the first.
1297e5606230SFrank Praznik 		 */
1298e5606230SFrank Praznik 		for (n = 0; n < 2; n++) {
12991adf904eSPavel Machek 			u16 x, y;
1300cdc1c021SRoderick Colenbrander 			bool active;
1301e5606230SFrank Praznik 
1302e5606230SFrank Praznik 			x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1303e5606230SFrank Praznik 			y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1304e5606230SFrank Praznik 
1305cdc1c021SRoderick Colenbrander 			active = !(rd[offset] >> 7);
1306e5606230SFrank Praznik 			input_mt_slot(input_dev, n);
1307cdc1c021SRoderick Colenbrander 			input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, active);
1308cdc1c021SRoderick Colenbrander 
1309cdc1c021SRoderick Colenbrander 			if (active) {
1310e5606230SFrank Praznik 				input_report_abs(input_dev, ABS_MT_POSITION_X, x);
1311e5606230SFrank Praznik 				input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
1312cdc1c021SRoderick Colenbrander 			}
1313e5606230SFrank Praznik 
1314e5606230SFrank Praznik 			offset += 4;
1315e5606230SFrank Praznik 		}
1316cdc1c021SRoderick Colenbrander 		input_mt_sync_frame(input_dev);
1317cdc1c021SRoderick Colenbrander 		input_sync(input_dev);
1318cdc1c021SRoderick Colenbrander 	}
1319d902f472SFrank Praznik }
1320d902f472SFrank Praznik 
1321c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
13221adf904eSPavel Machek 		u8 *rd, int size)
1323c9e4d877SSimon Wood {
1324c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1325c9e4d877SSimon Wood 
1326ad142b9eSFrank Praznik 	/*
1327ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1328c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1329c9e4d877SSimon Wood 	 */
1330fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
13318f5f0bc2SFrank Praznik 		/*
13328f5f0bc2SFrank Praznik 		 * When connected via Bluetooth the Sixaxis occasionally sends
13338f5f0bc2SFrank Praznik 		 * a report with the second byte 0xff and the rest zeroed.
13348f5f0bc2SFrank Praznik 		 *
13358f5f0bc2SFrank Praznik 		 * This report does not reflect the actual state of the
13368f5f0bc2SFrank Praznik 		 * controller must be ignored to avoid generating false input
13378f5f0bc2SFrank Praznik 		 * events.
13388f5f0bc2SFrank Praznik 		 */
13398f5f0bc2SFrank Praznik 		if (rd[1] == 0xff)
13408f5f0bc2SFrank Praznik 			return -EINVAL;
13418f5f0bc2SFrank Praznik 
1342c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1343c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1344c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1345c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1346d902f472SFrank Praznik 
1347d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
134812e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
134912e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
13504545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
13514545ee0aSSimon Wood 			size == 49) {
13524545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
135368330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
135468330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
135568330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
135649b9ca6cSRoderick Colenbrander 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
135749b9ca6cSRoderick Colenbrander 			/* CRC check */
135849b9ca6cSRoderick Colenbrander 			u8 bthdr = 0xA1;
135949b9ca6cSRoderick Colenbrander 			u32 crc;
136049b9ca6cSRoderick Colenbrander 			u32 report_crc;
136149b9ca6cSRoderick Colenbrander 
136249b9ca6cSRoderick Colenbrander 			crc = crc32_le(0xFFFFFFFF, &bthdr, 1);
136349b9ca6cSRoderick Colenbrander 			crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4);
136449b9ca6cSRoderick Colenbrander 			report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]);
136549b9ca6cSRoderick Colenbrander 			if (crc != report_crc) {
136649b9ca6cSRoderick Colenbrander 				hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n",
136749b9ca6cSRoderick Colenbrander 					report_crc, crc);
136849b9ca6cSRoderick Colenbrander 				return -EILSEQ;
136949b9ca6cSRoderick Colenbrander 			}
137049b9ca6cSRoderick Colenbrander 		}
1371d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1372c9e4d877SSimon Wood 	}
1373c9e4d877SSimon Wood 
13742a242932SFrank Praznik 	if (sc->defer_initialization) {
13752a242932SFrank Praznik 		sc->defer_initialization = 0;
13762a242932SFrank Praznik 		sony_schedule_work(sc);
13772a242932SFrank Praznik 	}
13782a242932SFrank Praznik 
1379c9e4d877SSimon Wood 	return 0;
1380c9e4d877SSimon Wood }
1381c9e4d877SSimon Wood 
1382f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1383f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1384f04d5140SColin Leitner 			unsigned long **bit, int *max)
1385f04d5140SColin Leitner {
1386f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1387f04d5140SColin Leitner 
1388f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1389f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1390f04d5140SColin Leitner 
1391f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1392f04d5140SColin Leitner 			return -1;
1393f04d5140SColin Leitner 
1394f04d5140SColin Leitner 		switch (usage->collection_index) {
1395f04d5140SColin Leitner 		case 1:
1396f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1397f04d5140SColin Leitner 				return -1;
1398f04d5140SColin Leitner 
1399f04d5140SColin Leitner 			key = buzz_keymap[key];
1400f04d5140SColin Leitner 			if (!key)
1401f04d5140SColin Leitner 				return -1;
1402f04d5140SColin Leitner 			break;
1403f04d5140SColin Leitner 		default:
1404f04d5140SColin Leitner 			return -1;
1405f04d5140SColin Leitner 		}
1406f04d5140SColin Leitner 
1407f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1408f04d5140SColin Leitner 		return 1;
1409f04d5140SColin Leitner 	}
1410f04d5140SColin Leitner 
1411078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1412078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1413078328daSJiri Kosina 
14146f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
14156f498018SBenjamin Tissoires 	return 0;
1416f04d5140SColin Leitner }
1417f04d5140SColin Leitner 
1418ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count,
1419ce8efc3bSFrank Praznik 					int w, int h)
1420ce8efc3bSFrank Praznik {
1421ce8efc3bSFrank Praznik 	struct input_dev *input_dev = hi->input;
1422ce8efc3bSFrank Praznik 	int ret;
1423ce8efc3bSFrank Praznik 
1424ce8efc3bSFrank Praznik 	ret = input_mt_init_slots(input_dev, touch_count, 0);
1425ce8efc3bSFrank Praznik 	if (ret < 0)
1426ce8efc3bSFrank Praznik 		return ret;
1427ce8efc3bSFrank Praznik 
1428ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
1429ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
1430ce8efc3bSFrank Praznik 
1431ce8efc3bSFrank Praznik 	return 0;
1432ce8efc3bSFrank Praznik }
1433ce8efc3bSFrank Praznik 
14349154301aSDmitry Torokhov 
14355710fabfSAntonio Ospite /*
1436bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1437bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1438bd28ce00SJiri Slaby  * events.
1439bd28ce00SJiri Slaby  */
1440816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1441bd28ce00SJiri Slaby {
1442a85d67b5SAntonio Ospite 	const int buf_size =
1443a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
14441adf904eSPavel Machek 	u8 *buf;
1445bd28ce00SJiri Slaby 	int ret;
1446bd28ce00SJiri Slaby 
14472e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1448bd28ce00SJiri Slaby 	if (!buf)
1449bd28ce00SJiri Slaby 		return -ENOMEM;
1450bd28ce00SJiri Slaby 
1451a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1452a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1453a7de9b86SLauri Kasanen 	if (ret < 0) {
1454a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1455a7de9b86SLauri Kasanen 		goto out;
1456a7de9b86SLauri Kasanen 	}
1457f204828aSBenjamin Tissoires 
1458a7de9b86SLauri Kasanen 	/*
1459a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1460a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1461a7de9b86SLauri Kasanen 	 */
1462a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1463a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1464a7de9b86SLauri Kasanen 	if (ret < 0) {
1465a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1466a7de9b86SLauri Kasanen 		goto out;
1467a7de9b86SLauri Kasanen 	}
1468a7de9b86SLauri Kasanen 
1469a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
147019f4c2baSBenjamin Tissoires 	if (ret < 0) {
147119f4c2baSBenjamin Tissoires 		hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
147219f4c2baSBenjamin Tissoires 		ret = 0;
147319f4c2baSBenjamin Tissoires 	}
1474bd28ce00SJiri Slaby 
1475a7de9b86SLauri Kasanen out:
1476bd28ce00SJiri Slaby 	kfree(buf);
1477bd28ce00SJiri Slaby 
1478bd28ce00SJiri Slaby 	return ret;
1479bd28ce00SJiri Slaby }
1480bd28ce00SJiri Slaby 
1481816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1482f9ce7c28SBastien Nocera {
14831adf904eSPavel Machek 	static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
14841adf904eSPavel Machek 	u8 *buf;
14859b2b5c9aSFrank Praznik 	int ret;
14869b2b5c9aSFrank Praznik 
14879b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
14889b2b5c9aSFrank Praznik 	if (!buf)
14899b2b5c9aSFrank Praznik 		return -ENOMEM;
14909b2b5c9aSFrank Praznik 
14919b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1492b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
14939b2b5c9aSFrank Praznik 
14949b2b5c9aSFrank Praznik 	kfree(buf);
14959b2b5c9aSFrank Praznik 
14969b2b5c9aSFrank Praznik 	return ret;
1497f9ce7c28SBastien Nocera }
1498f9ce7c28SBastien Nocera 
1499ad142b9eSFrank Praznik /*
1500ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
150168330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
150268330d83SFrank Praznik  */
150368330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
150468330d83SFrank Praznik {
15051adf904eSPavel Machek 	u8 *buf;
15069b2b5c9aSFrank Praznik 	int ret;
150768330d83SFrank Praznik 
15082c159de0SRoderick Colenbrander 	buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);
15099b2b5c9aSFrank Praznik 	if (!buf)
15109b2b5c9aSFrank Praznik 		return -ENOMEM;
15119b2b5c9aSFrank Praznik 
15122c159de0SRoderick Colenbrander 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE,
151368330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
15149b2b5c9aSFrank Praznik 
15159b2b5c9aSFrank Praznik 	kfree(buf);
15169b2b5c9aSFrank Praznik 
15179b2b5c9aSFrank Praznik 	return ret;
1518bd28ce00SJiri Slaby }
1519bd28ce00SJiri Slaby 
1520221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
15218025087aSFrank Praznik {
15221adf904eSPavel Machek 	static const u8 sixaxis_leds[10][4] = {
15238025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
15248025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
15258025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
15268025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
15278025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
15288025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
15298025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
15308025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
15318025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
15328025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
15338025087aSFrank Praznik 	};
15348025087aSFrank Praznik 
1535221399b3SFrank Praznik 	int id = sc->device_id;
1536221399b3SFrank Praznik 
1537221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
15388025087aSFrank Praznik 
15398025087aSFrank Praznik 	if (id < 0)
15408025087aSFrank Praznik 		return;
15418025087aSFrank Praznik 
15428025087aSFrank Praznik 	id %= 10;
1543221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
15448025087aSFrank Praznik }
15458025087aSFrank Praznik 
1546221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
15478025087aSFrank Praznik {
15488025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
15491adf904eSPavel Machek 	static const u8 color_code[7][3] = {
15508025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
15518025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
15528025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
15538025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
15548025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
15558025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
15568025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
15578025087aSFrank Praznik 	};
15588025087aSFrank Praznik 
1559221399b3SFrank Praznik 	int id = sc->device_id;
1560221399b3SFrank Praznik 
1561221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
15628025087aSFrank Praznik 
15638025087aSFrank Praznik 	if (id < 0)
15648025087aSFrank Praznik 		return;
15658025087aSFrank Praznik 
15668025087aSFrank Praznik 	id %= 7;
1567221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
15688025087aSFrank Praznik }
15698025087aSFrank Praznik 
1570221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1571f04d5140SColin Leitner {
1572221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1573f04d5140SColin Leitner 	struct list_head *report_list =
1574f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1575f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1576f04d5140SColin Leitner 		struct hid_report, list);
15771adf904eSPavel Machek 	s32 *value = report->field[0]->value;
1578f04d5140SColin Leitner 
1579221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1580221399b3SFrank Praznik 
1581f04d5140SColin Leitner 	value[0] = 0x00;
1582221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1583221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1584221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1585221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1586f04d5140SColin Leitner 	value[5] = 0x00;
1587f04d5140SColin Leitner 	value[6] = 0x00;
1588f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1589f04d5140SColin Leitner }
1590f04d5140SColin Leitner 
1591221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
15920a286ef2SSven Eckelmann {
1593221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
15942a242932SFrank Praznik 		sony_schedule_work(sc);
1595221399b3SFrank Praznik 	else
1596221399b3SFrank Praznik 		buzz_set_leds(sc);
15970a286ef2SSven Eckelmann }
15980a286ef2SSven Eckelmann 
1599c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1600f04d5140SColin Leitner 				    enum led_brightness value)
1601f04d5140SColin Leitner {
1602f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1603ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1604f04d5140SColin Leitner 	struct sony_sc *drv_data;
1605f04d5140SColin Leitner 
1606f04d5140SColin Leitner 	int n;
1607b3ed458cSFrank Praznik 	int force_update;
1608f04d5140SColin Leitner 
1609f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
16102251b85fSSven Eckelmann 	if (!drv_data) {
1611f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1612f04d5140SColin Leitner 		return;
1613f04d5140SColin Leitner 	}
1614f04d5140SColin Leitner 
1615b3ed458cSFrank Praznik 	/*
1616b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1617b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1618b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1619b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1620b3ed458cSFrank Praznik 	 * stop the flashing later on.
1621b3ed458cSFrank Praznik 	 */
1622b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1623b3ed458cSFrank Praznik 
162460781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1625b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1626b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1627b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1628b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1629b3ed458cSFrank Praznik 
163060781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1631b3ed458cSFrank Praznik 
1632b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1633b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1634b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1635b3ed458cSFrank Praznik 
1636221399b3SFrank Praznik 			sony_set_leds(drv_data);
1637f04d5140SColin Leitner 			break;
1638f04d5140SColin Leitner 		}
1639f04d5140SColin Leitner 	}
1640f04d5140SColin Leitner }
1641f04d5140SColin Leitner 
1642c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1643f04d5140SColin Leitner {
1644f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1645ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1646f04d5140SColin Leitner 	struct sony_sc *drv_data;
1647f04d5140SColin Leitner 
1648f04d5140SColin Leitner 	int n;
1649f04d5140SColin Leitner 
1650f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
16512251b85fSSven Eckelmann 	if (!drv_data) {
1652f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1653f04d5140SColin Leitner 		return LED_OFF;
1654f04d5140SColin Leitner 	}
1655f04d5140SColin Leitner 
165660781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
16577db7504aSSimon Wood 		if (led == drv_data->leds[n])
16587db7504aSSimon Wood 			return drv_data->led_state[n];
1659f04d5140SColin Leitner 	}
1660f04d5140SColin Leitner 
16617db7504aSSimon Wood 	return LED_OFF;
1662f04d5140SColin Leitner }
1663f04d5140SColin Leitner 
1664b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1665b3ed458cSFrank Praznik 				unsigned long *delay_off)
1666b3ed458cSFrank Praznik {
1667b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1668ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1669b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1670b3ed458cSFrank Praznik 	int n;
16711adf904eSPavel Machek 	u8 new_on, new_off;
1672b3ed458cSFrank Praznik 
1673b3ed458cSFrank Praznik 	if (!drv_data) {
1674b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1675b3ed458cSFrank Praznik 		return -EINVAL;
1676b3ed458cSFrank Praznik 	}
1677b3ed458cSFrank Praznik 
1678b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1679b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1680b3ed458cSFrank Praznik 		*delay_on = 2550;
1681b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1682b3ed458cSFrank Praznik 		*delay_off = 2550;
1683b3ed458cSFrank Praznik 
1684b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1685b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1686b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1687b3ed458cSFrank Praznik 
1688b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1689b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1690b3ed458cSFrank Praznik 
1691b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1692b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1693b3ed458cSFrank Praznik 			break;
1694b3ed458cSFrank Praznik 	}
1695b3ed458cSFrank Praznik 
1696b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1697b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1698b3ed458cSFrank Praznik 		return -EINVAL;
1699b3ed458cSFrank Praznik 
1700b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1701b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1702b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1703b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1704b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
17052a242932SFrank Praznik 		sony_schedule_work(drv_data);
1706b3ed458cSFrank Praznik 	}
1707b3ed458cSFrank Praznik 
1708b3ed458cSFrank Praznik 	return 0;
1709b3ed458cSFrank Praznik }
1710b3ed458cSFrank Praznik 
1711fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
17120a286ef2SSven Eckelmann {
17130a286ef2SSven Eckelmann 	struct led_classdev *led;
17140a286ef2SSven Eckelmann 	int n;
17150a286ef2SSven Eckelmann 
1716fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
17170a286ef2SSven Eckelmann 
1718fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1719fa57a810SFrank Praznik 		led = sc->leds[n];
1720fa57a810SFrank Praznik 		sc->leds[n] = NULL;
17210a286ef2SSven Eckelmann 		if (!led)
17220a286ef2SSven Eckelmann 			continue;
17230a286ef2SSven Eckelmann 		led_classdev_unregister(led);
17240a286ef2SSven Eckelmann 		kfree(led);
17250a286ef2SSven Eckelmann 	}
172660781cf4SFrank Praznik 
1727fa57a810SFrank Praznik 	sc->led_count = 0;
17280a286ef2SSven Eckelmann }
17290a286ef2SSven Eckelmann 
1730fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1731f04d5140SColin Leitner {
1732fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
173340e32ee6SJiri Kosina 	int n, ret = 0;
1734b3ed458cSFrank Praznik 	int use_ds4_names;
173540e32ee6SJiri Kosina 	struct led_classdev *led;
173640e32ee6SJiri Kosina 	size_t name_sz;
173740e32ee6SJiri Kosina 	char *name;
17380a286ef2SSven Eckelmann 	size_t name_len;
17390a286ef2SSven Eckelmann 	const char *name_fmt;
1740b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1741b3ed458cSFrank Praznik 						  "global" };
17421adf904eSPavel Machek 	u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
17431adf904eSPavel Machek 	u8 use_hw_blink[MAX_LEDS] = { 0 };
1744f04d5140SColin Leitner 
1745fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1746f04d5140SColin Leitner 
1747fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1748fa57a810SFrank Praznik 		sc->led_count = 4;
1749b3ed458cSFrank Praznik 		use_ds4_names = 0;
17500a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
17510a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
17529446edb9SKees Cook 		/* Validate expected report characteristics. */
17539446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
17549446edb9SKees Cook 			return -ENODEV;
1755fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1756221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1757221399b3SFrank Praznik 		sc->led_state[3] = 1;
1758b3ed458cSFrank Praznik 		sc->led_count = 4;
1759b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1760b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1761b3ed458cSFrank Praznik 		use_ds4_names = 1;
176261ebca93SFrank Praznik 		name_len = 0;
176361ebca93SFrank Praznik 		name_fmt = "%s:%s";
1764c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1765c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1766c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1767c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1768c5e0c1c4SFrank Praznik 		name_len = 0;
1769c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
17704545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
17711adf904eSPavel Machek 		static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
17724545ee0aSSimon Wood 
17734545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
17744545ee0aSSimon Wood 		sc->led_count = 1;
17754545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
17764545ee0aSSimon Wood 		use_ds4_names = 0;
17774545ee0aSSimon Wood 		name_len = strlen("::sony#");
17784545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
177960781cf4SFrank Praznik 	} else {
1780221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1781fa57a810SFrank Praznik 		sc->led_count = 4;
1782b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1783b3ed458cSFrank Praznik 		use_ds4_names = 0;
178461ebca93SFrank Praznik 		name_len = strlen("::sony#");
178561ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
178660781cf4SFrank Praznik 	}
178760781cf4SFrank Praznik 
1788ad142b9eSFrank Praznik 	/*
1789ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1790f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1791ad142b9eSFrank Praznik 	 * LEDs to on
1792ad142b9eSFrank Praznik 	 */
1793221399b3SFrank Praznik 	sony_set_leds(sc);
1794f04d5140SColin Leitner 
17950a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1796f04d5140SColin Leitner 
1797fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
179861ebca93SFrank Praznik 
1799b3ed458cSFrank Praznik 		if (use_ds4_names)
1800b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
180161ebca93SFrank Praznik 
1802f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1803f04d5140SColin Leitner 		if (!led) {
1804f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
18058cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1806f04d5140SColin Leitner 			goto error_leds;
1807f04d5140SColin Leitner 		}
1808f04d5140SColin Leitner 
1809f04d5140SColin Leitner 		name = (void *)(&led[1]);
1810b3ed458cSFrank Praznik 		if (use_ds4_names)
1811b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1812b3ed458cSFrank Praznik 			ds4_name_str[n]);
181361ebca93SFrank Praznik 		else
18140a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1815f04d5140SColin Leitner 		led->name = name;
1816221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1817b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1818c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1819c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1820f04d5140SColin Leitner 
1821b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1822b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1823b3ed458cSFrank Praznik 
18248025087aSFrank Praznik 		sc->leds[n] = led;
18258025087aSFrank Praznik 
18268cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
18278cd5fcdaSJulia Lawall 		if (ret) {
1828f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
18298025087aSFrank Praznik 			sc->leds[n] = NULL;
1830f04d5140SColin Leitner 			kfree(led);
1831f04d5140SColin Leitner 			goto error_leds;
1832f04d5140SColin Leitner 		}
1833f04d5140SColin Leitner 	}
1834f04d5140SColin Leitner 
1835f04d5140SColin Leitner 	return ret;
1836f04d5140SColin Leitner 
1837f04d5140SColin Leitner error_leds:
1838fa57a810SFrank Praznik 	sony_leds_remove(sc);
1839f04d5140SColin Leitner 
1840f04d5140SColin Leitner 	return ret;
1841f04d5140SColin Leitner }
1842f04d5140SColin Leitner 
1843d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc)
1844a08c22c0SSven Eckelmann {
18459b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
184655d3b664SFrank Praznik 		.buf = {
1847a08c22c0SSven Eckelmann 			0x01,
1848ad07b7a6SScott Moreau 			0x01, 0xff, 0x00, 0xff, 0x00,
18490a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1850a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1851a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1852a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1853a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1854a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
185555d3b664SFrank Praznik 		}
1856a08c22c0SSven Eckelmann 	};
18579b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
18589b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
18599b2b5c9aSFrank Praznik 	int n;
18609b2b5c9aSFrank Praznik 
18619b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
18629b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
18639f323b68SSven Eckelmann 
18640a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
18659b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
18669b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
18670a286ef2SSven Eckelmann #endif
18680a286ef2SSven Eckelmann 
18699b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
18709b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
18719b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
18729b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
18739f323b68SSven Eckelmann 
187488f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
18759b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
18769b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
187788f6576fSSimon Wood 
1878b3ed458cSFrank Praznik 	/*
1879b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
1880b3ed458cSFrank Praznik 	 * corresponding light on the controller.
1881b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
1882b3ed458cSFrank Praznik 	 *
1883b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
1884b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
1885b3ed458cSFrank Praznik 	 * always off.
1886b3ed458cSFrank Praznik 	 */
1887b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
1888b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
18899b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
18909b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
1891b3ed458cSFrank Praznik 		}
1892b3ed458cSFrank Praznik 	}
1893b3ed458cSFrank Praznik 
18941adf904eSPavel Machek 	hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
18959b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
18969b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18979f323b68SSven Eckelmann }
18989f323b68SSven Eckelmann 
1899d8aaccdaSFrank Praznik static void dualshock4_send_output_report(struct sony_sc *sc)
19000bd88dd3SFrank Praznik {
19010da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
19021adf904eSPavel Machek 	u8 *buf = sc->output_report_dmabuf;
190348220237SFrank Praznik 	int offset;
19040da8ea65SFrank Praznik 
1905c4425c8fSFrank Praznik 	/*
1906c4425c8fSFrank Praznik 	 * NOTE: The buf[1] field of the Bluetooth report controls
1907c4425c8fSFrank Praznik 	 * the Dualshock 4 reporting rate.
1908c4425c8fSFrank Praznik 	 *
1909c4425c8fSFrank Praznik 	 * Known values include:
1910c4425c8fSFrank Praznik 	 *
1911c4425c8fSFrank Praznik 	 * 0x80 - 1000hz (full speed)
1912c4425c8fSFrank Praznik 	 * 0xA0 - 31hz
1913c4425c8fSFrank Praznik 	 * 0xB0 - 20hz
1914c4425c8fSFrank Praznik 	 * 0xD0 - 66hz
1915c4425c8fSFrank Praznik 	 */
1916fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
19172c159de0SRoderick Colenbrander 		memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE);
191848220237SFrank Praznik 		buf[0] = 0x05;
1919b3ed458cSFrank Praznik 		buf[1] = 0xFF;
192048220237SFrank Praznik 		offset = 4;
1921fdcf105dSFrank Praznik 	} else {
19222c159de0SRoderick Colenbrander 		memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE);
1923fdcf105dSFrank Praznik 		buf[0] = 0x11;
1924e7ef53adSRoderick Colenbrander 		buf[1] = 0xC0; /* HID + CRC */
1925fdcf105dSFrank Praznik 		buf[3] = 0x0F;
1926fdcf105dSFrank Praznik 		offset = 6;
1927fdcf105dSFrank Praznik 	}
19280bd88dd3SFrank Praznik 
19290bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
193048220237SFrank Praznik 	buf[offset++] = sc->right;
193148220237SFrank Praznik 	buf[offset++] = sc->left;
193248220237SFrank Praznik #else
193348220237SFrank Praznik 	offset += 2;
19340bd88dd3SFrank Praznik #endif
19350bd88dd3SFrank Praznik 
1936b3ed458cSFrank Praznik 	/* LED 3 is the global control */
1937b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
193848220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
193948220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
194048220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
1941b3ed458cSFrank Praznik 	} else {
1942b3ed458cSFrank Praznik 		offset += 3;
1943b3ed458cSFrank Praznik 	}
1944b3ed458cSFrank Praznik 
1945b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
1946b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
1947b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
194860781cf4SFrank Praznik 
1949fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
19502c159de0SRoderick Colenbrander 		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE);
1951e7ef53adSRoderick Colenbrander 	else {
1952e7ef53adSRoderick Colenbrander 		/* CRC generation */
1953e7ef53adSRoderick Colenbrander 		u8 bthdr = 0xA2;
1954e7ef53adSRoderick Colenbrander 		u32 crc;
1955e7ef53adSRoderick Colenbrander 
1956e7ef53adSRoderick Colenbrander 		crc = crc32_le(0xFFFFFFFF, &bthdr, 1);
1957e7ef53adSRoderick Colenbrander 		crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4);
1958e7ef53adSRoderick Colenbrander 		put_unaligned_le32(crc, &buf[74]);
1959e7ef53adSRoderick Colenbrander 		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE);
1960e7ef53adSRoderick Colenbrander 	}
19610bd88dd3SFrank Praznik }
19620bd88dd3SFrank Praznik 
1963d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc)
1964c5e0c1c4SFrank Praznik {
1965c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1966c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
1967c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
1968c5e0c1c4SFrank Praznik 
196941d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
1970c5e0c1c4SFrank Praznik 
1971c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
1972c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
1973c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
1974c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
1975c5e0c1c4SFrank Praznik 
1976c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1977c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
1978c5e0c1c4SFrank Praznik #endif
1979c5e0c1c4SFrank Praznik 
19801adf904eSPavel Machek 	hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE);
1981c5e0c1c4SFrank Praznik }
1982c5e0c1c4SFrank Praznik 
1983decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc)
1984decd946cSFrank Praznik {
1985decd946cSFrank Praznik 	if (sc->send_output_report)
1986decd946cSFrank Praznik 		sc->send_output_report(sc);
1987decd946cSFrank Praznik }
1988decd946cSFrank Praznik 
1989d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work)
1990d8aaccdaSFrank Praznik {
1991d8aaccdaSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1992ef916ef5SAntonio Ospite 
1993d8aaccdaSFrank Praznik 	sc->send_output_report(sc);
1994d8aaccdaSFrank Praznik }
1995d8aaccdaSFrank Praznik 
19969b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
19979b2b5c9aSFrank Praznik {
19984545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
19994545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
20009b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
20019b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
20029b2b5c9aSFrank Praznik 				GFP_KERNEL);
20039b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
20042c159de0SRoderick Colenbrander 		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE,
20059b2b5c9aSFrank Praznik 						GFP_KERNEL);
20069b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
20072c159de0SRoderick Colenbrander 		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE,
20089b2b5c9aSFrank Praznik 						GFP_KERNEL);
2009c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
201041d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
2011c5e0c1c4SFrank Praznik 						GFP_KERNEL);
20129b2b5c9aSFrank Praznik 	else
20139b2b5c9aSFrank Praznik 		return 0;
20149b2b5c9aSFrank Praznik 
20159b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
20169b2b5c9aSFrank Praznik 		return -ENOMEM;
20179b2b5c9aSFrank Praznik 
20189b2b5c9aSFrank Praznik 	return 0;
20199b2b5c9aSFrank Praznik }
20209b2b5c9aSFrank Praznik 
20210a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
20229f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
20239f323b68SSven Eckelmann 			    struct ff_effect *effect)
20249f323b68SSven Eckelmann {
2025a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
20269f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
2027a08c22c0SSven Eckelmann 
2028a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
2029a08c22c0SSven Eckelmann 		return 0;
2030a08c22c0SSven Eckelmann 
20319f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
20320bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
2033a08c22c0SSven Eckelmann 
20342a242932SFrank Praznik 	sony_schedule_work(sc);
20359f323b68SSven Eckelmann 	return 0;
2036a08c22c0SSven Eckelmann }
2037a08c22c0SSven Eckelmann 
2038fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
2039a08c22c0SSven Eckelmann {
2040fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
2041a08c22c0SSven Eckelmann 						struct hid_input, list);
2042a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
2043a08c22c0SSven Eckelmann 
2044a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
2045a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
2046a08c22c0SSven Eckelmann }
2047a08c22c0SSven Eckelmann 
2048a08c22c0SSven Eckelmann #else
2049fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
2050a08c22c0SSven Eckelmann {
2051a08c22c0SSven Eckelmann 	return 0;
2052a08c22c0SSven Eckelmann }
20539f323b68SSven Eckelmann 
2054a08c22c0SSven Eckelmann #endif
2055a08c22c0SSven Eckelmann 
2056d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
2057d902f472SFrank Praznik 				     enum power_supply_property psp,
2058d902f472SFrank Praznik 				     union power_supply_propval *val)
2059c4e1ddf2SFrank Praznik {
2060297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
2061d902f472SFrank Praznik 	unsigned long flags;
2062d902f472SFrank Praznik 	int ret = 0;
2063d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
2064c4e1ddf2SFrank Praznik 
2065d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
2066d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
2067d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
2068d902f472SFrank Praznik 	cable_state = sc->cable_state;
2069d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
2070c4e1ddf2SFrank Praznik 
2071d902f472SFrank Praznik 	switch (psp) {
2072d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
2073d902f472SFrank Praznik 		val->intval = 1;
2074d902f472SFrank Praznik 		break;
2075d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
2076d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
2077d902f472SFrank Praznik 		break;
2078d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
2079d902f472SFrank Praznik 		val->intval = battery_capacity;
2080d902f472SFrank Praznik 		break;
2081d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
2082d902f472SFrank Praznik 		if (battery_charging)
2083d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
2084d902f472SFrank Praznik 		else
2085d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
2086d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
2087d902f472SFrank Praznik 			else
2088d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2089d902f472SFrank Praznik 		break;
2090d902f472SFrank Praznik 	default:
2091d902f472SFrank Praznik 		ret = -EINVAL;
2092d902f472SFrank Praznik 		break;
2093c4e1ddf2SFrank Praznik 	}
2094d902f472SFrank Praznik 	return ret;
2095d902f472SFrank Praznik }
2096d902f472SFrank Praznik 
20970f398230SFrank Praznik static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
2098d902f472SFrank Praznik {
20990f398230SFrank Praznik 	const char *battery_str_fmt = append_dev_id ?
21000f398230SFrank Praznik 		"sony_controller_battery_%pMR_%i" :
21010f398230SFrank Praznik 		"sony_controller_battery_%pMR";
2102297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
2103d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
2104d902f472SFrank Praznik 	int ret;
2105d902f472SFrank Praznik 
2106ad142b9eSFrank Praznik 	/*
2107ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
2108d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
2109d9a293a9SFrank Praznik 	 */
2110d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
2111d9a293a9SFrank Praznik 
2112297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
2113297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
2114297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
2115297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2116297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
21170f398230SFrank Praznik 	sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
21180f398230SFrank Praznik 					  sc->mac_address, sc->device_id);
2119297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2120d902f472SFrank Praznik 		return -ENOMEM;
2121d902f472SFrank Praznik 
2122297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
2123297d716fSKrzysztof Kozlowski 					    &psy_cfg);
2124297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
2125297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
2126d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
2127d902f472SFrank Praznik 		goto err_free;
2128d902f472SFrank Praznik 	}
2129d902f472SFrank Praznik 
2130297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
2131d902f472SFrank Praznik 	return 0;
2132d902f472SFrank Praznik 
2133d902f472SFrank Praznik err_free:
2134297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2135297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2136d902f472SFrank Praznik 	return ret;
2137d902f472SFrank Praznik }
2138d902f472SFrank Praznik 
2139d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
2140d902f472SFrank Praznik {
2141297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2142d902f472SFrank Praznik 		return;
2143d902f472SFrank Praznik 
2144297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
2145297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2146297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2147d902f472SFrank Praznik }
2148d902f472SFrank Praznik 
2149d2d782fcSFrank Praznik /*
2150d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
2151d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
2152d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
2153d2d782fcSFrank Praznik  * once.
21540f398230SFrank Praznik  *
21550f398230SFrank Praznik  * Some USB-only devices masquerade as Sixaxis controllers and all have the
21560f398230SFrank Praznik  * same dummy Bluetooth address, so a comparison of the connection type is
21570f398230SFrank Praznik  * required.  Devices are only rejected in the case where two devices have
21580f398230SFrank Praznik  * matching Bluetooth addresses on different bus types.
2159d2d782fcSFrank Praznik  */
21600f398230SFrank Praznik static inline int sony_compare_connection_type(struct sony_sc *sc0,
21610f398230SFrank Praznik 						struct sony_sc *sc1)
21620f398230SFrank Praznik {
21630f398230SFrank Praznik 	const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE);
21640f398230SFrank Praznik 	const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
21650f398230SFrank Praznik 
21660f398230SFrank Praznik 	return sc0_not_bt == sc1_not_bt;
21670f398230SFrank Praznik }
21680f398230SFrank Praznik 
2169d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
2170d2d782fcSFrank Praznik {
2171d2d782fcSFrank Praznik 	struct sony_sc *entry;
2172d2d782fcSFrank Praznik 	unsigned long flags;
2173d2d782fcSFrank Praznik 	int ret;
2174d2d782fcSFrank Praznik 
2175d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
2176d2d782fcSFrank Praznik 
2177d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
2178d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
2179d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
2180d2d782fcSFrank Praznik 		if (!ret) {
21810f398230SFrank Praznik 			if (sony_compare_connection_type(sc, entry)) {
21820f398230SFrank Praznik 				ret = 1;
21830f398230SFrank Praznik 			} else {
2184d2d782fcSFrank Praznik 				ret = -EEXIST;
21850f398230SFrank Praznik 				hid_info(sc->hdev,
21860f398230SFrank Praznik 				"controller with MAC address %pMR already connected\n",
2187d2d782fcSFrank Praznik 				sc->mac_address);
21880f398230SFrank Praznik 			}
2189d2d782fcSFrank Praznik 			goto unlock;
2190d2d782fcSFrank Praznik 		}
2191c4e1ddf2SFrank Praznik 	}
2192c4e1ddf2SFrank Praznik 
2193d2d782fcSFrank Praznik 	ret = 0;
2194d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
2195c4e1ddf2SFrank Praznik 
2196d2d782fcSFrank Praznik unlock:
2197d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2198d2d782fcSFrank Praznik 	return ret;
2199d2d782fcSFrank Praznik }
2200d2d782fcSFrank Praznik 
2201d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
2202d2d782fcSFrank Praznik {
2203d2d782fcSFrank Praznik 	unsigned long flags;
2204d2d782fcSFrank Praznik 
2205d2d782fcSFrank Praznik 	if (sc->list_node.next) {
2206d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
2207d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
2208d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2209d2d782fcSFrank Praznik 	}
2210d2d782fcSFrank Praznik }
2211d2d782fcSFrank Praznik 
2212d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
2213d2d782fcSFrank Praznik {
2214d2d782fcSFrank Praznik 	int ret;
2215d2d782fcSFrank Praznik 
2216d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2217d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2218d2d782fcSFrank Praznik 	if (ret != 17)
2219c4e1ddf2SFrank Praznik 		return -EINVAL;
2220d2d782fcSFrank Praznik 
2221d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2222d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2223d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2224d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2225d2d782fcSFrank Praznik 
2226d2d782fcSFrank Praznik 	if (ret != 6)
2227d2d782fcSFrank Praznik 		return -EINVAL;
2228d2d782fcSFrank Praznik 
2229d2d782fcSFrank Praznik 	return 0;
2230c4e1ddf2SFrank Praznik }
2231c4e1ddf2SFrank Praznik 
2232d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2233d2d782fcSFrank Praznik {
22341adf904eSPavel Machek 	u8 *buf = NULL;
2235d2d782fcSFrank Praznik 	int n, ret;
2236d2d782fcSFrank Praznik 
2237d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
223812e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
22394545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2240d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2241d2d782fcSFrank Praznik 		/*
2242d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2243d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2244d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2245d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2246d2d782fcSFrank Praznik 		 */
2247d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2248d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2249d2d782fcSFrank Praznik 			return 0;
2250d2d782fcSFrank Praznik 		}
2251d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
22522c159de0SRoderick Colenbrander 		buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL);
22539b2b5c9aSFrank Praznik 		if (!buf)
22549b2b5c9aSFrank Praznik 			return -ENOMEM;
2255d2d782fcSFrank Praznik 
2256d2d782fcSFrank Praznik 		/*
2257d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2258d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2259d2d782fcSFrank Praznik 		 * offset 1.
2260d2d782fcSFrank Praznik 		 */
22619b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
22622c159de0SRoderick Colenbrander 				DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
22639b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2264d2d782fcSFrank Praznik 
22652c159de0SRoderick Colenbrander 		if (ret != DS4_FEATURE_REPORT_0x81_SIZE) {
2266d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
22679b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22689b2b5c9aSFrank Praznik 			goto out_free;
2269d2d782fcSFrank Praznik 		}
2270d2d782fcSFrank Praznik 
2271d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
22724545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
22734545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
22749b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
22759b2b5c9aSFrank Praznik 		if (!buf)
22769b2b5c9aSFrank Praznik 			return -ENOMEM;
2277d2d782fcSFrank Praznik 
2278d2d782fcSFrank Praznik 		/*
2279d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2280d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2281d2d782fcSFrank Praznik 		 * offset 4.
2282d2d782fcSFrank Praznik 		 */
22839b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
22849b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
22859b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2286d2d782fcSFrank Praznik 
22879b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2288d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
22899b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22909b2b5c9aSFrank Praznik 			goto out_free;
2291d2d782fcSFrank Praznik 		}
2292d2d782fcSFrank Praznik 
2293d2d782fcSFrank Praznik 		/*
2294d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2295d2d782fcSFrank Praznik 		 * be byte-swapped.
2296d2d782fcSFrank Praznik 		 */
2297d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2298d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2299d2d782fcSFrank Praznik 	} else {
2300d2d782fcSFrank Praznik 		return 0;
2301d2d782fcSFrank Praznik 	}
2302d2d782fcSFrank Praznik 
23039b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
23049b2b5c9aSFrank Praznik 
23059b2b5c9aSFrank Praznik out_free:
23069b2b5c9aSFrank Praznik 
23079b2b5c9aSFrank Praznik 	kfree(buf);
23089b2b5c9aSFrank Praznik 
23099b2b5c9aSFrank Praznik 	return ret;
2310d2d782fcSFrank Praznik }
2311d2d782fcSFrank Praznik 
23128025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
23138025087aSFrank Praznik {
23148025087aSFrank Praznik 	int ret;
23158025087aSFrank Praznik 
23168025087aSFrank Praznik 	/*
23178025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
23188025087aSFrank Praznik 	 * All others are set to -1.
23198025087aSFrank Praznik 	 */
23208025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
23218025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
23228025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
23238025087aSFrank Praznik 					GFP_KERNEL);
23248025087aSFrank Praznik 		if (ret < 0) {
23258025087aSFrank Praznik 			sc->device_id = -1;
23268025087aSFrank Praznik 			return ret;
23278025087aSFrank Praznik 		}
23288025087aSFrank Praznik 		sc->device_id = ret;
23298025087aSFrank Praznik 	} else {
23308025087aSFrank Praznik 		sc->device_id = -1;
23318025087aSFrank Praznik 	}
23328025087aSFrank Praznik 
23338025087aSFrank Praznik 	return 0;
23348025087aSFrank Praznik }
23358025087aSFrank Praznik 
23368025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
23378025087aSFrank Praznik {
23388025087aSFrank Praznik 	if (sc->device_id >= 0) {
23398025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
23408025087aSFrank Praznik 		sc->device_id = -1;
23418025087aSFrank Praznik 	}
23428025087aSFrank Praznik }
23438025087aSFrank Praznik 
2344d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc,
2345d8aaccdaSFrank Praznik 				void (*send_output_report)(struct sony_sc *))
234646262047SFrank Praznik {
2347d8aaccdaSFrank Praznik 	sc->send_output_report = send_output_report;
2348d8aaccdaSFrank Praznik 
234946262047SFrank Praznik 	if (!sc->worker_initialized)
2350d8aaccdaSFrank Praznik 		INIT_WORK(&sc->state_worker, sony_state_worker);
235146262047SFrank Praznik 
235246262047SFrank Praznik 	sc->worker_initialized = 1;
235346262047SFrank Praznik }
235446262047SFrank Praznik 
235546262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
235646262047SFrank Praznik {
235746262047SFrank Praznik 	if (sc->worker_initialized)
235846262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
235946262047SFrank Praznik }
2360d2d782fcSFrank Praznik 
2361e1bc84d0SRoderick Colenbrander static int sony_input_configured(struct hid_device *hdev,
2362e1bc84d0SRoderick Colenbrander 					struct hid_input *hidinput)
2363bd28ce00SJiri Slaby {
2364e1bc84d0SRoderick Colenbrander 	struct sony_sc *sc = hid_get_drvdata(hdev);
23650f398230SFrank Praznik 	int append_dev_id;
2366e1bc84d0SRoderick Colenbrander 	int ret;
2367bd28ce00SJiri Slaby 
23688025087aSFrank Praznik 	ret = sony_set_device_id(sc);
23698025087aSFrank Praznik 	if (ret < 0) {
23708025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
23718025087aSFrank Praznik 		goto err_stop;
23728025087aSFrank Praznik 	}
23738025087aSFrank Praznik 
2374131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2375131a8a9aSFrank Praznik 	if (ret < 0) {
2376131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2377131a8a9aSFrank Praznik 		goto err_stop;
2378131a8a9aSFrank Praznik 	}
2379131a8a9aSFrank Praznik 
23804545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
23814545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2382e534a935SBenjamin Tissoires 		/*
2383e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2384e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2385e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2386e534a935SBenjamin Tissoires 		 *
2387e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2388e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2389e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2390e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
23912a242932SFrank Praznik 		 *
23922a242932SFrank Praznik 		 * Additionally, the Sixaxis on USB isn't properly initialized
23932a242932SFrank Praznik 		 * until the PS logo button is pressed and as such won't retain
23942a242932SFrank Praznik 		 * any state set by an output report, so the initial
23952a242932SFrank Praznik 		 * configuration report is deferred until the first input
23962a242932SFrank Praznik 		 * report arrives.
2397e534a935SBenjamin Tissoires 		 */
2398e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2399e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
24002a242932SFrank Praznik 		sc->defer_initialization = 1;
2401816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
2402d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
24034545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
24044545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
24052078b9bbSFrank Praznik 		/*
24062078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
24072078b9bbSFrank Praznik 		 * when connected via Bluetooth.
24082078b9bbSFrank Praznik 		 */
24092078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2410816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
2411d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
2412fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
241368330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
241468330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
241568330d83SFrank Praznik 			if (ret < 0) {
241668330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
241768330d83SFrank Praznik 				goto err_stop;
241868330d83SFrank Praznik 			}
241968330d83SFrank Praznik 		}
2420c4e1ddf2SFrank Praznik 
2421e1bc84d0SRoderick Colenbrander 		/*
2422e1bc84d0SRoderick Colenbrander 		 * The Dualshock 4 touchpad supports 2 touches and has a
2423e1bc84d0SRoderick Colenbrander 		 * resolution of 1920x942 (44.86 dots/mm).
2424e1bc84d0SRoderick Colenbrander 		 */
2425e1bc84d0SRoderick Colenbrander 		ret = sony_register_touchpad(hidinput, 2, 1920, 942);
2426e1bc84d0SRoderick Colenbrander 		if (ret) {
2427e1bc84d0SRoderick Colenbrander 			hid_err(sc->hdev,
2428e1bc84d0SRoderick Colenbrander 			"Unable to initialize multi-touch slots: %d\n",
2429e1bc84d0SRoderick Colenbrander 			ret);
2430e1bc84d0SRoderick Colenbrander 			return ret;
2431e1bc84d0SRoderick Colenbrander 		}
2432e1bc84d0SRoderick Colenbrander 
2433d8aaccdaSFrank Praznik 		sony_init_output_report(sc, dualshock4_send_output_report);
2434c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2435d8aaccdaSFrank Praznik 		sony_init_output_report(sc, motion_send_output_report);
24360bd88dd3SFrank Praznik 	} else {
24370bd88dd3SFrank Praznik 		ret = 0;
24380bd88dd3SFrank Praznik 	}
2439f9ce7c28SBastien Nocera 
24404dfdc464SJiri Kosina 	if (ret < 0)
2441bd28ce00SJiri Slaby 		goto err_stop;
2442bd28ce00SJiri Slaby 
24430f398230SFrank Praznik 	ret = append_dev_id = sony_check_add(sc);
2444d2d782fcSFrank Praznik 	if (ret < 0)
2445d2d782fcSFrank Praznik 		goto err_stop;
2446d2d782fcSFrank Praznik 
24470a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2448fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
24490a286ef2SSven Eckelmann 		if (ret < 0)
24500a286ef2SSven Eckelmann 			goto err_stop;
24510a286ef2SSven Eckelmann 	}
24520a286ef2SSven Eckelmann 
2453d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
24540f398230SFrank Praznik 		ret = sony_battery_probe(sc, append_dev_id);
2455a08c22c0SSven Eckelmann 		if (ret < 0)
2456a08c22c0SSven Eckelmann 			goto err_stop;
2457a08c22c0SSven Eckelmann 
2458d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2459d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2460d902f472SFrank Praznik 		if (ret < 0) {
2461d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2462d902f472SFrank Praznik 			goto err_stop;
2463d902f472SFrank Praznik 		}
2464d902f472SFrank Praznik 	}
2465d902f472SFrank Praznik 
2466c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2467fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2468d902f472SFrank Praznik 		if (ret < 0)
2469d902f472SFrank Praznik 			goto err_close;
24705f5750d2SFrank Praznik 	}
2471bd28ce00SJiri Slaby 
2472f425458eSH Hartley Sweeten 	return 0;
2473d902f472SFrank Praznik err_close:
2474d902f472SFrank Praznik 	hid_hw_close(hdev);
2475bd28ce00SJiri Slaby err_stop:
24760a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2477fa57a810SFrank Praznik 		sony_leds_remove(sc);
2478d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2479d902f472SFrank Praznik 		sony_battery_remove(sc);
248046262047SFrank Praznik 	sony_cancel_work_sync(sc);
24819b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2482d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
24838025087aSFrank Praznik 	sony_release_device_id(sc);
2484bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2485bd28ce00SJiri Slaby 	return ret;
2486bd28ce00SJiri Slaby }
2487bd28ce00SJiri Slaby 
2488e1bc84d0SRoderick Colenbrander static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2489e1bc84d0SRoderick Colenbrander {
2490e1bc84d0SRoderick Colenbrander 	int ret;
2491e1bc84d0SRoderick Colenbrander 	unsigned long quirks = id->driver_data;
2492e1bc84d0SRoderick Colenbrander 	struct sony_sc *sc;
2493e1bc84d0SRoderick Colenbrander 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2494e1bc84d0SRoderick Colenbrander 
2495e1bc84d0SRoderick Colenbrander 	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
2496e1bc84d0SRoderick Colenbrander 		quirks |= FUTUREMAX_DANCE_MAT;
2497e1bc84d0SRoderick Colenbrander 
2498e1bc84d0SRoderick Colenbrander 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2499e1bc84d0SRoderick Colenbrander 	if (sc == NULL) {
2500e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "can't alloc sony descriptor\n");
2501e1bc84d0SRoderick Colenbrander 		return -ENOMEM;
2502e1bc84d0SRoderick Colenbrander 	}
2503e1bc84d0SRoderick Colenbrander 
2504e1bc84d0SRoderick Colenbrander 	spin_lock_init(&sc->lock);
2505e1bc84d0SRoderick Colenbrander 
2506e1bc84d0SRoderick Colenbrander 	sc->quirks = quirks;
2507e1bc84d0SRoderick Colenbrander 	hid_set_drvdata(hdev, sc);
2508e1bc84d0SRoderick Colenbrander 	sc->hdev = hdev;
2509e1bc84d0SRoderick Colenbrander 
2510e1bc84d0SRoderick Colenbrander 	ret = hid_parse(hdev);
2511e1bc84d0SRoderick Colenbrander 	if (ret) {
2512e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "parse failed\n");
2513e1bc84d0SRoderick Colenbrander 		return ret;
2514e1bc84d0SRoderick Colenbrander 	}
2515e1bc84d0SRoderick Colenbrander 
2516e1bc84d0SRoderick Colenbrander 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2517e1bc84d0SRoderick Colenbrander 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2518e1bc84d0SRoderick Colenbrander 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2519e1bc84d0SRoderick Colenbrander 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2520e1bc84d0SRoderick Colenbrander 
2521e1bc84d0SRoderick Colenbrander 	ret = hid_hw_start(hdev, connect_mask);
2522e1bc84d0SRoderick Colenbrander 	if (ret) {
2523e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "hw start failed\n");
2524e1bc84d0SRoderick Colenbrander 		return ret;
2525e1bc84d0SRoderick Colenbrander 	}
2526e1bc84d0SRoderick Colenbrander 
2527e1bc84d0SRoderick Colenbrander 	return ret;
2528e1bc84d0SRoderick Colenbrander }
2529e1bc84d0SRoderick Colenbrander 
2530bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2531bd28ce00SJiri Slaby {
2532bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2533bd28ce00SJiri Slaby 
25340a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2535fa57a810SFrank Praznik 		sony_leds_remove(sc);
2536bd28ce00SJiri Slaby 
2537d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2538d902f472SFrank Praznik 		hid_hw_close(hdev);
2539d902f472SFrank Praznik 		sony_battery_remove(sc);
2540d902f472SFrank Praznik 	}
2541d902f472SFrank Praznik 
254246262047SFrank Praznik 	sony_cancel_work_sync(sc);
25439f323b68SSven Eckelmann 
25449b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
25459b2b5c9aSFrank Praznik 
2546d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2547bd28ce00SJiri Slaby 
25488025087aSFrank Praznik 	sony_release_device_id(sc);
25498025087aSFrank Praznik 
2550bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2551bd28ce00SJiri Slaby }
2552bd28ce00SJiri Slaby 
2553decd946cSFrank Praznik #ifdef CONFIG_PM
2554decd946cSFrank Praznik 
2555decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2556decd946cSFrank Praznik {
2557decd946cSFrank Praznik 	/*
2558decd946cSFrank Praznik 	 * On suspend save the current LED state,
2559decd946cSFrank Praznik 	 * stop running force-feedback and blank the LEDS.
2560decd946cSFrank Praznik 	 */
2561decd946cSFrank Praznik 	if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
2562decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2563decd946cSFrank Praznik 
2564decd946cSFrank Praznik #ifdef CONFIG_SONY_FF
2565decd946cSFrank Praznik 		sc->left = sc->right = 0;
2566decd946cSFrank Praznik #endif
2567decd946cSFrank Praznik 
2568decd946cSFrank Praznik 		memcpy(sc->resume_led_state, sc->led_state,
2569decd946cSFrank Praznik 			sizeof(sc->resume_led_state));
2570decd946cSFrank Praznik 		memset(sc->led_state, 0, sizeof(sc->led_state));
2571decd946cSFrank Praznik 
2572decd946cSFrank Praznik 		sony_send_output_report(sc);
2573decd946cSFrank Praznik 	}
2574decd946cSFrank Praznik 
2575decd946cSFrank Praznik 	return 0;
2576decd946cSFrank Praznik }
2577decd946cSFrank Praznik 
2578decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev)
2579decd946cSFrank Praznik {
2580decd946cSFrank Praznik 	/* Restore the state of controller LEDs on resume */
2581decd946cSFrank Praznik 	if (SONY_LED_SUPPORT) {
2582decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2583decd946cSFrank Praznik 
2584decd946cSFrank Praznik 		memcpy(sc->led_state, sc->resume_led_state,
2585decd946cSFrank Praznik 			sizeof(sc->led_state));
2586decd946cSFrank Praznik 
2587decd946cSFrank Praznik 		/*
2588decd946cSFrank Praznik 		 * The Sixaxis and navigation controllers on USB need to be
2589decd946cSFrank Praznik 		 * reinitialized on resume or they won't behave properly.
2590decd946cSFrank Praznik 		 */
2591decd946cSFrank Praznik 		if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
25922a242932SFrank Praznik 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2593decd946cSFrank Praznik 			sixaxis_set_operational_usb(sc->hdev);
25942a242932SFrank Praznik 			sc->defer_initialization = 1;
25952a242932SFrank Praznik 		}
2596decd946cSFrank Praznik 
2597decd946cSFrank Praznik 		sony_set_leds(sc);
2598decd946cSFrank Praznik 	}
2599decd946cSFrank Praznik 
2600decd946cSFrank Praznik 	return 0;
2601decd946cSFrank Praznik }
2602decd946cSFrank Praznik 
2603decd946cSFrank Praznik #endif
2604decd946cSFrank Praznik 
2605bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2606bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2607bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2608bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
26094545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
26106eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
26114545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2612c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2613b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2614a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2615b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2616bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2617bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2618bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2619bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2620bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2621bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2622ef916ef5SAntonio Ospite 	/*
2623ef916ef5SAntonio Ospite 	 * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2624ef916ef5SAntonio Ospite 	 * Logitech joystick from the device descriptor.
2625ef916ef5SAntonio Ospite 	 */
2626bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2627bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2628bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2629bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2630bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2631bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2632bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2633bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2634bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2635bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
263668a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
263768a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
263868a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
26390bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
26400bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
26418ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
26420bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
26438ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
2644*cf1015d6SRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
2645*cf1015d6SRoderick Colenbrander 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
2646*cf1015d6SRoderick Colenbrander 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
2647*cf1015d6SRoderick Colenbrander 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
264874500cc8SScott Moreau 	/* Nyko Core Controller for PS3 */
264974500cc8SScott Moreau 	{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
265074500cc8SScott Moreau 		.driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
2651bd28ce00SJiri Slaby 	{ }
2652bd28ce00SJiri Slaby };
2653bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2654bd28ce00SJiri Slaby 
2655bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2656bd28ce00SJiri Slaby 	.name             = "sony",
2657bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2658bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2659ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2660bd28ce00SJiri Slaby 	.probe            = sony_probe,
2661bd28ce00SJiri Slaby 	.remove           = sony_remove,
2662bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2663decd946cSFrank Praznik 	.raw_event        = sony_raw_event,
2664decd946cSFrank Praznik 
2665decd946cSFrank Praznik #ifdef CONFIG_PM
2666decd946cSFrank Praznik 	.suspend          = sony_suspend,
2667decd946cSFrank Praznik 	.resume	          = sony_resume,
2668decd946cSFrank Praznik 	.reset_resume     = sony_resume,
2669decd946cSFrank Praznik #endif
2670bd28ce00SJiri Slaby };
26718025087aSFrank Praznik 
26728025087aSFrank Praznik static int __init sony_init(void)
26738025087aSFrank Praznik {
26748025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
26758025087aSFrank Praznik 
26768025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
26778025087aSFrank Praznik }
26788025087aSFrank Praznik 
26798025087aSFrank Praznik static void __exit sony_exit(void)
26808025087aSFrank Praznik {
26818025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
26828025087aSFrank Praznik 
26838025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
26846c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
26858025087aSFrank Praznik }
26868025087aSFrank Praznik module_init(sony_init);
26878025087aSFrank Praznik module_exit(sony_exit);
2688bd28ce00SJiri Slaby 
2689bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2690