xref: /linux/drivers/hid/hid-sony.c (revision d542176f94c790016cc340dff74ba00d57410728)
1bd28ce00SJiri Slaby /*
2077147a3SFrank Praznik  *  HID driver for Sony / PS2 / PS3 / PS4 BD devices.
3bd28ce00SJiri Slaby  *
4bd28ce00SJiri Slaby  *  Copyright (c) 1999 Andreas Gal
5bd28ce00SJiri Slaby  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6bd28ce00SJiri Slaby  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7bd28ce00SJiri Slaby  *  Copyright (c) 2008 Jiri Slaby
8078328daSJiri Kosina  *  Copyright (c) 2012 David Dillow <dave@thedillows.org>
9078328daSJiri Kosina  *  Copyright (c) 2006-2013 Jiri Kosina
10f04d5140SColin Leitner  *  Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
11077147a3SFrank Praznik  *  Copyright (c) 2014 Frank Praznik <frank.praznik@gmail.com>
12bd28ce00SJiri Slaby  */
13bd28ce00SJiri Slaby 
14bd28ce00SJiri Slaby /*
15bd28ce00SJiri Slaby  * This program is free software; you can redistribute it and/or modify it
16bd28ce00SJiri Slaby  * under the terms of the GNU General Public License as published by the Free
17bd28ce00SJiri Slaby  * Software Foundation; either version 2 of the License, or (at your option)
18bd28ce00SJiri Slaby  * any later version.
19bd28ce00SJiri Slaby  */
20bd28ce00SJiri Slaby 
21ad142b9eSFrank Praznik /*
22ad142b9eSFrank Praznik  * NOTE: in order for the Sony PS3 BD Remote Control to be found by
23078328daSJiri Kosina  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
24078328daSJiri Kosina  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
25078328daSJiri Kosina  *
26078328daSJiri Kosina  * There will be no PIN request from the device.
27078328daSJiri Kosina  */
28078328daSJiri Kosina 
29bd28ce00SJiri Slaby #include <linux/device.h>
30bd28ce00SJiri Slaby #include <linux/hid.h>
31bd28ce00SJiri Slaby #include <linux/module.h>
325a0e3ad6STejun Heo #include <linux/slab.h>
3340e32ee6SJiri Kosina #include <linux/leds.h>
34d902f472SFrank Praznik #include <linux/power_supply.h>
35d902f472SFrank Praznik #include <linux/spinlock.h>
36d2d782fcSFrank Praznik #include <linux/list.h>
378025087aSFrank Praznik #include <linux/idr.h>
38e5606230SFrank Praznik #include <linux/input/mt.h>
39bd28ce00SJiri Slaby 
40bd28ce00SJiri Slaby #include "hid-ids.h"
41bd28ce00SJiri Slaby 
42f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT       BIT(0)
43f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB    BIT(1)
44f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT     BIT(2)
45f1c458caSSven Eckelmann #define BUZZ_CONTROLLER           BIT(3)
46f1c458caSSven Eckelmann #define PS3REMOTE                 BIT(4)
478ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5)
488ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
49b3bca326SSimon Wood #define MOTION_CONTROLLER_USB     BIT(7)
50b3bca326SSimon Wood #define MOTION_CONTROLLER_BT      BIT(8)
514545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9)
524545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT  BIT(10)
53cc6e0bbbSJiri Kosina 
54fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
55b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
564545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\
574545ee0aSSimon Wood 				NAVIGATION_CONTROLLER_BT)
5868330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
5968330d83SFrank Praznik 				DUALSHOCK4_CONTROLLER_BT)
60fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
614545ee0aSSimon Wood 				DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
624545ee0aSSimon Wood 				NAVIGATION_CONTROLLER)
6312e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
644545ee0aSSimon Wood 				MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
65c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
66c5e0c1c4SFrank Praznik 				MOTION_CONTROLLER)
6760781cf4SFrank Praznik 
6860781cf4SFrank Praznik #define MAX_LEDS 4
690a286ef2SSven Eckelmann 
704c3e8298SFrank Praznik /*
714c3e8298SFrank Praznik  * The Sixaxis reports both digital and analog values for each button on the
724c3e8298SFrank Praznik  * controller except for Start, Select and the PS button.  The controller ends
734c3e8298SFrank Praznik  * up reporting 27 axes which causes them to spill over into the multi-touch
744c3e8298SFrank Praznik  * axis values.  Additionally, the controller only has 20 actual, physical axes
754c3e8298SFrank Praznik  * so there are several unused axes in between the used ones.
764c3e8298SFrank Praznik  */
77c607fb8dSAntonio Ospite static __u8 sixaxis_rdesc[] = {
78fb705a6dSAntonio Ospite 	0x05, 0x01,         /*  Usage Page (Desktop),               */
794c3e8298SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
80fb705a6dSAntonio Ospite 	0xA1, 0x01,         /*  Collection (Application),           */
81fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
82fb705a6dSAntonio Ospite 	0x85, 0x01,         /*          Report ID (1),              */
83fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
84fb705a6dSAntonio Ospite 	0x95, 0x01,         /*          Report Count (1),           */
85fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
86fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
87fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
88fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
89fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
90fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
91fb705a6dSAntonio Ospite 	0x25, 0x01,         /*          Logical Maximum (1),        */
92fb705a6dSAntonio Ospite 	0x35, 0x00,         /*          Physical Minimum (0),       */
93fb705a6dSAntonio Ospite 	0x45, 0x01,         /*          Physical Maximum (1),       */
94fb705a6dSAntonio Ospite 	0x05, 0x09,         /*          Usage Page (Button),        */
95fb705a6dSAntonio Ospite 	0x19, 0x01,         /*          Usage Minimum (01h),        */
96fb705a6dSAntonio Ospite 	0x29, 0x13,         /*          Usage Maximum (13h),        */
97fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
98fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
99fb705a6dSAntonio Ospite 	0x95, 0x0D,         /*          Report Count (13),          */
100fb705a6dSAntonio Ospite 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
101fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
102fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
103fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
104fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
105fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
106fb705a6dSAntonio Ospite 	0xA1, 0x00,         /*          Collection (Physical),      */
107fb705a6dSAntonio Ospite 	0x75, 0x08,         /*              Report Size (8),        */
108fb705a6dSAntonio Ospite 	0x95, 0x04,         /*              Report Count (4),       */
109fb705a6dSAntonio Ospite 	0x35, 0x00,         /*              Physical Minimum (0),   */
110fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
111fb705a6dSAntonio Ospite 	0x09, 0x30,         /*              Usage (X),              */
112fb705a6dSAntonio Ospite 	0x09, 0x31,         /*              Usage (Y),              */
113fb705a6dSAntonio Ospite 	0x09, 0x32,         /*              Usage (Z),              */
114fb705a6dSAntonio Ospite 	0x09, 0x35,         /*              Usage (Rz),             */
115fb705a6dSAntonio Ospite 	0x81, 0x02,         /*              Input (Variable),       */
116fb705a6dSAntonio Ospite 	0xC0,               /*          End Collection,             */
117fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
118fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
119fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
120fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
121fb705a6dSAntonio Ospite 	0x95, 0x0C,         /*          Report Count (12),          */
122fb705a6dSAntonio Ospite 	0x81, 0x01,         /*          Input (Constant),           */
123fb705a6dSAntonio Ospite 	0x75, 0x10,         /*          Report Size (16),           */
124fb705a6dSAntonio Ospite 	0x95, 0x04,         /*          Report Count (4),           */
125fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
126fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
127fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
128fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
129fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
130fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
131fb705a6dSAntonio Ospite 	0x85, 0x02,         /*          Report ID (2),              */
132fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
133fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
134fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
135fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
136fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
137fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
138fb705a6dSAntonio Ospite 	0x85, 0xEE,         /*          Report ID (238),            */
139fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
140fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
141fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
142fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
143fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
144fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
145fb705a6dSAntonio Ospite 	0x85, 0xEF,         /*          Report ID (239),            */
146fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
147fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
148fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
149fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
150fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
151fb705a6dSAntonio Ospite 	0xC0                /*  End Collection                      */
152e57a67daSMauro Carvalho Chehab };
153e57a67daSMauro Carvalho Chehab 
154c5e0c1c4SFrank Praznik /* PS/3 Motion controller */
155c5e0c1c4SFrank Praznik static __u8 motion_rdesc[] = {
156c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
157c5e0c1c4SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
158c5e0c1c4SFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
159c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
160c5e0c1c4SFrank Praznik 	0x85, 0x01,         /*          Report ID (1),              */
161c5e0c1c4SFrank Praznik 	0x75, 0x01,         /*          Report Size (1),            */
1628b2513c3SSimon Wood 	0x95, 0x15,         /*          Report Count (21),          */
163c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
164c5e0c1c4SFrank Praznik 	0x25, 0x01,         /*          Logical Maximum (1),        */
165c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*          Physical Minimum (0),       */
166c5e0c1c4SFrank Praznik 	0x45, 0x01,         /*          Physical Maximum (1),       */
167c5e0c1c4SFrank Praznik 	0x05, 0x09,         /*          Usage Page (Button),        */
168c5e0c1c4SFrank Praznik 	0x19, 0x01,         /*          Usage Minimum (01h),        */
1698b2513c3SSimon Wood 	0x29, 0x15,         /*          Usage Maximum (15h),        */
1708b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           * Buttons */
1718b2513c3SSimon Wood 	0x95, 0x0B,         /*          Report Count (11),          */
172c5e0c1c4SFrank Praznik 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1738b2513c3SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), * Padding */
174c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
175c5e0c1c4SFrank Praznik 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
176c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
177c5e0c1c4SFrank Praznik 	0xA1, 0x00,         /*          Collection (Physical),      */
178c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*              Report Size (8),        */
1798b2513c3SSimon Wood 	0x95, 0x01,         /*              Report Count (1),       */
180c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*              Physical Minimum (0),   */
181c5e0c1c4SFrank Praznik 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
182c5e0c1c4SFrank Praznik 	0x09, 0x30,         /*              Usage (X),              */
1838b2513c3SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       * Trigger */
184c5e0c1c4SFrank Praznik 	0xC0,               /*          End Collection,             */
1858b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1868b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
1878b2513c3SSimon Wood 	0x95, 0x07,         /*          Report Count (7),           * skip 7 bytes */
1888b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
189c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
190c5e0c1c4SFrank Praznik 	0x75, 0x10,         /*          Report Size (16),           */
1918b2513c3SSimon Wood 	0x46, 0xFF, 0xFF,   /*          Physical Maximum (65535),   */
1928b2513c3SSimon Wood 	0x27, 0xFF, 0xFF, 0x00, 0x00, /*      Logical Maximum (65535),    */
1938b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Accels */
1948b2513c3SSimon Wood 	0x09, 0x33,         /*              Usage (rX),             */
1958b2513c3SSimon Wood 	0x09, 0x34,         /*              Usage (rY),             */
1968b2513c3SSimon Wood 	0x09, 0x35,         /*              Usage (rZ),             */
197c5e0c1c4SFrank Praznik 	0x81, 0x02,         /*          Input (Variable),           */
1988b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1998b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Accels 2nd frame */
2008b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2018b2513c3SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
2028b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2038b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Gyros */
2048b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2058b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2068b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Gyros 2nd frame */
2078b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2088b2513c3SSimon Wood 	0x75, 0x0C,         /*          Report Size (12),           */
2098b2513c3SSimon Wood 	0x46, 0xFF, 0x0F,   /*          Physical Maximum (4095),    */
2108b2513c3SSimon Wood 	0x26, 0xFF, 0x0F,   /*          Logical Maximum (4095),     */
2118b2513c3SSimon Wood 	0x95, 0x04,         /*          Report Count (4),           * Skip Temp and Magnetometers */
2128b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2138b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2148b2513c3SSimon Wood 	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
2158b2513c3SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
2168b2513c3SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           * Skip Timestamp and Extension Bytes */
2178b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2188b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2198b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2208b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2218b2513c3SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
2228b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2238b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2248b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2258b2513c3SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
226c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
227c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
228c5e0c1c4SFrank Praznik 	0x85, 0x02,         /*          Report ID (2),              */
229c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
230c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
231c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
232c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
233c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
234c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
235c5e0c1c4SFrank Praznik 	0x85, 0xEE,         /*          Report ID (238),            */
236c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
237c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
238c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
239c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
240c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
241c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
242c5e0c1c4SFrank Praznik 	0x85, 0xEF,         /*          Report ID (239),            */
243c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
244c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
245c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
246c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
247c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
248c5e0c1c4SFrank Praznik 	0xC0                /*  End Collection                      */
249c5e0c1c4SFrank Praznik };
250c5e0c1c4SFrank Praznik 
251b2723eb7SSimon Wood /* PS/3 Navigation controller */
252b2723eb7SSimon Wood static __u8 navigation_rdesc[] = {
253b2723eb7SSimon Wood 	0x05, 0x01,         /*  Usage Page (Desktop),               */
254*d542176fSAntonio Ospite 	0x09, 0x04,         /*  Usage (Joystick),                   */
255b2723eb7SSimon Wood 	0xA1, 0x01,         /*  Collection (Application),           */
256b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
257b2723eb7SSimon Wood 	0x85, 0x01,         /*          Report ID (1),              */
258b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
259b2723eb7SSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
260b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
261b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
262b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
263b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
264b2723eb7SSimon Wood 	0x95, 0x13,         /*          Report Count (19),          */
265b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
266b2723eb7SSimon Wood 	0x25, 0x01,         /*          Logical Maximum (1),        */
267b2723eb7SSimon Wood 	0x35, 0x00,         /*          Physical Minimum (0),       */
268b2723eb7SSimon Wood 	0x45, 0x01,         /*          Physical Maximum (1),       */
269b2723eb7SSimon Wood 	0x05, 0x09,         /*          Usage Page (Button),        */
270b2723eb7SSimon Wood 	0x19, 0x01,         /*          Usage Minimum (01h),        */
271b2723eb7SSimon Wood 	0x29, 0x13,         /*          Usage Maximum (13h),        */
272b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
273b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
274b2723eb7SSimon Wood 	0x95, 0x0D,         /*          Report Count (13),          */
275b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
276b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
277b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
278b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
279b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
280b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
281b2723eb7SSimon Wood 	0xA1, 0x00,         /*          Collection (Physical),      */
282b2723eb7SSimon Wood 	0x75, 0x08,         /*              Report Size (8),        */
283b2723eb7SSimon Wood 	0x95, 0x02,         /*              Report Count (2),       */
284b2723eb7SSimon Wood 	0x35, 0x00,         /*              Physical Minimum (0),   */
285b2723eb7SSimon Wood 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
286b2723eb7SSimon Wood 	0x09, 0x30,         /*              Usage (X),              */
287b2723eb7SSimon Wood 	0x09, 0x31,         /*              Usage (Y),              */
288b2723eb7SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       */
289b2723eb7SSimon Wood 	0xC0,               /*          End Collection,             */
290b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
291b2723eb7SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           */
292b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
293b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
294b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
295b2723eb7SSimon Wood 	0x95, 0x05,         /*          Report Count (5),           */
296b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
297b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
298b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2992259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3002259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3012259b5bbSSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
3022259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3032259b5bbSSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
3042259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3052259b5bbSSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3062259b5bbSSimon Wood 	0x95, 0x1E,         /*          Report Count (24),          */
307b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
308b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
309b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
310b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
311b2723eb7SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
312b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
313b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
314b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
315b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
316b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
317b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
318b2723eb7SSimon Wood 	0x85, 0x02,         /*          Report ID (2),              */
319b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
320b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
321b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
322b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
323b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
324b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
325b2723eb7SSimon Wood 	0x85, 0xEE,         /*          Report ID (238),            */
326b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
327b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
328b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
329b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
330b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
331b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
332b2723eb7SSimon Wood 	0x85, 0xEF,         /*          Report ID (239),            */
333b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
334b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
335b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
336b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
337b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
338b2723eb7SSimon Wood 	0xC0                /*  End Collection                      */
339b2723eb7SSimon Wood };
340c5e0c1c4SFrank Praznik 
341ad142b9eSFrank Praznik /*
342ad142b9eSFrank Praznik  * The default descriptor doesn't provide mapping for the accelerometers
34358d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
34458d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
34558d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
34658d7027bSFrank Praznik  */
347ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
34858d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
34958d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
35058d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
35158d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
35258d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
35358d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
35458d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
35558d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
35658d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
35758d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
35858d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
35958d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
36058d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
36158d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
36258d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36358d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
36458d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
36558d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
36658d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
36758d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
36858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
36958d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
37058d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
37158d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
37258d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
37358d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
37458d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
37558d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
37658d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
37758d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
37858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
37958d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
38058d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
38158d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
38258d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
38358d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
384fb291cbdSFrank Praznik 	0x25, 0x3F,         /*      Logical Maximum (63),           */
38558d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
38658d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
38758d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
38858d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
38958d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
39058d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
39158d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
39258d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
39358d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39458d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
39558d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
39658d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
39758d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39858d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
39958d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
40058d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
40158d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
40258d7027bSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
40358d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
40458d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40558d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40658d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
40758d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
408fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
409fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
41058d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
41158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41258d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
41358d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
41458d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
415fb291cbdSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
41658d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
41758d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
41858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41958d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
42058d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
42158d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
42258d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
42358d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
42458d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
42558d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
42658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42758d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
42858d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
42958d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
43058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43158d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
43258d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
43358d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
43458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43558d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
43658d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
43758d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
43858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43958d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
44058d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
44158d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
44258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44358d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
44458d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
44558d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
44658d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
44758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44858d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
44958d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
45058d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
45158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45258d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
45358d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
45458d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
45558d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
45658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45758d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
45858d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
45958d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
46058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46158d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
46258d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
46358d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
46458d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
46558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46658d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
46758d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
46858d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
46958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47058d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
47158d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
47258d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
47358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47458d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
47558d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
47658d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
47758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47858d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
47958d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
48058d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
48158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48258d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
48358d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
48458d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
48558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48658d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
48758d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
48858d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
48958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49058d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
49158d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
49258d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
49358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49458d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
49558d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
49658d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
49758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49858d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
49958d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
50058d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
50158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50258d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
50358d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
50458d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
50558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50658d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
50758d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
50858d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
50958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51058d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
51158d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
51258d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51458d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
51558d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
51658d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
51758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51858d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
51958d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
52058d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
52158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52258d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
52358d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
52458d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
52558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52658d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
52758d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
52858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
52958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53058d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
53158d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
53258d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
53358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53458d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
53558d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
53658d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
53758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53858d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
53958d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
54058d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54258d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
54358d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
54458d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54658d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
54758d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
54858d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
54958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55058d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
55158d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
55258d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55458d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
55558d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
55658d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
55758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55858d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
55958d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
56058d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56258d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
56358d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
56458d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56658d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
56758d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
56858d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
56958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57058d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
57158d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
57258d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
57358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57458d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
57558d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
57658d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
57758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57858d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
57958d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
58058d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58258d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
58358d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
58458d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
58558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58658d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
58758d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
58858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
58958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59058d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
59158d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
59258d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
59358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59458d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
59558d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
59658d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
59758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59858d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
599ed19d8cfSFrank Praznik };
600ed19d8cfSFrank Praznik 
601ad142b9eSFrank Praznik /*
602ad142b9eSFrank Praznik  * The default behavior of the Dualshock 4 is to send reports using report
603077147a3SFrank Praznik  * type 1 when running over Bluetooth. However, when feature report 2 is
604077147a3SFrank Praznik  * requested during the controller initialization it starts sending input
605077147a3SFrank Praznik  * reports in report 17.  Since report 17 is undefined in the default HID
606d829674dSFrank Praznik  * descriptor the button and axis definitions must be moved to report 17 or
607077147a3SFrank Praznik  * the HID layer won't process the received input.
608d829674dSFrank Praznik  */
609d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = {
610d829674dSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
611d829674dSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
612d829674dSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
613d829674dSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
614d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
615d829674dSFrank Praznik 	0x95, 0x0A,         /*      Report Count (9),               */
616d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
617d829674dSFrank Praznik 	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
618d829674dSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
619d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
620d829674dSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
621d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
622d829674dSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
623d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
624d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
625d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
626d829674dSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
627d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
628d829674dSFrank Praznik 	0x95, 0x28,         /*      Report Count (40),              */
629d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
630d829674dSFrank Praznik 	0x85, 0x06,         /*      Report ID (6),                  */
631d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
632d829674dSFrank Praznik 	0x95, 0x34,         /*      Report Count (52),              */
633d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
634d829674dSFrank Praznik 	0x85, 0x07,         /*      Report ID (7),                  */
635d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
636d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
637d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
638d829674dSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
639d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
640d829674dSFrank Praznik 	0x95, 0x2F,         /*      Report Count (47),              */
641d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
642d829674dSFrank Praznik 	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
643d829674dSFrank Praznik 	0x85, 0x03,         /*      Report ID (3),                  */
644d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
645d829674dSFrank Praznik 	0x95, 0x26,         /*      Report Count (38),              */
646d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
647d829674dSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
648d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
649d829674dSFrank Praznik 	0x95, 0x2E,         /*      Report Count (46),              */
650d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
651d829674dSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
652d829674dSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
653d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
654d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
655d829674dSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
656d829674dSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
657d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
658d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
659d829674dSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
660d829674dSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
661d829674dSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
662d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
663d829674dSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
664d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
665d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
666d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
667d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
668d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
669d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
670d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
671d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
672d829674dSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
673d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
674d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
675d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
676d829674dSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
677d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
678d829674dSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
679d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
680d829674dSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
681d829674dSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
682d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
683d829674dSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
684d829674dSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
685d829674dSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
686d829674dSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
687d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
688d829674dSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
689d829674dSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
690d829674dSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
691d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
692d829674dSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
693d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
694d829674dSFrank Praznik 	0x81, 0x01,         /*      Input (Constant),               */
695d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
696d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
697d829674dSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
698d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
699d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
700d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
701d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
702d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
703d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
704d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
705d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
706d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
707d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
708d829674dSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
709d829674dSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
710d829674dSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
711d829674dSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
712d829674dSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
713d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
714d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
715d829674dSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
716d829674dSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
717fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
718fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
719d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
720d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
721d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
722d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
723d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
724d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
725d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
726d829674dSFrank Praznik 	0x95, 0x31,         /*      Report Count (51),              */
727d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
728d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
729d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
730d829674dSFrank Praznik 	0x95, 0x4D,         /*      Report Count (77),              */
731d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
732d829674dSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
733d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
734d829674dSFrank Praznik 	0x95, 0x8D,         /*      Report Count (141),             */
735d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
736d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
737d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
738d829674dSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
739d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
740d829674dSFrank Praznik 	0x95, 0xCD,         /*      Report Count (205),             */
741d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
742d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
743d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
744d829674dSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
745d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
746d829674dSFrank Praznik 	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
747d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
748d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
749d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
750d829674dSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
751d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
752d829674dSFrank Praznik 	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
753d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
754d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
755d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
756d829674dSFrank Praznik 	0x85, 0x16,         /*      Report ID (22),                 */
757d829674dSFrank Praznik 	0x09, 0x2A,         /*      Usage (2Ah),                    */
758d829674dSFrank Praznik 	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
759d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
760d829674dSFrank Praznik 	0x09, 0x2B,         /*      Usage (2Bh),                    */
761d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
762d829674dSFrank Praznik 	0x85, 0x17,         /*      Report ID (23),                 */
763d829674dSFrank Praznik 	0x09, 0x2C,         /*      Usage (2Ch),                    */
764d829674dSFrank Praznik 	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
765d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
766d829674dSFrank Praznik 	0x09, 0x2D,         /*      Usage (2Dh),                    */
767d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
768d829674dSFrank Praznik 	0x85, 0x18,         /*      Report ID (24),                 */
769d829674dSFrank Praznik 	0x09, 0x2E,         /*      Usage (2Eh),                    */
770d829674dSFrank Praznik 	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
771d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
772d829674dSFrank Praznik 	0x09, 0x2F,         /*      Usage (2Fh),                    */
773d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
774d829674dSFrank Praznik 	0x85, 0x19,         /*      Report ID (25),                 */
775d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
776d829674dSFrank Praznik 	0x96, 0x22, 0x02,   /*      Report Count (546),             */
777d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
778d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
779d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
780d829674dSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
781d829674dSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
782d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
783d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
784d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
785d829674dSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
786d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
787d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
788d829674dSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
789d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
790d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
791d829674dSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
792d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
793d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
794d829674dSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
795d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
796d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
797d829674dSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
798d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
799d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
800d829674dSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
801d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
802d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
803d829674dSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
804d829674dSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
805d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
806d829674dSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
807d829674dSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
808d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
809d829674dSFrank Praznik 	0xC0                /*  End Collection                      */
810d829674dSFrank Praznik };
811d829674dSFrank Praznik 
812078328daSJiri Kosina static __u8 ps3remote_rdesc[] = {
813078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
814078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
815078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
816078328daSJiri Kosina 
817078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
818078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
819078328daSJiri Kosina 
820078328daSJiri Kosina 	  /* Ignore the 1st byte, maybe it is used for a controller
821078328daSJiri Kosina 	   * number but it's not needed for correct operation */
822078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
823078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
824078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
825078328daSJiri Kosina 
826078328daSJiri Kosina 	  /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
827078328daSJiri Kosina 	   * buttons multiple keypresses are allowed */
828078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
829078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
830078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
831078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
832078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
833078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
834078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
835078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
836078328daSJiri Kosina 
837078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
838078328daSJiri Kosina 
839078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
840078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
841078328daSJiri Kosina 
842078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
843078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
844078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
845078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
846078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
847078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
848078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
849078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
850078328daSJiri Kosina 	  0x80,              /* MInput  */
851078328daSJiri Kosina 
852078328daSJiri Kosina 	  /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
853078328daSJiri Kosina 	   * 0xff and 11th is for press indication */
854078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
855078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
856078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
857078328daSJiri Kosina 
858078328daSJiri Kosina 	  /* 12th byte is for battery strength */
859078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
860078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
861078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
862078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
863078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
864078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
865078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
866078328daSJiri Kosina 
867078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
868078328daSJiri Kosina 
869078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
870078328daSJiri Kosina };
871078328daSJiri Kosina 
872078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
873078328daSJiri Kosina 	[0x01] = KEY_SELECT,
874078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
875078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
876078328daSJiri Kosina 	[0x04] = BTN_START,
877078328daSJiri Kosina 	[0x05] = KEY_UP,
878078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
879078328daSJiri Kosina 	[0x07] = KEY_DOWN,
880078328daSJiri Kosina 	[0x08] = KEY_LEFT,
881078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
882078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
883078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
884078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
885078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
886078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
887078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
888078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
889078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
890078328daSJiri Kosina 	[0x14] = KEY_ENTER,
891078328daSJiri Kosina };
892078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
893078328daSJiri Kosina 	[0x00] = KEY_1,
894078328daSJiri Kosina 	[0x01] = KEY_2,
895078328daSJiri Kosina 	[0x02] = KEY_3,
896078328daSJiri Kosina 	[0x03] = KEY_4,
897078328daSJiri Kosina 	[0x04] = KEY_5,
898078328daSJiri Kosina 	[0x05] = KEY_6,
899078328daSJiri Kosina 	[0x06] = KEY_7,
900078328daSJiri Kosina 	[0x07] = KEY_8,
901078328daSJiri Kosina 	[0x08] = KEY_9,
902078328daSJiri Kosina 	[0x09] = KEY_0,
903078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
904078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
905078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
906078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
907078328daSJiri Kosina 	[0x28] = KEY_TIME,
908078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
909078328daSJiri Kosina 	[0x31] = KEY_NEXT,
910078328daSJiri Kosina 	[0x32] = KEY_PLAY,
911078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
912078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
913078328daSJiri Kosina 	[0x38] = KEY_STOP,
914078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
915078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
916078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
917078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
918078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
919078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
920078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
921078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
922078328daSJiri Kosina 	[0x80] = KEY_BLUE,
923078328daSJiri Kosina 	[0x81] = KEY_RED,
924078328daSJiri Kosina 	[0x82] = KEY_GREEN,
925078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
926078328daSJiri Kosina };
927078328daSJiri Kosina 
928f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
929ad142b9eSFrank Praznik 	/*
930ad142b9eSFrank Praznik 	 * The controller has 4 remote buzzers, each with one LED and 5
931f04d5140SColin Leitner 	 * buttons.
932f04d5140SColin Leitner 	 *
933f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
934f04d5140SColin Leitner 	 *
935f04d5140SColin Leitner 	 * Key          Offset
936f04d5140SColin Leitner 	 * -------------------
937f04d5140SColin Leitner 	 * Buzz              1
938f04d5140SColin Leitner 	 * Blue              5
939f04d5140SColin Leitner 	 * Orange            4
940f04d5140SColin Leitner 	 * Green             3
941f04d5140SColin Leitner 	 * Yellow            2
942f04d5140SColin Leitner 	 *
943f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
944f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
945f04d5140SColin Leitner 	 */
946f04d5140SColin Leitner 	[ 1] = BTN_TRIGGER_HAPPY1,
947f04d5140SColin Leitner 	[ 2] = BTN_TRIGGER_HAPPY2,
948f04d5140SColin Leitner 	[ 3] = BTN_TRIGGER_HAPPY3,
949f04d5140SColin Leitner 	[ 4] = BTN_TRIGGER_HAPPY4,
950f04d5140SColin Leitner 	[ 5] = BTN_TRIGGER_HAPPY5,
951f04d5140SColin Leitner 	[ 6] = BTN_TRIGGER_HAPPY6,
952f04d5140SColin Leitner 	[ 7] = BTN_TRIGGER_HAPPY7,
953f04d5140SColin Leitner 	[ 8] = BTN_TRIGGER_HAPPY8,
954f04d5140SColin Leitner 	[ 9] = BTN_TRIGGER_HAPPY9,
955f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
956f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
957f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
958f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
959f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
960f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
961f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
962f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
963f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
964f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
965f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
966f04d5140SColin Leitner };
967f04d5140SColin Leitner 
968d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
969d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
970d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
971d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
972d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
973d902f472SFrank Praznik };
974d902f472SFrank Praznik 
97555d3b664SFrank Praznik struct sixaxis_led {
97655d3b664SFrank Praznik 	__u8 time_enabled; /* the total time the led is active (0xff means forever) */
97755d3b664SFrank Praznik 	__u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
97855d3b664SFrank Praznik 	__u8 enabled;
97955d3b664SFrank Praznik 	__u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
98055d3b664SFrank Praznik 	__u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
98155d3b664SFrank Praznik } __packed;
98255d3b664SFrank Praznik 
98355d3b664SFrank Praznik struct sixaxis_rumble {
98455d3b664SFrank Praznik 	__u8 padding;
98555d3b664SFrank Praznik 	__u8 right_duration; /* Right motor duration (0xff means forever) */
98655d3b664SFrank Praznik 	__u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
98755d3b664SFrank Praznik 	__u8 left_duration;    /* Left motor duration (0xff means forever) */
98855d3b664SFrank Praznik 	__u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
98955d3b664SFrank Praznik } __packed;
99055d3b664SFrank Praznik 
99155d3b664SFrank Praznik struct sixaxis_output_report {
99255d3b664SFrank Praznik 	__u8 report_id;
99355d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
99455d3b664SFrank Praznik 	__u8 padding[4];
99555d3b664SFrank Praznik 	__u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
99655d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
99755d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
99855d3b664SFrank Praznik } __packed;
99955d3b664SFrank Praznik 
100055d3b664SFrank Praznik union sixaxis_output_report_01 {
100155d3b664SFrank Praznik 	struct sixaxis_output_report data;
100255d3b664SFrank Praznik 	__u8 buf[36];
100355d3b664SFrank Praznik };
100455d3b664SFrank Praznik 
1005c5e0c1c4SFrank Praznik struct motion_output_report_02 {
1006c5e0c1c4SFrank Praznik 	u8 type, zero;
1007c5e0c1c4SFrank Praznik 	u8 r, g, b;
1008c5e0c1c4SFrank Praznik 	u8 zero2;
1009c5e0c1c4SFrank Praznik 	u8 rumble;
1010c5e0c1c4SFrank Praznik };
1011c5e0c1c4SFrank Praznik 
10129b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37
10139b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32
10149b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78
10159b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7
101629b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
1017a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
101841d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
10199b2b5c9aSFrank Praznik 
10208b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
1021d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
10228025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
1023d2d782fcSFrank Praznik 
1024cc6e0bbbSJiri Kosina struct sony_sc {
1025d902f472SFrank Praznik 	spinlock_t lock;
1026d2d782fcSFrank Praznik 	struct list_head list_node;
10270a286ef2SSven Eckelmann 	struct hid_device *hdev;
102860781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
1029cc6e0bbbSJiri Kosina 	unsigned long quirks;
10300a286ef2SSven Eckelmann 	struct work_struct state_worker;
1031d8aaccdaSFrank Praznik 	void(*send_output_report)(struct sony_sc*);
1032297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
1033297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
10348025087aSFrank Praznik 	int device_id;
10359b2b5c9aSFrank Praznik 	__u8 *output_report_dmabuf;
1036f04d5140SColin Leitner 
10379f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
10389f323b68SSven Eckelmann 	__u8 left;
10399f323b68SSven Eckelmann 	__u8 right;
10409f323b68SSven Eckelmann #endif
10419f323b68SSven Eckelmann 
1042d2d782fcSFrank Praznik 	__u8 mac_address[6];
10435f5750d2SFrank Praznik 	__u8 worker_initialized;
1044d902f472SFrank Praznik 	__u8 cable_state;
1045d902f472SFrank Praznik 	__u8 battery_charging;
1046d902f472SFrank Praznik 	__u8 battery_capacity;
104760781cf4SFrank Praznik 	__u8 led_state[MAX_LEDS];
1048decd946cSFrank Praznik 	__u8 resume_led_state[MAX_LEDS];
1049b3ed458cSFrank Praznik 	__u8 led_delay_on[MAX_LEDS];
1050b3ed458cSFrank Praznik 	__u8 led_delay_off[MAX_LEDS];
105160781cf4SFrank Praznik 	__u8 led_count;
1052cc6e0bbbSJiri Kosina };
1053cc6e0bbbSJiri Kosina 
1054c607fb8dSAntonio Ospite static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc,
1055c607fb8dSAntonio Ospite 			     unsigned int *rsize)
1056c607fb8dSAntonio Ospite {
1057c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
1058c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
1059c607fb8dSAntonio Ospite }
1060c607fb8dSAntonio Ospite 
1061c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
1062c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
1063c5e0c1c4SFrank Praznik {
1064c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
1065c5e0c1c4SFrank Praznik 	return motion_rdesc;
1066c5e0c1c4SFrank Praznik }
1067c5e0c1c4SFrank Praznik 
1068b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc,
1069b2723eb7SSimon Wood 			     unsigned int *rsize)
1070b2723eb7SSimon Wood {
1071b2723eb7SSimon Wood 	*rsize = sizeof(navigation_rdesc);
1072b2723eb7SSimon Wood 	return navigation_rdesc;
1073b2723eb7SSimon Wood }
1074b2723eb7SSimon Wood 
1075078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
1076078328daSJiri Kosina 			     unsigned int *rsize)
1077078328daSJiri Kosina {
1078078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
1079078328daSJiri Kosina 	return ps3remote_rdesc;
1080078328daSJiri Kosina }
1081078328daSJiri Kosina 
1082078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
1083078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
1084078328daSJiri Kosina 			     unsigned long **bit, int *max)
1085078328daSJiri Kosina {
1086078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
1087078328daSJiri Kosina 
1088078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1089078328daSJiri Kosina 		return -1;
1090078328daSJiri Kosina 
1091078328daSJiri Kosina 	switch (usage->collection_index) {
1092078328daSJiri Kosina 	case 1:
1093078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
1094078328daSJiri Kosina 			return -1;
1095078328daSJiri Kosina 
1096078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
1097078328daSJiri Kosina 		if (!key)
1098078328daSJiri Kosina 			return -1;
1099078328daSJiri Kosina 		break;
1100078328daSJiri Kosina 	case 2:
1101078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1102078328daSJiri Kosina 			return -1;
1103078328daSJiri Kosina 
1104078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1105078328daSJiri Kosina 		if (!key)
1106078328daSJiri Kosina 			return -1;
1107078328daSJiri Kosina 		break;
1108078328daSJiri Kosina 	default:
1109078328daSJiri Kosina 		return -1;
1110078328daSJiri Kosina 	}
1111078328daSJiri Kosina 
1112078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1113078328daSJiri Kosina 	return 1;
1114078328daSJiri Kosina }
1115078328daSJiri Kosina 
111673e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
111773e4008dSNikolai Kondrashov 		unsigned int *rsize)
1118cc6e0bbbSJiri Kosina {
1119cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1120cc6e0bbbSJiri Kosina 
112199d24902SFernando Luis Vázquez Cao 	/*
112299d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
112399d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
112499d24902SFernando Luis Vázquez Cao 	 */
112599d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
112699d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
112799d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
112899d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
112999d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
113099d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
113199d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1132a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
113399d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1134cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1135cc6e0bbbSJiri Kosina 	}
113661ab44beSSimon Wood 
1137ed19d8cfSFrank Praznik 	/*
1138ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1139ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1140ed19d8cfSFrank Praznik 	 * modified one.
1141ed19d8cfSFrank Praznik 	 */
1142b71b5578SFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1143ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1144ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1145ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1146b71b5578SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
1147d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1148d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1149d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1150ed19d8cfSFrank Praznik 	}
1151ed19d8cfSFrank Praznik 
1152c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1153c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1154078328daSJiri Kosina 
1155c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1156c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1157c5e0c1c4SFrank Praznik 
11584545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1159b2723eb7SSimon Wood 		return navigation_fixup(hdev, rdesc, rsize);
11604545ee0aSSimon Wood 
1161078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1162078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1163078328daSJiri Kosina 
116473e4008dSNikolai Kondrashov 	return rdesc;
1165cc6e0bbbSJiri Kosina }
1166cc6e0bbbSJiri Kosina 
1167d902f472SFrank Praznik static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
1168d902f472SFrank Praznik {
1169d902f472SFrank Praznik 	static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1170d902f472SFrank Praznik 	unsigned long flags;
117112e9a6d7SSimon Wood 	int offset;
1172d902f472SFrank Praznik 	__u8 cable_state, battery_capacity, battery_charging;
1173d902f472SFrank Praznik 
1174ad142b9eSFrank Praznik 	/*
1175ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1176d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1177d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1178d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1179d902f472SFrank Praznik 	 */
118012e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
118112e9a6d7SSimon Wood 
118212e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1183d902f472SFrank Praznik 		battery_capacity = 100;
118412e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
11859fddd74aSFrank Praznik 		cable_state = 1;
1186d902f472SFrank Praznik 	} else {
118712e9a6d7SSimon Wood 		__u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1188ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1189d902f472SFrank Praznik 		battery_charging = 0;
11909fddd74aSFrank Praznik 		cable_state = 0;
1191d902f472SFrank Praznik 	}
1192d902f472SFrank Praznik 
1193d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1194d902f472SFrank Praznik 	sc->cable_state = cable_state;
1195d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1196d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1197d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1198d902f472SFrank Praznik }
1199d902f472SFrank Praznik 
1200d902f472SFrank Praznik static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
1201d902f472SFrank Praznik {
1202e5606230SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1203e5606230SFrank Praznik 						struct hid_input, list);
1204e5606230SFrank Praznik 	struct input_dev *input_dev = hidinput->input;
1205d902f472SFrank Praznik 	unsigned long flags;
12066c5f860dSFrank Praznik 	int n, offset;
1207d902f472SFrank Praznik 	__u8 cable_state, battery_capacity, battery_charging;
1208d902f472SFrank Praznik 
1209ad142b9eSFrank Praznik 	/*
1210ad142b9eSFrank Praznik 	 * Battery and touchpad data starts at byte 30 in the USB report and
12116c5f860dSFrank Praznik 	 * 32 in Bluetooth report.
12126c5f860dSFrank Praznik 	 */
12136c5f860dSFrank Praznik 	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
12146c5f860dSFrank Praznik 
1215ad142b9eSFrank Praznik 	/*
1216ad142b9eSFrank Praznik 	 * The lower 4 bits of byte 30 contain the battery level
1217d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1218d902f472SFrank Praznik 	 */
12196c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
12206c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1221d902f472SFrank Praznik 
1222ad142b9eSFrank Praznik 	/*
1223ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
12246c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
12256c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1226d902f472SFrank Praznik 	 */
12276c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1228d902f472SFrank Praznik 		battery_charging = 0;
1229d902f472SFrank Praznik 	else
1230d902f472SFrank Praznik 		battery_charging = 1;
1231d902f472SFrank Praznik 
12326c5f860dSFrank Praznik 	if (!cable_state)
12336c5f860dSFrank Praznik 		battery_capacity++;
1234d902f472SFrank Praznik 	if (battery_capacity > 10)
12356c5f860dSFrank Praznik 		battery_capacity = 10;
12366c5f860dSFrank Praznik 
1237d902f472SFrank Praznik 	battery_capacity *= 10;
1238d902f472SFrank Praznik 
1239d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1240d902f472SFrank Praznik 	sc->cable_state = cable_state;
1241d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1242d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1243d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1244e5606230SFrank Praznik 
12456c5f860dSFrank Praznik 	offset += 5;
12466c5f860dSFrank Praznik 
1247ad142b9eSFrank Praznik 	/*
1248ad142b9eSFrank Praznik 	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
12496c5f860dSFrank Praznik 	 * and 37 on Bluetooth.
1250e5606230SFrank Praznik 	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
1251e5606230SFrank Praznik 	 * indicator that is 0 when pressed and 1 when not pressed.
1252e5606230SFrank Praznik 	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1253e5606230SFrank Praznik 	 * The data for the second touch is in the same format and immediatly
1254e5606230SFrank Praznik 	 * follows the data for the first.
1255e5606230SFrank Praznik 	 */
1256e5606230SFrank Praznik 	for (n = 0; n < 2; n++) {
1257e5606230SFrank Praznik 		__u16 x, y;
1258e5606230SFrank Praznik 
1259e5606230SFrank Praznik 		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1260e5606230SFrank Praznik 		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1261e5606230SFrank Praznik 
1262e5606230SFrank Praznik 		input_mt_slot(input_dev, n);
1263e5606230SFrank Praznik 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
1264e5606230SFrank Praznik 					!(rd[offset] >> 7));
1265e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
1266e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
1267e5606230SFrank Praznik 
1268e5606230SFrank Praznik 		offset += 4;
1269e5606230SFrank Praznik 	}
1270d902f472SFrank Praznik }
1271d902f472SFrank Praznik 
1272c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
1273c9e4d877SSimon Wood 		__u8 *rd, int size)
1274c9e4d877SSimon Wood {
1275c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1276c9e4d877SSimon Wood 
1277ad142b9eSFrank Praznik 	/*
1278ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1279c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1280c9e4d877SSimon Wood 	 */
1281fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
12828f5f0bc2SFrank Praznik 		/*
12838f5f0bc2SFrank Praznik 		 * When connected via Bluetooth the Sixaxis occasionally sends
12848f5f0bc2SFrank Praznik 		 * a report with the second byte 0xff and the rest zeroed.
12858f5f0bc2SFrank Praznik 		 *
12868f5f0bc2SFrank Praznik 		 * This report does not reflect the actual state of the
12878f5f0bc2SFrank Praznik 		 * controller must be ignored to avoid generating false input
12888f5f0bc2SFrank Praznik 		 * events.
12898f5f0bc2SFrank Praznik 		 */
12908f5f0bc2SFrank Praznik 		if (rd[1] == 0xff)
12918f5f0bc2SFrank Praznik 			return -EINVAL;
12928f5f0bc2SFrank Praznik 
1293c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1294c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1295c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1296c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1297d902f472SFrank Praznik 
1298d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
129912e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
130012e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
13014545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
13024545ee0aSSimon Wood 			size == 49) {
13034545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
130468330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
130568330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
130668330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
1307d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1308c9e4d877SSimon Wood 	}
1309c9e4d877SSimon Wood 
1310c9e4d877SSimon Wood 	return 0;
1311c9e4d877SSimon Wood }
1312c9e4d877SSimon Wood 
1313f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1314f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1315f04d5140SColin Leitner 			unsigned long **bit, int *max)
1316f04d5140SColin Leitner {
1317f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1318f04d5140SColin Leitner 
1319f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1320f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1321f04d5140SColin Leitner 
1322f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1323f04d5140SColin Leitner 			return -1;
1324f04d5140SColin Leitner 
1325f04d5140SColin Leitner 		switch (usage->collection_index) {
1326f04d5140SColin Leitner 		case 1:
1327f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1328f04d5140SColin Leitner 				return -1;
1329f04d5140SColin Leitner 
1330f04d5140SColin Leitner 			key = buzz_keymap[key];
1331f04d5140SColin Leitner 			if (!key)
1332f04d5140SColin Leitner 				return -1;
1333f04d5140SColin Leitner 			break;
1334f04d5140SColin Leitner 		default:
1335f04d5140SColin Leitner 			return -1;
1336f04d5140SColin Leitner 		}
1337f04d5140SColin Leitner 
1338f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1339f04d5140SColin Leitner 		return 1;
1340f04d5140SColin Leitner 	}
1341f04d5140SColin Leitner 
1342078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1343078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1344078328daSJiri Kosina 
13456f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
13466f498018SBenjamin Tissoires 	return 0;
1347f04d5140SColin Leitner }
1348f04d5140SColin Leitner 
1349ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count,
1350ce8efc3bSFrank Praznik 					int w, int h)
1351ce8efc3bSFrank Praznik {
1352ce8efc3bSFrank Praznik 	struct input_dev *input_dev = hi->input;
1353ce8efc3bSFrank Praznik 	int ret;
1354ce8efc3bSFrank Praznik 
1355ce8efc3bSFrank Praznik 	ret = input_mt_init_slots(input_dev, touch_count, 0);
1356ce8efc3bSFrank Praznik 	if (ret < 0)
1357ce8efc3bSFrank Praznik 		return ret;
1358ce8efc3bSFrank Praznik 
1359ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
1360ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
1361ce8efc3bSFrank Praznik 
1362ce8efc3bSFrank Praznik 	return 0;
1363ce8efc3bSFrank Praznik }
1364ce8efc3bSFrank Praznik 
13659154301aSDmitry Torokhov static int sony_input_configured(struct hid_device *hdev,
1366ce8efc3bSFrank Praznik 					struct hid_input *hidinput)
1367ce8efc3bSFrank Praznik {
1368ce8efc3bSFrank Praznik 	struct sony_sc *sc = hid_get_drvdata(hdev);
13699154301aSDmitry Torokhov 	int ret;
1370ce8efc3bSFrank Praznik 
1371ce8efc3bSFrank Praznik 	/*
1372ce8efc3bSFrank Praznik 	 * The Dualshock 4 touchpad supports 2 touches and has a
1373981c5b4aSFrank Praznik 	 * resolution of 1920x942 (44.86 dots/mm).
1374ce8efc3bSFrank Praznik 	 */
1375ce8efc3bSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER) {
13769154301aSDmitry Torokhov 		ret = sony_register_touchpad(hidinput, 2, 1920, 942);
13779154301aSDmitry Torokhov 		if (ret) {
1378ce8efc3bSFrank Praznik 			hid_err(sc->hdev,
13799154301aSDmitry Torokhov 				"Unable to initialize multi-touch slots: %d\n",
13809154301aSDmitry Torokhov 				ret);
13819154301aSDmitry Torokhov 			return ret;
1382ce8efc3bSFrank Praznik 		}
1383ce8efc3bSFrank Praznik 	}
1384ce8efc3bSFrank Praznik 
13859154301aSDmitry Torokhov 	return 0;
13869154301aSDmitry Torokhov }
13879154301aSDmitry Torokhov 
13885710fabfSAntonio Ospite /*
1389bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1390bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1391bd28ce00SJiri Slaby  * events.
1392bd28ce00SJiri Slaby  */
1393816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1394bd28ce00SJiri Slaby {
1395a85d67b5SAntonio Ospite 	const int buf_size =
1396a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
13972e701a35SAntonio Ospite 	__u8 *buf;
1398bd28ce00SJiri Slaby 	int ret;
1399bd28ce00SJiri Slaby 
14002e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1401bd28ce00SJiri Slaby 	if (!buf)
1402bd28ce00SJiri Slaby 		return -ENOMEM;
1403bd28ce00SJiri Slaby 
1404a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1405a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1406a7de9b86SLauri Kasanen 	if (ret < 0) {
1407a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1408a7de9b86SLauri Kasanen 		goto out;
1409a7de9b86SLauri Kasanen 	}
1410f204828aSBenjamin Tissoires 
1411a7de9b86SLauri Kasanen 	/*
1412a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1413a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1414a7de9b86SLauri Kasanen 	 */
1415a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1416a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1417a7de9b86SLauri Kasanen 	if (ret < 0) {
1418a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1419a7de9b86SLauri Kasanen 		goto out;
1420a7de9b86SLauri Kasanen 	}
1421a7de9b86SLauri Kasanen 
1422a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
1423bd28ce00SJiri Slaby 	if (ret < 0)
1424a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 3\n");
1425bd28ce00SJiri Slaby 
1426a7de9b86SLauri Kasanen out:
1427bd28ce00SJiri Slaby 	kfree(buf);
1428bd28ce00SJiri Slaby 
1429bd28ce00SJiri Slaby 	return ret;
1430bd28ce00SJiri Slaby }
1431bd28ce00SJiri Slaby 
1432816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1433f9ce7c28SBastien Nocera {
14349b2b5c9aSFrank Praznik 	static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
14359b2b5c9aSFrank Praznik 	__u8 *buf;
14369b2b5c9aSFrank Praznik 	int ret;
14379b2b5c9aSFrank Praznik 
14389b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
14399b2b5c9aSFrank Praznik 	if (!buf)
14409b2b5c9aSFrank Praznik 		return -ENOMEM;
14419b2b5c9aSFrank Praznik 
14429b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1443b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
14449b2b5c9aSFrank Praznik 
14459b2b5c9aSFrank Praznik 	kfree(buf);
14469b2b5c9aSFrank Praznik 
14479b2b5c9aSFrank Praznik 	return ret;
1448f9ce7c28SBastien Nocera }
1449f9ce7c28SBastien Nocera 
1450ad142b9eSFrank Praznik /*
1451ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
145268330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
145368330d83SFrank Praznik  */
145468330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
145568330d83SFrank Praznik {
14569b2b5c9aSFrank Praznik 	__u8 *buf;
14579b2b5c9aSFrank Praznik 	int ret;
145868330d83SFrank Praznik 
14599b2b5c9aSFrank Praznik 	buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);
14609b2b5c9aSFrank Praznik 	if (!buf)
14619b2b5c9aSFrank Praznik 		return -ENOMEM;
14629b2b5c9aSFrank Praznik 
14639b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,
146468330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
14659b2b5c9aSFrank Praznik 
14669b2b5c9aSFrank Praznik 	kfree(buf);
14679b2b5c9aSFrank Praznik 
14689b2b5c9aSFrank Praznik 	return ret;
1469bd28ce00SJiri Slaby }
1470bd28ce00SJiri Slaby 
1471221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
14728025087aSFrank Praznik {
14738025087aSFrank Praznik 	static const __u8 sixaxis_leds[10][4] = {
14748025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
14758025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
14768025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
14778025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
14788025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
14798025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
14808025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
14818025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
14828025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
14838025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
14848025087aSFrank Praznik 	};
14858025087aSFrank Praznik 
1486221399b3SFrank Praznik 	int id = sc->device_id;
1487221399b3SFrank Praznik 
1488221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
14898025087aSFrank Praznik 
14908025087aSFrank Praznik 	if (id < 0)
14918025087aSFrank Praznik 		return;
14928025087aSFrank Praznik 
14938025087aSFrank Praznik 	id %= 10;
1494221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
14958025087aSFrank Praznik }
14968025087aSFrank Praznik 
1497221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
14988025087aSFrank Praznik {
14998025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
15008025087aSFrank Praznik 	static const __u8 color_code[7][3] = {
15018025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
15028025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
15038025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
15048025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
15058025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
15068025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
15078025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
15088025087aSFrank Praznik 	};
15098025087aSFrank Praznik 
1510221399b3SFrank Praznik 	int id = sc->device_id;
1511221399b3SFrank Praznik 
1512221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
15138025087aSFrank Praznik 
15148025087aSFrank Praznik 	if (id < 0)
15158025087aSFrank Praznik 		return;
15168025087aSFrank Praznik 
15178025087aSFrank Praznik 	id %= 7;
1518221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
15198025087aSFrank Praznik }
15208025087aSFrank Praznik 
1521221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1522f04d5140SColin Leitner {
1523221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1524f04d5140SColin Leitner 	struct list_head *report_list =
1525f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1526f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1527f04d5140SColin Leitner 		struct hid_report, list);
1528f04d5140SColin Leitner 	__s32 *value = report->field[0]->value;
1529f04d5140SColin Leitner 
1530221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1531221399b3SFrank Praznik 
1532f04d5140SColin Leitner 	value[0] = 0x00;
1533221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1534221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1535221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1536221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1537f04d5140SColin Leitner 	value[5] = 0x00;
1538f04d5140SColin Leitner 	value[6] = 0x00;
1539f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1540f04d5140SColin Leitner }
1541f04d5140SColin Leitner 
1542221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
15430a286ef2SSven Eckelmann {
1544221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
1545fa57a810SFrank Praznik 		schedule_work(&sc->state_worker);
1546221399b3SFrank Praznik 	else
1547221399b3SFrank Praznik 		buzz_set_leds(sc);
15480a286ef2SSven Eckelmann }
15490a286ef2SSven Eckelmann 
1550c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1551f04d5140SColin Leitner 				    enum led_brightness value)
1552f04d5140SColin Leitner {
1553f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1554ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1555f04d5140SColin Leitner 	struct sony_sc *drv_data;
1556f04d5140SColin Leitner 
1557f04d5140SColin Leitner 	int n;
1558b3ed458cSFrank Praznik 	int force_update;
1559f04d5140SColin Leitner 
1560f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
15612251b85fSSven Eckelmann 	if (!drv_data) {
1562f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1563f04d5140SColin Leitner 		return;
1564f04d5140SColin Leitner 	}
1565f04d5140SColin Leitner 
1566b3ed458cSFrank Praznik 	/*
1567b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1568b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1569b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1570b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1571b3ed458cSFrank Praznik 	 * stop the flashing later on.
1572b3ed458cSFrank Praznik 	 */
1573b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1574b3ed458cSFrank Praznik 
157560781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1576b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1577b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1578b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1579b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1580b3ed458cSFrank Praznik 
158160781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1582b3ed458cSFrank Praznik 
1583b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1584b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1585b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1586b3ed458cSFrank Praznik 
1587221399b3SFrank Praznik 			sony_set_leds(drv_data);
1588f04d5140SColin Leitner 			break;
1589f04d5140SColin Leitner 		}
1590f04d5140SColin Leitner 	}
1591f04d5140SColin Leitner }
1592f04d5140SColin Leitner 
1593c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1594f04d5140SColin Leitner {
1595f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1596ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1597f04d5140SColin Leitner 	struct sony_sc *drv_data;
1598f04d5140SColin Leitner 
1599f04d5140SColin Leitner 	int n;
1600f04d5140SColin Leitner 
1601f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
16022251b85fSSven Eckelmann 	if (!drv_data) {
1603f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1604f04d5140SColin Leitner 		return LED_OFF;
1605f04d5140SColin Leitner 	}
1606f04d5140SColin Leitner 
160760781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
16087db7504aSSimon Wood 		if (led == drv_data->leds[n])
16097db7504aSSimon Wood 			return drv_data->led_state[n];
1610f04d5140SColin Leitner 	}
1611f04d5140SColin Leitner 
16127db7504aSSimon Wood 	return LED_OFF;
1613f04d5140SColin Leitner }
1614f04d5140SColin Leitner 
1615b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1616b3ed458cSFrank Praznik 				unsigned long *delay_off)
1617b3ed458cSFrank Praznik {
1618b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1619ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1620b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1621b3ed458cSFrank Praznik 	int n;
1622b3ed458cSFrank Praznik 	__u8 new_on, new_off;
1623b3ed458cSFrank Praznik 
1624b3ed458cSFrank Praznik 	if (!drv_data) {
1625b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1626b3ed458cSFrank Praznik 		return -EINVAL;
1627b3ed458cSFrank Praznik 	}
1628b3ed458cSFrank Praznik 
1629b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1630b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1631b3ed458cSFrank Praznik 		*delay_on = 2550;
1632b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1633b3ed458cSFrank Praznik 		*delay_off = 2550;
1634b3ed458cSFrank Praznik 
1635b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1636b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1637b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1638b3ed458cSFrank Praznik 
1639b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1640b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1641b3ed458cSFrank Praznik 
1642b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1643b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1644b3ed458cSFrank Praznik 			break;
1645b3ed458cSFrank Praznik 	}
1646b3ed458cSFrank Praznik 
1647b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1648b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1649b3ed458cSFrank Praznik 		return -EINVAL;
1650b3ed458cSFrank Praznik 
1651b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1652b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1653b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1654b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1655b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
1656b3ed458cSFrank Praznik 		schedule_work(&drv_data->state_worker);
1657b3ed458cSFrank Praznik 	}
1658b3ed458cSFrank Praznik 
1659b3ed458cSFrank Praznik 	return 0;
1660b3ed458cSFrank Praznik }
1661b3ed458cSFrank Praznik 
1662fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
16630a286ef2SSven Eckelmann {
16640a286ef2SSven Eckelmann 	struct led_classdev *led;
16650a286ef2SSven Eckelmann 	int n;
16660a286ef2SSven Eckelmann 
1667fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
16680a286ef2SSven Eckelmann 
1669fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1670fa57a810SFrank Praznik 		led = sc->leds[n];
1671fa57a810SFrank Praznik 		sc->leds[n] = NULL;
16720a286ef2SSven Eckelmann 		if (!led)
16730a286ef2SSven Eckelmann 			continue;
16740a286ef2SSven Eckelmann 		led_classdev_unregister(led);
16750a286ef2SSven Eckelmann 		kfree(led);
16760a286ef2SSven Eckelmann 	}
167760781cf4SFrank Praznik 
1678fa57a810SFrank Praznik 	sc->led_count = 0;
16790a286ef2SSven Eckelmann }
16800a286ef2SSven Eckelmann 
1681fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1682f04d5140SColin Leitner {
1683fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
168440e32ee6SJiri Kosina 	int n, ret = 0;
1685b3ed458cSFrank Praznik 	int use_ds4_names;
168640e32ee6SJiri Kosina 	struct led_classdev *led;
168740e32ee6SJiri Kosina 	size_t name_sz;
168840e32ee6SJiri Kosina 	char *name;
16890a286ef2SSven Eckelmann 	size_t name_len;
16900a286ef2SSven Eckelmann 	const char *name_fmt;
1691b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1692b3ed458cSFrank Praznik 						  "global" };
16935607c89aSFrank Praznik 	__u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
1694b3ed458cSFrank Praznik 	__u8 use_hw_blink[MAX_LEDS] = { 0 };
1695f04d5140SColin Leitner 
1696fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1697f04d5140SColin Leitner 
1698fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1699fa57a810SFrank Praznik 		sc->led_count = 4;
1700b3ed458cSFrank Praznik 		use_ds4_names = 0;
17010a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
17020a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
17039446edb9SKees Cook 		/* Validate expected report characteristics. */
17049446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
17059446edb9SKees Cook 			return -ENODEV;
1706fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1707221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1708221399b3SFrank Praznik 		sc->led_state[3] = 1;
1709b3ed458cSFrank Praznik 		sc->led_count = 4;
1710b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1711b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1712b3ed458cSFrank Praznik 		use_ds4_names = 1;
171361ebca93SFrank Praznik 		name_len = 0;
171461ebca93SFrank Praznik 		name_fmt = "%s:%s";
1715c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1716c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1717c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1718c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1719c5e0c1c4SFrank Praznik 		name_len = 0;
1720c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
17214545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
17224545ee0aSSimon Wood 		static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
17234545ee0aSSimon Wood 
17244545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
17254545ee0aSSimon Wood 		sc->led_count = 1;
17264545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
17274545ee0aSSimon Wood 		use_ds4_names = 0;
17284545ee0aSSimon Wood 		name_len = strlen("::sony#");
17294545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
173060781cf4SFrank Praznik 	} else {
1731221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1732fa57a810SFrank Praznik 		sc->led_count = 4;
1733b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1734b3ed458cSFrank Praznik 		use_ds4_names = 0;
173561ebca93SFrank Praznik 		name_len = strlen("::sony#");
173661ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
173760781cf4SFrank Praznik 	}
173860781cf4SFrank Praznik 
1739ad142b9eSFrank Praznik 	/*
1740ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1741f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1742ad142b9eSFrank Praznik 	 * LEDs to on
1743ad142b9eSFrank Praznik 	 */
1744221399b3SFrank Praznik 	sony_set_leds(sc);
1745f04d5140SColin Leitner 
17460a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1747f04d5140SColin Leitner 
1748fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
174961ebca93SFrank Praznik 
1750b3ed458cSFrank Praznik 		if (use_ds4_names)
1751b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
175261ebca93SFrank Praznik 
1753f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1754f04d5140SColin Leitner 		if (!led) {
1755f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
17568cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1757f04d5140SColin Leitner 			goto error_leds;
1758f04d5140SColin Leitner 		}
1759f04d5140SColin Leitner 
1760f04d5140SColin Leitner 		name = (void *)(&led[1]);
1761b3ed458cSFrank Praznik 		if (use_ds4_names)
1762b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1763b3ed458cSFrank Praznik 			ds4_name_str[n]);
176461ebca93SFrank Praznik 		else
17650a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1766f04d5140SColin Leitner 		led->name = name;
1767221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1768b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1769c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1770c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1771f04d5140SColin Leitner 
1772b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1773b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1774b3ed458cSFrank Praznik 
17758025087aSFrank Praznik 		sc->leds[n] = led;
17768025087aSFrank Praznik 
17778cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
17788cd5fcdaSJulia Lawall 		if (ret) {
1779f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
17808025087aSFrank Praznik 			sc->leds[n] = NULL;
1781f04d5140SColin Leitner 			kfree(led);
1782f04d5140SColin Leitner 			goto error_leds;
1783f04d5140SColin Leitner 		}
1784f04d5140SColin Leitner 	}
1785f04d5140SColin Leitner 
1786f04d5140SColin Leitner 	return ret;
1787f04d5140SColin Leitner 
1788f04d5140SColin Leitner error_leds:
1789fa57a810SFrank Praznik 	sony_leds_remove(sc);
1790f04d5140SColin Leitner 
1791f04d5140SColin Leitner 	return ret;
1792f04d5140SColin Leitner }
1793f04d5140SColin Leitner 
1794d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc)
1795a08c22c0SSven Eckelmann {
17969b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
179755d3b664SFrank Praznik 		.buf = {
1798a08c22c0SSven Eckelmann 			0x01,
1799a08c22c0SSven Eckelmann 			0x00, 0xff, 0x00, 0xff, 0x00,
18000a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1801a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1802a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1803a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1804a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1805a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
180655d3b664SFrank Praznik 		}
1807a08c22c0SSven Eckelmann 	};
18089b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
18099b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
18109b2b5c9aSFrank Praznik 	int n;
18119b2b5c9aSFrank Praznik 
18129b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
18139b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
18149f323b68SSven Eckelmann 
18150a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
18169b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
18179b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
18180a286ef2SSven Eckelmann #endif
18190a286ef2SSven Eckelmann 
18209b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
18219b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
18229b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
18239b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
18249f323b68SSven Eckelmann 
182588f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
18269b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
18279b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
182888f6576fSSimon Wood 
1829b3ed458cSFrank Praznik 	/*
1830b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
1831b3ed458cSFrank Praznik 	 * corresponding light on the controller.
1832b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
1833b3ed458cSFrank Praznik 	 *
1834b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
1835b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
1836b3ed458cSFrank Praznik 	 * always off.
1837b3ed458cSFrank Praznik 	 */
1838b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
1839b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
18409b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
18419b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
1842b3ed458cSFrank Praznik 		}
1843b3ed458cSFrank Praznik 	}
1844b3ed458cSFrank Praznik 
18459b2b5c9aSFrank Praznik 	hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report,
18469b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
18479b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18489f323b68SSven Eckelmann }
18499f323b68SSven Eckelmann 
1850d8aaccdaSFrank Praznik static void dualshock4_send_output_report(struct sony_sc *sc)
18510bd88dd3SFrank Praznik {
18520da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
18539b2b5c9aSFrank Praznik 	__u8 *buf = sc->output_report_dmabuf;
185448220237SFrank Praznik 	int offset;
18550da8ea65SFrank Praznik 
1856fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
18579b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x05_SIZE);
185848220237SFrank Praznik 		buf[0] = 0x05;
1859b3ed458cSFrank Praznik 		buf[1] = 0xFF;
186048220237SFrank Praznik 		offset = 4;
1861fdcf105dSFrank Praznik 	} else {
18629b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x11_SIZE);
1863fdcf105dSFrank Praznik 		buf[0] = 0x11;
1864824deff8SRostislav Pehlivanov 		buf[1] = 0x80;
1865fdcf105dSFrank Praznik 		buf[3] = 0x0F;
1866fdcf105dSFrank Praznik 		offset = 6;
1867fdcf105dSFrank Praznik 	}
18680bd88dd3SFrank Praznik 
18690bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
187048220237SFrank Praznik 	buf[offset++] = sc->right;
187148220237SFrank Praznik 	buf[offset++] = sc->left;
187248220237SFrank Praznik #else
187348220237SFrank Praznik 	offset += 2;
18740bd88dd3SFrank Praznik #endif
18750bd88dd3SFrank Praznik 
1876b3ed458cSFrank Praznik 	/* LED 3 is the global control */
1877b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
187848220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
187948220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
188048220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
1881b3ed458cSFrank Praznik 	} else {
1882b3ed458cSFrank Praznik 		offset += 3;
1883b3ed458cSFrank Praznik 	}
1884b3ed458cSFrank Praznik 
1885b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
1886b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
1887b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
188860781cf4SFrank Praznik 
1889fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
18909b2b5c9aSFrank Praznik 		hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);
1891fdcf105dSFrank Praznik 	else
18929b2b5c9aSFrank Praznik 		hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,
1893fdcf105dSFrank Praznik 				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18940bd88dd3SFrank Praznik }
18950bd88dd3SFrank Praznik 
1896d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc)
1897c5e0c1c4SFrank Praznik {
1898c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1899c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
1900c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
1901c5e0c1c4SFrank Praznik 
190241d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
1903c5e0c1c4SFrank Praznik 
1904c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
1905c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
1906c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
1907c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
1908c5e0c1c4SFrank Praznik 
1909c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1910c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
1911c5e0c1c4SFrank Praznik #endif
1912c5e0c1c4SFrank Praznik 
191341d2d425SSimon Wood 	hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
1914c5e0c1c4SFrank Praznik }
1915c5e0c1c4SFrank Praznik 
1916decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc)
1917decd946cSFrank Praznik {
1918decd946cSFrank Praznik 	if (sc->send_output_report)
1919decd946cSFrank Praznik 		sc->send_output_report(sc);
1920decd946cSFrank Praznik }
1921decd946cSFrank Praznik 
1922d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work)
1923d8aaccdaSFrank Praznik {
1924d8aaccdaSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1925d8aaccdaSFrank Praznik 	sc->send_output_report(sc);
1926d8aaccdaSFrank Praznik }
1927d8aaccdaSFrank Praznik 
19289b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
19299b2b5c9aSFrank Praznik {
19304545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
19314545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
19329b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
19339b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
19349b2b5c9aSFrank Praznik 				GFP_KERNEL);
19359b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
19369b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,
19379b2b5c9aSFrank Praznik 						GFP_KERNEL);
19389b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
19399b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
19409b2b5c9aSFrank Praznik 						GFP_KERNEL);
1941c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
194241d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
1943c5e0c1c4SFrank Praznik 						GFP_KERNEL);
19449b2b5c9aSFrank Praznik 	else
19459b2b5c9aSFrank Praznik 		return 0;
19469b2b5c9aSFrank Praznik 
19479b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
19489b2b5c9aSFrank Praznik 		return -ENOMEM;
19499b2b5c9aSFrank Praznik 
19509b2b5c9aSFrank Praznik 	return 0;
19519b2b5c9aSFrank Praznik }
19529b2b5c9aSFrank Praznik 
19530a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
19549f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
19559f323b68SSven Eckelmann 			    struct ff_effect *effect)
19569f323b68SSven Eckelmann {
1957a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
19589f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
1959a08c22c0SSven Eckelmann 
1960a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
1961a08c22c0SSven Eckelmann 		return 0;
1962a08c22c0SSven Eckelmann 
19639f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
19640bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
1965a08c22c0SSven Eckelmann 
196692b5c411SSven Eckelmann 	schedule_work(&sc->state_worker);
19679f323b68SSven Eckelmann 	return 0;
1968a08c22c0SSven Eckelmann }
1969a08c22c0SSven Eckelmann 
1970fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1971a08c22c0SSven Eckelmann {
1972fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1973a08c22c0SSven Eckelmann 						struct hid_input, list);
1974a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
1975a08c22c0SSven Eckelmann 
1976a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
1977a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
1978a08c22c0SSven Eckelmann }
1979a08c22c0SSven Eckelmann 
1980a08c22c0SSven Eckelmann #else
1981fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1982a08c22c0SSven Eckelmann {
1983a08c22c0SSven Eckelmann 	return 0;
1984a08c22c0SSven Eckelmann }
19859f323b68SSven Eckelmann 
1986a08c22c0SSven Eckelmann #endif
1987a08c22c0SSven Eckelmann 
1988d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
1989d902f472SFrank Praznik 				     enum power_supply_property psp,
1990d902f472SFrank Praznik 				     union power_supply_propval *val)
1991c4e1ddf2SFrank Praznik {
1992297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
1993d902f472SFrank Praznik 	unsigned long flags;
1994d902f472SFrank Praznik 	int ret = 0;
1995d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
1996c4e1ddf2SFrank Praznik 
1997d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1998d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
1999d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
2000d902f472SFrank Praznik 	cable_state = sc->cable_state;
2001d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
2002c4e1ddf2SFrank Praznik 
2003d902f472SFrank Praznik 	switch (psp) {
2004d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
2005d902f472SFrank Praznik 		val->intval = 1;
2006d902f472SFrank Praznik 		break;
2007d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
2008d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
2009d902f472SFrank Praznik 		break;
2010d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
2011d902f472SFrank Praznik 		val->intval = battery_capacity;
2012d902f472SFrank Praznik 		break;
2013d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
2014d902f472SFrank Praznik 		if (battery_charging)
2015d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
2016d902f472SFrank Praznik 		else
2017d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
2018d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
2019d902f472SFrank Praznik 			else
2020d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2021d902f472SFrank Praznik 		break;
2022d902f472SFrank Praznik 	default:
2023d902f472SFrank Praznik 		ret = -EINVAL;
2024d902f472SFrank Praznik 		break;
2025c4e1ddf2SFrank Praznik 	}
2026d902f472SFrank Praznik 	return ret;
2027d902f472SFrank Praznik }
2028d902f472SFrank Praznik 
2029d902f472SFrank Praznik static int sony_battery_probe(struct sony_sc *sc)
2030d902f472SFrank Praznik {
2031297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
2032d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
2033d902f472SFrank Praznik 	int ret;
2034d902f472SFrank Praznik 
2035ad142b9eSFrank Praznik 	/*
2036ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
2037d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
2038d9a293a9SFrank Praznik 	 */
2039d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
2040d9a293a9SFrank Praznik 
2041297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
2042297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
2043297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
2044297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2045297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
2046297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = kasprintf(GFP_KERNEL,
2047297d716fSKrzysztof Kozlowski 					  "sony_controller_battery_%pMR",
2048314531f1SFrank Praznik 					  sc->mac_address);
2049297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2050d902f472SFrank Praznik 		return -ENOMEM;
2051d902f472SFrank Praznik 
2052297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
2053297d716fSKrzysztof Kozlowski 					    &psy_cfg);
2054297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
2055297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
2056d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
2057d902f472SFrank Praznik 		goto err_free;
2058d902f472SFrank Praznik 	}
2059d902f472SFrank Praznik 
2060297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
2061d902f472SFrank Praznik 	return 0;
2062d902f472SFrank Praznik 
2063d902f472SFrank Praznik err_free:
2064297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2065297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2066d902f472SFrank Praznik 	return ret;
2067d902f472SFrank Praznik }
2068d902f472SFrank Praznik 
2069d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
2070d902f472SFrank Praznik {
2071297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2072d902f472SFrank Praznik 		return;
2073d902f472SFrank Praznik 
2074297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
2075297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2076297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2077d902f472SFrank Praznik }
2078d902f472SFrank Praznik 
2079d2d782fcSFrank Praznik /*
2080d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
2081d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
2082d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
2083d2d782fcSFrank Praznik  * once.
2084d2d782fcSFrank Praznik  */
2085d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
2086d2d782fcSFrank Praznik {
2087d2d782fcSFrank Praznik 	struct sony_sc *entry;
2088d2d782fcSFrank Praznik 	unsigned long flags;
2089d2d782fcSFrank Praznik 	int ret;
2090d2d782fcSFrank Praznik 
2091d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
2092d2d782fcSFrank Praznik 
2093d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
2094d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
2095d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
2096d2d782fcSFrank Praznik 		if (!ret) {
2097d2d782fcSFrank Praznik 			ret = -EEXIST;
2098d2d782fcSFrank Praznik 			hid_info(sc->hdev, "controller with MAC address %pMR already connected\n",
2099d2d782fcSFrank Praznik 				sc->mac_address);
2100d2d782fcSFrank Praznik 			goto unlock;
2101d2d782fcSFrank Praznik 		}
2102c4e1ddf2SFrank Praznik 	}
2103c4e1ddf2SFrank Praznik 
2104d2d782fcSFrank Praznik 	ret = 0;
2105d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
2106c4e1ddf2SFrank Praznik 
2107d2d782fcSFrank Praznik unlock:
2108d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2109d2d782fcSFrank Praznik 	return ret;
2110d2d782fcSFrank Praznik }
2111d2d782fcSFrank Praznik 
2112d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
2113d2d782fcSFrank Praznik {
2114d2d782fcSFrank Praznik 	unsigned long flags;
2115d2d782fcSFrank Praznik 
2116d2d782fcSFrank Praznik 	if (sc->list_node.next) {
2117d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
2118d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
2119d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2120d2d782fcSFrank Praznik 	}
2121d2d782fcSFrank Praznik }
2122d2d782fcSFrank Praznik 
2123d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
2124d2d782fcSFrank Praznik {
2125d2d782fcSFrank Praznik 	int ret;
2126d2d782fcSFrank Praznik 
2127d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2128d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2129d2d782fcSFrank Praznik 	if (ret != 17)
2130c4e1ddf2SFrank Praznik 		return -EINVAL;
2131d2d782fcSFrank Praznik 
2132d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2133d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2134d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2135d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2136d2d782fcSFrank Praznik 
2137d2d782fcSFrank Praznik 	if (ret != 6)
2138d2d782fcSFrank Praznik 		return -EINVAL;
2139d2d782fcSFrank Praznik 
2140d2d782fcSFrank Praznik 	return 0;
2141c4e1ddf2SFrank Praznik }
2142c4e1ddf2SFrank Praznik 
2143d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2144d2d782fcSFrank Praznik {
21459b2b5c9aSFrank Praznik 	__u8 *buf = NULL;
2146d2d782fcSFrank Praznik 	int n, ret;
2147d2d782fcSFrank Praznik 
2148d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
214912e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
21504545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2151d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2152d2d782fcSFrank Praznik 		/*
2153d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2154d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2155d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2156d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2157d2d782fcSFrank Praznik 		 */
2158d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2159d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2160d2d782fcSFrank Praznik 			return 0;
2161d2d782fcSFrank Praznik 		}
2162d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
21639b2b5c9aSFrank Praznik 		buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);
21649b2b5c9aSFrank Praznik 		if (!buf)
21659b2b5c9aSFrank Praznik 			return -ENOMEM;
2166d2d782fcSFrank Praznik 
2167d2d782fcSFrank Praznik 		/*
2168d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2169d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2170d2d782fcSFrank Praznik 		 * offset 1.
2171d2d782fcSFrank Praznik 		 */
21729b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
21739b2b5c9aSFrank Praznik 				DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
21749b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2175d2d782fcSFrank Praznik 
21769b2b5c9aSFrank Praznik 		if (ret != DS4_REPORT_0x81_SIZE) {
2177d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
21789b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
21799b2b5c9aSFrank Praznik 			goto out_free;
2180d2d782fcSFrank Praznik 		}
2181d2d782fcSFrank Praznik 
2182d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
21834545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
21844545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
21859b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
21869b2b5c9aSFrank Praznik 		if (!buf)
21879b2b5c9aSFrank Praznik 			return -ENOMEM;
2188d2d782fcSFrank Praznik 
2189d2d782fcSFrank Praznik 		/*
2190d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2191d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2192d2d782fcSFrank Praznik 		 * offset 4.
2193d2d782fcSFrank Praznik 		 */
21949b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
21959b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
21969b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2197d2d782fcSFrank Praznik 
21989b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2199d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
22009b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22019b2b5c9aSFrank Praznik 			goto out_free;
2202d2d782fcSFrank Praznik 		}
2203d2d782fcSFrank Praznik 
2204d2d782fcSFrank Praznik 		/*
2205d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2206d2d782fcSFrank Praznik 		 * be byte-swapped.
2207d2d782fcSFrank Praznik 		 */
2208d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2209d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2210d2d782fcSFrank Praznik 	} else {
2211d2d782fcSFrank Praznik 		return 0;
2212d2d782fcSFrank Praznik 	}
2213d2d782fcSFrank Praznik 
22149b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
22159b2b5c9aSFrank Praznik 
22169b2b5c9aSFrank Praznik out_free:
22179b2b5c9aSFrank Praznik 
22189b2b5c9aSFrank Praznik 	kfree(buf);
22199b2b5c9aSFrank Praznik 
22209b2b5c9aSFrank Praznik 	return ret;
2221d2d782fcSFrank Praznik }
2222d2d782fcSFrank Praznik 
22238025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
22248025087aSFrank Praznik {
22258025087aSFrank Praznik 	int ret;
22268025087aSFrank Praznik 
22278025087aSFrank Praznik 	/*
22288025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
22298025087aSFrank Praznik 	 * All others are set to -1.
22308025087aSFrank Praznik 	 */
22318025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
22328025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
22338025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
22348025087aSFrank Praznik 					GFP_KERNEL);
22358025087aSFrank Praznik 		if (ret < 0) {
22368025087aSFrank Praznik 			sc->device_id = -1;
22378025087aSFrank Praznik 			return ret;
22388025087aSFrank Praznik 		}
22398025087aSFrank Praznik 		sc->device_id = ret;
22408025087aSFrank Praznik 	} else {
22418025087aSFrank Praznik 		sc->device_id = -1;
22428025087aSFrank Praznik 	}
22438025087aSFrank Praznik 
22448025087aSFrank Praznik 	return 0;
22458025087aSFrank Praznik }
22468025087aSFrank Praznik 
22478025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
22488025087aSFrank Praznik {
22498025087aSFrank Praznik 	if (sc->device_id >= 0) {
22508025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
22518025087aSFrank Praznik 		sc->device_id = -1;
22528025087aSFrank Praznik 	}
22538025087aSFrank Praznik }
22548025087aSFrank Praznik 
2255d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc,
2256d8aaccdaSFrank Praznik 				void(*send_output_report)(struct sony_sc*))
225746262047SFrank Praznik {
2258d8aaccdaSFrank Praznik 	sc->send_output_report = send_output_report;
2259d8aaccdaSFrank Praznik 
226046262047SFrank Praznik 	if (!sc->worker_initialized)
2261d8aaccdaSFrank Praznik 		INIT_WORK(&sc->state_worker, sony_state_worker);
226246262047SFrank Praznik 
226346262047SFrank Praznik 	sc->worker_initialized = 1;
226446262047SFrank Praznik }
226546262047SFrank Praznik 
226646262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
226746262047SFrank Praznik {
226846262047SFrank Praznik 	if (sc->worker_initialized)
226946262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
227046262047SFrank Praznik }
2271d2d782fcSFrank Praznik 
2272bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2273bd28ce00SJiri Slaby {
2274bd28ce00SJiri Slaby 	int ret;
2275cc6e0bbbSJiri Kosina 	unsigned long quirks = id->driver_data;
2276cc6e0bbbSJiri Kosina 	struct sony_sc *sc;
2277f04d5140SColin Leitner 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2278cc6e0bbbSJiri Kosina 
2279abf832bfSBenjamin Tissoires 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2280cc6e0bbbSJiri Kosina 	if (sc == NULL) {
22814291ee30SJoe Perches 		hid_err(hdev, "can't alloc sony descriptor\n");
2282cc6e0bbbSJiri Kosina 		return -ENOMEM;
2283cc6e0bbbSJiri Kosina 	}
2284cc6e0bbbSJiri Kosina 
2285b94993f6SFrank Praznik 	spin_lock_init(&sc->lock);
2286b94993f6SFrank Praznik 
2287cc6e0bbbSJiri Kosina 	sc->quirks = quirks;
2288cc6e0bbbSJiri Kosina 	hid_set_drvdata(hdev, sc);
22890a286ef2SSven Eckelmann 	sc->hdev = hdev;
2290bd28ce00SJiri Slaby 
2291bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
2292bd28ce00SJiri Slaby 	if (ret) {
22934291ee30SJoe Perches 		hid_err(hdev, "parse failed\n");
2294abf832bfSBenjamin Tissoires 		return ret;
2295bd28ce00SJiri Slaby 	}
2296bd28ce00SJiri Slaby 
2297f04d5140SColin Leitner 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2298f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
229950764650SAntonio Ospite 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2300f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2301f04d5140SColin Leitner 
2302f04d5140SColin Leitner 	ret = hid_hw_start(hdev, connect_mask);
2303bd28ce00SJiri Slaby 	if (ret) {
23044291ee30SJoe Perches 		hid_err(hdev, "hw start failed\n");
2305abf832bfSBenjamin Tissoires 		return ret;
2306bd28ce00SJiri Slaby 	}
2307bd28ce00SJiri Slaby 
23088025087aSFrank Praznik 	ret = sony_set_device_id(sc);
23098025087aSFrank Praznik 	if (ret < 0) {
23108025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
23118025087aSFrank Praznik 		goto err_stop;
23128025087aSFrank Praznik 	}
23138025087aSFrank Praznik 
2314131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2315131a8a9aSFrank Praznik 	if (ret < 0) {
2316131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2317131a8a9aSFrank Praznik 		goto err_stop;
2318131a8a9aSFrank Praznik 	}
2319131a8a9aSFrank Praznik 
23204545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
23214545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2322e534a935SBenjamin Tissoires 		/*
2323e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2324e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2325e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2326e534a935SBenjamin Tissoires 		 *
2327e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2328e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2329e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2330e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
2331e534a935SBenjamin Tissoires 		 */
2332e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2333e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
2334816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
2335d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
23364545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
23374545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
23382078b9bbSFrank Praznik 		/*
23392078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
23402078b9bbSFrank Praznik 		 * when connected via Bluetooth.
23412078b9bbSFrank Praznik 		 */
23422078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2343816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
2344d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
2345fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
234668330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
23472078b9bbSFrank Praznik 			/*
23482078b9bbSFrank Praznik 			 * The DualShock 4 wants output reports sent on the ctrl
23492078b9bbSFrank Praznik 			 * endpoint when connected via Bluetooth.
23502078b9bbSFrank Praznik 			 */
23512078b9bbSFrank Praznik 			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
235268330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
235368330d83SFrank Praznik 			if (ret < 0) {
235468330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
235568330d83SFrank Praznik 				goto err_stop;
235668330d83SFrank Praznik 			}
235768330d83SFrank Praznik 		}
2358c4e1ddf2SFrank Praznik 
2359d8aaccdaSFrank Praznik 		sony_init_output_report(sc, dualshock4_send_output_report);
2360c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2361d8aaccdaSFrank Praznik 		sony_init_output_report(sc, motion_send_output_report);
23620bd88dd3SFrank Praznik 	} else {
23630bd88dd3SFrank Praznik 		ret = 0;
23640bd88dd3SFrank Praznik 	}
2365f9ce7c28SBastien Nocera 
23664dfdc464SJiri Kosina 	if (ret < 0)
2367bd28ce00SJiri Slaby 		goto err_stop;
2368bd28ce00SJiri Slaby 
2369d2d782fcSFrank Praznik 	ret = sony_check_add(sc);
2370d2d782fcSFrank Praznik 	if (ret < 0)
2371d2d782fcSFrank Praznik 		goto err_stop;
2372d2d782fcSFrank Praznik 
23730a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2374fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
23750a286ef2SSven Eckelmann 		if (ret < 0)
23760a286ef2SSven Eckelmann 			goto err_stop;
23770a286ef2SSven Eckelmann 	}
23780a286ef2SSven Eckelmann 
2379d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2380d902f472SFrank Praznik 		ret = sony_battery_probe(sc);
2381a08c22c0SSven Eckelmann 		if (ret < 0)
2382a08c22c0SSven Eckelmann 			goto err_stop;
2383a08c22c0SSven Eckelmann 
2384d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2385d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2386d902f472SFrank Praznik 		if (ret < 0) {
2387d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2388d902f472SFrank Praznik 			goto err_stop;
2389d902f472SFrank Praznik 		}
2390d902f472SFrank Praznik 	}
2391d902f472SFrank Praznik 
2392c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2393fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2394d902f472SFrank Praznik 		if (ret < 0)
2395d902f472SFrank Praznik 			goto err_close;
23965f5750d2SFrank Praznik 	}
2397bd28ce00SJiri Slaby 
2398f425458eSH Hartley Sweeten 	return 0;
2399d902f472SFrank Praznik err_close:
2400d902f472SFrank Praznik 	hid_hw_close(hdev);
2401bd28ce00SJiri Slaby err_stop:
24020a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2403fa57a810SFrank Praznik 		sony_leds_remove(sc);
2404d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2405d902f472SFrank Praznik 		sony_battery_remove(sc);
240646262047SFrank Praznik 	sony_cancel_work_sync(sc);
24079b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2408d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
24098025087aSFrank Praznik 	sony_release_device_id(sc);
2410bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2411bd28ce00SJiri Slaby 	return ret;
2412bd28ce00SJiri Slaby }
2413bd28ce00SJiri Slaby 
2414bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2415bd28ce00SJiri Slaby {
2416bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2417bd28ce00SJiri Slaby 
24180a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2419fa57a810SFrank Praznik 		sony_leds_remove(sc);
2420bd28ce00SJiri Slaby 
2421d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2422d902f472SFrank Praznik 		hid_hw_close(hdev);
2423d902f472SFrank Praznik 		sony_battery_remove(sc);
2424d902f472SFrank Praznik 	}
2425d902f472SFrank Praznik 
242646262047SFrank Praznik 	sony_cancel_work_sync(sc);
24279f323b68SSven Eckelmann 
24289b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
24299b2b5c9aSFrank Praznik 
2430d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2431bd28ce00SJiri Slaby 
24328025087aSFrank Praznik 	sony_release_device_id(sc);
24338025087aSFrank Praznik 
2434bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2435bd28ce00SJiri Slaby }
2436bd28ce00SJiri Slaby 
2437decd946cSFrank Praznik #ifdef CONFIG_PM
2438decd946cSFrank Praznik 
2439decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2440decd946cSFrank Praznik {
2441decd946cSFrank Praznik 	/*
2442decd946cSFrank Praznik 	 * On suspend save the current LED state,
2443decd946cSFrank Praznik 	 * stop running force-feedback and blank the LEDS.
2444decd946cSFrank Praznik          */
2445decd946cSFrank Praznik 	if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
2446decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2447decd946cSFrank Praznik 
2448decd946cSFrank Praznik #ifdef CONFIG_SONY_FF
2449decd946cSFrank Praznik 		sc->left = sc->right = 0;
2450decd946cSFrank Praznik #endif
2451decd946cSFrank Praznik 
2452decd946cSFrank Praznik 		memcpy(sc->resume_led_state, sc->led_state,
2453decd946cSFrank Praznik 			sizeof(sc->resume_led_state));
2454decd946cSFrank Praznik 		memset(sc->led_state, 0, sizeof(sc->led_state));
2455decd946cSFrank Praznik 
2456decd946cSFrank Praznik 		sony_send_output_report(sc);
2457decd946cSFrank Praznik 	}
2458decd946cSFrank Praznik 
2459decd946cSFrank Praznik 	return 0;
2460decd946cSFrank Praznik }
2461decd946cSFrank Praznik 
2462decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev)
2463decd946cSFrank Praznik {
2464decd946cSFrank Praznik 	/* Restore the state of controller LEDs on resume */
2465decd946cSFrank Praznik 	if (SONY_LED_SUPPORT) {
2466decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2467decd946cSFrank Praznik 
2468decd946cSFrank Praznik 		memcpy(sc->led_state, sc->resume_led_state,
2469decd946cSFrank Praznik 			sizeof(sc->led_state));
2470decd946cSFrank Praznik 
2471decd946cSFrank Praznik 		/*
2472decd946cSFrank Praznik 		 * The Sixaxis and navigation controllers on USB need to be
2473decd946cSFrank Praznik 		 * reinitialized on resume or they won't behave properly.
2474decd946cSFrank Praznik 		 */
2475decd946cSFrank Praznik 		if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
2476decd946cSFrank Praznik 			(sc->quirks & NAVIGATION_CONTROLLER_USB))
2477decd946cSFrank Praznik 			sixaxis_set_operational_usb(sc->hdev);
2478decd946cSFrank Praznik 
2479decd946cSFrank Praznik 		sony_set_leds(sc);
2480decd946cSFrank Praznik 	}
2481decd946cSFrank Praznik 
2482decd946cSFrank Praznik 	return 0;
2483decd946cSFrank Praznik }
2484decd946cSFrank Praznik 
2485decd946cSFrank Praznik #endif
2486decd946cSFrank Praznik 
2487bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2488bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2489bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2490bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
24914545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
24926eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
24934545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2494c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2495b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2496a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2497b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2498bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2499bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2500bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2501bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2502bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2503bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2504bd28ce00SJiri Slaby 	/* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2505bd28ce00SJiri Slaby 	 * Logitech joystick from the device descriptor. */
2506bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2507bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2508bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2509bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2510bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2511bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2512bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2513bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2514bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2515bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
251668a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
251768a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
251868a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
25190bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
25200bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
25218ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
25220bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
25238ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
2524bd28ce00SJiri Slaby 	{ }
2525bd28ce00SJiri Slaby };
2526bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2527bd28ce00SJiri Slaby 
2528bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2529bd28ce00SJiri Slaby 	.name             = "sony",
2530bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2531bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2532ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2533bd28ce00SJiri Slaby 	.probe            = sony_probe,
2534bd28ce00SJiri Slaby 	.remove           = sony_remove,
2535bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2536decd946cSFrank Praznik 	.raw_event        = sony_raw_event,
2537decd946cSFrank Praznik 
2538decd946cSFrank Praznik #ifdef CONFIG_PM
2539decd946cSFrank Praznik 	.suspend          = sony_suspend,
2540decd946cSFrank Praznik 	.resume	          = sony_resume,
2541decd946cSFrank Praznik 	.reset_resume     = sony_resume,
2542decd946cSFrank Praznik #endif
2543bd28ce00SJiri Slaby };
25448025087aSFrank Praznik 
25458025087aSFrank Praznik static int __init sony_init(void)
25468025087aSFrank Praznik {
25478025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
25488025087aSFrank Praznik 
25498025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
25508025087aSFrank Praznik }
25518025087aSFrank Praznik 
25528025087aSFrank Praznik static void __exit sony_exit(void)
25538025087aSFrank Praznik {
25548025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
25558025087aSFrank Praznik 
25568025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
25576c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
25588025087aSFrank Praznik }
25598025087aSFrank Praznik module_init(sony_init);
25608025087aSFrank Praznik module_exit(sony_exit);
2561bd28ce00SJiri Slaby 
2562bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2563