xref: /linux/drivers/hid/hid-sony.c (revision b2723eb73c6dc014980beb0f3e5f47d6cac57939)
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 
251*b2723eb7SSimon Wood /* PS/3 Navigation controller */
252*b2723eb7SSimon Wood static __u8 navigation_rdesc[] = {
253*b2723eb7SSimon Wood 	0x05, 0x01,         /*  Usage Page (Desktop),               */
254*b2723eb7SSimon Wood 	0x09, 0x04,         /*  Usage (Joystik),                    */
255*b2723eb7SSimon Wood 	0xA1, 0x01,         /*  Collection (Application),           */
256*b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
257*b2723eb7SSimon Wood 	0x85, 0x01,         /*          Report ID (1),              */
258*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
259*b2723eb7SSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
260*b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
261*b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
262*b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
263*b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
264*b2723eb7SSimon Wood 	0x95, 0x13,         /*          Report Count (19),          */
265*b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
266*b2723eb7SSimon Wood 	0x25, 0x01,         /*          Logical Maximum (1),        */
267*b2723eb7SSimon Wood 	0x35, 0x00,         /*          Physical Minimum (0),       */
268*b2723eb7SSimon Wood 	0x45, 0x01,         /*          Physical Maximum (1),       */
269*b2723eb7SSimon Wood 	0x05, 0x09,         /*          Usage Page (Button),        */
270*b2723eb7SSimon Wood 	0x19, 0x01,         /*          Usage Minimum (01h),        */
271*b2723eb7SSimon Wood 	0x29, 0x13,         /*          Usage Maximum (13h),        */
272*b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
273*b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
274*b2723eb7SSimon Wood 	0x95, 0x0D,         /*          Report Count (13),          */
275*b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
276*b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
277*b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
278*b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
279*b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
280*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
281*b2723eb7SSimon Wood 	0xA1, 0x00,         /*          Collection (Physical),      */
282*b2723eb7SSimon Wood 	0x75, 0x08,         /*              Report Size (8),        */
283*b2723eb7SSimon Wood 	0x95, 0x02,         /*              Report Count (2),       */
284*b2723eb7SSimon Wood 	0x35, 0x00,         /*              Physical Minimum (0),   */
285*b2723eb7SSimon Wood 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
286*b2723eb7SSimon Wood 	0x09, 0x30,         /*              Usage (X),              */
287*b2723eb7SSimon Wood 	0x09, 0x31,         /*              Usage (Y),              */
288*b2723eb7SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       */
289*b2723eb7SSimon Wood 	0xC0,               /*          End Collection,             */
290*b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
291*b2723eb7SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           */
292*b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
293*b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
294*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
295*b2723eb7SSimon Wood 	0x95, 0x05,         /*          Report Count (5),           */
296*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
297*b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
298*b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
299*b2723eb7SSimon Wood 	0x95, 0x20,         /*          Report Count (26),          */
300*b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
301*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
302*b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
303*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
304*b2723eb7SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
305*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
306*b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
307*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
308*b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
309*b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
310*b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
311*b2723eb7SSimon Wood 	0x85, 0x02,         /*          Report ID (2),              */
312*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
313*b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
314*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
315*b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
316*b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
317*b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
318*b2723eb7SSimon Wood 	0x85, 0xEE,         /*          Report ID (238),            */
319*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
320*b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
321*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
322*b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
323*b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
324*b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
325*b2723eb7SSimon Wood 	0x85, 0xEF,         /*          Report ID (239),            */
326*b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
327*b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
328*b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
329*b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
330*b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
331*b2723eb7SSimon Wood 	0xC0                /*  End Collection                      */
332*b2723eb7SSimon Wood };
333c5e0c1c4SFrank Praznik 
334ad142b9eSFrank Praznik /*
335ad142b9eSFrank Praznik  * The default descriptor doesn't provide mapping for the accelerometers
33658d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
33758d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
33858d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
33958d7027bSFrank Praznik  */
340ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
34158d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
34258d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
34358d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
34458d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
34558d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
34658d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
34758d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
34858d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
34958d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
35058d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
35158d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
35258d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
35358d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
35458d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
35558d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
35658d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
35758d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
35858d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
35958d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
36058d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
36158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
36258d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
36358d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
36458d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
36558d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
36658d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
36758d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36858d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
36958d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
37058d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
37158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
37258d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
37358d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
37458d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
37558d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
37658d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
377fb291cbdSFrank Praznik 	0x25, 0x3F,         /*      Logical Maximum (63),           */
37858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
37958d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
38058d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
38158d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
38258d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
38358d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
38458d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
38558d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
38658d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
38758d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
38858d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
38958d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
39058d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39158d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
39258d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
39358d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
39458d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
39558d7027bSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
39658d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
39758d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
39858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39958d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
40058d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
401fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
402fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
40358d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40458d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40558d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
40658d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
40758d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
408fb291cbdSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
40958d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
41058d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
41158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41258d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
41358d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
41458d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
41558d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
41658d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
41758d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
41858d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
41958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42058d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
42158d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
42258d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
42358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42458d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
42558d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
42658d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
42758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42858d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
42958d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
43058d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
43158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43258d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
43358d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
43458d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
43558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43658d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
43758d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
43858d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
43958d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
44058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44158d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
44258d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
44358d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
44458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44558d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
44658d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
44758d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
44858d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
44958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45058d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
45158d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
45258d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
45358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45458d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
45558d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
45658d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
45758d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
45858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45958d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
46058d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
46158d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
46258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46358d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
46458d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
46558d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
46658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46758d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
46858d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
46958d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
47058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47158d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
47258d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
47358d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
47458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47558d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
47658d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
47758d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
47858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47958d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
48058d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
48158d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
48258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48358d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
48458d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
48558d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
48658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48758d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
48858d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
48958d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
49058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49158d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
49258d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
49358d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
49458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49558d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
49658d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
49758d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
49858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49958d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
50058d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
50158d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
50258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50358d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
50458d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
50558d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
50658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50758d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
50858d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
50958d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
51058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51158d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
51258d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
51358d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
51458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51558d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
51658d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
51758d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
51858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51958d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
52058d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
52158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
52258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52358d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
52458d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
52558d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
52658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52758d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
52858d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
52958d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
53058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53158d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
53258d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
53358d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
53458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53558d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
53658d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
53758d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
53858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53958d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
54058d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
54158d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
54258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54358d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
54458d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
54558d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
54658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54758d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
54858d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
54958d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
55058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55158d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
55258d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
55358d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
55458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55558d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
55658d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
55758d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
55858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55958d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
56058d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
56158d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
56258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56358d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
56458d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
56558d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56758d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
56858d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
56958d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
57058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57158d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
57258d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
57358d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
57458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57558d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
57658d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
57758d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
57858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57958d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
58058d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
58158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
58258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58358d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
58458d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
58558d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
58658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58758d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
58858d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
58958d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
59058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59158d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
592ed19d8cfSFrank Praznik };
593ed19d8cfSFrank Praznik 
594ad142b9eSFrank Praznik /*
595ad142b9eSFrank Praznik  * The default behavior of the Dualshock 4 is to send reports using report
596077147a3SFrank Praznik  * type 1 when running over Bluetooth. However, when feature report 2 is
597077147a3SFrank Praznik  * requested during the controller initialization it starts sending input
598077147a3SFrank Praznik  * reports in report 17.  Since report 17 is undefined in the default HID
599d829674dSFrank Praznik  * descriptor the button and axis definitions must be moved to report 17 or
600077147a3SFrank Praznik  * the HID layer won't process the received input.
601d829674dSFrank Praznik  */
602d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = {
603d829674dSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
604d829674dSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
605d829674dSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
606d829674dSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
607d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
608d829674dSFrank Praznik 	0x95, 0x0A,         /*      Report Count (9),               */
609d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
610d829674dSFrank Praznik 	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
611d829674dSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
612d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
613d829674dSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
614d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
615d829674dSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
616d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
617d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
618d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
619d829674dSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
620d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
621d829674dSFrank Praznik 	0x95, 0x28,         /*      Report Count (40),              */
622d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
623d829674dSFrank Praznik 	0x85, 0x06,         /*      Report ID (6),                  */
624d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
625d829674dSFrank Praznik 	0x95, 0x34,         /*      Report Count (52),              */
626d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
627d829674dSFrank Praznik 	0x85, 0x07,         /*      Report ID (7),                  */
628d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
629d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
630d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
631d829674dSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
632d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
633d829674dSFrank Praznik 	0x95, 0x2F,         /*      Report Count (47),              */
634d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
635d829674dSFrank Praznik 	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
636d829674dSFrank Praznik 	0x85, 0x03,         /*      Report ID (3),                  */
637d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
638d829674dSFrank Praznik 	0x95, 0x26,         /*      Report Count (38),              */
639d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
640d829674dSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
641d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
642d829674dSFrank Praznik 	0x95, 0x2E,         /*      Report Count (46),              */
643d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
644d829674dSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
645d829674dSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
646d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
647d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
648d829674dSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
649d829674dSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
650d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
651d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
652d829674dSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
653d829674dSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
654d829674dSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
655d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
656d829674dSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
657d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
658d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
659d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
660d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
661d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
662d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
663d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
664d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
665d829674dSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
666d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
667d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
668d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
669d829674dSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
670d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
671d829674dSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
672d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
673d829674dSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
674d829674dSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
675d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
676d829674dSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
677d829674dSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
678d829674dSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
679d829674dSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
680d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
681d829674dSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
682d829674dSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
683d829674dSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
684d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
685d829674dSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
686d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
687d829674dSFrank Praznik 	0x81, 0x01,         /*      Input (Constant),               */
688d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
689d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
690d829674dSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
691d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
692d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
693d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
694d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
695d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
696d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
697d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
698d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
699d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
700d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
701d829674dSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
702d829674dSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
703d829674dSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
704d829674dSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
705d829674dSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
706d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
707d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
708d829674dSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
709d829674dSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
710fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
711fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
712d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
713d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
714d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
715d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
716d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
717d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
718d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
719d829674dSFrank Praznik 	0x95, 0x31,         /*      Report Count (51),              */
720d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
721d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
722d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
723d829674dSFrank Praznik 	0x95, 0x4D,         /*      Report Count (77),              */
724d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
725d829674dSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
726d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
727d829674dSFrank Praznik 	0x95, 0x8D,         /*      Report Count (141),             */
728d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
729d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
730d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
731d829674dSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
732d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
733d829674dSFrank Praznik 	0x95, 0xCD,         /*      Report Count (205),             */
734d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
735d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
736d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
737d829674dSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
738d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
739d829674dSFrank Praznik 	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
740d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
741d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
742d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
743d829674dSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
744d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
745d829674dSFrank Praznik 	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
746d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
747d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
748d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
749d829674dSFrank Praznik 	0x85, 0x16,         /*      Report ID (22),                 */
750d829674dSFrank Praznik 	0x09, 0x2A,         /*      Usage (2Ah),                    */
751d829674dSFrank Praznik 	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
752d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
753d829674dSFrank Praznik 	0x09, 0x2B,         /*      Usage (2Bh),                    */
754d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
755d829674dSFrank Praznik 	0x85, 0x17,         /*      Report ID (23),                 */
756d829674dSFrank Praznik 	0x09, 0x2C,         /*      Usage (2Ch),                    */
757d829674dSFrank Praznik 	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
758d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
759d829674dSFrank Praznik 	0x09, 0x2D,         /*      Usage (2Dh),                    */
760d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
761d829674dSFrank Praznik 	0x85, 0x18,         /*      Report ID (24),                 */
762d829674dSFrank Praznik 	0x09, 0x2E,         /*      Usage (2Eh),                    */
763d829674dSFrank Praznik 	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
764d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
765d829674dSFrank Praznik 	0x09, 0x2F,         /*      Usage (2Fh),                    */
766d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
767d829674dSFrank Praznik 	0x85, 0x19,         /*      Report ID (25),                 */
768d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
769d829674dSFrank Praznik 	0x96, 0x22, 0x02,   /*      Report Count (546),             */
770d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
771d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
772d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
773d829674dSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
774d829674dSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
775d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
776d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
777d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
778d829674dSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
779d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
780d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
781d829674dSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
782d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
783d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
784d829674dSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
785d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
786d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
787d829674dSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
788d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
789d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
790d829674dSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
791d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
792d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
793d829674dSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
794d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
795d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
796d829674dSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
797d829674dSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
798d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
799d829674dSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
800d829674dSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
801d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
802d829674dSFrank Praznik 	0xC0                /*  End Collection                      */
803d829674dSFrank Praznik };
804d829674dSFrank Praznik 
805078328daSJiri Kosina static __u8 ps3remote_rdesc[] = {
806078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
807078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
808078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
809078328daSJiri Kosina 
810078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
811078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
812078328daSJiri Kosina 
813078328daSJiri Kosina 	  /* Ignore the 1st byte, maybe it is used for a controller
814078328daSJiri Kosina 	   * number but it's not needed for correct operation */
815078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
816078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
817078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
818078328daSJiri Kosina 
819078328daSJiri Kosina 	  /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
820078328daSJiri Kosina 	   * buttons multiple keypresses are allowed */
821078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
822078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
823078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
824078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
825078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
826078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
827078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
828078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
829078328daSJiri Kosina 
830078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
831078328daSJiri Kosina 
832078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
833078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
834078328daSJiri Kosina 
835078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
836078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
837078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
838078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
839078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
840078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
841078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
842078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
843078328daSJiri Kosina 	  0x80,              /* MInput  */
844078328daSJiri Kosina 
845078328daSJiri Kosina 	  /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
846078328daSJiri Kosina 	   * 0xff and 11th is for press indication */
847078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
848078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
849078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
850078328daSJiri Kosina 
851078328daSJiri Kosina 	  /* 12th byte is for battery strength */
852078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
853078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
854078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
855078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
856078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
857078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
858078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
859078328daSJiri Kosina 
860078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
861078328daSJiri Kosina 
862078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
863078328daSJiri Kosina };
864078328daSJiri Kosina 
865078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
866078328daSJiri Kosina 	[0x01] = KEY_SELECT,
867078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
868078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
869078328daSJiri Kosina 	[0x04] = BTN_START,
870078328daSJiri Kosina 	[0x05] = KEY_UP,
871078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
872078328daSJiri Kosina 	[0x07] = KEY_DOWN,
873078328daSJiri Kosina 	[0x08] = KEY_LEFT,
874078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
875078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
876078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
877078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
878078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
879078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
880078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
881078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
882078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
883078328daSJiri Kosina 	[0x14] = KEY_ENTER,
884078328daSJiri Kosina };
885078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
886078328daSJiri Kosina 	[0x00] = KEY_1,
887078328daSJiri Kosina 	[0x01] = KEY_2,
888078328daSJiri Kosina 	[0x02] = KEY_3,
889078328daSJiri Kosina 	[0x03] = KEY_4,
890078328daSJiri Kosina 	[0x04] = KEY_5,
891078328daSJiri Kosina 	[0x05] = KEY_6,
892078328daSJiri Kosina 	[0x06] = KEY_7,
893078328daSJiri Kosina 	[0x07] = KEY_8,
894078328daSJiri Kosina 	[0x08] = KEY_9,
895078328daSJiri Kosina 	[0x09] = KEY_0,
896078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
897078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
898078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
899078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
900078328daSJiri Kosina 	[0x28] = KEY_TIME,
901078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
902078328daSJiri Kosina 	[0x31] = KEY_NEXT,
903078328daSJiri Kosina 	[0x32] = KEY_PLAY,
904078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
905078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
906078328daSJiri Kosina 	[0x38] = KEY_STOP,
907078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
908078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
909078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
910078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
911078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
912078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
913078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
914078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
915078328daSJiri Kosina 	[0x80] = KEY_BLUE,
916078328daSJiri Kosina 	[0x81] = KEY_RED,
917078328daSJiri Kosina 	[0x82] = KEY_GREEN,
918078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
919078328daSJiri Kosina };
920078328daSJiri Kosina 
921f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
922ad142b9eSFrank Praznik 	/*
923ad142b9eSFrank Praznik 	 * The controller has 4 remote buzzers, each with one LED and 5
924f04d5140SColin Leitner 	 * buttons.
925f04d5140SColin Leitner 	 *
926f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
927f04d5140SColin Leitner 	 *
928f04d5140SColin Leitner 	 * Key          Offset
929f04d5140SColin Leitner 	 * -------------------
930f04d5140SColin Leitner 	 * Buzz              1
931f04d5140SColin Leitner 	 * Blue              5
932f04d5140SColin Leitner 	 * Orange            4
933f04d5140SColin Leitner 	 * Green             3
934f04d5140SColin Leitner 	 * Yellow            2
935f04d5140SColin Leitner 	 *
936f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
937f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
938f04d5140SColin Leitner 	 */
939f04d5140SColin Leitner 	[ 1] = BTN_TRIGGER_HAPPY1,
940f04d5140SColin Leitner 	[ 2] = BTN_TRIGGER_HAPPY2,
941f04d5140SColin Leitner 	[ 3] = BTN_TRIGGER_HAPPY3,
942f04d5140SColin Leitner 	[ 4] = BTN_TRIGGER_HAPPY4,
943f04d5140SColin Leitner 	[ 5] = BTN_TRIGGER_HAPPY5,
944f04d5140SColin Leitner 	[ 6] = BTN_TRIGGER_HAPPY6,
945f04d5140SColin Leitner 	[ 7] = BTN_TRIGGER_HAPPY7,
946f04d5140SColin Leitner 	[ 8] = BTN_TRIGGER_HAPPY8,
947f04d5140SColin Leitner 	[ 9] = BTN_TRIGGER_HAPPY9,
948f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
949f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
950f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
951f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
952f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
953f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
954f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
955f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
956f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
957f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
958f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
959f04d5140SColin Leitner };
960f04d5140SColin Leitner 
961d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
962d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
963d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
964d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
965d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
966d902f472SFrank Praznik };
967d902f472SFrank Praznik 
96855d3b664SFrank Praznik struct sixaxis_led {
96955d3b664SFrank Praznik 	__u8 time_enabled; /* the total time the led is active (0xff means forever) */
97055d3b664SFrank Praznik 	__u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
97155d3b664SFrank Praznik 	__u8 enabled;
97255d3b664SFrank Praznik 	__u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
97355d3b664SFrank Praznik 	__u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
97455d3b664SFrank Praznik } __packed;
97555d3b664SFrank Praznik 
97655d3b664SFrank Praznik struct sixaxis_rumble {
97755d3b664SFrank Praznik 	__u8 padding;
97855d3b664SFrank Praznik 	__u8 right_duration; /* Right motor duration (0xff means forever) */
97955d3b664SFrank Praznik 	__u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
98055d3b664SFrank Praznik 	__u8 left_duration;    /* Left motor duration (0xff means forever) */
98155d3b664SFrank Praznik 	__u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
98255d3b664SFrank Praznik } __packed;
98355d3b664SFrank Praznik 
98455d3b664SFrank Praznik struct sixaxis_output_report {
98555d3b664SFrank Praznik 	__u8 report_id;
98655d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
98755d3b664SFrank Praznik 	__u8 padding[4];
98855d3b664SFrank Praznik 	__u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
98955d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
99055d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
99155d3b664SFrank Praznik } __packed;
99255d3b664SFrank Praznik 
99355d3b664SFrank Praznik union sixaxis_output_report_01 {
99455d3b664SFrank Praznik 	struct sixaxis_output_report data;
99555d3b664SFrank Praznik 	__u8 buf[36];
99655d3b664SFrank Praznik };
99755d3b664SFrank Praznik 
998c5e0c1c4SFrank Praznik struct motion_output_report_02 {
999c5e0c1c4SFrank Praznik 	u8 type, zero;
1000c5e0c1c4SFrank Praznik 	u8 r, g, b;
1001c5e0c1c4SFrank Praznik 	u8 zero2;
1002c5e0c1c4SFrank Praznik 	u8 rumble;
1003c5e0c1c4SFrank Praznik };
1004c5e0c1c4SFrank Praznik 
10059b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37
10069b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32
10079b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78
10089b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7
100929b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
1010a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
101141d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
10129b2b5c9aSFrank Praznik 
10138b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
1014d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
10158025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
1016d2d782fcSFrank Praznik 
1017cc6e0bbbSJiri Kosina struct sony_sc {
1018d902f472SFrank Praznik 	spinlock_t lock;
1019d2d782fcSFrank Praznik 	struct list_head list_node;
10200a286ef2SSven Eckelmann 	struct hid_device *hdev;
102160781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
1022cc6e0bbbSJiri Kosina 	unsigned long quirks;
10230a286ef2SSven Eckelmann 	struct work_struct state_worker;
1024297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
1025297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
10268025087aSFrank Praznik 	int device_id;
10279b2b5c9aSFrank Praznik 	__u8 *output_report_dmabuf;
1028f04d5140SColin Leitner 
10299f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
10309f323b68SSven Eckelmann 	__u8 left;
10319f323b68SSven Eckelmann 	__u8 right;
10329f323b68SSven Eckelmann #endif
10339f323b68SSven Eckelmann 
1034d2d782fcSFrank Praznik 	__u8 mac_address[6];
10355f5750d2SFrank Praznik 	__u8 worker_initialized;
1036d902f472SFrank Praznik 	__u8 cable_state;
1037d902f472SFrank Praznik 	__u8 battery_charging;
1038d902f472SFrank Praznik 	__u8 battery_capacity;
103960781cf4SFrank Praznik 	__u8 led_state[MAX_LEDS];
1040b3ed458cSFrank Praznik 	__u8 led_delay_on[MAX_LEDS];
1041b3ed458cSFrank Praznik 	__u8 led_delay_off[MAX_LEDS];
104260781cf4SFrank Praznik 	__u8 led_count;
1043cc6e0bbbSJiri Kosina };
1044cc6e0bbbSJiri Kosina 
1045c607fb8dSAntonio Ospite static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc,
1046c607fb8dSAntonio Ospite 			     unsigned int *rsize)
1047c607fb8dSAntonio Ospite {
1048c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
1049c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
1050c607fb8dSAntonio Ospite }
1051c607fb8dSAntonio Ospite 
1052c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
1053c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
1054c5e0c1c4SFrank Praznik {
1055c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
1056c5e0c1c4SFrank Praznik 	return motion_rdesc;
1057c5e0c1c4SFrank Praznik }
1058c5e0c1c4SFrank Praznik 
1059*b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc,
1060*b2723eb7SSimon Wood 			     unsigned int *rsize)
1061*b2723eb7SSimon Wood {
1062*b2723eb7SSimon Wood 	*rsize = sizeof(navigation_rdesc);
1063*b2723eb7SSimon Wood 	return navigation_rdesc;
1064*b2723eb7SSimon Wood }
1065*b2723eb7SSimon Wood 
1066078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
1067078328daSJiri Kosina 			     unsigned int *rsize)
1068078328daSJiri Kosina {
1069078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
1070078328daSJiri Kosina 	return ps3remote_rdesc;
1071078328daSJiri Kosina }
1072078328daSJiri Kosina 
1073078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
1074078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
1075078328daSJiri Kosina 			     unsigned long **bit, int *max)
1076078328daSJiri Kosina {
1077078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
1078078328daSJiri Kosina 
1079078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1080078328daSJiri Kosina 		return -1;
1081078328daSJiri Kosina 
1082078328daSJiri Kosina 	switch (usage->collection_index) {
1083078328daSJiri Kosina 	case 1:
1084078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
1085078328daSJiri Kosina 			return -1;
1086078328daSJiri Kosina 
1087078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
1088078328daSJiri Kosina 		if (!key)
1089078328daSJiri Kosina 			return -1;
1090078328daSJiri Kosina 		break;
1091078328daSJiri Kosina 	case 2:
1092078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1093078328daSJiri Kosina 			return -1;
1094078328daSJiri Kosina 
1095078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1096078328daSJiri Kosina 		if (!key)
1097078328daSJiri Kosina 			return -1;
1098078328daSJiri Kosina 		break;
1099078328daSJiri Kosina 	default:
1100078328daSJiri Kosina 		return -1;
1101078328daSJiri Kosina 	}
1102078328daSJiri Kosina 
1103078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1104078328daSJiri Kosina 	return 1;
1105078328daSJiri Kosina }
1106078328daSJiri Kosina 
110773e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
110873e4008dSNikolai Kondrashov 		unsigned int *rsize)
1109cc6e0bbbSJiri Kosina {
1110cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1111cc6e0bbbSJiri Kosina 
111299d24902SFernando Luis Vázquez Cao 	/*
111399d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
111499d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
111599d24902SFernando Luis Vázquez Cao 	 */
111699d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
111799d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
111899d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
111999d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
112099d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
112199d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
112299d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1123a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
112499d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1125cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1126cc6e0bbbSJiri Kosina 	}
112761ab44beSSimon Wood 
1128ed19d8cfSFrank Praznik 	/*
1129ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1130ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1131ed19d8cfSFrank Praznik 	 * modified one.
1132ed19d8cfSFrank Praznik 	 */
1133ed19d8cfSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) {
1134ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1135ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1136ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1137d829674dSFrank Praznik 	} else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) {
1138d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1139d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1140d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1141ed19d8cfSFrank Praznik 	}
1142ed19d8cfSFrank Praznik 
1143c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1144c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1145078328daSJiri Kosina 
1146c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1147c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1148c5e0c1c4SFrank Praznik 
11494545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1150*b2723eb7SSimon Wood 		return navigation_fixup(hdev, rdesc, rsize);
11514545ee0aSSimon Wood 
1152078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1153078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1154078328daSJiri Kosina 
115573e4008dSNikolai Kondrashov 	return rdesc;
1156cc6e0bbbSJiri Kosina }
1157cc6e0bbbSJiri Kosina 
1158d902f472SFrank Praznik static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
1159d902f472SFrank Praznik {
1160d902f472SFrank Praznik 	static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1161d902f472SFrank Praznik 	unsigned long flags;
116212e9a6d7SSimon Wood 	int offset;
1163d902f472SFrank Praznik 	__u8 cable_state, battery_capacity, battery_charging;
1164d902f472SFrank Praznik 
1165ad142b9eSFrank Praznik 	/*
1166ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1167d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1168d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1169d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1170d902f472SFrank Praznik 	 */
117112e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
117212e9a6d7SSimon Wood 
117312e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1174d902f472SFrank Praznik 		battery_capacity = 100;
117512e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
11769fddd74aSFrank Praznik 		cable_state = 1;
1177d902f472SFrank Praznik 	} else {
117812e9a6d7SSimon Wood 		__u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1179ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1180d902f472SFrank Praznik 		battery_charging = 0;
11819fddd74aSFrank Praznik 		cable_state = 0;
1182d902f472SFrank Praznik 	}
1183d902f472SFrank Praznik 
1184d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1185d902f472SFrank Praznik 	sc->cable_state = cable_state;
1186d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1187d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1188d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1189d902f472SFrank Praznik }
1190d902f472SFrank Praznik 
1191d902f472SFrank Praznik static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
1192d902f472SFrank Praznik {
1193e5606230SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1194e5606230SFrank Praznik 						struct hid_input, list);
1195e5606230SFrank Praznik 	struct input_dev *input_dev = hidinput->input;
1196d902f472SFrank Praznik 	unsigned long flags;
11976c5f860dSFrank Praznik 	int n, offset;
1198d902f472SFrank Praznik 	__u8 cable_state, battery_capacity, battery_charging;
1199d902f472SFrank Praznik 
1200ad142b9eSFrank Praznik 	/*
1201ad142b9eSFrank Praznik 	 * Battery and touchpad data starts at byte 30 in the USB report and
12026c5f860dSFrank Praznik 	 * 32 in Bluetooth report.
12036c5f860dSFrank Praznik 	 */
12046c5f860dSFrank Praznik 	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
12056c5f860dSFrank Praznik 
1206ad142b9eSFrank Praznik 	/*
1207ad142b9eSFrank Praznik 	 * The lower 4 bits of byte 30 contain the battery level
1208d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1209d902f472SFrank Praznik 	 */
12106c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
12116c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1212d902f472SFrank Praznik 
1213ad142b9eSFrank Praznik 	/*
1214ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
12156c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
12166c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1217d902f472SFrank Praznik 	 */
12186c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1219d902f472SFrank Praznik 		battery_charging = 0;
1220d902f472SFrank Praznik 	else
1221d902f472SFrank Praznik 		battery_charging = 1;
1222d902f472SFrank Praznik 
12236c5f860dSFrank Praznik 	if (!cable_state)
12246c5f860dSFrank Praznik 		battery_capacity++;
1225d902f472SFrank Praznik 	if (battery_capacity > 10)
12266c5f860dSFrank Praznik 		battery_capacity = 10;
12276c5f860dSFrank Praznik 
1228d902f472SFrank Praznik 	battery_capacity *= 10;
1229d902f472SFrank Praznik 
1230d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1231d902f472SFrank Praznik 	sc->cable_state = cable_state;
1232d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1233d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1234d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1235e5606230SFrank Praznik 
12366c5f860dSFrank Praznik 	offset += 5;
12376c5f860dSFrank Praznik 
1238ad142b9eSFrank Praznik 	/*
1239ad142b9eSFrank Praznik 	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
12406c5f860dSFrank Praznik 	 * and 37 on Bluetooth.
1241e5606230SFrank Praznik 	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
1242e5606230SFrank Praznik 	 * indicator that is 0 when pressed and 1 when not pressed.
1243e5606230SFrank Praznik 	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1244e5606230SFrank Praznik 	 * The data for the second touch is in the same format and immediatly
1245e5606230SFrank Praznik 	 * follows the data for the first.
1246e5606230SFrank Praznik 	 */
1247e5606230SFrank Praznik 	for (n = 0; n < 2; n++) {
1248e5606230SFrank Praznik 		__u16 x, y;
1249e5606230SFrank Praznik 
1250e5606230SFrank Praznik 		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1251e5606230SFrank Praznik 		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1252e5606230SFrank Praznik 
1253e5606230SFrank Praznik 		input_mt_slot(input_dev, n);
1254e5606230SFrank Praznik 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
1255e5606230SFrank Praznik 					!(rd[offset] >> 7));
1256e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
1257e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
1258e5606230SFrank Praznik 
1259e5606230SFrank Praznik 		offset += 4;
1260e5606230SFrank Praznik 	}
1261d902f472SFrank Praznik }
1262d902f472SFrank Praznik 
1263c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
1264c9e4d877SSimon Wood 		__u8 *rd, int size)
1265c9e4d877SSimon Wood {
1266c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1267c9e4d877SSimon Wood 
1268ad142b9eSFrank Praznik 	/*
1269ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1270c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1271c9e4d877SSimon Wood 	 */
1272fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
1273c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1274c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1275c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1276c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1277d902f472SFrank Praznik 
1278d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
127912e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
128012e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
12814545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
12824545ee0aSSimon Wood 			size == 49) {
12834545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
128468330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
128568330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
128668330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
1287d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1288c9e4d877SSimon Wood 	}
1289c9e4d877SSimon Wood 
1290c9e4d877SSimon Wood 	return 0;
1291c9e4d877SSimon Wood }
1292c9e4d877SSimon Wood 
1293f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1294f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1295f04d5140SColin Leitner 			unsigned long **bit, int *max)
1296f04d5140SColin Leitner {
1297f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1298f04d5140SColin Leitner 
1299f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1300f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1301f04d5140SColin Leitner 
1302f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1303f04d5140SColin Leitner 			return -1;
1304f04d5140SColin Leitner 
1305f04d5140SColin Leitner 		switch (usage->collection_index) {
1306f04d5140SColin Leitner 		case 1:
1307f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1308f04d5140SColin Leitner 				return -1;
1309f04d5140SColin Leitner 
1310f04d5140SColin Leitner 			key = buzz_keymap[key];
1311f04d5140SColin Leitner 			if (!key)
1312f04d5140SColin Leitner 				return -1;
1313f04d5140SColin Leitner 			break;
1314f04d5140SColin Leitner 		default:
1315f04d5140SColin Leitner 			return -1;
1316f04d5140SColin Leitner 		}
1317f04d5140SColin Leitner 
1318f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1319f04d5140SColin Leitner 		return 1;
1320f04d5140SColin Leitner 	}
1321f04d5140SColin Leitner 
1322078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1323078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1324078328daSJiri Kosina 
13256f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
13266f498018SBenjamin Tissoires 	return 0;
1327f04d5140SColin Leitner }
1328f04d5140SColin Leitner 
1329ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count,
1330ce8efc3bSFrank Praznik 					int w, int h)
1331ce8efc3bSFrank Praznik {
1332ce8efc3bSFrank Praznik 	struct input_dev *input_dev = hi->input;
1333ce8efc3bSFrank Praznik 	int ret;
1334ce8efc3bSFrank Praznik 
1335ce8efc3bSFrank Praznik 	ret = input_mt_init_slots(input_dev, touch_count, 0);
1336ce8efc3bSFrank Praznik 	if (ret < 0)
1337ce8efc3bSFrank Praznik 		return ret;
1338ce8efc3bSFrank Praznik 
1339ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
1340ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
1341ce8efc3bSFrank Praznik 
1342ce8efc3bSFrank Praznik 	return 0;
1343ce8efc3bSFrank Praznik }
1344ce8efc3bSFrank Praznik 
1345ce8efc3bSFrank Praznik static void sony_input_configured(struct hid_device *hdev,
1346ce8efc3bSFrank Praznik 					struct hid_input *hidinput)
1347ce8efc3bSFrank Praznik {
1348ce8efc3bSFrank Praznik 	struct sony_sc *sc = hid_get_drvdata(hdev);
1349ce8efc3bSFrank Praznik 
1350ce8efc3bSFrank Praznik 	/*
1351ce8efc3bSFrank Praznik 	 * The Dualshock 4 touchpad supports 2 touches and has a
1352981c5b4aSFrank Praznik 	 * resolution of 1920x942 (44.86 dots/mm).
1353ce8efc3bSFrank Praznik 	 */
1354ce8efc3bSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1355981c5b4aSFrank Praznik 		if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0)
1356ce8efc3bSFrank Praznik 			hid_err(sc->hdev,
1357ce8efc3bSFrank Praznik 				"Unable to initialize multi-touch slots\n");
1358ce8efc3bSFrank Praznik 	}
1359ce8efc3bSFrank Praznik }
1360ce8efc3bSFrank Praznik 
13615710fabfSAntonio Ospite /*
1362bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1363bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1364bd28ce00SJiri Slaby  * events.
1365bd28ce00SJiri Slaby  */
1366816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1367bd28ce00SJiri Slaby {
1368a85d67b5SAntonio Ospite 	const int buf_size =
1369a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
13702e701a35SAntonio Ospite 	__u8 *buf;
1371bd28ce00SJiri Slaby 	int ret;
1372bd28ce00SJiri Slaby 
13732e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1374bd28ce00SJiri Slaby 	if (!buf)
1375bd28ce00SJiri Slaby 		return -ENOMEM;
1376bd28ce00SJiri Slaby 
1377a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1378a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1379a7de9b86SLauri Kasanen 	if (ret < 0) {
1380a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1381a7de9b86SLauri Kasanen 		goto out;
1382a7de9b86SLauri Kasanen 	}
1383f204828aSBenjamin Tissoires 
1384a7de9b86SLauri Kasanen 	/*
1385a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1386a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1387a7de9b86SLauri Kasanen 	 */
1388a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1389a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1390a7de9b86SLauri Kasanen 	if (ret < 0) {
1391a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1392a7de9b86SLauri Kasanen 		goto out;
1393a7de9b86SLauri Kasanen 	}
1394a7de9b86SLauri Kasanen 
1395a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
1396bd28ce00SJiri Slaby 	if (ret < 0)
1397a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 3\n");
1398bd28ce00SJiri Slaby 
1399a7de9b86SLauri Kasanen out:
1400bd28ce00SJiri Slaby 	kfree(buf);
1401bd28ce00SJiri Slaby 
1402bd28ce00SJiri Slaby 	return ret;
1403bd28ce00SJiri Slaby }
1404bd28ce00SJiri Slaby 
1405816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1406f9ce7c28SBastien Nocera {
14079b2b5c9aSFrank Praznik 	static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
14089b2b5c9aSFrank Praznik 	__u8 *buf;
14099b2b5c9aSFrank Praznik 	int ret;
14109b2b5c9aSFrank Praznik 
14119b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
14129b2b5c9aSFrank Praznik 	if (!buf)
14139b2b5c9aSFrank Praznik 		return -ENOMEM;
14149b2b5c9aSFrank Praznik 
14159b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1416b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
14179b2b5c9aSFrank Praznik 
14189b2b5c9aSFrank Praznik 	kfree(buf);
14199b2b5c9aSFrank Praznik 
14209b2b5c9aSFrank Praznik 	return ret;
1421f9ce7c28SBastien Nocera }
1422f9ce7c28SBastien Nocera 
1423ad142b9eSFrank Praznik /*
1424ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
142568330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
142668330d83SFrank Praznik  */
142768330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
142868330d83SFrank Praznik {
14299b2b5c9aSFrank Praznik 	__u8 *buf;
14309b2b5c9aSFrank Praznik 	int ret;
143168330d83SFrank Praznik 
14329b2b5c9aSFrank Praznik 	buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);
14339b2b5c9aSFrank Praznik 	if (!buf)
14349b2b5c9aSFrank Praznik 		return -ENOMEM;
14359b2b5c9aSFrank Praznik 
14369b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,
143768330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
14389b2b5c9aSFrank Praznik 
14399b2b5c9aSFrank Praznik 	kfree(buf);
14409b2b5c9aSFrank Praznik 
14419b2b5c9aSFrank Praznik 	return ret;
1442bd28ce00SJiri Slaby }
1443bd28ce00SJiri Slaby 
1444221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
14458025087aSFrank Praznik {
14468025087aSFrank Praznik 	static const __u8 sixaxis_leds[10][4] = {
14478025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
14488025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
14498025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
14508025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
14518025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
14528025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
14538025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
14548025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
14558025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
14568025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
14578025087aSFrank Praznik 	};
14588025087aSFrank Praznik 
1459221399b3SFrank Praznik 	int id = sc->device_id;
1460221399b3SFrank Praznik 
1461221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
14628025087aSFrank Praznik 
14638025087aSFrank Praznik 	if (id < 0)
14648025087aSFrank Praznik 		return;
14658025087aSFrank Praznik 
14668025087aSFrank Praznik 	id %= 10;
1467221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
14688025087aSFrank Praznik }
14698025087aSFrank Praznik 
1470221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
14718025087aSFrank Praznik {
14728025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
14738025087aSFrank Praznik 	static const __u8 color_code[7][3] = {
14748025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
14758025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
14768025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
14778025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
14788025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
14798025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
14808025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
14818025087aSFrank Praznik 	};
14828025087aSFrank Praznik 
1483221399b3SFrank Praznik 	int id = sc->device_id;
1484221399b3SFrank Praznik 
1485221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
14868025087aSFrank Praznik 
14878025087aSFrank Praznik 	if (id < 0)
14888025087aSFrank Praznik 		return;
14898025087aSFrank Praznik 
14908025087aSFrank Praznik 	id %= 7;
1491221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
14928025087aSFrank Praznik }
14938025087aSFrank Praznik 
1494221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1495f04d5140SColin Leitner {
1496221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1497f04d5140SColin Leitner 	struct list_head *report_list =
1498f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1499f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1500f04d5140SColin Leitner 		struct hid_report, list);
1501f04d5140SColin Leitner 	__s32 *value = report->field[0]->value;
1502f04d5140SColin Leitner 
1503221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1504221399b3SFrank Praznik 
1505f04d5140SColin Leitner 	value[0] = 0x00;
1506221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1507221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1508221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1509221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1510f04d5140SColin Leitner 	value[5] = 0x00;
1511f04d5140SColin Leitner 	value[6] = 0x00;
1512f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1513f04d5140SColin Leitner }
1514f04d5140SColin Leitner 
1515221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
15160a286ef2SSven Eckelmann {
1517221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
1518fa57a810SFrank Praznik 		schedule_work(&sc->state_worker);
1519221399b3SFrank Praznik 	else
1520221399b3SFrank Praznik 		buzz_set_leds(sc);
15210a286ef2SSven Eckelmann }
15220a286ef2SSven Eckelmann 
1523c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1524f04d5140SColin Leitner 				    enum led_brightness value)
1525f04d5140SColin Leitner {
1526f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1527f04d5140SColin Leitner 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1528f04d5140SColin Leitner 	struct sony_sc *drv_data;
1529f04d5140SColin Leitner 
1530f04d5140SColin Leitner 	int n;
1531b3ed458cSFrank Praznik 	int force_update;
1532f04d5140SColin Leitner 
1533f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
15342251b85fSSven Eckelmann 	if (!drv_data) {
1535f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1536f04d5140SColin Leitner 		return;
1537f04d5140SColin Leitner 	}
1538f04d5140SColin Leitner 
1539b3ed458cSFrank Praznik 	/*
1540b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1541b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1542b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1543b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1544b3ed458cSFrank Praznik 	 * stop the flashing later on.
1545b3ed458cSFrank Praznik 	 */
1546b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1547b3ed458cSFrank Praznik 
154860781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1549b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1550b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1551b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1552b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1553b3ed458cSFrank Praznik 
155460781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1555b3ed458cSFrank Praznik 
1556b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1557b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1558b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1559b3ed458cSFrank Praznik 
1560221399b3SFrank Praznik 			sony_set_leds(drv_data);
1561f04d5140SColin Leitner 			break;
1562f04d5140SColin Leitner 		}
1563f04d5140SColin Leitner 	}
1564f04d5140SColin Leitner }
1565f04d5140SColin Leitner 
1566c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1567f04d5140SColin Leitner {
1568f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1569f04d5140SColin Leitner 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1570f04d5140SColin Leitner 	struct sony_sc *drv_data;
1571f04d5140SColin Leitner 
1572f04d5140SColin Leitner 	int n;
1573f04d5140SColin Leitner 
1574f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
15752251b85fSSven Eckelmann 	if (!drv_data) {
1576f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1577f04d5140SColin Leitner 		return LED_OFF;
1578f04d5140SColin Leitner 	}
1579f04d5140SColin Leitner 
158060781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
15817db7504aSSimon Wood 		if (led == drv_data->leds[n])
15827db7504aSSimon Wood 			return drv_data->led_state[n];
1583f04d5140SColin Leitner 	}
1584f04d5140SColin Leitner 
15857db7504aSSimon Wood 	return LED_OFF;
1586f04d5140SColin Leitner }
1587f04d5140SColin Leitner 
1588b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1589b3ed458cSFrank Praznik 				unsigned long *delay_off)
1590b3ed458cSFrank Praznik {
1591b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1592b3ed458cSFrank Praznik 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1593b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1594b3ed458cSFrank Praznik 	int n;
1595b3ed458cSFrank Praznik 	__u8 new_on, new_off;
1596b3ed458cSFrank Praznik 
1597b3ed458cSFrank Praznik 	if (!drv_data) {
1598b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1599b3ed458cSFrank Praznik 		return -EINVAL;
1600b3ed458cSFrank Praznik 	}
1601b3ed458cSFrank Praznik 
1602b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1603b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1604b3ed458cSFrank Praznik 		*delay_on = 2550;
1605b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1606b3ed458cSFrank Praznik 		*delay_off = 2550;
1607b3ed458cSFrank Praznik 
1608b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1609b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1610b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1611b3ed458cSFrank Praznik 
1612b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1613b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1614b3ed458cSFrank Praznik 
1615b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1616b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1617b3ed458cSFrank Praznik 			break;
1618b3ed458cSFrank Praznik 	}
1619b3ed458cSFrank Praznik 
1620b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1621b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1622b3ed458cSFrank Praznik 		return -EINVAL;
1623b3ed458cSFrank Praznik 
1624b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1625b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1626b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1627b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1628b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
1629b3ed458cSFrank Praznik 		schedule_work(&drv_data->state_worker);
1630b3ed458cSFrank Praznik 	}
1631b3ed458cSFrank Praznik 
1632b3ed458cSFrank Praznik 	return 0;
1633b3ed458cSFrank Praznik }
1634b3ed458cSFrank Praznik 
1635fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
16360a286ef2SSven Eckelmann {
16370a286ef2SSven Eckelmann 	struct led_classdev *led;
16380a286ef2SSven Eckelmann 	int n;
16390a286ef2SSven Eckelmann 
1640fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
16410a286ef2SSven Eckelmann 
1642fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1643fa57a810SFrank Praznik 		led = sc->leds[n];
1644fa57a810SFrank Praznik 		sc->leds[n] = NULL;
16450a286ef2SSven Eckelmann 		if (!led)
16460a286ef2SSven Eckelmann 			continue;
16470a286ef2SSven Eckelmann 		led_classdev_unregister(led);
16480a286ef2SSven Eckelmann 		kfree(led);
16490a286ef2SSven Eckelmann 	}
165060781cf4SFrank Praznik 
1651fa57a810SFrank Praznik 	sc->led_count = 0;
16520a286ef2SSven Eckelmann }
16530a286ef2SSven Eckelmann 
1654fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1655f04d5140SColin Leitner {
1656fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
165740e32ee6SJiri Kosina 	int n, ret = 0;
1658b3ed458cSFrank Praznik 	int use_ds4_names;
165940e32ee6SJiri Kosina 	struct led_classdev *led;
166040e32ee6SJiri Kosina 	size_t name_sz;
166140e32ee6SJiri Kosina 	char *name;
16620a286ef2SSven Eckelmann 	size_t name_len;
16630a286ef2SSven Eckelmann 	const char *name_fmt;
1664b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1665b3ed458cSFrank Praznik 						  "global" };
16665607c89aSFrank Praznik 	__u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
1667b3ed458cSFrank Praznik 	__u8 use_hw_blink[MAX_LEDS] = { 0 };
1668f04d5140SColin Leitner 
1669fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1670f04d5140SColin Leitner 
1671fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1672fa57a810SFrank Praznik 		sc->led_count = 4;
1673b3ed458cSFrank Praznik 		use_ds4_names = 0;
16740a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
16750a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
16769446edb9SKees Cook 		/* Validate expected report characteristics. */
16779446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
16789446edb9SKees Cook 			return -ENODEV;
1679fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1680221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1681221399b3SFrank Praznik 		sc->led_state[3] = 1;
1682b3ed458cSFrank Praznik 		sc->led_count = 4;
1683b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1684b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1685b3ed458cSFrank Praznik 		use_ds4_names = 1;
168661ebca93SFrank Praznik 		name_len = 0;
168761ebca93SFrank Praznik 		name_fmt = "%s:%s";
1688c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1689c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1690c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1691c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1692c5e0c1c4SFrank Praznik 		name_len = 0;
1693c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
16944545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
16954545ee0aSSimon Wood 		static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
16964545ee0aSSimon Wood 
16974545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
16984545ee0aSSimon Wood 		sc->led_count = 1;
16994545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
17004545ee0aSSimon Wood 		use_ds4_names = 0;
17014545ee0aSSimon Wood 		name_len = strlen("::sony#");
17024545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
170360781cf4SFrank Praznik 	} else {
1704221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1705fa57a810SFrank Praznik 		sc->led_count = 4;
1706b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1707b3ed458cSFrank Praznik 		use_ds4_names = 0;
170861ebca93SFrank Praznik 		name_len = strlen("::sony#");
170961ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
171060781cf4SFrank Praznik 	}
171160781cf4SFrank Praznik 
1712ad142b9eSFrank Praznik 	/*
1713ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1714f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1715ad142b9eSFrank Praznik 	 * LEDs to on
1716ad142b9eSFrank Praznik 	 */
1717221399b3SFrank Praznik 	sony_set_leds(sc);
1718f04d5140SColin Leitner 
17190a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1720f04d5140SColin Leitner 
1721fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
172261ebca93SFrank Praznik 
1723b3ed458cSFrank Praznik 		if (use_ds4_names)
1724b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
172561ebca93SFrank Praznik 
1726f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1727f04d5140SColin Leitner 		if (!led) {
1728f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
17298cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1730f04d5140SColin Leitner 			goto error_leds;
1731f04d5140SColin Leitner 		}
1732f04d5140SColin Leitner 
1733f04d5140SColin Leitner 		name = (void *)(&led[1]);
1734b3ed458cSFrank Praznik 		if (use_ds4_names)
1735b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1736b3ed458cSFrank Praznik 			ds4_name_str[n]);
173761ebca93SFrank Praznik 		else
17380a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1739f04d5140SColin Leitner 		led->name = name;
1740221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1741b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1742c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1743c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1744f04d5140SColin Leitner 
1745b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1746b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1747b3ed458cSFrank Praznik 
17488025087aSFrank Praznik 		sc->leds[n] = led;
17498025087aSFrank Praznik 
17508cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
17518cd5fcdaSJulia Lawall 		if (ret) {
1752f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
17538025087aSFrank Praznik 			sc->leds[n] = NULL;
1754f04d5140SColin Leitner 			kfree(led);
1755f04d5140SColin Leitner 			goto error_leds;
1756f04d5140SColin Leitner 		}
1757f04d5140SColin Leitner 	}
1758f04d5140SColin Leitner 
1759f04d5140SColin Leitner 	return ret;
1760f04d5140SColin Leitner 
1761f04d5140SColin Leitner error_leds:
1762fa57a810SFrank Praznik 	sony_leds_remove(sc);
1763f04d5140SColin Leitner 
1764f04d5140SColin Leitner 	return ret;
1765f04d5140SColin Leitner }
1766f04d5140SColin Leitner 
1767cad665a2SFrank Praznik static void sixaxis_state_worker(struct work_struct *work)
1768a08c22c0SSven Eckelmann {
17699b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
177055d3b664SFrank Praznik 		.buf = {
1771a08c22c0SSven Eckelmann 			0x01,
1772a08c22c0SSven Eckelmann 			0x00, 0xff, 0x00, 0xff, 0x00,
17730a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1774a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1775a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1776a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1777a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1778a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
177955d3b664SFrank Praznik 		}
1780a08c22c0SSven Eckelmann 	};
17819b2b5c9aSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
17829b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
17839b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
17849b2b5c9aSFrank Praznik 	int n;
17859b2b5c9aSFrank Praznik 
17869b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
17879b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
17889f323b68SSven Eckelmann 
17890a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
17909b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
17919b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
17920a286ef2SSven Eckelmann #endif
17930a286ef2SSven Eckelmann 
17949b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
17959b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
17969b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
17979b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
17989f323b68SSven Eckelmann 
179988f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
18009b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
18019b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
180288f6576fSSimon Wood 
1803b3ed458cSFrank Praznik 	/*
1804b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
1805b3ed458cSFrank Praznik 	 * corresponding light on the controller.
1806b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
1807b3ed458cSFrank Praznik 	 *
1808b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
1809b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
1810b3ed458cSFrank Praznik 	 * always off.
1811b3ed458cSFrank Praznik 	 */
1812b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
1813b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
18149b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
18159b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
1816b3ed458cSFrank Praznik 		}
1817b3ed458cSFrank Praznik 	}
1818b3ed458cSFrank Praznik 
18199b2b5c9aSFrank Praznik 	hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report,
18209b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
18219b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18229f323b68SSven Eckelmann }
18239f323b68SSven Eckelmann 
18240bd88dd3SFrank Praznik static void dualshock4_state_worker(struct work_struct *work)
18250bd88dd3SFrank Praznik {
18260bd88dd3SFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
18270da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
18289b2b5c9aSFrank Praznik 	__u8 *buf = sc->output_report_dmabuf;
182948220237SFrank Praznik 	int offset;
18300da8ea65SFrank Praznik 
1831fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
18329b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x05_SIZE);
183348220237SFrank Praznik 		buf[0] = 0x05;
1834b3ed458cSFrank Praznik 		buf[1] = 0xFF;
183548220237SFrank Praznik 		offset = 4;
1836fdcf105dSFrank Praznik 	} else {
18379b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x11_SIZE);
1838fdcf105dSFrank Praznik 		buf[0] = 0x11;
1839fdcf105dSFrank Praznik 		buf[1] = 0xB0;
1840fdcf105dSFrank Praznik 		buf[3] = 0x0F;
1841fdcf105dSFrank Praznik 		offset = 6;
1842fdcf105dSFrank Praznik 	}
18430bd88dd3SFrank Praznik 
18440bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
184548220237SFrank Praznik 	buf[offset++] = sc->right;
184648220237SFrank Praznik 	buf[offset++] = sc->left;
184748220237SFrank Praznik #else
184848220237SFrank Praznik 	offset += 2;
18490bd88dd3SFrank Praznik #endif
18500bd88dd3SFrank Praznik 
1851b3ed458cSFrank Praznik 	/* LED 3 is the global control */
1852b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
185348220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
185448220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
185548220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
1856b3ed458cSFrank Praznik 	} else {
1857b3ed458cSFrank Praznik 		offset += 3;
1858b3ed458cSFrank Praznik 	}
1859b3ed458cSFrank Praznik 
1860b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
1861b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
1862b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
186360781cf4SFrank Praznik 
1864fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
18659b2b5c9aSFrank Praznik 		hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);
1866fdcf105dSFrank Praznik 	else
18679b2b5c9aSFrank Praznik 		hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,
1868fdcf105dSFrank Praznik 				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18690bd88dd3SFrank Praznik }
18700bd88dd3SFrank Praznik 
1871c5e0c1c4SFrank Praznik static void motion_state_worker(struct work_struct *work)
1872c5e0c1c4SFrank Praznik {
1873c5e0c1c4SFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1874c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1875c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
1876c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
1877c5e0c1c4SFrank Praznik 
187841d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
1879c5e0c1c4SFrank Praznik 
1880c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
1881c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
1882c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
1883c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
1884c5e0c1c4SFrank Praznik 
1885c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1886c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
1887c5e0c1c4SFrank Praznik #endif
1888c5e0c1c4SFrank Praznik 
188941d2d425SSimon Wood 	hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
1890c5e0c1c4SFrank Praznik }
1891c5e0c1c4SFrank Praznik 
18929b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
18939b2b5c9aSFrank Praznik {
18944545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
18954545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
18969b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
18979b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
18989b2b5c9aSFrank Praznik 				GFP_KERNEL);
18999b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
19009b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,
19019b2b5c9aSFrank Praznik 						GFP_KERNEL);
19029b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
19039b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
19049b2b5c9aSFrank Praznik 						GFP_KERNEL);
1905c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
190641d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
1907c5e0c1c4SFrank Praznik 						GFP_KERNEL);
19089b2b5c9aSFrank Praznik 	else
19099b2b5c9aSFrank Praznik 		return 0;
19109b2b5c9aSFrank Praznik 
19119b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
19129b2b5c9aSFrank Praznik 		return -ENOMEM;
19139b2b5c9aSFrank Praznik 
19149b2b5c9aSFrank Praznik 	return 0;
19159b2b5c9aSFrank Praznik }
19169b2b5c9aSFrank Praznik 
19170a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
19189f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
19199f323b68SSven Eckelmann 			    struct ff_effect *effect)
19209f323b68SSven Eckelmann {
1921a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
19229f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
1923a08c22c0SSven Eckelmann 
1924a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
1925a08c22c0SSven Eckelmann 		return 0;
1926a08c22c0SSven Eckelmann 
19279f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
19280bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
1929a08c22c0SSven Eckelmann 
193092b5c411SSven Eckelmann 	schedule_work(&sc->state_worker);
19319f323b68SSven Eckelmann 	return 0;
1932a08c22c0SSven Eckelmann }
1933a08c22c0SSven Eckelmann 
1934fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1935a08c22c0SSven Eckelmann {
1936fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1937a08c22c0SSven Eckelmann 						struct hid_input, list);
1938a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
1939a08c22c0SSven Eckelmann 
1940a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
1941a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
1942a08c22c0SSven Eckelmann }
1943a08c22c0SSven Eckelmann 
1944a08c22c0SSven Eckelmann #else
1945fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1946a08c22c0SSven Eckelmann {
1947a08c22c0SSven Eckelmann 	return 0;
1948a08c22c0SSven Eckelmann }
19499f323b68SSven Eckelmann 
1950a08c22c0SSven Eckelmann #endif
1951a08c22c0SSven Eckelmann 
1952d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
1953d902f472SFrank Praznik 				     enum power_supply_property psp,
1954d902f472SFrank Praznik 				     union power_supply_propval *val)
1955c4e1ddf2SFrank Praznik {
1956297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
1957d902f472SFrank Praznik 	unsigned long flags;
1958d902f472SFrank Praznik 	int ret = 0;
1959d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
1960c4e1ddf2SFrank Praznik 
1961d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1962d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
1963d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
1964d902f472SFrank Praznik 	cable_state = sc->cable_state;
1965d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1966c4e1ddf2SFrank Praznik 
1967d902f472SFrank Praznik 	switch (psp) {
1968d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
1969d902f472SFrank Praznik 		val->intval = 1;
1970d902f472SFrank Praznik 		break;
1971d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
1972d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
1973d902f472SFrank Praznik 		break;
1974d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
1975d902f472SFrank Praznik 		val->intval = battery_capacity;
1976d902f472SFrank Praznik 		break;
1977d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
1978d902f472SFrank Praznik 		if (battery_charging)
1979d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
1980d902f472SFrank Praznik 		else
1981d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
1982d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
1983d902f472SFrank Praznik 			else
1984d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
1985d902f472SFrank Praznik 		break;
1986d902f472SFrank Praznik 	default:
1987d902f472SFrank Praznik 		ret = -EINVAL;
1988d902f472SFrank Praznik 		break;
1989c4e1ddf2SFrank Praznik 	}
1990d902f472SFrank Praznik 	return ret;
1991d902f472SFrank Praznik }
1992d902f472SFrank Praznik 
1993d902f472SFrank Praznik static int sony_battery_probe(struct sony_sc *sc)
1994d902f472SFrank Praznik {
1995297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
1996d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1997d902f472SFrank Praznik 	int ret;
1998d902f472SFrank Praznik 
1999ad142b9eSFrank Praznik 	/*
2000ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
2001d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
2002d9a293a9SFrank Praznik 	 */
2003d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
2004d9a293a9SFrank Praznik 
2005297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
2006297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
2007297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
2008297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2009297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
2010297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = kasprintf(GFP_KERNEL,
2011297d716fSKrzysztof Kozlowski 					  "sony_controller_battery_%pMR",
2012314531f1SFrank Praznik 					  sc->mac_address);
2013297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2014d902f472SFrank Praznik 		return -ENOMEM;
2015d902f472SFrank Praznik 
2016297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
2017297d716fSKrzysztof Kozlowski 					    &psy_cfg);
2018297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
2019297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
2020d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
2021d902f472SFrank Praznik 		goto err_free;
2022d902f472SFrank Praznik 	}
2023d902f472SFrank Praznik 
2024297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
2025d902f472SFrank Praznik 	return 0;
2026d902f472SFrank Praznik 
2027d902f472SFrank Praznik err_free:
2028297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2029297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2030d902f472SFrank Praznik 	return ret;
2031d902f472SFrank Praznik }
2032d902f472SFrank Praznik 
2033d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
2034d902f472SFrank Praznik {
2035297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2036d902f472SFrank Praznik 		return;
2037d902f472SFrank Praznik 
2038297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
2039297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2040297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2041d902f472SFrank Praznik }
2042d902f472SFrank Praznik 
2043d2d782fcSFrank Praznik /*
2044d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
2045d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
2046d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
2047d2d782fcSFrank Praznik  * once.
2048d2d782fcSFrank Praznik  */
2049d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
2050d2d782fcSFrank Praznik {
2051d2d782fcSFrank Praznik 	struct sony_sc *entry;
2052d2d782fcSFrank Praznik 	unsigned long flags;
2053d2d782fcSFrank Praznik 	int ret;
2054d2d782fcSFrank Praznik 
2055d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
2056d2d782fcSFrank Praznik 
2057d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
2058d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
2059d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
2060d2d782fcSFrank Praznik 		if (!ret) {
2061d2d782fcSFrank Praznik 			ret = -EEXIST;
2062d2d782fcSFrank Praznik 			hid_info(sc->hdev, "controller with MAC address %pMR already connected\n",
2063d2d782fcSFrank Praznik 				sc->mac_address);
2064d2d782fcSFrank Praznik 			goto unlock;
2065d2d782fcSFrank Praznik 		}
2066c4e1ddf2SFrank Praznik 	}
2067c4e1ddf2SFrank Praznik 
2068d2d782fcSFrank Praznik 	ret = 0;
2069d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
2070c4e1ddf2SFrank Praznik 
2071d2d782fcSFrank Praznik unlock:
2072d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2073d2d782fcSFrank Praznik 	return ret;
2074d2d782fcSFrank Praznik }
2075d2d782fcSFrank Praznik 
2076d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
2077d2d782fcSFrank Praznik {
2078d2d782fcSFrank Praznik 	unsigned long flags;
2079d2d782fcSFrank Praznik 
2080d2d782fcSFrank Praznik 	if (sc->list_node.next) {
2081d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
2082d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
2083d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2084d2d782fcSFrank Praznik 	}
2085d2d782fcSFrank Praznik }
2086d2d782fcSFrank Praznik 
2087d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
2088d2d782fcSFrank Praznik {
2089d2d782fcSFrank Praznik 	int ret;
2090d2d782fcSFrank Praznik 
2091d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2092d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2093d2d782fcSFrank Praznik 	if (ret != 17)
2094c4e1ddf2SFrank Praznik 		return -EINVAL;
2095d2d782fcSFrank Praznik 
2096d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2097d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2098d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2099d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2100d2d782fcSFrank Praznik 
2101d2d782fcSFrank Praznik 	if (ret != 6)
2102d2d782fcSFrank Praznik 		return -EINVAL;
2103d2d782fcSFrank Praznik 
2104d2d782fcSFrank Praznik 	return 0;
2105c4e1ddf2SFrank Praznik }
2106c4e1ddf2SFrank Praznik 
2107d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2108d2d782fcSFrank Praznik {
21099b2b5c9aSFrank Praznik 	__u8 *buf = NULL;
2110d2d782fcSFrank Praznik 	int n, ret;
2111d2d782fcSFrank Praznik 
2112d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
211312e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
21144545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2115d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2116d2d782fcSFrank Praznik 		/*
2117d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2118d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2119d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2120d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2121d2d782fcSFrank Praznik 		 */
2122d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2123d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2124d2d782fcSFrank Praznik 			return 0;
2125d2d782fcSFrank Praznik 		}
2126d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
21279b2b5c9aSFrank Praznik 		buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);
21289b2b5c9aSFrank Praznik 		if (!buf)
21299b2b5c9aSFrank Praznik 			return -ENOMEM;
2130d2d782fcSFrank Praznik 
2131d2d782fcSFrank Praznik 		/*
2132d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2133d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2134d2d782fcSFrank Praznik 		 * offset 1.
2135d2d782fcSFrank Praznik 		 */
21369b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
21379b2b5c9aSFrank Praznik 				DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
21389b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2139d2d782fcSFrank Praznik 
21409b2b5c9aSFrank Praznik 		if (ret != DS4_REPORT_0x81_SIZE) {
2141d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
21429b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
21439b2b5c9aSFrank Praznik 			goto out_free;
2144d2d782fcSFrank Praznik 		}
2145d2d782fcSFrank Praznik 
2146d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
21474545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
21484545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
21499b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
21509b2b5c9aSFrank Praznik 		if (!buf)
21519b2b5c9aSFrank Praznik 			return -ENOMEM;
2152d2d782fcSFrank Praznik 
2153d2d782fcSFrank Praznik 		/*
2154d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2155d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2156d2d782fcSFrank Praznik 		 * offset 4.
2157d2d782fcSFrank Praznik 		 */
21589b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
21599b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
21609b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2161d2d782fcSFrank Praznik 
21629b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2163d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
21649b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
21659b2b5c9aSFrank Praznik 			goto out_free;
2166d2d782fcSFrank Praznik 		}
2167d2d782fcSFrank Praznik 
2168d2d782fcSFrank Praznik 		/*
2169d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2170d2d782fcSFrank Praznik 		 * be byte-swapped.
2171d2d782fcSFrank Praznik 		 */
2172d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2173d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2174d2d782fcSFrank Praznik 	} else {
2175d2d782fcSFrank Praznik 		return 0;
2176d2d782fcSFrank Praznik 	}
2177d2d782fcSFrank Praznik 
21789b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
21799b2b5c9aSFrank Praznik 
21809b2b5c9aSFrank Praznik out_free:
21819b2b5c9aSFrank Praznik 
21829b2b5c9aSFrank Praznik 	kfree(buf);
21839b2b5c9aSFrank Praznik 
21849b2b5c9aSFrank Praznik 	return ret;
2185d2d782fcSFrank Praznik }
2186d2d782fcSFrank Praznik 
21878025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
21888025087aSFrank Praznik {
21898025087aSFrank Praznik 	int ret;
21908025087aSFrank Praznik 
21918025087aSFrank Praznik 	/*
21928025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
21938025087aSFrank Praznik 	 * All others are set to -1.
21948025087aSFrank Praznik 	 */
21958025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
21968025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
21978025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
21988025087aSFrank Praznik 					GFP_KERNEL);
21998025087aSFrank Praznik 		if (ret < 0) {
22008025087aSFrank Praznik 			sc->device_id = -1;
22018025087aSFrank Praznik 			return ret;
22028025087aSFrank Praznik 		}
22038025087aSFrank Praznik 		sc->device_id = ret;
22048025087aSFrank Praznik 	} else {
22058025087aSFrank Praznik 		sc->device_id = -1;
22068025087aSFrank Praznik 	}
22078025087aSFrank Praznik 
22088025087aSFrank Praznik 	return 0;
22098025087aSFrank Praznik }
22108025087aSFrank Praznik 
22118025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
22128025087aSFrank Praznik {
22138025087aSFrank Praznik 	if (sc->device_id >= 0) {
22148025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
22158025087aSFrank Praznik 		sc->device_id = -1;
22168025087aSFrank Praznik 	}
22178025087aSFrank Praznik }
22188025087aSFrank Praznik 
221946262047SFrank Praznik static inline void sony_init_work(struct sony_sc *sc,
222046262047SFrank Praznik 					void (*worker)(struct work_struct *))
222146262047SFrank Praznik {
222246262047SFrank Praznik 	if (!sc->worker_initialized)
222346262047SFrank Praznik 		INIT_WORK(&sc->state_worker, worker);
222446262047SFrank Praznik 
222546262047SFrank Praznik 	sc->worker_initialized = 1;
222646262047SFrank Praznik }
222746262047SFrank Praznik 
222846262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
222946262047SFrank Praznik {
223046262047SFrank Praznik 	if (sc->worker_initialized)
223146262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
223246262047SFrank Praznik }
2233d2d782fcSFrank Praznik 
2234bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2235bd28ce00SJiri Slaby {
2236bd28ce00SJiri Slaby 	int ret;
2237cc6e0bbbSJiri Kosina 	unsigned long quirks = id->driver_data;
2238cc6e0bbbSJiri Kosina 	struct sony_sc *sc;
2239f04d5140SColin Leitner 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2240cc6e0bbbSJiri Kosina 
2241abf832bfSBenjamin Tissoires 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2242cc6e0bbbSJiri Kosina 	if (sc == NULL) {
22434291ee30SJoe Perches 		hid_err(hdev, "can't alloc sony descriptor\n");
2244cc6e0bbbSJiri Kosina 		return -ENOMEM;
2245cc6e0bbbSJiri Kosina 	}
2246cc6e0bbbSJiri Kosina 
2247b94993f6SFrank Praznik 	spin_lock_init(&sc->lock);
2248b94993f6SFrank Praznik 
2249cc6e0bbbSJiri Kosina 	sc->quirks = quirks;
2250cc6e0bbbSJiri Kosina 	hid_set_drvdata(hdev, sc);
22510a286ef2SSven Eckelmann 	sc->hdev = hdev;
2252bd28ce00SJiri Slaby 
2253bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
2254bd28ce00SJiri Slaby 	if (ret) {
22554291ee30SJoe Perches 		hid_err(hdev, "parse failed\n");
2256abf832bfSBenjamin Tissoires 		return ret;
2257bd28ce00SJiri Slaby 	}
2258bd28ce00SJiri Slaby 
2259f04d5140SColin Leitner 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2260f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
226150764650SAntonio Ospite 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2262f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2263f04d5140SColin Leitner 
2264f04d5140SColin Leitner 	ret = hid_hw_start(hdev, connect_mask);
2265bd28ce00SJiri Slaby 	if (ret) {
22664291ee30SJoe Perches 		hid_err(hdev, "hw start failed\n");
2267abf832bfSBenjamin Tissoires 		return ret;
2268bd28ce00SJiri Slaby 	}
2269bd28ce00SJiri Slaby 
22708025087aSFrank Praznik 	ret = sony_set_device_id(sc);
22718025087aSFrank Praznik 	if (ret < 0) {
22728025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
22738025087aSFrank Praznik 		goto err_stop;
22748025087aSFrank Praznik 	}
22758025087aSFrank Praznik 
2276131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2277131a8a9aSFrank Praznik 	if (ret < 0) {
2278131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2279131a8a9aSFrank Praznik 		goto err_stop;
2280131a8a9aSFrank Praznik 	}
2281131a8a9aSFrank Praznik 
22824545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
22834545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2284e534a935SBenjamin Tissoires 		/*
2285e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2286e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2287e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2288e534a935SBenjamin Tissoires 		 *
2289e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2290e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2291e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2292e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
2293e534a935SBenjamin Tissoires 		 */
2294e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2295e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
2296816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
229746262047SFrank Praznik 		sony_init_work(sc, sixaxis_state_worker);
22984545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
22994545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
23002078b9bbSFrank Praznik 		/*
23012078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
23022078b9bbSFrank Praznik 		 * when connected via Bluetooth.
23032078b9bbSFrank Praznik 		 */
23042078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2305816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
230646262047SFrank Praznik 		sony_init_work(sc, sixaxis_state_worker);
2307fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
230868330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
23092078b9bbSFrank Praznik 			/*
23102078b9bbSFrank Praznik 			 * The DualShock 4 wants output reports sent on the ctrl
23112078b9bbSFrank Praznik 			 * endpoint when connected via Bluetooth.
23122078b9bbSFrank Praznik 			 */
23132078b9bbSFrank Praznik 			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
231468330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
231568330d83SFrank Praznik 			if (ret < 0) {
231668330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
231768330d83SFrank Praznik 				goto err_stop;
231868330d83SFrank Praznik 			}
231968330d83SFrank Praznik 		}
2320c4e1ddf2SFrank Praznik 
232146262047SFrank Praznik 		sony_init_work(sc, dualshock4_state_worker);
2322c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2323c5e0c1c4SFrank Praznik 		sony_init_work(sc, motion_state_worker);
23240bd88dd3SFrank Praznik 	} else {
23250bd88dd3SFrank Praznik 		ret = 0;
23260bd88dd3SFrank Praznik 	}
2327f9ce7c28SBastien Nocera 
23284dfdc464SJiri Kosina 	if (ret < 0)
2329bd28ce00SJiri Slaby 		goto err_stop;
2330bd28ce00SJiri Slaby 
2331d2d782fcSFrank Praznik 	ret = sony_check_add(sc);
2332d2d782fcSFrank Praznik 	if (ret < 0)
2333d2d782fcSFrank Praznik 		goto err_stop;
2334d2d782fcSFrank Praznik 
23350a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2336fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
23370a286ef2SSven Eckelmann 		if (ret < 0)
23380a286ef2SSven Eckelmann 			goto err_stop;
23390a286ef2SSven Eckelmann 	}
23400a286ef2SSven Eckelmann 
2341d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2342d902f472SFrank Praznik 		ret = sony_battery_probe(sc);
2343a08c22c0SSven Eckelmann 		if (ret < 0)
2344a08c22c0SSven Eckelmann 			goto err_stop;
2345a08c22c0SSven Eckelmann 
2346d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2347d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2348d902f472SFrank Praznik 		if (ret < 0) {
2349d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2350d902f472SFrank Praznik 			goto err_stop;
2351d902f472SFrank Praznik 		}
2352d902f472SFrank Praznik 	}
2353d902f472SFrank Praznik 
2354c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2355fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2356d902f472SFrank Praznik 		if (ret < 0)
2357d902f472SFrank Praznik 			goto err_close;
23585f5750d2SFrank Praznik 	}
2359bd28ce00SJiri Slaby 
2360f425458eSH Hartley Sweeten 	return 0;
2361d902f472SFrank Praznik err_close:
2362d902f472SFrank Praznik 	hid_hw_close(hdev);
2363bd28ce00SJiri Slaby err_stop:
23640a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2365fa57a810SFrank Praznik 		sony_leds_remove(sc);
2366d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2367d902f472SFrank Praznik 		sony_battery_remove(sc);
236846262047SFrank Praznik 	sony_cancel_work_sync(sc);
23699b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2370d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
23718025087aSFrank Praznik 	sony_release_device_id(sc);
2372bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2373bd28ce00SJiri Slaby 	return ret;
2374bd28ce00SJiri Slaby }
2375bd28ce00SJiri Slaby 
2376bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2377bd28ce00SJiri Slaby {
2378bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2379bd28ce00SJiri Slaby 
23800a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2381fa57a810SFrank Praznik 		sony_leds_remove(sc);
2382bd28ce00SJiri Slaby 
2383d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2384d902f472SFrank Praznik 		hid_hw_close(hdev);
2385d902f472SFrank Praznik 		sony_battery_remove(sc);
2386d902f472SFrank Praznik 	}
2387d902f472SFrank Praznik 
238846262047SFrank Praznik 	sony_cancel_work_sync(sc);
23899f323b68SSven Eckelmann 
23909b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
23919b2b5c9aSFrank Praznik 
2392d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2393bd28ce00SJiri Slaby 
23948025087aSFrank Praznik 	sony_release_device_id(sc);
23958025087aSFrank Praznik 
2396bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2397bd28ce00SJiri Slaby }
2398bd28ce00SJiri Slaby 
2399bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2400bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2401bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2402bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
24034545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
24046eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
24054545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2406c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2407b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2408a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2409b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2410bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2411bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2412bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2413bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2414bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2415bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2416bd28ce00SJiri Slaby 	/* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2417bd28ce00SJiri Slaby 	 * Logitech joystick from the device descriptor. */
2418bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2419bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2420bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2421bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2422bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2423bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2424bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2425bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2426bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2427bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
242868a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
242968a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
243068a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
24310bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
24320bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
24338ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
24340bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
24358ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
2436bd28ce00SJiri Slaby 	{ }
2437bd28ce00SJiri Slaby };
2438bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2439bd28ce00SJiri Slaby 
2440bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2441bd28ce00SJiri Slaby 	.name             = "sony",
2442bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2443bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2444ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2445bd28ce00SJiri Slaby 	.probe            = sony_probe,
2446bd28ce00SJiri Slaby 	.remove           = sony_remove,
2447bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2448bd28ce00SJiri Slaby 	.raw_event        = sony_raw_event
2449bd28ce00SJiri Slaby };
24508025087aSFrank Praznik 
24518025087aSFrank Praznik static int __init sony_init(void)
24528025087aSFrank Praznik {
24538025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
24548025087aSFrank Praznik 
24558025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
24568025087aSFrank Praznik }
24578025087aSFrank Praznik 
24588025087aSFrank Praznik static void __exit sony_exit(void)
24598025087aSFrank Praznik {
24608025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
24618025087aSFrank Praznik 
24628025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
24636c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
24648025087aSFrank Praznik }
24658025087aSFrank Praznik module_init(sony_init);
24668025087aSFrank Praznik module_exit(sony_exit);
2467bd28ce00SJiri Slaby 
2468bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2469