xref: /linux/drivers/hid/hid-sony.c (revision 2c159de05082a70d3b3e75d8e167f4b5ca996405)
1bd28ce00SJiri Slaby /*
2077147a3SFrank Praznik  *  HID driver for Sony / PS2 / PS3 / PS4 BD devices.
3bd28ce00SJiri Slaby  *
4bd28ce00SJiri Slaby  *  Copyright (c) 1999 Andreas Gal
5bd28ce00SJiri Slaby  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6bd28ce00SJiri Slaby  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7bd28ce00SJiri Slaby  *  Copyright (c) 2008 Jiri Slaby
8078328daSJiri Kosina  *  Copyright (c) 2012 David Dillow <dave@thedillows.org>
9078328daSJiri Kosina  *  Copyright (c) 2006-2013 Jiri Kosina
10f04d5140SColin Leitner  *  Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
11c4425c8fSFrank Praznik  *  Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>
12bd28ce00SJiri Slaby  */
13bd28ce00SJiri Slaby 
14bd28ce00SJiri Slaby /*
15bd28ce00SJiri Slaby  * This program is free software; you can redistribute it and/or modify it
16bd28ce00SJiri Slaby  * under the terms of the GNU General Public License as published by the Free
17bd28ce00SJiri Slaby  * Software Foundation; either version 2 of the License, or (at your option)
18bd28ce00SJiri Slaby  * any later version.
19bd28ce00SJiri Slaby  */
20bd28ce00SJiri Slaby 
21ad142b9eSFrank Praznik /*
22ad142b9eSFrank Praznik  * NOTE: in order for the Sony PS3 BD Remote Control to be found by
23078328daSJiri Kosina  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
24078328daSJiri Kosina  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
25078328daSJiri Kosina  *
26078328daSJiri Kosina  * There will be no PIN request from the device.
27078328daSJiri Kosina  */
28078328daSJiri Kosina 
29bd28ce00SJiri Slaby #include <linux/device.h>
30bd28ce00SJiri Slaby #include <linux/hid.h>
31bd28ce00SJiri Slaby #include <linux/module.h>
325a0e3ad6STejun Heo #include <linux/slab.h>
3340e32ee6SJiri Kosina #include <linux/leds.h>
34d902f472SFrank Praznik #include <linux/power_supply.h>
35d902f472SFrank Praznik #include <linux/spinlock.h>
36d2d782fcSFrank Praznik #include <linux/list.h>
378025087aSFrank Praznik #include <linux/idr.h>
38e5606230SFrank Praznik #include <linux/input/mt.h>
39bd28ce00SJiri Slaby 
40bd28ce00SJiri Slaby #include "hid-ids.h"
41bd28ce00SJiri Slaby 
42f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT       BIT(0)
43f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB    BIT(1)
44f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT     BIT(2)
45f1c458caSSven Eckelmann #define BUZZ_CONTROLLER           BIT(3)
46f1c458caSSven Eckelmann #define PS3REMOTE                 BIT(4)
478ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5)
488ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
49b3bca326SSimon Wood #define MOTION_CONTROLLER_USB     BIT(7)
50b3bca326SSimon Wood #define MOTION_CONTROLLER_BT      BIT(8)
514545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9)
524545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT  BIT(10)
5374500cc8SScott Moreau #define SINO_LITE_CONTROLLER      BIT(11)
544ba1eeebSMikko Perttunen #define FUTUREMAX_DANCE_MAT       BIT(12)
55cc6e0bbbSJiri Kosina 
56fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
57b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
584545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\
594545ee0aSSimon Wood 				NAVIGATION_CONTROLLER_BT)
6068330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
6168330d83SFrank Praznik 				DUALSHOCK4_CONTROLLER_BT)
62fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
634545ee0aSSimon Wood 				DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
644545ee0aSSimon Wood 				NAVIGATION_CONTROLLER)
6512e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
664545ee0aSSimon Wood 				MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
67c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
68c5e0c1c4SFrank Praznik 				MOTION_CONTROLLER)
690f398230SFrank Praznik #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\
700f398230SFrank Praznik 			MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT)
7160781cf4SFrank Praznik 
7260781cf4SFrank Praznik #define MAX_LEDS 4
730a286ef2SSven Eckelmann 
744c3e8298SFrank Praznik /*
754c3e8298SFrank Praznik  * The Sixaxis reports both digital and analog values for each button on the
764c3e8298SFrank Praznik  * controller except for Start, Select and the PS button.  The controller ends
774c3e8298SFrank Praznik  * up reporting 27 axes which causes them to spill over into the multi-touch
784c3e8298SFrank Praznik  * axis values.  Additionally, the controller only has 20 actual, physical axes
794c3e8298SFrank Praznik  * so there are several unused axes in between the used ones.
804c3e8298SFrank Praznik  */
811adf904eSPavel Machek static u8 sixaxis_rdesc[] = {
82fb705a6dSAntonio Ospite 	0x05, 0x01,         /*  Usage Page (Desktop),               */
834c3e8298SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
84fb705a6dSAntonio Ospite 	0xA1, 0x01,         /*  Collection (Application),           */
85fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
86fb705a6dSAntonio Ospite 	0x85, 0x01,         /*          Report ID (1),              */
87fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
88fb705a6dSAntonio Ospite 	0x95, 0x01,         /*          Report Count (1),           */
89fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
90fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
91fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
92fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
93fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
94fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
95fb705a6dSAntonio Ospite 	0x25, 0x01,         /*          Logical Maximum (1),        */
96fb705a6dSAntonio Ospite 	0x35, 0x00,         /*          Physical Minimum (0),       */
97fb705a6dSAntonio Ospite 	0x45, 0x01,         /*          Physical Maximum (1),       */
98fb705a6dSAntonio Ospite 	0x05, 0x09,         /*          Usage Page (Button),        */
99fb705a6dSAntonio Ospite 	0x19, 0x01,         /*          Usage Minimum (01h),        */
100fb705a6dSAntonio Ospite 	0x29, 0x13,         /*          Usage Maximum (13h),        */
101fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
102fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
103fb705a6dSAntonio Ospite 	0x95, 0x0D,         /*          Report Count (13),          */
104fb705a6dSAntonio Ospite 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
105fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
106fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
107fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
108fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
109fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
110fb705a6dSAntonio Ospite 	0xA1, 0x00,         /*          Collection (Physical),      */
111fb705a6dSAntonio Ospite 	0x75, 0x08,         /*              Report Size (8),        */
112fb705a6dSAntonio Ospite 	0x95, 0x04,         /*              Report Count (4),       */
113fb705a6dSAntonio Ospite 	0x35, 0x00,         /*              Physical Minimum (0),   */
114fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
115fb705a6dSAntonio Ospite 	0x09, 0x30,         /*              Usage (X),              */
116fb705a6dSAntonio Ospite 	0x09, 0x31,         /*              Usage (Y),              */
117fb705a6dSAntonio Ospite 	0x09, 0x32,         /*              Usage (Z),              */
118fb705a6dSAntonio Ospite 	0x09, 0x35,         /*              Usage (Rz),             */
119fb705a6dSAntonio Ospite 	0x81, 0x02,         /*              Input (Variable),       */
120fb705a6dSAntonio Ospite 	0xC0,               /*          End Collection,             */
121fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
122fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
123fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
124fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
125fb705a6dSAntonio Ospite 	0x95, 0x0C,         /*          Report Count (12),          */
126fb705a6dSAntonio Ospite 	0x81, 0x01,         /*          Input (Constant),           */
127fb705a6dSAntonio Ospite 	0x75, 0x10,         /*          Report Size (16),           */
128fb705a6dSAntonio Ospite 	0x95, 0x04,         /*          Report Count (4),           */
129fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
130fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
131fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
132fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
133fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
134fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
135fb705a6dSAntonio Ospite 	0x85, 0x02,         /*          Report ID (2),              */
136fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
137fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
138fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
139fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
140fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
141fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
142fb705a6dSAntonio Ospite 	0x85, 0xEE,         /*          Report ID (238),            */
143fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
144fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
145fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
146fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
147fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
148fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
149fb705a6dSAntonio Ospite 	0x85, 0xEF,         /*          Report ID (239),            */
150fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
151fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
152fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
153fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
154fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
155fb705a6dSAntonio Ospite 	0xC0                /*  End Collection                      */
156e57a67daSMauro Carvalho Chehab };
157e57a67daSMauro Carvalho Chehab 
158c5e0c1c4SFrank Praznik /* PS/3 Motion controller */
1591adf904eSPavel Machek static u8 motion_rdesc[] = {
160c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
161c5e0c1c4SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
162c5e0c1c4SFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
163c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
164c5e0c1c4SFrank Praznik 	0x85, 0x01,         /*          Report ID (1),              */
165c5e0c1c4SFrank Praznik 	0x75, 0x01,         /*          Report Size (1),            */
1668b2513c3SSimon Wood 	0x95, 0x15,         /*          Report Count (21),          */
167c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
168c5e0c1c4SFrank Praznik 	0x25, 0x01,         /*          Logical Maximum (1),        */
169c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*          Physical Minimum (0),       */
170c5e0c1c4SFrank Praznik 	0x45, 0x01,         /*          Physical Maximum (1),       */
171c5e0c1c4SFrank Praznik 	0x05, 0x09,         /*          Usage Page (Button),        */
172c5e0c1c4SFrank Praznik 	0x19, 0x01,         /*          Usage Minimum (01h),        */
1738b2513c3SSimon Wood 	0x29, 0x15,         /*          Usage Maximum (15h),        */
1748b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           * Buttons */
1758b2513c3SSimon Wood 	0x95, 0x0B,         /*          Report Count (11),          */
176c5e0c1c4SFrank Praznik 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1778b2513c3SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), * Padding */
178c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
179c5e0c1c4SFrank Praznik 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
180c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
181c5e0c1c4SFrank Praznik 	0xA1, 0x00,         /*          Collection (Physical),      */
182c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*              Report Size (8),        */
1838b2513c3SSimon Wood 	0x95, 0x01,         /*              Report Count (1),       */
184c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*              Physical Minimum (0),   */
185c5e0c1c4SFrank Praznik 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
186c5e0c1c4SFrank Praznik 	0x09, 0x30,         /*              Usage (X),              */
1878b2513c3SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       * Trigger */
188c5e0c1c4SFrank Praznik 	0xC0,               /*          End Collection,             */
1898b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1908b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
1918b2513c3SSimon Wood 	0x95, 0x07,         /*          Report Count (7),           * skip 7 bytes */
1928b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
193c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
194c5e0c1c4SFrank Praznik 	0x75, 0x10,         /*          Report Size (16),           */
1958b2513c3SSimon Wood 	0x46, 0xFF, 0xFF,   /*          Physical Maximum (65535),   */
1968b2513c3SSimon Wood 	0x27, 0xFF, 0xFF, 0x00, 0x00, /*      Logical Maximum (65535),    */
1978b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Accels */
1988b2513c3SSimon Wood 	0x09, 0x33,         /*              Usage (rX),             */
1998b2513c3SSimon Wood 	0x09, 0x34,         /*              Usage (rY),             */
2008b2513c3SSimon Wood 	0x09, 0x35,         /*              Usage (rZ),             */
201c5e0c1c4SFrank Praznik 	0x81, 0x02,         /*          Input (Variable),           */
2028b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2038b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Accels 2nd frame */
2048b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2058b2513c3SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
2068b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2078b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Gyros */
2088b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2098b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2108b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Gyros 2nd frame */
2118b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2128b2513c3SSimon Wood 	0x75, 0x0C,         /*          Report Size (12),           */
2138b2513c3SSimon Wood 	0x46, 0xFF, 0x0F,   /*          Physical Maximum (4095),    */
2148b2513c3SSimon Wood 	0x26, 0xFF, 0x0F,   /*          Logical Maximum (4095),     */
2158b2513c3SSimon Wood 	0x95, 0x04,         /*          Report Count (4),           * Skip Temp and Magnetometers */
2168b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2178b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2188b2513c3SSimon Wood 	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
2198b2513c3SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
2208b2513c3SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           * Skip Timestamp and Extension Bytes */
2218b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2228b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2238b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2248b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2258b2513c3SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
2268b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2278b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2288b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2298b2513c3SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
230c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
231c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
232c5e0c1c4SFrank Praznik 	0x85, 0x02,         /*          Report ID (2),              */
233c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
234c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
235c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
236c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
237c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
238c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
239c5e0c1c4SFrank Praznik 	0x85, 0xEE,         /*          Report ID (238),            */
240c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
241c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
242c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
243c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
244c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
245c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
246c5e0c1c4SFrank Praznik 	0x85, 0xEF,         /*          Report ID (239),            */
247c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
248c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
249c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
250c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
251c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
252c5e0c1c4SFrank Praznik 	0xC0                /*  End Collection                      */
253c5e0c1c4SFrank Praznik };
254c5e0c1c4SFrank Praznik 
255b2723eb7SSimon Wood /* PS/3 Navigation controller */
2561adf904eSPavel Machek static u8 navigation_rdesc[] = {
257b2723eb7SSimon Wood 	0x05, 0x01,         /*  Usage Page (Desktop),               */
258d542176fSAntonio Ospite 	0x09, 0x04,         /*  Usage (Joystick),                   */
259b2723eb7SSimon Wood 	0xA1, 0x01,         /*  Collection (Application),           */
260b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
261b2723eb7SSimon Wood 	0x85, 0x01,         /*          Report ID (1),              */
262b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
263b2723eb7SSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
264b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
265b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
266b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
267b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
268b2723eb7SSimon Wood 	0x95, 0x13,         /*          Report Count (19),          */
269b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
270b2723eb7SSimon Wood 	0x25, 0x01,         /*          Logical Maximum (1),        */
271b2723eb7SSimon Wood 	0x35, 0x00,         /*          Physical Minimum (0),       */
272b2723eb7SSimon Wood 	0x45, 0x01,         /*          Physical Maximum (1),       */
273b2723eb7SSimon Wood 	0x05, 0x09,         /*          Usage Page (Button),        */
274b2723eb7SSimon Wood 	0x19, 0x01,         /*          Usage Minimum (01h),        */
275b2723eb7SSimon Wood 	0x29, 0x13,         /*          Usage Maximum (13h),        */
276b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
277b2723eb7SSimon Wood 	0x75, 0x01,         /*          Report Size (1),            */
278b2723eb7SSimon Wood 	0x95, 0x0D,         /*          Report Count (13),          */
279b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
280b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
281b2723eb7SSimon Wood 	0x15, 0x00,         /*          Logical Minimum (0),        */
282b2723eb7SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
283b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
284b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
285b2723eb7SSimon Wood 	0xA1, 0x00,         /*          Collection (Physical),      */
286b2723eb7SSimon Wood 	0x75, 0x08,         /*              Report Size (8),        */
287b2723eb7SSimon Wood 	0x95, 0x02,         /*              Report Count (2),       */
288b2723eb7SSimon Wood 	0x35, 0x00,         /*              Physical Minimum (0),   */
289b2723eb7SSimon Wood 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
290b2723eb7SSimon Wood 	0x09, 0x30,         /*              Usage (X),              */
291b2723eb7SSimon Wood 	0x09, 0x31,         /*              Usage (Y),              */
292b2723eb7SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       */
293b2723eb7SSimon Wood 	0xC0,               /*          End Collection,             */
294b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
295b2723eb7SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           */
296b2723eb7SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), */
297b2723eb7SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
298b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
299b2723eb7SSimon Wood 	0x95, 0x05,         /*          Report Count (5),           */
300b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
301b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
302b2723eb7SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3032259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3042259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3052259b5bbSSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
3062259b5bbSSimon Wood 	0x95, 0x01,         /*          Report Count (1),           */
3072259b5bbSSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
3082259b5bbSSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
3092259b5bbSSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
3102259b5bbSSimon Wood 	0x95, 0x1E,         /*          Report Count (24),          */
311b2723eb7SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
312b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
313b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
314b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
315b2723eb7SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
316b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
317b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
318b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
319b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
320b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
321b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
322b2723eb7SSimon Wood 	0x85, 0x02,         /*          Report ID (2),              */
323b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
324b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
325b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
326b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
327b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
328b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
329b2723eb7SSimon Wood 	0x85, 0xEE,         /*          Report ID (238),            */
330b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
331b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
332b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
333b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
334b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
335b2723eb7SSimon Wood 	0xA1, 0x02,         /*      Collection (Logical),           */
336b2723eb7SSimon Wood 	0x85, 0xEF,         /*          Report ID (239),            */
337b2723eb7SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
338b2723eb7SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
339b2723eb7SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
340b2723eb7SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
341b2723eb7SSimon Wood 	0xC0,               /*      End Collection,                 */
342b2723eb7SSimon Wood 	0xC0                /*  End Collection                      */
343b2723eb7SSimon Wood };
344c5e0c1c4SFrank Praznik 
345ad142b9eSFrank Praznik /*
346ad142b9eSFrank Praznik  * The default descriptor doesn't provide mapping for the accelerometers
34758d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
34858d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
34958d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
35058d7027bSFrank Praznik  */
351ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
35258d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
35358d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
35458d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
35558d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
35658d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
35758d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
35858d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
35958d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
36058d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36158d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
36258d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
36358d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
36458d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
36558d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
36658d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
36758d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
36858d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
36958d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
37058d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
37158d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
37258d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
37358d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
37458d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
37558d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
37658d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
37758d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
37858d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
37958d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
38058d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
38158d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
38258d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
38358d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
38458d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
38558d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
38658d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
38758d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
388fb291cbdSFrank Praznik 	0x25, 0x3F,         /*      Logical Maximum (63),           */
38958d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39058d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
39158d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
39258d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
39358d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
39458d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
39558d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
39658d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
39758d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
39858d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
39958d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
40058d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
40258d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
40358d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
40458d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
40558d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
40658d7027bSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
40758d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
40858d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
40958d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41058d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
41158d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
412fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
413fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
41458d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
41558d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
41658d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
41758d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
41858d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
419fb291cbdSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
42058d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
42158d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
42258d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
42358d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
42458d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
42558d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
42658d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
42758d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
42858d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
42958d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
43058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43158d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
43258d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
43358d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
43458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43558d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
43658d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
43758d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
43858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43958d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
44058d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
44158d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
44258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44358d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
44458d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
44558d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
44658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44758d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
44858d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
44958d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
45058d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
45158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45258d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
45358d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
45458d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
45558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45658d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
45758d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
45858d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
45958d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
46058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46158d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
46258d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
46358d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
46458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46558d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
46658d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
46758d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
46858d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
46958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47058d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
47158d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
47258d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
47358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47458d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
47558d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
47658d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
47758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47858d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
47958d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
48058d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
48158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48258d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
48358d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
48458d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
48558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48658d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
48758d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
48858d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
48958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49058d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
49158d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
49258d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
49358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49458d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
49558d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
49658d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
49758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49858d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
49958d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
50058d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
50158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50258d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
50358d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
50458d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
50558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50658d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
50758d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
50858d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
50958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51058d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
51158d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
51258d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51458d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
51558d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
51658d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
51758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
51858d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
51958d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
52058d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
52158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52258d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
52358d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
52458d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
52558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
52658d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
52758d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
52858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
52958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53058d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
53158d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
53258d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
53358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53458d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
53558d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
53658d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
53758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
53858d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
53958d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
54058d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
54158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54258d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
54358d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
54458d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
54658d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
54758d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
54858d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
54958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55058d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
55158d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
55258d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55458d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
55558d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
55658d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
55758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
55858d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
55958d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
56058d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
56158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56258d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
56358d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
56458d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
56658d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
56758d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
56858d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
56958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57058d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
57158d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
57258d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
57358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57458d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
57558d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
57658d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
57758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
57858d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
57958d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
58058d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58258d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
58358d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
58458d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
58558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
58658d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
58758d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
58858d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
58958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59058d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
59158d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
59258d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
59358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59458d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
59558d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
59658d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
59758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
59858d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
59958d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
60058d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
60158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
60258d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
603ed19d8cfSFrank Praznik };
604ed19d8cfSFrank Praznik 
605ad142b9eSFrank Praznik /*
606ad142b9eSFrank Praznik  * The default behavior of the Dualshock 4 is to send reports using report
607077147a3SFrank Praznik  * type 1 when running over Bluetooth. However, when feature report 2 is
608077147a3SFrank Praznik  * requested during the controller initialization it starts sending input
609077147a3SFrank Praznik  * reports in report 17.  Since report 17 is undefined in the default HID
610d829674dSFrank Praznik  * descriptor the button and axis definitions must be moved to report 17 or
611077147a3SFrank Praznik  * the HID layer won't process the received input.
612d829674dSFrank Praznik  */
613d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = {
614d829674dSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
615d829674dSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
616d829674dSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
617d829674dSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
618d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
619d829674dSFrank Praznik 	0x95, 0x0A,         /*      Report Count (9),               */
620d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
621d829674dSFrank Praznik 	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
622d829674dSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
623d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
624d829674dSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
625d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
626d829674dSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
627d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
628d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
629d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
630d829674dSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
631d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
632d829674dSFrank Praznik 	0x95, 0x28,         /*      Report Count (40),              */
633d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
634d829674dSFrank Praznik 	0x85, 0x06,         /*      Report ID (6),                  */
635d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
636d829674dSFrank Praznik 	0x95, 0x34,         /*      Report Count (52),              */
637d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
638d829674dSFrank Praznik 	0x85, 0x07,         /*      Report ID (7),                  */
639d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
640d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
641d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
642d829674dSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
643d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
644d829674dSFrank Praznik 	0x95, 0x2F,         /*      Report Count (47),              */
645d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
646d829674dSFrank Praznik 	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
647d829674dSFrank Praznik 	0x85, 0x03,         /*      Report ID (3),                  */
648d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
649d829674dSFrank Praznik 	0x95, 0x26,         /*      Report Count (38),              */
650d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
651d829674dSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
652d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
653d829674dSFrank Praznik 	0x95, 0x2E,         /*      Report Count (46),              */
654d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
655d829674dSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
656d829674dSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
657d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
658d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
659d829674dSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
660d829674dSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
661d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
662d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
663d829674dSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
664d829674dSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
665d829674dSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
666d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
667d829674dSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
668d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
669d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
670d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
671d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
672d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
673d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
674d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
675d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
676d829674dSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
677d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
678d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
679d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
680d829674dSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
681d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
682d829674dSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
683d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
684d829674dSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
685d829674dSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
686d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
687d829674dSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
688d829674dSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
689d829674dSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
690d829674dSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
691d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
692d829674dSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
693d829674dSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
694d829674dSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
695d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
696d829674dSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
697d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
698d829674dSFrank Praznik 	0x81, 0x01,         /*      Input (Constant),               */
699d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
700d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
701d829674dSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
702d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
703d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
704d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
705d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
706d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
707d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
708d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
709d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
710d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
711d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
712d829674dSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
713d829674dSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
714d829674dSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
715d829674dSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
716d829674dSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
717d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
718d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
719d829674dSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
720d829674dSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
721fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
722fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
723d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
724d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
725d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
726d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
727d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
728d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
729d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
730d829674dSFrank Praznik 	0x95, 0x31,         /*      Report Count (51),              */
731d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
732d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
733d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
734d829674dSFrank Praznik 	0x95, 0x4D,         /*      Report Count (77),              */
735d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
736d829674dSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
737d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
738d829674dSFrank Praznik 	0x95, 0x8D,         /*      Report Count (141),             */
739d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
740d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
741d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
742d829674dSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
743d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
744d829674dSFrank Praznik 	0x95, 0xCD,         /*      Report Count (205),             */
745d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
746d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
747d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
748d829674dSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
749d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
750d829674dSFrank Praznik 	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
751d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
752d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
753d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
754d829674dSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
755d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
756d829674dSFrank Praznik 	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
757d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
758d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
759d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
760d829674dSFrank Praznik 	0x85, 0x16,         /*      Report ID (22),                 */
761d829674dSFrank Praznik 	0x09, 0x2A,         /*      Usage (2Ah),                    */
762d829674dSFrank Praznik 	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
763d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
764d829674dSFrank Praznik 	0x09, 0x2B,         /*      Usage (2Bh),                    */
765d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
766d829674dSFrank Praznik 	0x85, 0x17,         /*      Report ID (23),                 */
767d829674dSFrank Praznik 	0x09, 0x2C,         /*      Usage (2Ch),                    */
768d829674dSFrank Praznik 	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
769d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
770d829674dSFrank Praznik 	0x09, 0x2D,         /*      Usage (2Dh),                    */
771d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
772d829674dSFrank Praznik 	0x85, 0x18,         /*      Report ID (24),                 */
773d829674dSFrank Praznik 	0x09, 0x2E,         /*      Usage (2Eh),                    */
774d829674dSFrank Praznik 	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
775d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
776d829674dSFrank Praznik 	0x09, 0x2F,         /*      Usage (2Fh),                    */
777d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
778d829674dSFrank Praznik 	0x85, 0x19,         /*      Report ID (25),                 */
779d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
780d829674dSFrank Praznik 	0x96, 0x22, 0x02,   /*      Report Count (546),             */
781d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
782d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
783d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
784d829674dSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
785d829674dSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
786d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
787d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
788d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
789d829674dSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
790d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
791d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
792d829674dSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
793d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
794d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
795d829674dSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
796d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
797d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
798d829674dSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
799d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
800d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
801d829674dSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
802d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
803d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
804d829674dSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
805d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
806d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
807d829674dSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
808d829674dSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
809d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
810d829674dSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
811d829674dSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
812d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
813d829674dSFrank Praznik 	0xC0                /*  End Collection                      */
814d829674dSFrank Praznik };
815d829674dSFrank Praznik 
8161adf904eSPavel Machek static u8 ps3remote_rdesc[] = {
817078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
818078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
819078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
820078328daSJiri Kosina 
821078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
822078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
823078328daSJiri Kosina 
824ef916ef5SAntonio Ospite 	  /*
825ef916ef5SAntonio Ospite 	   * Ignore the 1st byte, maybe it is used for a controller
826ef916ef5SAntonio Ospite 	   * number but it's not needed for correct operation
827ef916ef5SAntonio Ospite 	   */
828078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
829078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
830078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
831078328daSJiri Kosina 
832ef916ef5SAntonio Ospite 	  /*
833ef916ef5SAntonio Ospite 	   * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
834ef916ef5SAntonio Ospite 	   * buttons multiple keypresses are allowed
835ef916ef5SAntonio Ospite 	   */
836078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
837078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
838078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
839078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
840078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
841078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
842078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
843078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
844078328daSJiri Kosina 
845078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
846078328daSJiri Kosina 
847078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
848078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
849078328daSJiri Kosina 
850078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
851078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
852078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
853078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
854078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
855078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
856078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
857078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
858078328daSJiri Kosina 	  0x80,              /* MInput  */
859078328daSJiri Kosina 
860ef916ef5SAntonio Ospite 	  /*
861ef916ef5SAntonio Ospite 	   * Ignore bytes from 6th to 11th, 6th to 10th are always constant at
862ef916ef5SAntonio Ospite 	   * 0xff and 11th is for press indication
863ef916ef5SAntonio Ospite 	   */
864078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
865078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
866078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
867078328daSJiri Kosina 
868078328daSJiri Kosina 	  /* 12th byte is for battery strength */
869078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
870078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
871078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
872078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
873078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
874078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
875078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
876078328daSJiri Kosina 
877078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
878078328daSJiri Kosina 
879078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
880078328daSJiri Kosina };
881078328daSJiri Kosina 
882078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
883078328daSJiri Kosina 	[0x01] = KEY_SELECT,
884078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
885078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
886078328daSJiri Kosina 	[0x04] = BTN_START,
887078328daSJiri Kosina 	[0x05] = KEY_UP,
888078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
889078328daSJiri Kosina 	[0x07] = KEY_DOWN,
890078328daSJiri Kosina 	[0x08] = KEY_LEFT,
891078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
892078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
893078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
894078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
895078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
896078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
897078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
898078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
899078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
900078328daSJiri Kosina 	[0x14] = KEY_ENTER,
901078328daSJiri Kosina };
902078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
903078328daSJiri Kosina 	[0x00] = KEY_1,
904078328daSJiri Kosina 	[0x01] = KEY_2,
905078328daSJiri Kosina 	[0x02] = KEY_3,
906078328daSJiri Kosina 	[0x03] = KEY_4,
907078328daSJiri Kosina 	[0x04] = KEY_5,
908078328daSJiri Kosina 	[0x05] = KEY_6,
909078328daSJiri Kosina 	[0x06] = KEY_7,
910078328daSJiri Kosina 	[0x07] = KEY_8,
911078328daSJiri Kosina 	[0x08] = KEY_9,
912078328daSJiri Kosina 	[0x09] = KEY_0,
913078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
914078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
915078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
916078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
917078328daSJiri Kosina 	[0x28] = KEY_TIME,
918078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
919078328daSJiri Kosina 	[0x31] = KEY_NEXT,
920078328daSJiri Kosina 	[0x32] = KEY_PLAY,
921078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
922078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
923078328daSJiri Kosina 	[0x38] = KEY_STOP,
924078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
925078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
926078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
927078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
928078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
929078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
930078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
931078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
932078328daSJiri Kosina 	[0x80] = KEY_BLUE,
933078328daSJiri Kosina 	[0x81] = KEY_RED,
934078328daSJiri Kosina 	[0x82] = KEY_GREEN,
935078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
936078328daSJiri Kosina };
937078328daSJiri Kosina 
938f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
939ad142b9eSFrank Praznik 	/*
940ad142b9eSFrank Praznik 	 * The controller has 4 remote buzzers, each with one LED and 5
941f04d5140SColin Leitner 	 * buttons.
942f04d5140SColin Leitner 	 *
943f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
944f04d5140SColin Leitner 	 *
945f04d5140SColin Leitner 	 * Key          Offset
946f04d5140SColin Leitner 	 * -------------------
947f04d5140SColin Leitner 	 * Buzz              1
948f04d5140SColin Leitner 	 * Blue              5
949f04d5140SColin Leitner 	 * Orange            4
950f04d5140SColin Leitner 	 * Green             3
951f04d5140SColin Leitner 	 * Yellow            2
952f04d5140SColin Leitner 	 *
953f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
954f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
955f04d5140SColin Leitner 	 */
956f04d5140SColin Leitner 	 [1] = BTN_TRIGGER_HAPPY1,
957f04d5140SColin Leitner 	 [2] = BTN_TRIGGER_HAPPY2,
958f04d5140SColin Leitner 	 [3] = BTN_TRIGGER_HAPPY3,
959f04d5140SColin Leitner 	 [4] = BTN_TRIGGER_HAPPY4,
960f04d5140SColin Leitner 	 [5] = BTN_TRIGGER_HAPPY5,
961f04d5140SColin Leitner 	 [6] = BTN_TRIGGER_HAPPY6,
962f04d5140SColin Leitner 	 [7] = BTN_TRIGGER_HAPPY7,
963f04d5140SColin Leitner 	 [8] = BTN_TRIGGER_HAPPY8,
964f04d5140SColin Leitner 	 [9] = BTN_TRIGGER_HAPPY9,
965f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
966f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
967f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
968f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
969f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
970f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
971f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
972f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
973f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
974f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
975f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
976f04d5140SColin Leitner };
977f04d5140SColin Leitner 
978d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
979d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
980d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
981d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
982d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
983d902f472SFrank Praznik };
984d902f472SFrank Praznik 
98555d3b664SFrank Praznik struct sixaxis_led {
9861adf904eSPavel Machek 	u8 time_enabled; /* the total time the led is active (0xff means forever) */
9871adf904eSPavel Machek 	u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
9881adf904eSPavel Machek 	u8 enabled;
9891adf904eSPavel Machek 	u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
9901adf904eSPavel Machek 	u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
99155d3b664SFrank Praznik } __packed;
99255d3b664SFrank Praznik 
99355d3b664SFrank Praznik struct sixaxis_rumble {
9941adf904eSPavel Machek 	u8 padding;
9951adf904eSPavel Machek 	u8 right_duration; /* Right motor duration (0xff means forever) */
9961adf904eSPavel Machek 	u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
9971adf904eSPavel Machek 	u8 left_duration;    /* Left motor duration (0xff means forever) */
9981adf904eSPavel Machek 	u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
99955d3b664SFrank Praznik } __packed;
100055d3b664SFrank Praznik 
100155d3b664SFrank Praznik struct sixaxis_output_report {
10021adf904eSPavel Machek 	u8 report_id;
100355d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
10041adf904eSPavel Machek 	u8 padding[4];
10051adf904eSPavel Machek 	u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
100655d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
100755d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
100855d3b664SFrank Praznik } __packed;
100955d3b664SFrank Praznik 
101055d3b664SFrank Praznik union sixaxis_output_report_01 {
101155d3b664SFrank Praznik 	struct sixaxis_output_report data;
10121adf904eSPavel Machek 	u8 buf[36];
101355d3b664SFrank Praznik };
101455d3b664SFrank Praznik 
1015c5e0c1c4SFrank Praznik struct motion_output_report_02 {
1016c5e0c1c4SFrank Praznik 	u8 type, zero;
1017c5e0c1c4SFrank Praznik 	u8 r, g, b;
1018c5e0c1c4SFrank Praznik 	u8 zero2;
1019c5e0c1c4SFrank Praznik 	u8 rumble;
1020c5e0c1c4SFrank Praznik };
1021c5e0c1c4SFrank Praznik 
1022*2c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x02_SIZE 37
1023*2c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x81_SIZE 7
1024*2c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x05_SIZE 32
1025*2c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x11_SIZE 78
102629b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
1027a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
102841d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
10299b2b5c9aSFrank Praznik 
10308b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
1031d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
10328025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
1033d2d782fcSFrank Praznik 
1034cc6e0bbbSJiri Kosina struct sony_sc {
1035d902f472SFrank Praznik 	spinlock_t lock;
1036d2d782fcSFrank Praznik 	struct list_head list_node;
10370a286ef2SSven Eckelmann 	struct hid_device *hdev;
103860781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
1039cc6e0bbbSJiri Kosina 	unsigned long quirks;
10400a286ef2SSven Eckelmann 	struct work_struct state_worker;
1041d8aaccdaSFrank Praznik 	void (*send_output_report)(struct sony_sc *);
1042297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
1043297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
10448025087aSFrank Praznik 	int device_id;
10451adf904eSPavel Machek 	u8 *output_report_dmabuf;
1046f04d5140SColin Leitner 
10479f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
10481adf904eSPavel Machek 	u8 left;
10491adf904eSPavel Machek 	u8 right;
10509f323b68SSven Eckelmann #endif
10519f323b68SSven Eckelmann 
10521adf904eSPavel Machek 	u8 mac_address[6];
10531adf904eSPavel Machek 	u8 worker_initialized;
10542a242932SFrank Praznik 	u8 defer_initialization;
10551adf904eSPavel Machek 	u8 cable_state;
10561adf904eSPavel Machek 	u8 battery_charging;
10571adf904eSPavel Machek 	u8 battery_capacity;
10581adf904eSPavel Machek 	u8 led_state[MAX_LEDS];
10591adf904eSPavel Machek 	u8 resume_led_state[MAX_LEDS];
10601adf904eSPavel Machek 	u8 led_delay_on[MAX_LEDS];
10611adf904eSPavel Machek 	u8 led_delay_off[MAX_LEDS];
10621adf904eSPavel Machek 	u8 led_count;
1063cc6e0bbbSJiri Kosina };
1064cc6e0bbbSJiri Kosina 
10652a242932SFrank Praznik static inline void sony_schedule_work(struct sony_sc *sc)
10662a242932SFrank Praznik {
10672a242932SFrank Praznik 	if (!sc->defer_initialization)
10682a242932SFrank Praznik 		schedule_work(&sc->state_worker);
10692a242932SFrank Praznik }
10702a242932SFrank Praznik 
10711adf904eSPavel Machek static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc,
1072c607fb8dSAntonio Ospite 			     unsigned int *rsize)
1073c607fb8dSAntonio Ospite {
1074c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
1075c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
1076c607fb8dSAntonio Ospite }
1077c607fb8dSAntonio Ospite 
1078c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
1079c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
1080c5e0c1c4SFrank Praznik {
1081c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
1082c5e0c1c4SFrank Praznik 	return motion_rdesc;
1083c5e0c1c4SFrank Praznik }
1084c5e0c1c4SFrank Praznik 
1085b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc,
1086b2723eb7SSimon Wood 			     unsigned int *rsize)
1087b2723eb7SSimon Wood {
1088b2723eb7SSimon Wood 	*rsize = sizeof(navigation_rdesc);
1089b2723eb7SSimon Wood 	return navigation_rdesc;
1090b2723eb7SSimon Wood }
1091b2723eb7SSimon Wood 
10921adf904eSPavel Machek static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc,
1093078328daSJiri Kosina 			     unsigned int *rsize)
1094078328daSJiri Kosina {
1095078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
1096078328daSJiri Kosina 	return ps3remote_rdesc;
1097078328daSJiri Kosina }
1098078328daSJiri Kosina 
1099078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
1100078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
1101078328daSJiri Kosina 			     unsigned long **bit, int *max)
1102078328daSJiri Kosina {
1103078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
1104078328daSJiri Kosina 
1105078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1106078328daSJiri Kosina 		return -1;
1107078328daSJiri Kosina 
1108078328daSJiri Kosina 	switch (usage->collection_index) {
1109078328daSJiri Kosina 	case 1:
1110078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
1111078328daSJiri Kosina 			return -1;
1112078328daSJiri Kosina 
1113078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
1114078328daSJiri Kosina 		if (!key)
1115078328daSJiri Kosina 			return -1;
1116078328daSJiri Kosina 		break;
1117078328daSJiri Kosina 	case 2:
1118078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1119078328daSJiri Kosina 			return -1;
1120078328daSJiri Kosina 
1121078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1122078328daSJiri Kosina 		if (!key)
1123078328daSJiri Kosina 			return -1;
1124078328daSJiri Kosina 		break;
1125078328daSJiri Kosina 	default:
1126078328daSJiri Kosina 		return -1;
1127078328daSJiri Kosina 	}
1128078328daSJiri Kosina 
1129078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1130078328daSJiri Kosina 	return 1;
1131078328daSJiri Kosina }
1132078328daSJiri Kosina 
11331adf904eSPavel Machek static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
113473e4008dSNikolai Kondrashov 		unsigned int *rsize)
1135cc6e0bbbSJiri Kosina {
1136cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1137cc6e0bbbSJiri Kosina 
11384ba1eeebSMikko Perttunen 	if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
113974500cc8SScott Moreau 		return rdesc;
114074500cc8SScott Moreau 
114199d24902SFernando Luis Vázquez Cao 	/*
114299d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
114399d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
114499d24902SFernando Luis Vázquez Cao 	 */
114599d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
114699d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
114799d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
114899d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
114999d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
115099d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
115199d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1152a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
115399d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1154cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1155cc6e0bbbSJiri Kosina 	}
115661ab44beSSimon Wood 
1157ed19d8cfSFrank Praznik 	/*
1158ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1159ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1160ed19d8cfSFrank Praznik 	 * modified one.
1161ed19d8cfSFrank Praznik 	 */
1162b71b5578SFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1163ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1164ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1165ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1166b71b5578SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
1167d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1168d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1169d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1170ed19d8cfSFrank Praznik 	}
1171ed19d8cfSFrank Praznik 
1172c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1173c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1174078328daSJiri Kosina 
1175c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1176c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1177c5e0c1c4SFrank Praznik 
11784545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1179b2723eb7SSimon Wood 		return navigation_fixup(hdev, rdesc, rsize);
11804545ee0aSSimon Wood 
1181078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1182078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1183078328daSJiri Kosina 
118473e4008dSNikolai Kondrashov 	return rdesc;
1185cc6e0bbbSJiri Kosina }
1186cc6e0bbbSJiri Kosina 
11871adf904eSPavel Machek static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
1188d902f472SFrank Praznik {
11891adf904eSPavel Machek 	static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1190d902f472SFrank Praznik 	unsigned long flags;
119112e9a6d7SSimon Wood 	int offset;
11921adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1193d902f472SFrank Praznik 
1194ad142b9eSFrank Praznik 	/*
1195ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1196d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1197d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1198d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1199d902f472SFrank Praznik 	 */
120012e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
120112e9a6d7SSimon Wood 
120212e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1203d902f472SFrank Praznik 		battery_capacity = 100;
120412e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
12059fddd74aSFrank Praznik 		cable_state = 1;
1206d902f472SFrank Praznik 	} else {
12071adf904eSPavel Machek 		u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1208ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1209d902f472SFrank Praznik 		battery_charging = 0;
12109fddd74aSFrank Praznik 		cable_state = 0;
1211d902f472SFrank Praznik 	}
1212d902f472SFrank Praznik 
1213d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1214d902f472SFrank Praznik 	sc->cable_state = cable_state;
1215d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1216d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1217d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1218d902f472SFrank Praznik }
1219d902f472SFrank Praznik 
12201adf904eSPavel Machek static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
1221d902f472SFrank Praznik {
1222e5606230SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1223e5606230SFrank Praznik 						struct hid_input, list);
1224e5606230SFrank Praznik 	struct input_dev *input_dev = hidinput->input;
1225d902f472SFrank Praznik 	unsigned long flags;
12266c5f860dSFrank Praznik 	int n, offset;
12271adf904eSPavel Machek 	u8 cable_state, battery_capacity, battery_charging;
1228d902f472SFrank Praznik 
1229ad142b9eSFrank Praznik 	/*
1230ad142b9eSFrank Praznik 	 * Battery and touchpad data starts at byte 30 in the USB report and
12316c5f860dSFrank Praznik 	 * 32 in Bluetooth report.
12326c5f860dSFrank Praznik 	 */
12336c5f860dSFrank Praznik 	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
12346c5f860dSFrank Praznik 
1235ad142b9eSFrank Praznik 	/*
1236ad142b9eSFrank Praznik 	 * The lower 4 bits of byte 30 contain the battery level
1237d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1238d902f472SFrank Praznik 	 */
12396c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
12406c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1241d902f472SFrank Praznik 
1242ad142b9eSFrank Praznik 	/*
1243ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
12446c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
12456c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1246d902f472SFrank Praznik 	 */
12476c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1248d902f472SFrank Praznik 		battery_charging = 0;
1249d902f472SFrank Praznik 	else
1250d902f472SFrank Praznik 		battery_charging = 1;
1251d902f472SFrank Praznik 
12526c5f860dSFrank Praznik 	if (!cable_state)
12536c5f860dSFrank Praznik 		battery_capacity++;
1254d902f472SFrank Praznik 	if (battery_capacity > 10)
12556c5f860dSFrank Praznik 		battery_capacity = 10;
12566c5f860dSFrank Praznik 
1257d902f472SFrank Praznik 	battery_capacity *= 10;
1258d902f472SFrank Praznik 
1259d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1260d902f472SFrank Praznik 	sc->cable_state = cable_state;
1261d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1262d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1263d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1264e5606230SFrank Praznik 
12656c5f860dSFrank Praznik 	offset += 5;
12666c5f860dSFrank Praznik 
1267ad142b9eSFrank Praznik 	/*
1268ad142b9eSFrank Praznik 	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
12696c5f860dSFrank Praznik 	 * and 37 on Bluetooth.
1270e5606230SFrank Praznik 	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
1271e5606230SFrank Praznik 	 * indicator that is 0 when pressed and 1 when not pressed.
1272e5606230SFrank Praznik 	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1273e5606230SFrank Praznik 	 * The data for the second touch is in the same format and immediatly
1274e5606230SFrank Praznik 	 * follows the data for the first.
1275e5606230SFrank Praznik 	 */
1276e5606230SFrank Praznik 	for (n = 0; n < 2; n++) {
12771adf904eSPavel Machek 		u16 x, y;
1278e5606230SFrank Praznik 
1279e5606230SFrank Praznik 		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1280e5606230SFrank Praznik 		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1281e5606230SFrank Praznik 
1282e5606230SFrank Praznik 		input_mt_slot(input_dev, n);
1283e5606230SFrank Praznik 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
1284e5606230SFrank Praznik 					!(rd[offset] >> 7));
1285e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
1286e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
1287e5606230SFrank Praznik 
1288e5606230SFrank Praznik 		offset += 4;
1289e5606230SFrank Praznik 	}
1290d902f472SFrank Praznik }
1291d902f472SFrank Praznik 
1292c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
12931adf904eSPavel Machek 		u8 *rd, int size)
1294c9e4d877SSimon Wood {
1295c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1296c9e4d877SSimon Wood 
1297ad142b9eSFrank Praznik 	/*
1298ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1299c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1300c9e4d877SSimon Wood 	 */
1301fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
13028f5f0bc2SFrank Praznik 		/*
13038f5f0bc2SFrank Praznik 		 * When connected via Bluetooth the Sixaxis occasionally sends
13048f5f0bc2SFrank Praznik 		 * a report with the second byte 0xff and the rest zeroed.
13058f5f0bc2SFrank Praznik 		 *
13068f5f0bc2SFrank Praznik 		 * This report does not reflect the actual state of the
13078f5f0bc2SFrank Praznik 		 * controller must be ignored to avoid generating false input
13088f5f0bc2SFrank Praznik 		 * events.
13098f5f0bc2SFrank Praznik 		 */
13108f5f0bc2SFrank Praznik 		if (rd[1] == 0xff)
13118f5f0bc2SFrank Praznik 			return -EINVAL;
13128f5f0bc2SFrank Praznik 
1313c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1314c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1315c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1316c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1317d902f472SFrank Praznik 
1318d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
131912e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
132012e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
13214545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
13224545ee0aSSimon Wood 			size == 49) {
13234545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
132468330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
132568330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
132668330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
1327d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1328c9e4d877SSimon Wood 	}
1329c9e4d877SSimon Wood 
13302a242932SFrank Praznik 	if (sc->defer_initialization) {
13312a242932SFrank Praznik 		sc->defer_initialization = 0;
13322a242932SFrank Praznik 		sony_schedule_work(sc);
13332a242932SFrank Praznik 	}
13342a242932SFrank Praznik 
1335c9e4d877SSimon Wood 	return 0;
1336c9e4d877SSimon Wood }
1337c9e4d877SSimon Wood 
1338f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1339f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1340f04d5140SColin Leitner 			unsigned long **bit, int *max)
1341f04d5140SColin Leitner {
1342f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1343f04d5140SColin Leitner 
1344f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1345f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1346f04d5140SColin Leitner 
1347f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1348f04d5140SColin Leitner 			return -1;
1349f04d5140SColin Leitner 
1350f04d5140SColin Leitner 		switch (usage->collection_index) {
1351f04d5140SColin Leitner 		case 1:
1352f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1353f04d5140SColin Leitner 				return -1;
1354f04d5140SColin Leitner 
1355f04d5140SColin Leitner 			key = buzz_keymap[key];
1356f04d5140SColin Leitner 			if (!key)
1357f04d5140SColin Leitner 				return -1;
1358f04d5140SColin Leitner 			break;
1359f04d5140SColin Leitner 		default:
1360f04d5140SColin Leitner 			return -1;
1361f04d5140SColin Leitner 		}
1362f04d5140SColin Leitner 
1363f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1364f04d5140SColin Leitner 		return 1;
1365f04d5140SColin Leitner 	}
1366f04d5140SColin Leitner 
1367078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1368078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1369078328daSJiri Kosina 
13706f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
13716f498018SBenjamin Tissoires 	return 0;
1372f04d5140SColin Leitner }
1373f04d5140SColin Leitner 
1374ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count,
1375ce8efc3bSFrank Praznik 					int w, int h)
1376ce8efc3bSFrank Praznik {
1377ce8efc3bSFrank Praznik 	struct input_dev *input_dev = hi->input;
1378ce8efc3bSFrank Praznik 	int ret;
1379ce8efc3bSFrank Praznik 
1380ce8efc3bSFrank Praznik 	ret = input_mt_init_slots(input_dev, touch_count, 0);
1381ce8efc3bSFrank Praznik 	if (ret < 0)
1382ce8efc3bSFrank Praznik 		return ret;
1383ce8efc3bSFrank Praznik 
1384ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
1385ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
1386ce8efc3bSFrank Praznik 
1387ce8efc3bSFrank Praznik 	return 0;
1388ce8efc3bSFrank Praznik }
1389ce8efc3bSFrank Praznik 
13909154301aSDmitry Torokhov 
13915710fabfSAntonio Ospite /*
1392bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1393bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1394bd28ce00SJiri Slaby  * events.
1395bd28ce00SJiri Slaby  */
1396816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1397bd28ce00SJiri Slaby {
1398a85d67b5SAntonio Ospite 	const int buf_size =
1399a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
14001adf904eSPavel Machek 	u8 *buf;
1401bd28ce00SJiri Slaby 	int ret;
1402bd28ce00SJiri Slaby 
14032e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1404bd28ce00SJiri Slaby 	if (!buf)
1405bd28ce00SJiri Slaby 		return -ENOMEM;
1406bd28ce00SJiri Slaby 
1407a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1408a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1409a7de9b86SLauri Kasanen 	if (ret < 0) {
1410a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1411a7de9b86SLauri Kasanen 		goto out;
1412a7de9b86SLauri Kasanen 	}
1413f204828aSBenjamin Tissoires 
1414a7de9b86SLauri Kasanen 	/*
1415a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1416a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1417a7de9b86SLauri Kasanen 	 */
1418a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1419a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1420a7de9b86SLauri Kasanen 	if (ret < 0) {
1421a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1422a7de9b86SLauri Kasanen 		goto out;
1423a7de9b86SLauri Kasanen 	}
1424a7de9b86SLauri Kasanen 
1425a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
142619f4c2baSBenjamin Tissoires 	if (ret < 0) {
142719f4c2baSBenjamin Tissoires 		hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
142819f4c2baSBenjamin Tissoires 		ret = 0;
142919f4c2baSBenjamin Tissoires 	}
1430bd28ce00SJiri Slaby 
1431a7de9b86SLauri Kasanen out:
1432bd28ce00SJiri Slaby 	kfree(buf);
1433bd28ce00SJiri Slaby 
1434bd28ce00SJiri Slaby 	return ret;
1435bd28ce00SJiri Slaby }
1436bd28ce00SJiri Slaby 
1437816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1438f9ce7c28SBastien Nocera {
14391adf904eSPavel Machek 	static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
14401adf904eSPavel Machek 	u8 *buf;
14419b2b5c9aSFrank Praznik 	int ret;
14429b2b5c9aSFrank Praznik 
14439b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
14449b2b5c9aSFrank Praznik 	if (!buf)
14459b2b5c9aSFrank Praznik 		return -ENOMEM;
14469b2b5c9aSFrank Praznik 
14479b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1448b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
14499b2b5c9aSFrank Praznik 
14509b2b5c9aSFrank Praznik 	kfree(buf);
14519b2b5c9aSFrank Praznik 
14529b2b5c9aSFrank Praznik 	return ret;
1453f9ce7c28SBastien Nocera }
1454f9ce7c28SBastien Nocera 
1455ad142b9eSFrank Praznik /*
1456ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
145768330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
145868330d83SFrank Praznik  */
145968330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
146068330d83SFrank Praznik {
14611adf904eSPavel Machek 	u8 *buf;
14629b2b5c9aSFrank Praznik 	int ret;
146368330d83SFrank Praznik 
1464*2c159de0SRoderick Colenbrander 	buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);
14659b2b5c9aSFrank Praznik 	if (!buf)
14669b2b5c9aSFrank Praznik 		return -ENOMEM;
14679b2b5c9aSFrank Praznik 
1468*2c159de0SRoderick Colenbrander 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE,
146968330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
14709b2b5c9aSFrank Praznik 
14719b2b5c9aSFrank Praznik 	kfree(buf);
14729b2b5c9aSFrank Praznik 
14739b2b5c9aSFrank Praznik 	return ret;
1474bd28ce00SJiri Slaby }
1475bd28ce00SJiri Slaby 
1476221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
14778025087aSFrank Praznik {
14781adf904eSPavel Machek 	static const u8 sixaxis_leds[10][4] = {
14798025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
14808025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
14818025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
14828025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
14838025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
14848025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
14858025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
14868025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
14878025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
14888025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
14898025087aSFrank Praznik 	};
14908025087aSFrank Praznik 
1491221399b3SFrank Praznik 	int id = sc->device_id;
1492221399b3SFrank Praznik 
1493221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
14948025087aSFrank Praznik 
14958025087aSFrank Praznik 	if (id < 0)
14968025087aSFrank Praznik 		return;
14978025087aSFrank Praznik 
14988025087aSFrank Praznik 	id %= 10;
1499221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
15008025087aSFrank Praznik }
15018025087aSFrank Praznik 
1502221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
15038025087aSFrank Praznik {
15048025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
15051adf904eSPavel Machek 	static const u8 color_code[7][3] = {
15068025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
15078025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
15088025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
15098025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
15108025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
15118025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
15128025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
15138025087aSFrank Praznik 	};
15148025087aSFrank Praznik 
1515221399b3SFrank Praznik 	int id = sc->device_id;
1516221399b3SFrank Praznik 
1517221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
15188025087aSFrank Praznik 
15198025087aSFrank Praznik 	if (id < 0)
15208025087aSFrank Praznik 		return;
15218025087aSFrank Praznik 
15228025087aSFrank Praznik 	id %= 7;
1523221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
15248025087aSFrank Praznik }
15258025087aSFrank Praznik 
1526221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1527f04d5140SColin Leitner {
1528221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1529f04d5140SColin Leitner 	struct list_head *report_list =
1530f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1531f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1532f04d5140SColin Leitner 		struct hid_report, list);
15331adf904eSPavel Machek 	s32 *value = report->field[0]->value;
1534f04d5140SColin Leitner 
1535221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1536221399b3SFrank Praznik 
1537f04d5140SColin Leitner 	value[0] = 0x00;
1538221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1539221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1540221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1541221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1542f04d5140SColin Leitner 	value[5] = 0x00;
1543f04d5140SColin Leitner 	value[6] = 0x00;
1544f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1545f04d5140SColin Leitner }
1546f04d5140SColin Leitner 
1547221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
15480a286ef2SSven Eckelmann {
1549221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
15502a242932SFrank Praznik 		sony_schedule_work(sc);
1551221399b3SFrank Praznik 	else
1552221399b3SFrank Praznik 		buzz_set_leds(sc);
15530a286ef2SSven Eckelmann }
15540a286ef2SSven Eckelmann 
1555c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1556f04d5140SColin Leitner 				    enum led_brightness value)
1557f04d5140SColin Leitner {
1558f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1559ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1560f04d5140SColin Leitner 	struct sony_sc *drv_data;
1561f04d5140SColin Leitner 
1562f04d5140SColin Leitner 	int n;
1563b3ed458cSFrank Praznik 	int force_update;
1564f04d5140SColin Leitner 
1565f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
15662251b85fSSven Eckelmann 	if (!drv_data) {
1567f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1568f04d5140SColin Leitner 		return;
1569f04d5140SColin Leitner 	}
1570f04d5140SColin Leitner 
1571b3ed458cSFrank Praznik 	/*
1572b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1573b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1574b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1575b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1576b3ed458cSFrank Praznik 	 * stop the flashing later on.
1577b3ed458cSFrank Praznik 	 */
1578b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1579b3ed458cSFrank Praznik 
158060781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1581b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1582b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1583b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1584b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1585b3ed458cSFrank Praznik 
158660781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1587b3ed458cSFrank Praznik 
1588b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1589b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1590b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1591b3ed458cSFrank Praznik 
1592221399b3SFrank Praznik 			sony_set_leds(drv_data);
1593f04d5140SColin Leitner 			break;
1594f04d5140SColin Leitner 		}
1595f04d5140SColin Leitner 	}
1596f04d5140SColin Leitner }
1597f04d5140SColin Leitner 
1598c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1599f04d5140SColin Leitner {
1600f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1601ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1602f04d5140SColin Leitner 	struct sony_sc *drv_data;
1603f04d5140SColin Leitner 
1604f04d5140SColin Leitner 	int n;
1605f04d5140SColin Leitner 
1606f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
16072251b85fSSven Eckelmann 	if (!drv_data) {
1608f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1609f04d5140SColin Leitner 		return LED_OFF;
1610f04d5140SColin Leitner 	}
1611f04d5140SColin Leitner 
161260781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
16137db7504aSSimon Wood 		if (led == drv_data->leds[n])
16147db7504aSSimon Wood 			return drv_data->led_state[n];
1615f04d5140SColin Leitner 	}
1616f04d5140SColin Leitner 
16177db7504aSSimon Wood 	return LED_OFF;
1618f04d5140SColin Leitner }
1619f04d5140SColin Leitner 
1620b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1621b3ed458cSFrank Praznik 				unsigned long *delay_off)
1622b3ed458cSFrank Praznik {
1623b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1624ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
1625b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1626b3ed458cSFrank Praznik 	int n;
16271adf904eSPavel Machek 	u8 new_on, new_off;
1628b3ed458cSFrank Praznik 
1629b3ed458cSFrank Praznik 	if (!drv_data) {
1630b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1631b3ed458cSFrank Praznik 		return -EINVAL;
1632b3ed458cSFrank Praznik 	}
1633b3ed458cSFrank Praznik 
1634b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1635b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1636b3ed458cSFrank Praznik 		*delay_on = 2550;
1637b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1638b3ed458cSFrank Praznik 		*delay_off = 2550;
1639b3ed458cSFrank Praznik 
1640b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1641b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1642b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1643b3ed458cSFrank Praznik 
1644b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1645b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1646b3ed458cSFrank Praznik 
1647b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1648b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1649b3ed458cSFrank Praznik 			break;
1650b3ed458cSFrank Praznik 	}
1651b3ed458cSFrank Praznik 
1652b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1653b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1654b3ed458cSFrank Praznik 		return -EINVAL;
1655b3ed458cSFrank Praznik 
1656b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1657b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1658b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1659b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1660b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
16612a242932SFrank Praznik 		sony_schedule_work(drv_data);
1662b3ed458cSFrank Praznik 	}
1663b3ed458cSFrank Praznik 
1664b3ed458cSFrank Praznik 	return 0;
1665b3ed458cSFrank Praznik }
1666b3ed458cSFrank Praznik 
1667fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
16680a286ef2SSven Eckelmann {
16690a286ef2SSven Eckelmann 	struct led_classdev *led;
16700a286ef2SSven Eckelmann 	int n;
16710a286ef2SSven Eckelmann 
1672fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
16730a286ef2SSven Eckelmann 
1674fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1675fa57a810SFrank Praznik 		led = sc->leds[n];
1676fa57a810SFrank Praznik 		sc->leds[n] = NULL;
16770a286ef2SSven Eckelmann 		if (!led)
16780a286ef2SSven Eckelmann 			continue;
16790a286ef2SSven Eckelmann 		led_classdev_unregister(led);
16800a286ef2SSven Eckelmann 		kfree(led);
16810a286ef2SSven Eckelmann 	}
168260781cf4SFrank Praznik 
1683fa57a810SFrank Praznik 	sc->led_count = 0;
16840a286ef2SSven Eckelmann }
16850a286ef2SSven Eckelmann 
1686fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1687f04d5140SColin Leitner {
1688fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
168940e32ee6SJiri Kosina 	int n, ret = 0;
1690b3ed458cSFrank Praznik 	int use_ds4_names;
169140e32ee6SJiri Kosina 	struct led_classdev *led;
169240e32ee6SJiri Kosina 	size_t name_sz;
169340e32ee6SJiri Kosina 	char *name;
16940a286ef2SSven Eckelmann 	size_t name_len;
16950a286ef2SSven Eckelmann 	const char *name_fmt;
1696b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1697b3ed458cSFrank Praznik 						  "global" };
16981adf904eSPavel Machek 	u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
16991adf904eSPavel Machek 	u8 use_hw_blink[MAX_LEDS] = { 0 };
1700f04d5140SColin Leitner 
1701fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1702f04d5140SColin Leitner 
1703fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1704fa57a810SFrank Praznik 		sc->led_count = 4;
1705b3ed458cSFrank Praznik 		use_ds4_names = 0;
17060a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
17070a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
17089446edb9SKees Cook 		/* Validate expected report characteristics. */
17099446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
17109446edb9SKees Cook 			return -ENODEV;
1711fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1712221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1713221399b3SFrank Praznik 		sc->led_state[3] = 1;
1714b3ed458cSFrank Praznik 		sc->led_count = 4;
1715b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1716b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1717b3ed458cSFrank Praznik 		use_ds4_names = 1;
171861ebca93SFrank Praznik 		name_len = 0;
171961ebca93SFrank Praznik 		name_fmt = "%s:%s";
1720c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1721c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1722c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1723c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1724c5e0c1c4SFrank Praznik 		name_len = 0;
1725c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
17264545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
17271adf904eSPavel Machek 		static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
17284545ee0aSSimon Wood 
17294545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
17304545ee0aSSimon Wood 		sc->led_count = 1;
17314545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
17324545ee0aSSimon Wood 		use_ds4_names = 0;
17334545ee0aSSimon Wood 		name_len = strlen("::sony#");
17344545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
173560781cf4SFrank Praznik 	} else {
1736221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1737fa57a810SFrank Praznik 		sc->led_count = 4;
1738b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1739b3ed458cSFrank Praznik 		use_ds4_names = 0;
174061ebca93SFrank Praznik 		name_len = strlen("::sony#");
174161ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
174260781cf4SFrank Praznik 	}
174360781cf4SFrank Praznik 
1744ad142b9eSFrank Praznik 	/*
1745ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1746f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1747ad142b9eSFrank Praznik 	 * LEDs to on
1748ad142b9eSFrank Praznik 	 */
1749221399b3SFrank Praznik 	sony_set_leds(sc);
1750f04d5140SColin Leitner 
17510a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1752f04d5140SColin Leitner 
1753fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
175461ebca93SFrank Praznik 
1755b3ed458cSFrank Praznik 		if (use_ds4_names)
1756b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
175761ebca93SFrank Praznik 
1758f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1759f04d5140SColin Leitner 		if (!led) {
1760f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
17618cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1762f04d5140SColin Leitner 			goto error_leds;
1763f04d5140SColin Leitner 		}
1764f04d5140SColin Leitner 
1765f04d5140SColin Leitner 		name = (void *)(&led[1]);
1766b3ed458cSFrank Praznik 		if (use_ds4_names)
1767b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1768b3ed458cSFrank Praznik 			ds4_name_str[n]);
176961ebca93SFrank Praznik 		else
17700a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1771f04d5140SColin Leitner 		led->name = name;
1772221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1773b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1774c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1775c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1776f04d5140SColin Leitner 
1777b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1778b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1779b3ed458cSFrank Praznik 
17808025087aSFrank Praznik 		sc->leds[n] = led;
17818025087aSFrank Praznik 
17828cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
17838cd5fcdaSJulia Lawall 		if (ret) {
1784f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
17858025087aSFrank Praznik 			sc->leds[n] = NULL;
1786f04d5140SColin Leitner 			kfree(led);
1787f04d5140SColin Leitner 			goto error_leds;
1788f04d5140SColin Leitner 		}
1789f04d5140SColin Leitner 	}
1790f04d5140SColin Leitner 
1791f04d5140SColin Leitner 	return ret;
1792f04d5140SColin Leitner 
1793f04d5140SColin Leitner error_leds:
1794fa57a810SFrank Praznik 	sony_leds_remove(sc);
1795f04d5140SColin Leitner 
1796f04d5140SColin Leitner 	return ret;
1797f04d5140SColin Leitner }
1798f04d5140SColin Leitner 
1799d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc)
1800a08c22c0SSven Eckelmann {
18019b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
180255d3b664SFrank Praznik 		.buf = {
1803a08c22c0SSven Eckelmann 			0x01,
1804ad07b7a6SScott Moreau 			0x01, 0xff, 0x00, 0xff, 0x00,
18050a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1806a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1807a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1808a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1809a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1810a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
181155d3b664SFrank Praznik 		}
1812a08c22c0SSven Eckelmann 	};
18139b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
18149b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
18159b2b5c9aSFrank Praznik 	int n;
18169b2b5c9aSFrank Praznik 
18179b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
18189b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
18199f323b68SSven Eckelmann 
18200a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
18219b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
18229b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
18230a286ef2SSven Eckelmann #endif
18240a286ef2SSven Eckelmann 
18259b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
18269b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
18279b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
18289b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
18299f323b68SSven Eckelmann 
183088f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
18319b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
18329b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
183388f6576fSSimon Wood 
1834b3ed458cSFrank Praznik 	/*
1835b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
1836b3ed458cSFrank Praznik 	 * corresponding light on the controller.
1837b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
1838b3ed458cSFrank Praznik 	 *
1839b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
1840b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
1841b3ed458cSFrank Praznik 	 * always off.
1842b3ed458cSFrank Praznik 	 */
1843b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
1844b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
18459b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
18469b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
1847b3ed458cSFrank Praznik 		}
1848b3ed458cSFrank Praznik 	}
1849b3ed458cSFrank Praznik 
18501adf904eSPavel Machek 	hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
18519b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
18529b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
18539f323b68SSven Eckelmann }
18549f323b68SSven Eckelmann 
1855d8aaccdaSFrank Praznik static void dualshock4_send_output_report(struct sony_sc *sc)
18560bd88dd3SFrank Praznik {
18570da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
18581adf904eSPavel Machek 	u8 *buf = sc->output_report_dmabuf;
185948220237SFrank Praznik 	int offset;
18600da8ea65SFrank Praznik 
1861c4425c8fSFrank Praznik 	/*
1862c4425c8fSFrank Praznik 	 * NOTE: The buf[1] field of the Bluetooth report controls
1863c4425c8fSFrank Praznik 	 * the Dualshock 4 reporting rate.
1864c4425c8fSFrank Praznik 	 *
1865c4425c8fSFrank Praznik 	 * Known values include:
1866c4425c8fSFrank Praznik 	 *
1867c4425c8fSFrank Praznik 	 * 0x80 - 1000hz (full speed)
1868c4425c8fSFrank Praznik 	 * 0xA0 - 31hz
1869c4425c8fSFrank Praznik 	 * 0xB0 - 20hz
1870c4425c8fSFrank Praznik 	 * 0xD0 - 66hz
1871c4425c8fSFrank Praznik 	 */
1872fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1873*2c159de0SRoderick Colenbrander 		memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE);
187448220237SFrank Praznik 		buf[0] = 0x05;
1875b3ed458cSFrank Praznik 		buf[1] = 0xFF;
187648220237SFrank Praznik 		offset = 4;
1877fdcf105dSFrank Praznik 	} else {
1878*2c159de0SRoderick Colenbrander 		memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE);
1879fdcf105dSFrank Praznik 		buf[0] = 0x11;
1880824deff8SRostislav Pehlivanov 		buf[1] = 0x80;
1881fdcf105dSFrank Praznik 		buf[3] = 0x0F;
1882fdcf105dSFrank Praznik 		offset = 6;
1883fdcf105dSFrank Praznik 	}
18840bd88dd3SFrank Praznik 
18850bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
188648220237SFrank Praznik 	buf[offset++] = sc->right;
188748220237SFrank Praznik 	buf[offset++] = sc->left;
188848220237SFrank Praznik #else
188948220237SFrank Praznik 	offset += 2;
18900bd88dd3SFrank Praznik #endif
18910bd88dd3SFrank Praznik 
1892b3ed458cSFrank Praznik 	/* LED 3 is the global control */
1893b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
189448220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
189548220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
189648220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
1897b3ed458cSFrank Praznik 	} else {
1898b3ed458cSFrank Praznik 		offset += 3;
1899b3ed458cSFrank Praznik 	}
1900b3ed458cSFrank Praznik 
1901b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
1902b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
1903b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
190460781cf4SFrank Praznik 
1905fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
1906*2c159de0SRoderick Colenbrander 		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE);
1907fdcf105dSFrank Praznik 	else
1908*2c159de0SRoderick Colenbrander 		hid_hw_raw_request(hdev, 0x11, buf, DS4_OUTPUT_REPORT_0x11_SIZE,
1909fdcf105dSFrank Praznik 				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
19100bd88dd3SFrank Praznik }
19110bd88dd3SFrank Praznik 
1912d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc)
1913c5e0c1c4SFrank Praznik {
1914c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1915c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
1916c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
1917c5e0c1c4SFrank Praznik 
191841d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
1919c5e0c1c4SFrank Praznik 
1920c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
1921c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
1922c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
1923c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
1924c5e0c1c4SFrank Praznik 
1925c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1926c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
1927c5e0c1c4SFrank Praznik #endif
1928c5e0c1c4SFrank Praznik 
19291adf904eSPavel Machek 	hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE);
1930c5e0c1c4SFrank Praznik }
1931c5e0c1c4SFrank Praznik 
1932decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc)
1933decd946cSFrank Praznik {
1934decd946cSFrank Praznik 	if (sc->send_output_report)
1935decd946cSFrank Praznik 		sc->send_output_report(sc);
1936decd946cSFrank Praznik }
1937decd946cSFrank Praznik 
1938d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work)
1939d8aaccdaSFrank Praznik {
1940d8aaccdaSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1941ef916ef5SAntonio Ospite 
1942d8aaccdaSFrank Praznik 	sc->send_output_report(sc);
1943d8aaccdaSFrank Praznik }
1944d8aaccdaSFrank Praznik 
19459b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
19469b2b5c9aSFrank Praznik {
19474545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
19484545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
19499b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
19509b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
19519b2b5c9aSFrank Praznik 				GFP_KERNEL);
19529b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
1953*2c159de0SRoderick Colenbrander 		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE,
19549b2b5c9aSFrank Praznik 						GFP_KERNEL);
19559b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
1956*2c159de0SRoderick Colenbrander 		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE,
19579b2b5c9aSFrank Praznik 						GFP_KERNEL);
1958c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
195941d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
1960c5e0c1c4SFrank Praznik 						GFP_KERNEL);
19619b2b5c9aSFrank Praznik 	else
19629b2b5c9aSFrank Praznik 		return 0;
19639b2b5c9aSFrank Praznik 
19649b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
19659b2b5c9aSFrank Praznik 		return -ENOMEM;
19669b2b5c9aSFrank Praznik 
19679b2b5c9aSFrank Praznik 	return 0;
19689b2b5c9aSFrank Praznik }
19699b2b5c9aSFrank Praznik 
19700a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
19719f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
19729f323b68SSven Eckelmann 			    struct ff_effect *effect)
19739f323b68SSven Eckelmann {
1974a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
19759f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
1976a08c22c0SSven Eckelmann 
1977a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
1978a08c22c0SSven Eckelmann 		return 0;
1979a08c22c0SSven Eckelmann 
19809f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
19810bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
1982a08c22c0SSven Eckelmann 
19832a242932SFrank Praznik 	sony_schedule_work(sc);
19849f323b68SSven Eckelmann 	return 0;
1985a08c22c0SSven Eckelmann }
1986a08c22c0SSven Eckelmann 
1987fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1988a08c22c0SSven Eckelmann {
1989fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1990a08c22c0SSven Eckelmann 						struct hid_input, list);
1991a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
1992a08c22c0SSven Eckelmann 
1993a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
1994a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
1995a08c22c0SSven Eckelmann }
1996a08c22c0SSven Eckelmann 
1997a08c22c0SSven Eckelmann #else
1998fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1999a08c22c0SSven Eckelmann {
2000a08c22c0SSven Eckelmann 	return 0;
2001a08c22c0SSven Eckelmann }
20029f323b68SSven Eckelmann 
2003a08c22c0SSven Eckelmann #endif
2004a08c22c0SSven Eckelmann 
2005d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
2006d902f472SFrank Praznik 				     enum power_supply_property psp,
2007d902f472SFrank Praznik 				     union power_supply_propval *val)
2008c4e1ddf2SFrank Praznik {
2009297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
2010d902f472SFrank Praznik 	unsigned long flags;
2011d902f472SFrank Praznik 	int ret = 0;
2012d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
2013c4e1ddf2SFrank Praznik 
2014d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
2015d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
2016d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
2017d902f472SFrank Praznik 	cable_state = sc->cable_state;
2018d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
2019c4e1ddf2SFrank Praznik 
2020d902f472SFrank Praznik 	switch (psp) {
2021d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
2022d902f472SFrank Praznik 		val->intval = 1;
2023d902f472SFrank Praznik 		break;
2024d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
2025d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
2026d902f472SFrank Praznik 		break;
2027d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
2028d902f472SFrank Praznik 		val->intval = battery_capacity;
2029d902f472SFrank Praznik 		break;
2030d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
2031d902f472SFrank Praznik 		if (battery_charging)
2032d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
2033d902f472SFrank Praznik 		else
2034d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
2035d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
2036d902f472SFrank Praznik 			else
2037d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2038d902f472SFrank Praznik 		break;
2039d902f472SFrank Praznik 	default:
2040d902f472SFrank Praznik 		ret = -EINVAL;
2041d902f472SFrank Praznik 		break;
2042c4e1ddf2SFrank Praznik 	}
2043d902f472SFrank Praznik 	return ret;
2044d902f472SFrank Praznik }
2045d902f472SFrank Praznik 
20460f398230SFrank Praznik static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
2047d902f472SFrank Praznik {
20480f398230SFrank Praznik 	const char *battery_str_fmt = append_dev_id ?
20490f398230SFrank Praznik 		"sony_controller_battery_%pMR_%i" :
20500f398230SFrank Praznik 		"sony_controller_battery_%pMR";
2051297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
2052d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
2053d902f472SFrank Praznik 	int ret;
2054d902f472SFrank Praznik 
2055ad142b9eSFrank Praznik 	/*
2056ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
2057d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
2058d9a293a9SFrank Praznik 	 */
2059d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
2060d9a293a9SFrank Praznik 
2061297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
2062297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
2063297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
2064297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2065297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
20660f398230SFrank Praznik 	sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
20670f398230SFrank Praznik 					  sc->mac_address, sc->device_id);
2068297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2069d902f472SFrank Praznik 		return -ENOMEM;
2070d902f472SFrank Praznik 
2071297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
2072297d716fSKrzysztof Kozlowski 					    &psy_cfg);
2073297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
2074297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
2075d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
2076d902f472SFrank Praznik 		goto err_free;
2077d902f472SFrank Praznik 	}
2078d902f472SFrank Praznik 
2079297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
2080d902f472SFrank Praznik 	return 0;
2081d902f472SFrank Praznik 
2082d902f472SFrank Praznik err_free:
2083297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2084297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2085d902f472SFrank Praznik 	return ret;
2086d902f472SFrank Praznik }
2087d902f472SFrank Praznik 
2088d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
2089d902f472SFrank Praznik {
2090297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
2091d902f472SFrank Praznik 		return;
2092d902f472SFrank Praznik 
2093297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
2094297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
2095297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
2096d902f472SFrank Praznik }
2097d902f472SFrank Praznik 
2098d2d782fcSFrank Praznik /*
2099d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
2100d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
2101d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
2102d2d782fcSFrank Praznik  * once.
21030f398230SFrank Praznik  *
21040f398230SFrank Praznik  * Some USB-only devices masquerade as Sixaxis controllers and all have the
21050f398230SFrank Praznik  * same dummy Bluetooth address, so a comparison of the connection type is
21060f398230SFrank Praznik  * required.  Devices are only rejected in the case where two devices have
21070f398230SFrank Praznik  * matching Bluetooth addresses on different bus types.
2108d2d782fcSFrank Praznik  */
21090f398230SFrank Praznik static inline int sony_compare_connection_type(struct sony_sc *sc0,
21100f398230SFrank Praznik 						struct sony_sc *sc1)
21110f398230SFrank Praznik {
21120f398230SFrank Praznik 	const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE);
21130f398230SFrank Praznik 	const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
21140f398230SFrank Praznik 
21150f398230SFrank Praznik 	return sc0_not_bt == sc1_not_bt;
21160f398230SFrank Praznik }
21170f398230SFrank Praznik 
2118d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
2119d2d782fcSFrank Praznik {
2120d2d782fcSFrank Praznik 	struct sony_sc *entry;
2121d2d782fcSFrank Praznik 	unsigned long flags;
2122d2d782fcSFrank Praznik 	int ret;
2123d2d782fcSFrank Praznik 
2124d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
2125d2d782fcSFrank Praznik 
2126d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
2127d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
2128d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
2129d2d782fcSFrank Praznik 		if (!ret) {
21300f398230SFrank Praznik 			if (sony_compare_connection_type(sc, entry)) {
21310f398230SFrank Praznik 				ret = 1;
21320f398230SFrank Praznik 			} else {
2133d2d782fcSFrank Praznik 				ret = -EEXIST;
21340f398230SFrank Praznik 				hid_info(sc->hdev,
21350f398230SFrank Praznik 				"controller with MAC address %pMR already connected\n",
2136d2d782fcSFrank Praznik 				sc->mac_address);
21370f398230SFrank Praznik 			}
2138d2d782fcSFrank Praznik 			goto unlock;
2139d2d782fcSFrank Praznik 		}
2140c4e1ddf2SFrank Praznik 	}
2141c4e1ddf2SFrank Praznik 
2142d2d782fcSFrank Praznik 	ret = 0;
2143d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
2144c4e1ddf2SFrank Praznik 
2145d2d782fcSFrank Praznik unlock:
2146d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2147d2d782fcSFrank Praznik 	return ret;
2148d2d782fcSFrank Praznik }
2149d2d782fcSFrank Praznik 
2150d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
2151d2d782fcSFrank Praznik {
2152d2d782fcSFrank Praznik 	unsigned long flags;
2153d2d782fcSFrank Praznik 
2154d2d782fcSFrank Praznik 	if (sc->list_node.next) {
2155d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
2156d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
2157d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
2158d2d782fcSFrank Praznik 	}
2159d2d782fcSFrank Praznik }
2160d2d782fcSFrank Praznik 
2161d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
2162d2d782fcSFrank Praznik {
2163d2d782fcSFrank Praznik 	int ret;
2164d2d782fcSFrank Praznik 
2165d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2166d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2167d2d782fcSFrank Praznik 	if (ret != 17)
2168c4e1ddf2SFrank Praznik 		return -EINVAL;
2169d2d782fcSFrank Praznik 
2170d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2171d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2172d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2173d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2174d2d782fcSFrank Praznik 
2175d2d782fcSFrank Praznik 	if (ret != 6)
2176d2d782fcSFrank Praznik 		return -EINVAL;
2177d2d782fcSFrank Praznik 
2178d2d782fcSFrank Praznik 	return 0;
2179c4e1ddf2SFrank Praznik }
2180c4e1ddf2SFrank Praznik 
2181d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2182d2d782fcSFrank Praznik {
21831adf904eSPavel Machek 	u8 *buf = NULL;
2184d2d782fcSFrank Praznik 	int n, ret;
2185d2d782fcSFrank Praznik 
2186d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
218712e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
21884545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2189d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2190d2d782fcSFrank Praznik 		/*
2191d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2192d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2193d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2194d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2195d2d782fcSFrank Praznik 		 */
2196d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2197d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2198d2d782fcSFrank Praznik 			return 0;
2199d2d782fcSFrank Praznik 		}
2200d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
2201*2c159de0SRoderick Colenbrander 		buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL);
22029b2b5c9aSFrank Praznik 		if (!buf)
22039b2b5c9aSFrank Praznik 			return -ENOMEM;
2204d2d782fcSFrank Praznik 
2205d2d782fcSFrank Praznik 		/*
2206d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2207d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2208d2d782fcSFrank Praznik 		 * offset 1.
2209d2d782fcSFrank Praznik 		 */
22109b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
2211*2c159de0SRoderick Colenbrander 				DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
22129b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2213d2d782fcSFrank Praznik 
2214*2c159de0SRoderick Colenbrander 		if (ret != DS4_FEATURE_REPORT_0x81_SIZE) {
2215d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
22169b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22179b2b5c9aSFrank Praznik 			goto out_free;
2218d2d782fcSFrank Praznik 		}
2219d2d782fcSFrank Praznik 
2220d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
22214545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
22224545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
22239b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
22249b2b5c9aSFrank Praznik 		if (!buf)
22259b2b5c9aSFrank Praznik 			return -ENOMEM;
2226d2d782fcSFrank Praznik 
2227d2d782fcSFrank Praznik 		/*
2228d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2229d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2230d2d782fcSFrank Praznik 		 * offset 4.
2231d2d782fcSFrank Praznik 		 */
22329b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
22339b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
22349b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2235d2d782fcSFrank Praznik 
22369b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2237d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
22389b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
22399b2b5c9aSFrank Praznik 			goto out_free;
2240d2d782fcSFrank Praznik 		}
2241d2d782fcSFrank Praznik 
2242d2d782fcSFrank Praznik 		/*
2243d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2244d2d782fcSFrank Praznik 		 * be byte-swapped.
2245d2d782fcSFrank Praznik 		 */
2246d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2247d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2248d2d782fcSFrank Praznik 	} else {
2249d2d782fcSFrank Praznik 		return 0;
2250d2d782fcSFrank Praznik 	}
2251d2d782fcSFrank Praznik 
22529b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
22539b2b5c9aSFrank Praznik 
22549b2b5c9aSFrank Praznik out_free:
22559b2b5c9aSFrank Praznik 
22569b2b5c9aSFrank Praznik 	kfree(buf);
22579b2b5c9aSFrank Praznik 
22589b2b5c9aSFrank Praznik 	return ret;
2259d2d782fcSFrank Praznik }
2260d2d782fcSFrank Praznik 
22618025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
22628025087aSFrank Praznik {
22638025087aSFrank Praznik 	int ret;
22648025087aSFrank Praznik 
22658025087aSFrank Praznik 	/*
22668025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
22678025087aSFrank Praznik 	 * All others are set to -1.
22688025087aSFrank Praznik 	 */
22698025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
22708025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
22718025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
22728025087aSFrank Praznik 					GFP_KERNEL);
22738025087aSFrank Praznik 		if (ret < 0) {
22748025087aSFrank Praznik 			sc->device_id = -1;
22758025087aSFrank Praznik 			return ret;
22768025087aSFrank Praznik 		}
22778025087aSFrank Praznik 		sc->device_id = ret;
22788025087aSFrank Praznik 	} else {
22798025087aSFrank Praznik 		sc->device_id = -1;
22808025087aSFrank Praznik 	}
22818025087aSFrank Praznik 
22828025087aSFrank Praznik 	return 0;
22838025087aSFrank Praznik }
22848025087aSFrank Praznik 
22858025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
22868025087aSFrank Praznik {
22878025087aSFrank Praznik 	if (sc->device_id >= 0) {
22888025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
22898025087aSFrank Praznik 		sc->device_id = -1;
22908025087aSFrank Praznik 	}
22918025087aSFrank Praznik }
22928025087aSFrank Praznik 
2293d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc,
2294d8aaccdaSFrank Praznik 				void (*send_output_report)(struct sony_sc *))
229546262047SFrank Praznik {
2296d8aaccdaSFrank Praznik 	sc->send_output_report = send_output_report;
2297d8aaccdaSFrank Praznik 
229846262047SFrank Praznik 	if (!sc->worker_initialized)
2299d8aaccdaSFrank Praznik 		INIT_WORK(&sc->state_worker, sony_state_worker);
230046262047SFrank Praznik 
230146262047SFrank Praznik 	sc->worker_initialized = 1;
230246262047SFrank Praznik }
230346262047SFrank Praznik 
230446262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
230546262047SFrank Praznik {
230646262047SFrank Praznik 	if (sc->worker_initialized)
230746262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
230846262047SFrank Praznik }
2309d2d782fcSFrank Praznik 
2310e1bc84d0SRoderick Colenbrander static int sony_input_configured(struct hid_device *hdev,
2311e1bc84d0SRoderick Colenbrander 					struct hid_input *hidinput)
2312bd28ce00SJiri Slaby {
2313e1bc84d0SRoderick Colenbrander 	struct sony_sc *sc = hid_get_drvdata(hdev);
23140f398230SFrank Praznik 	int append_dev_id;
2315e1bc84d0SRoderick Colenbrander 	int ret;
2316bd28ce00SJiri Slaby 
23178025087aSFrank Praznik 	ret = sony_set_device_id(sc);
23188025087aSFrank Praznik 	if (ret < 0) {
23198025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
23208025087aSFrank Praznik 		goto err_stop;
23218025087aSFrank Praznik 	}
23228025087aSFrank Praznik 
2323131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2324131a8a9aSFrank Praznik 	if (ret < 0) {
2325131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2326131a8a9aSFrank Praznik 		goto err_stop;
2327131a8a9aSFrank Praznik 	}
2328131a8a9aSFrank Praznik 
23294545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
23304545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2331e534a935SBenjamin Tissoires 		/*
2332e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2333e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2334e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2335e534a935SBenjamin Tissoires 		 *
2336e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2337e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2338e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2339e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
23402a242932SFrank Praznik 		 *
23412a242932SFrank Praznik 		 * Additionally, the Sixaxis on USB isn't properly initialized
23422a242932SFrank Praznik 		 * until the PS logo button is pressed and as such won't retain
23432a242932SFrank Praznik 		 * any state set by an output report, so the initial
23442a242932SFrank Praznik 		 * configuration report is deferred until the first input
23452a242932SFrank Praznik 		 * report arrives.
2346e534a935SBenjamin Tissoires 		 */
2347e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2348e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
23492a242932SFrank Praznik 		sc->defer_initialization = 1;
2350816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
2351d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
23524545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
23534545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
23542078b9bbSFrank Praznik 		/*
23552078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
23562078b9bbSFrank Praznik 		 * when connected via Bluetooth.
23572078b9bbSFrank Praznik 		 */
23582078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2359816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
2360d8aaccdaSFrank Praznik 		sony_init_output_report(sc, sixaxis_send_output_report);
2361fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
236268330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
23632078b9bbSFrank Praznik 			/*
23642078b9bbSFrank Praznik 			 * The DualShock 4 wants output reports sent on the ctrl
23652078b9bbSFrank Praznik 			 * endpoint when connected via Bluetooth.
23662078b9bbSFrank Praznik 			 */
23672078b9bbSFrank Praznik 			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
236868330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
236968330d83SFrank Praznik 			if (ret < 0) {
237068330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
237168330d83SFrank Praznik 				goto err_stop;
237268330d83SFrank Praznik 			}
237368330d83SFrank Praznik 		}
2374c4e1ddf2SFrank Praznik 
2375e1bc84d0SRoderick Colenbrander 		/*
2376e1bc84d0SRoderick Colenbrander 		 * The Dualshock 4 touchpad supports 2 touches and has a
2377e1bc84d0SRoderick Colenbrander 		 * resolution of 1920x942 (44.86 dots/mm).
2378e1bc84d0SRoderick Colenbrander 		 */
2379e1bc84d0SRoderick Colenbrander 		ret = sony_register_touchpad(hidinput, 2, 1920, 942);
2380e1bc84d0SRoderick Colenbrander 		if (ret) {
2381e1bc84d0SRoderick Colenbrander 			hid_err(sc->hdev,
2382e1bc84d0SRoderick Colenbrander 			"Unable to initialize multi-touch slots: %d\n",
2383e1bc84d0SRoderick Colenbrander 			ret);
2384e1bc84d0SRoderick Colenbrander 			return ret;
2385e1bc84d0SRoderick Colenbrander 		}
2386e1bc84d0SRoderick Colenbrander 
2387d8aaccdaSFrank Praznik 		sony_init_output_report(sc, dualshock4_send_output_report);
2388c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2389d8aaccdaSFrank Praznik 		sony_init_output_report(sc, motion_send_output_report);
23900bd88dd3SFrank Praznik 	} else {
23910bd88dd3SFrank Praznik 		ret = 0;
23920bd88dd3SFrank Praznik 	}
2393f9ce7c28SBastien Nocera 
23944dfdc464SJiri Kosina 	if (ret < 0)
2395bd28ce00SJiri Slaby 		goto err_stop;
2396bd28ce00SJiri Slaby 
23970f398230SFrank Praznik 	ret = append_dev_id = sony_check_add(sc);
2398d2d782fcSFrank Praznik 	if (ret < 0)
2399d2d782fcSFrank Praznik 		goto err_stop;
2400d2d782fcSFrank Praznik 
24010a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2402fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
24030a286ef2SSven Eckelmann 		if (ret < 0)
24040a286ef2SSven Eckelmann 			goto err_stop;
24050a286ef2SSven Eckelmann 	}
24060a286ef2SSven Eckelmann 
2407d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
24080f398230SFrank Praznik 		ret = sony_battery_probe(sc, append_dev_id);
2409a08c22c0SSven Eckelmann 		if (ret < 0)
2410a08c22c0SSven Eckelmann 			goto err_stop;
2411a08c22c0SSven Eckelmann 
2412d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2413d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2414d902f472SFrank Praznik 		if (ret < 0) {
2415d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2416d902f472SFrank Praznik 			goto err_stop;
2417d902f472SFrank Praznik 		}
2418d902f472SFrank Praznik 	}
2419d902f472SFrank Praznik 
2420c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2421fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2422d902f472SFrank Praznik 		if (ret < 0)
2423d902f472SFrank Praznik 			goto err_close;
24245f5750d2SFrank Praznik 	}
2425bd28ce00SJiri Slaby 
2426f425458eSH Hartley Sweeten 	return 0;
2427d902f472SFrank Praznik err_close:
2428d902f472SFrank Praznik 	hid_hw_close(hdev);
2429bd28ce00SJiri Slaby err_stop:
24300a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2431fa57a810SFrank Praznik 		sony_leds_remove(sc);
2432d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2433d902f472SFrank Praznik 		sony_battery_remove(sc);
243446262047SFrank Praznik 	sony_cancel_work_sync(sc);
24359b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2436d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
24378025087aSFrank Praznik 	sony_release_device_id(sc);
2438bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2439bd28ce00SJiri Slaby 	return ret;
2440bd28ce00SJiri Slaby }
2441bd28ce00SJiri Slaby 
2442e1bc84d0SRoderick Colenbrander static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2443e1bc84d0SRoderick Colenbrander {
2444e1bc84d0SRoderick Colenbrander 	int ret;
2445e1bc84d0SRoderick Colenbrander 	unsigned long quirks = id->driver_data;
2446e1bc84d0SRoderick Colenbrander 	struct sony_sc *sc;
2447e1bc84d0SRoderick Colenbrander 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2448e1bc84d0SRoderick Colenbrander 
2449e1bc84d0SRoderick Colenbrander 	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
2450e1bc84d0SRoderick Colenbrander 		quirks |= FUTUREMAX_DANCE_MAT;
2451e1bc84d0SRoderick Colenbrander 
2452e1bc84d0SRoderick Colenbrander 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2453e1bc84d0SRoderick Colenbrander 	if (sc == NULL) {
2454e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "can't alloc sony descriptor\n");
2455e1bc84d0SRoderick Colenbrander 		return -ENOMEM;
2456e1bc84d0SRoderick Colenbrander 	}
2457e1bc84d0SRoderick Colenbrander 
2458e1bc84d0SRoderick Colenbrander 	spin_lock_init(&sc->lock);
2459e1bc84d0SRoderick Colenbrander 
2460e1bc84d0SRoderick Colenbrander 	sc->quirks = quirks;
2461e1bc84d0SRoderick Colenbrander 	hid_set_drvdata(hdev, sc);
2462e1bc84d0SRoderick Colenbrander 	sc->hdev = hdev;
2463e1bc84d0SRoderick Colenbrander 
2464e1bc84d0SRoderick Colenbrander 	ret = hid_parse(hdev);
2465e1bc84d0SRoderick Colenbrander 	if (ret) {
2466e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "parse failed\n");
2467e1bc84d0SRoderick Colenbrander 		return ret;
2468e1bc84d0SRoderick Colenbrander 	}
2469e1bc84d0SRoderick Colenbrander 
2470e1bc84d0SRoderick Colenbrander 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2471e1bc84d0SRoderick Colenbrander 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2472e1bc84d0SRoderick Colenbrander 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2473e1bc84d0SRoderick Colenbrander 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2474e1bc84d0SRoderick Colenbrander 
2475e1bc84d0SRoderick Colenbrander 	ret = hid_hw_start(hdev, connect_mask);
2476e1bc84d0SRoderick Colenbrander 	if (ret) {
2477e1bc84d0SRoderick Colenbrander 		hid_err(hdev, "hw start failed\n");
2478e1bc84d0SRoderick Colenbrander 		return ret;
2479e1bc84d0SRoderick Colenbrander 	}
2480e1bc84d0SRoderick Colenbrander 
2481e1bc84d0SRoderick Colenbrander 	return ret;
2482e1bc84d0SRoderick Colenbrander }
2483e1bc84d0SRoderick Colenbrander 
2484bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2485bd28ce00SJiri Slaby {
2486bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2487bd28ce00SJiri Slaby 
24880a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2489fa57a810SFrank Praznik 		sony_leds_remove(sc);
2490bd28ce00SJiri Slaby 
2491d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2492d902f472SFrank Praznik 		hid_hw_close(hdev);
2493d902f472SFrank Praznik 		sony_battery_remove(sc);
2494d902f472SFrank Praznik 	}
2495d902f472SFrank Praznik 
249646262047SFrank Praznik 	sony_cancel_work_sync(sc);
24979f323b68SSven Eckelmann 
24989b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
24999b2b5c9aSFrank Praznik 
2500d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2501bd28ce00SJiri Slaby 
25028025087aSFrank Praznik 	sony_release_device_id(sc);
25038025087aSFrank Praznik 
2504bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2505bd28ce00SJiri Slaby }
2506bd28ce00SJiri Slaby 
2507decd946cSFrank Praznik #ifdef CONFIG_PM
2508decd946cSFrank Praznik 
2509decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2510decd946cSFrank Praznik {
2511decd946cSFrank Praznik 	/*
2512decd946cSFrank Praznik 	 * On suspend save the current LED state,
2513decd946cSFrank Praznik 	 * stop running force-feedback and blank the LEDS.
2514decd946cSFrank Praznik 	 */
2515decd946cSFrank Praznik 	if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
2516decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2517decd946cSFrank Praznik 
2518decd946cSFrank Praznik #ifdef CONFIG_SONY_FF
2519decd946cSFrank Praznik 		sc->left = sc->right = 0;
2520decd946cSFrank Praznik #endif
2521decd946cSFrank Praznik 
2522decd946cSFrank Praznik 		memcpy(sc->resume_led_state, sc->led_state,
2523decd946cSFrank Praznik 			sizeof(sc->resume_led_state));
2524decd946cSFrank Praznik 		memset(sc->led_state, 0, sizeof(sc->led_state));
2525decd946cSFrank Praznik 
2526decd946cSFrank Praznik 		sony_send_output_report(sc);
2527decd946cSFrank Praznik 	}
2528decd946cSFrank Praznik 
2529decd946cSFrank Praznik 	return 0;
2530decd946cSFrank Praznik }
2531decd946cSFrank Praznik 
2532decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev)
2533decd946cSFrank Praznik {
2534decd946cSFrank Praznik 	/* Restore the state of controller LEDs on resume */
2535decd946cSFrank Praznik 	if (SONY_LED_SUPPORT) {
2536decd946cSFrank Praznik 		struct sony_sc *sc = hid_get_drvdata(hdev);
2537decd946cSFrank Praznik 
2538decd946cSFrank Praznik 		memcpy(sc->led_state, sc->resume_led_state,
2539decd946cSFrank Praznik 			sizeof(sc->led_state));
2540decd946cSFrank Praznik 
2541decd946cSFrank Praznik 		/*
2542decd946cSFrank Praznik 		 * The Sixaxis and navigation controllers on USB need to be
2543decd946cSFrank Praznik 		 * reinitialized on resume or they won't behave properly.
2544decd946cSFrank Praznik 		 */
2545decd946cSFrank Praznik 		if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
25462a242932SFrank Praznik 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2547decd946cSFrank Praznik 			sixaxis_set_operational_usb(sc->hdev);
25482a242932SFrank Praznik 			sc->defer_initialization = 1;
25492a242932SFrank Praznik 		}
2550decd946cSFrank Praznik 
2551decd946cSFrank Praznik 		sony_set_leds(sc);
2552decd946cSFrank Praznik 	}
2553decd946cSFrank Praznik 
2554decd946cSFrank Praznik 	return 0;
2555decd946cSFrank Praznik }
2556decd946cSFrank Praznik 
2557decd946cSFrank Praznik #endif
2558decd946cSFrank Praznik 
2559bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2560bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2561bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2562bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
25634545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
25646eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
25654545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2566c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2567b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2568a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2569b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2570bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2571bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2572bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2573bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2574bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2575bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2576ef916ef5SAntonio Ospite 	/*
2577ef916ef5SAntonio Ospite 	 * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2578ef916ef5SAntonio Ospite 	 * Logitech joystick from the device descriptor.
2579ef916ef5SAntonio Ospite 	 */
2580bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2581bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2582bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2583bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2584bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2585bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2586bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2587bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2588bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2589bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
259068a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
259168a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
259268a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
25930bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
25940bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
25958ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
25960bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
25978ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
259874500cc8SScott Moreau 	/* Nyko Core Controller for PS3 */
259974500cc8SScott Moreau 	{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
260074500cc8SScott Moreau 		.driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
2601bd28ce00SJiri Slaby 	{ }
2602bd28ce00SJiri Slaby };
2603bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2604bd28ce00SJiri Slaby 
2605bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2606bd28ce00SJiri Slaby 	.name             = "sony",
2607bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2608bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2609ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2610bd28ce00SJiri Slaby 	.probe            = sony_probe,
2611bd28ce00SJiri Slaby 	.remove           = sony_remove,
2612bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2613decd946cSFrank Praznik 	.raw_event        = sony_raw_event,
2614decd946cSFrank Praznik 
2615decd946cSFrank Praznik #ifdef CONFIG_PM
2616decd946cSFrank Praznik 	.suspend          = sony_suspend,
2617decd946cSFrank Praznik 	.resume	          = sony_resume,
2618decd946cSFrank Praznik 	.reset_resume     = sony_resume,
2619decd946cSFrank Praznik #endif
2620bd28ce00SJiri Slaby };
26218025087aSFrank Praznik 
26228025087aSFrank Praznik static int __init sony_init(void)
26238025087aSFrank Praznik {
26248025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
26258025087aSFrank Praznik 
26268025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
26278025087aSFrank Praznik }
26288025087aSFrank Praznik 
26298025087aSFrank Praznik static void __exit sony_exit(void)
26308025087aSFrank Praznik {
26318025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
26328025087aSFrank Praznik 
26338025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
26346c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
26358025087aSFrank Praznik }
26368025087aSFrank Praznik module_init(sony_init);
26378025087aSFrank Praznik module_exit(sony_exit);
2638bd28ce00SJiri Slaby 
2639bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2640