xref: /linux/drivers/hid/hid-sony.c (revision 4545ee0a70e49b7d355181540a77c0a1aa2a7fe4)
1bd28ce00SJiri Slaby /*
2077147a3SFrank Praznik  *  HID driver for Sony / PS2 / PS3 / PS4 BD devices.
3bd28ce00SJiri Slaby  *
4bd28ce00SJiri Slaby  *  Copyright (c) 1999 Andreas Gal
5bd28ce00SJiri Slaby  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6bd28ce00SJiri Slaby  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7bd28ce00SJiri Slaby  *  Copyright (c) 2008 Jiri Slaby
8078328daSJiri Kosina  *  Copyright (c) 2012 David Dillow <dave@thedillows.org>
9078328daSJiri Kosina  *  Copyright (c) 2006-2013 Jiri Kosina
10f04d5140SColin Leitner  *  Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
11077147a3SFrank Praznik  *  Copyright (c) 2014 Frank Praznik <frank.praznik@gmail.com>
12bd28ce00SJiri Slaby  */
13bd28ce00SJiri Slaby 
14bd28ce00SJiri Slaby /*
15bd28ce00SJiri Slaby  * This program is free software; you can redistribute it and/or modify it
16bd28ce00SJiri Slaby  * under the terms of the GNU General Public License as published by the Free
17bd28ce00SJiri Slaby  * Software Foundation; either version 2 of the License, or (at your option)
18bd28ce00SJiri Slaby  * any later version.
19bd28ce00SJiri Slaby  */
20bd28ce00SJiri Slaby 
21ad142b9eSFrank Praznik /*
22ad142b9eSFrank Praznik  * NOTE: in order for the Sony PS3 BD Remote Control to be found by
23078328daSJiri Kosina  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
24078328daSJiri Kosina  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
25078328daSJiri Kosina  *
26078328daSJiri Kosina  * There will be no PIN request from the device.
27078328daSJiri Kosina  */
28078328daSJiri Kosina 
29bd28ce00SJiri Slaby #include <linux/device.h>
30bd28ce00SJiri Slaby #include <linux/hid.h>
31bd28ce00SJiri Slaby #include <linux/module.h>
325a0e3ad6STejun Heo #include <linux/slab.h>
3340e32ee6SJiri Kosina #include <linux/leds.h>
34d902f472SFrank Praznik #include <linux/power_supply.h>
35d902f472SFrank Praznik #include <linux/spinlock.h>
36d2d782fcSFrank Praznik #include <linux/list.h>
378025087aSFrank Praznik #include <linux/idr.h>
38e5606230SFrank Praznik #include <linux/input/mt.h>
39bd28ce00SJiri Slaby 
40bd28ce00SJiri Slaby #include "hid-ids.h"
41bd28ce00SJiri Slaby 
42f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT       BIT(0)
43f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB    BIT(1)
44f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT     BIT(2)
45f1c458caSSven Eckelmann #define BUZZ_CONTROLLER           BIT(3)
46f1c458caSSven Eckelmann #define PS3REMOTE                 BIT(4)
478ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5)
488ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
49b3bca326SSimon Wood #define MOTION_CONTROLLER_USB     BIT(7)
50b3bca326SSimon Wood #define MOTION_CONTROLLER_BT      BIT(8)
51*4545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9)
52*4545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT  BIT(10)
53cc6e0bbbSJiri Kosina 
54fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
55b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
56*4545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\
57*4545ee0aSSimon Wood 				NAVIGATION_CONTROLLER_BT)
5868330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
5968330d83SFrank Praznik 				DUALSHOCK4_CONTROLLER_BT)
60fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
61*4545ee0aSSimon Wood 				DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
62*4545ee0aSSimon Wood 				NAVIGATION_CONTROLLER)
6312e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
64*4545ee0aSSimon Wood 				MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
65c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
66c5e0c1c4SFrank Praznik 				MOTION_CONTROLLER)
6760781cf4SFrank Praznik 
6860781cf4SFrank Praznik #define MAX_LEDS 4
690a286ef2SSven Eckelmann 
704c3e8298SFrank Praznik /*
714c3e8298SFrank Praznik  * The Sixaxis reports both digital and analog values for each button on the
724c3e8298SFrank Praznik  * controller except for Start, Select and the PS button.  The controller ends
734c3e8298SFrank Praznik  * up reporting 27 axes which causes them to spill over into the multi-touch
744c3e8298SFrank Praznik  * axis values.  Additionally, the controller only has 20 actual, physical axes
754c3e8298SFrank Praznik  * so there are several unused axes in between the used ones.
764c3e8298SFrank Praznik  */
77c607fb8dSAntonio Ospite static __u8 sixaxis_rdesc[] = {
78fb705a6dSAntonio Ospite 	0x05, 0x01,         /*  Usage Page (Desktop),               */
794c3e8298SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
80fb705a6dSAntonio Ospite 	0xA1, 0x01,         /*  Collection (Application),           */
81fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
82fb705a6dSAntonio Ospite 	0x85, 0x01,         /*          Report ID (1),              */
83fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
84fb705a6dSAntonio Ospite 	0x95, 0x01,         /*          Report Count (1),           */
85fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
86fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
87fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
88fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
89fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
90fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
91fb705a6dSAntonio Ospite 	0x25, 0x01,         /*          Logical Maximum (1),        */
92fb705a6dSAntonio Ospite 	0x35, 0x00,         /*          Physical Minimum (0),       */
93fb705a6dSAntonio Ospite 	0x45, 0x01,         /*          Physical Maximum (1),       */
94fb705a6dSAntonio Ospite 	0x05, 0x09,         /*          Usage Page (Button),        */
95fb705a6dSAntonio Ospite 	0x19, 0x01,         /*          Usage Minimum (01h),        */
96fb705a6dSAntonio Ospite 	0x29, 0x13,         /*          Usage Maximum (13h),        */
97fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
98fb705a6dSAntonio Ospite 	0x75, 0x01,         /*          Report Size (1),            */
99fb705a6dSAntonio Ospite 	0x95, 0x0D,         /*          Report Count (13),          */
100fb705a6dSAntonio Ospite 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
101fb705a6dSAntonio Ospite 	0x81, 0x03,         /*          Input (Constant, Variable), */
102fb705a6dSAntonio Ospite 	0x15, 0x00,         /*          Logical Minimum (0),        */
103fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
104fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
105fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
106fb705a6dSAntonio Ospite 	0xA1, 0x00,         /*          Collection (Physical),      */
107fb705a6dSAntonio Ospite 	0x75, 0x08,         /*              Report Size (8),        */
108fb705a6dSAntonio Ospite 	0x95, 0x04,         /*              Report Count (4),       */
109fb705a6dSAntonio Ospite 	0x35, 0x00,         /*              Physical Minimum (0),   */
110fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
111fb705a6dSAntonio Ospite 	0x09, 0x30,         /*              Usage (X),              */
112fb705a6dSAntonio Ospite 	0x09, 0x31,         /*              Usage (Y),              */
113fb705a6dSAntonio Ospite 	0x09, 0x32,         /*              Usage (Z),              */
114fb705a6dSAntonio Ospite 	0x09, 0x35,         /*              Usage (Rz),             */
115fb705a6dSAntonio Ospite 	0x81, 0x02,         /*              Input (Variable),       */
116fb705a6dSAntonio Ospite 	0xC0,               /*          End Collection,             */
117fb705a6dSAntonio Ospite 	0x05, 0x01,         /*          Usage Page (Desktop),       */
118fb705a6dSAntonio Ospite 	0x95, 0x13,         /*          Report Count (19),          */
119fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
120fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
121fb705a6dSAntonio Ospite 	0x95, 0x0C,         /*          Report Count (12),          */
122fb705a6dSAntonio Ospite 	0x81, 0x01,         /*          Input (Constant),           */
123fb705a6dSAntonio Ospite 	0x75, 0x10,         /*          Report Size (16),           */
124fb705a6dSAntonio Ospite 	0x95, 0x04,         /*          Report Count (4),           */
125fb705a6dSAntonio Ospite 	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
126fb705a6dSAntonio Ospite 	0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
127fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
128fb705a6dSAntonio Ospite 	0x81, 0x02,         /*          Input (Variable),           */
129fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
130fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
131fb705a6dSAntonio Ospite 	0x85, 0x02,         /*          Report ID (2),              */
132fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
133fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
134fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
135fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
136fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
137fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
138fb705a6dSAntonio Ospite 	0x85, 0xEE,         /*          Report ID (238),            */
139fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
140fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
141fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
142fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
143fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
144fb705a6dSAntonio Ospite 	0xA1, 0x02,         /*      Collection (Logical),           */
145fb705a6dSAntonio Ospite 	0x85, 0xEF,         /*          Report ID (239),            */
146fb705a6dSAntonio Ospite 	0x75, 0x08,         /*          Report Size (8),            */
147fb705a6dSAntonio Ospite 	0x95, 0x30,         /*          Report Count (48),          */
148fb705a6dSAntonio Ospite 	0x09, 0x01,         /*          Usage (Pointer),            */
149fb705a6dSAntonio Ospite 	0xB1, 0x02,         /*          Feature (Variable),         */
150fb705a6dSAntonio Ospite 	0xC0,               /*      End Collection,                 */
151fb705a6dSAntonio Ospite 	0xC0                /*  End Collection                      */
152e57a67daSMauro Carvalho Chehab };
153e57a67daSMauro Carvalho Chehab 
154c5e0c1c4SFrank Praznik /* PS/3 Motion controller */
155c5e0c1c4SFrank Praznik static __u8 motion_rdesc[] = {
156c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
157c5e0c1c4SFrank Praznik 	0x09, 0x04,         /*  Usage (Joystick),                   */
158c5e0c1c4SFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
159c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
160c5e0c1c4SFrank Praznik 	0x85, 0x01,         /*          Report ID (1),              */
161c5e0c1c4SFrank Praznik 	0x75, 0x01,         /*          Report Size (1),            */
1628b2513c3SSimon Wood 	0x95, 0x15,         /*          Report Count (21),          */
163c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
164c5e0c1c4SFrank Praznik 	0x25, 0x01,         /*          Logical Maximum (1),        */
165c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*          Physical Minimum (0),       */
166c5e0c1c4SFrank Praznik 	0x45, 0x01,         /*          Physical Maximum (1),       */
167c5e0c1c4SFrank Praznik 	0x05, 0x09,         /*          Usage Page (Button),        */
168c5e0c1c4SFrank Praznik 	0x19, 0x01,         /*          Usage Minimum (01h),        */
1698b2513c3SSimon Wood 	0x29, 0x15,         /*          Usage Maximum (15h),        */
1708b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           * Buttons */
1718b2513c3SSimon Wood 	0x95, 0x0B,         /*          Report Count (11),          */
172c5e0c1c4SFrank Praznik 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1738b2513c3SSimon Wood 	0x81, 0x03,         /*          Input (Constant, Variable), * Padding */
174c5e0c1c4SFrank Praznik 	0x15, 0x00,         /*          Logical Minimum (0),        */
175c5e0c1c4SFrank Praznik 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
176c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
177c5e0c1c4SFrank Praznik 	0xA1, 0x00,         /*          Collection (Physical),      */
178c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*              Report Size (8),        */
1798b2513c3SSimon Wood 	0x95, 0x01,         /*              Report Count (1),       */
180c5e0c1c4SFrank Praznik 	0x35, 0x00,         /*              Physical Minimum (0),   */
181c5e0c1c4SFrank Praznik 	0x46, 0xFF, 0x00,   /*              Physical Maximum (255), */
182c5e0c1c4SFrank Praznik 	0x09, 0x30,         /*              Usage (X),              */
1838b2513c3SSimon Wood 	0x81, 0x02,         /*              Input (Variable),       * Trigger */
184c5e0c1c4SFrank Praznik 	0xC0,               /*          End Collection,             */
1858b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1868b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
1878b2513c3SSimon Wood 	0x95, 0x07,         /*          Report Count (7),           * skip 7 bytes */
1888b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
189c5e0c1c4SFrank Praznik 	0x05, 0x01,         /*          Usage Page (Desktop),       */
190c5e0c1c4SFrank Praznik 	0x75, 0x10,         /*          Report Size (16),           */
1918b2513c3SSimon Wood 	0x46, 0xFF, 0xFF,   /*          Physical Maximum (65535),   */
1928b2513c3SSimon Wood 	0x27, 0xFF, 0xFF, 0x00, 0x00, /*      Logical Maximum (65535),    */
1938b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Accels */
1948b2513c3SSimon Wood 	0x09, 0x33,         /*              Usage (rX),             */
1958b2513c3SSimon Wood 	0x09, 0x34,         /*              Usage (rY),             */
1968b2513c3SSimon Wood 	0x09, 0x35,         /*              Usage (rZ),             */
197c5e0c1c4SFrank Praznik 	0x81, 0x02,         /*          Input (Variable),           */
1988b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
1998b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Accels 2nd frame */
2008b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2018b2513c3SSimon Wood 	0x05, 0x01,         /*          Usage Page (Desktop),       */
2028b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2038b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * 3x Gyros */
2048b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2058b2513c3SSimon Wood 	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
2068b2513c3SSimon Wood 	0x95, 0x03,         /*          Report Count (3),           * Skip Gyros 2nd frame */
2078b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2088b2513c3SSimon Wood 	0x75, 0x0C,         /*          Report Size (12),           */
2098b2513c3SSimon Wood 	0x46, 0xFF, 0x0F,   /*          Physical Maximum (4095),    */
2108b2513c3SSimon Wood 	0x26, 0xFF, 0x0F,   /*          Logical Maximum (4095),     */
2118b2513c3SSimon Wood 	0x95, 0x04,         /*          Report Count (4),           * Skip Temp and Magnetometers */
2128b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2138b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2148b2513c3SSimon Wood 	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
2158b2513c3SSimon Wood 	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
2168b2513c3SSimon Wood 	0x95, 0x06,         /*          Report Count (6),           * Skip Timestamp and Extension Bytes */
2178b2513c3SSimon Wood 	0x81, 0x02,         /*          Input (Variable),           */
2188b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2198b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2208b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2218b2513c3SSimon Wood 	0x91, 0x02,         /*          Output (Variable),          */
2228b2513c3SSimon Wood 	0x75, 0x08,         /*          Report Size (8),            */
2238b2513c3SSimon Wood 	0x95, 0x30,         /*          Report Count (48),          */
2248b2513c3SSimon Wood 	0x09, 0x01,         /*          Usage (Pointer),            */
2258b2513c3SSimon Wood 	0xB1, 0x02,         /*          Feature (Variable),         */
226c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
227c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
228c5e0c1c4SFrank Praznik 	0x85, 0x02,         /*          Report ID (2),              */
229c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
230c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
231c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
232c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
233c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
234c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
235c5e0c1c4SFrank Praznik 	0x85, 0xEE,         /*          Report ID (238),            */
236c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
237c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
238c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
239c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
240c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
241c5e0c1c4SFrank Praznik 	0xA1, 0x02,         /*      Collection (Logical),           */
242c5e0c1c4SFrank Praznik 	0x85, 0xEF,         /*          Report ID (239),            */
243c5e0c1c4SFrank Praznik 	0x75, 0x08,         /*          Report Size (8),            */
244c5e0c1c4SFrank Praznik 	0x95, 0x30,         /*          Report Count (48),          */
245c5e0c1c4SFrank Praznik 	0x09, 0x01,         /*          Usage (Pointer),            */
246c5e0c1c4SFrank Praznik 	0xB1, 0x02,         /*          Feature (Variable),         */
247c5e0c1c4SFrank Praznik 	0xC0,               /*      End Collection,                 */
248c5e0c1c4SFrank Praznik 	0xC0                /*  End Collection                      */
249c5e0c1c4SFrank Praznik };
250c5e0c1c4SFrank Praznik 
251c5e0c1c4SFrank Praznik 
252ad142b9eSFrank Praznik /*
253ad142b9eSFrank Praznik  * The default descriptor doesn't provide mapping for the accelerometers
25458d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
25558d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
25658d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
25758d7027bSFrank Praznik  */
258ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
25958d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
26058d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
26158d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
26258d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
26358d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
26458d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
26558d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
26658d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
26758d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
26858d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
26958d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
27058d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
27158d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
27258d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
27358d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
27458d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
27558d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
27658d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
27758d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
27858d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
27958d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
28058d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
28158d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
28258d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
28358d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
28458d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
28558d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
28658d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
28758d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
28858d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
28958d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
29058d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
29158d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
29258d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
29358d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
29458d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
295fb291cbdSFrank Praznik 	0x25, 0x3F,         /*      Logical Maximum (63),           */
29658d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
29758d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
29858d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
29958d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
30058d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
30158d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
30258d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
30358d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
30458d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
30558d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
30658d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
30758d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
30858d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
30958d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
31058d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
31158d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
31258d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
31358d7027bSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
31458d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
31558d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
31658d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
31758d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
31858d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
319fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
320fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
32158d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
32258d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
32358d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
32458d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
32558d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
326fb291cbdSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
32758d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
32858d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
32958d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
33058d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
33158d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
33258d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
33358d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
33458d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
33558d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
33658d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
33758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
33858d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
33958d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
34058d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
34158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
34258d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
34358d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
34458d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
34558d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
34658d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
34758d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
34858d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
34958d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
35058d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
35158d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
35258d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
35358d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
35458d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
35558d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
35658d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
35758d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
35858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
35958d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
36058d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
36158d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
36258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
36358d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
36458d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
36558d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
36658d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
36758d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
36858d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
36958d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
37058d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
37158d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
37258d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
37358d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
37458d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
37558d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
37658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
37758d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
37858d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
37958d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
38058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
38158d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
38258d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
38358d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
38458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
38558d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
38658d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
38758d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
38858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
38958d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
39058d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
39158d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
39258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
39358d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
39458d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
39558d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
39658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
39758d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
39858d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
39958d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
40058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
40158d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
40258d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
40358d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
40458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
40558d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
40658d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
40758d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
40858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
40958d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
41058d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
41158d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
41258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
41358d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
41458d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
41558d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
41658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
41758d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
41858d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
41958d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
42058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42158d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
42258d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
42358d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
42458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42558d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
42658d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
42758d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
42858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
42958d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
43058d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
43158d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
43258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43358d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
43458d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
43558d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
43658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
43758d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
43858d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
43958d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
44058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44158d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
44258d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
44358d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
44458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44558d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
44658d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
44758d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
44858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
44958d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
45058d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
45158d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
45258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45358d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
45458d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
45558d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
45658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
45758d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
45858d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
45958d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
46058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46158d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
46258d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
46358d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
46458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46558d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
46658d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
46758d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
46858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
46958d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
47058d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
47158d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
47258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47358d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
47458d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
47558d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
47658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
47758d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
47858d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
47958d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
48058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48158d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
48258d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
48358d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
48458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48558d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
48658d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
48758d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
48858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
48958d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
49058d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
49158d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
49258d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49358d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
49458d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
49558d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
49658d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
49758d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
49858d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
49958d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
50058d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50158d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
50258d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
50358d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
50458d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50558d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
50658d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
50758d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
50858d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
50958d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
510ed19d8cfSFrank Praznik };
511ed19d8cfSFrank Praznik 
512ad142b9eSFrank Praznik /*
513ad142b9eSFrank Praznik  * The default behavior of the Dualshock 4 is to send reports using report
514077147a3SFrank Praznik  * type 1 when running over Bluetooth. However, when feature report 2 is
515077147a3SFrank Praznik  * requested during the controller initialization it starts sending input
516077147a3SFrank Praznik  * reports in report 17.  Since report 17 is undefined in the default HID
517d829674dSFrank Praznik  * descriptor the button and axis definitions must be moved to report 17 or
518077147a3SFrank Praznik  * the HID layer won't process the received input.
519d829674dSFrank Praznik  */
520d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = {
521d829674dSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
522d829674dSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
523d829674dSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
524d829674dSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
525d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
526d829674dSFrank Praznik 	0x95, 0x0A,         /*      Report Count (9),               */
527d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
528d829674dSFrank Praznik 	0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
529d829674dSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
530d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
531d829674dSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
532d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
533d829674dSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
534d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
535d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
536d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
537d829674dSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
538d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
539d829674dSFrank Praznik 	0x95, 0x28,         /*      Report Count (40),              */
540d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
541d829674dSFrank Praznik 	0x85, 0x06,         /*      Report ID (6),                  */
542d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
543d829674dSFrank Praznik 	0x95, 0x34,         /*      Report Count (52),              */
544d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
545d829674dSFrank Praznik 	0x85, 0x07,         /*      Report ID (7),                  */
546d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
547d829674dSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
548d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
549d829674dSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
550d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
551d829674dSFrank Praznik 	0x95, 0x2F,         /*      Report Count (47),              */
552d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
553d829674dSFrank Praznik 	0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
554d829674dSFrank Praznik 	0x85, 0x03,         /*      Report ID (3),                  */
555d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
556d829674dSFrank Praznik 	0x95, 0x26,         /*      Report Count (38),              */
557d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
558d829674dSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
559d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
560d829674dSFrank Praznik 	0x95, 0x2E,         /*      Report Count (46),              */
561d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
562d829674dSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
563d829674dSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
564d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
565d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
566d829674dSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
567d829674dSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
568d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
569d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
570d829674dSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
571d829674dSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
572d829674dSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
573d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
574d829674dSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
575d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
576d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
577d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
578d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
579d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
580d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
581d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
582d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
583d829674dSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
584d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
585d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
586d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
587d829674dSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
588d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
589d829674dSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
590d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
591d829674dSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
592d829674dSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
593d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
594d829674dSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
595d829674dSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
596d829674dSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
597d829674dSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
598d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
599d829674dSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
600d829674dSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
601d829674dSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
602d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
603d829674dSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
604d829674dSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
605d829674dSFrank Praznik 	0x81, 0x01,         /*      Input (Constant),               */
606d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
607d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
608d829674dSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
609d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
610d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
611d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
612d829674dSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
613d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
614d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
615d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
616d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
617d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
618d829674dSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
619d829674dSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
620d829674dSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
621d829674dSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
622d829674dSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
623d829674dSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
624d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
625d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
626d829674dSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
627d829674dSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
628fb291cbdSFrank Praznik 	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
629fb291cbdSFrank Praznik 	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
630d829674dSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
631d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
632d829674dSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
633d829674dSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
634d829674dSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
635d829674dSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
636d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
637d829674dSFrank Praznik 	0x95, 0x31,         /*      Report Count (51),              */
638d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
639d829674dSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
640d829674dSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
641d829674dSFrank Praznik 	0x95, 0x4D,         /*      Report Count (77),              */
642d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
643d829674dSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
644d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
645d829674dSFrank Praznik 	0x95, 0x8D,         /*      Report Count (141),             */
646d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
647d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
648d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
649d829674dSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
650d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
651d829674dSFrank Praznik 	0x95, 0xCD,         /*      Report Count (205),             */
652d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
653d829674dSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
654d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
655d829674dSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
656d829674dSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
657d829674dSFrank Praznik 	0x96, 0x0D, 0x01,   /*      Report Count (269),             */
658d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
659d829674dSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
660d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
661d829674dSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
662d829674dSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
663d829674dSFrank Praznik 	0x96, 0x4D, 0x01,   /*      Report Count (333),             */
664d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
665d829674dSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
666d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
667d829674dSFrank Praznik 	0x85, 0x16,         /*      Report ID (22),                 */
668d829674dSFrank Praznik 	0x09, 0x2A,         /*      Usage (2Ah),                    */
669d829674dSFrank Praznik 	0x96, 0x8D, 0x01,   /*      Report Count (397),             */
670d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
671d829674dSFrank Praznik 	0x09, 0x2B,         /*      Usage (2Bh),                    */
672d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
673d829674dSFrank Praznik 	0x85, 0x17,         /*      Report ID (23),                 */
674d829674dSFrank Praznik 	0x09, 0x2C,         /*      Usage (2Ch),                    */
675d829674dSFrank Praznik 	0x96, 0xCD, 0x01,   /*      Report Count (461),             */
676d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
677d829674dSFrank Praznik 	0x09, 0x2D,         /*      Usage (2Dh),                    */
678d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
679d829674dSFrank Praznik 	0x85, 0x18,         /*      Report ID (24),                 */
680d829674dSFrank Praznik 	0x09, 0x2E,         /*      Usage (2Eh),                    */
681d829674dSFrank Praznik 	0x96, 0x0D, 0x02,   /*      Report Count (525),             */
682d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
683d829674dSFrank Praznik 	0x09, 0x2F,         /*      Usage (2Fh),                    */
684d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
685d829674dSFrank Praznik 	0x85, 0x19,         /*      Report ID (25),                 */
686d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
687d829674dSFrank Praznik 	0x96, 0x22, 0x02,   /*      Report Count (546),             */
688d829674dSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
689d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
690d829674dSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
691d829674dSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
692d829674dSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
693d829674dSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
694d829674dSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
695d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
696d829674dSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
697d829674dSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
698d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
699d829674dSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
700d829674dSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
701d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
702d829674dSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
703d829674dSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
704d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
705d829674dSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
706d829674dSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
707d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
708d829674dSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
709d829674dSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
710d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
711d829674dSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
712d829674dSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
713d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
714d829674dSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
715d829674dSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
716d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
717d829674dSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
718d829674dSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
719d829674dSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
720d829674dSFrank Praznik 	0xC0                /*  End Collection                      */
721d829674dSFrank Praznik };
722d829674dSFrank Praznik 
723078328daSJiri Kosina static __u8 ps3remote_rdesc[] = {
724078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
725078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
726078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
727078328daSJiri Kosina 
728078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
729078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
730078328daSJiri Kosina 
731078328daSJiri Kosina 	  /* Ignore the 1st byte, maybe it is used for a controller
732078328daSJiri Kosina 	   * number but it's not needed for correct operation */
733078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
734078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
735078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
736078328daSJiri Kosina 
737078328daSJiri Kosina 	  /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
738078328daSJiri Kosina 	   * buttons multiple keypresses are allowed */
739078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
740078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
741078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
742078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
743078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
744078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
745078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
746078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
747078328daSJiri Kosina 
748078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
749078328daSJiri Kosina 
750078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
751078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
752078328daSJiri Kosina 
753078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
754078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
755078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
756078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
757078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
758078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
759078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
760078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
761078328daSJiri Kosina 	  0x80,              /* MInput  */
762078328daSJiri Kosina 
763078328daSJiri Kosina 	  /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
764078328daSJiri Kosina 	   * 0xff and 11th is for press indication */
765078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
766078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
767078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
768078328daSJiri Kosina 
769078328daSJiri Kosina 	  /* 12th byte is for battery strength */
770078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
771078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
772078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
773078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
774078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
775078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
776078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
777078328daSJiri Kosina 
778078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
779078328daSJiri Kosina 
780078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
781078328daSJiri Kosina };
782078328daSJiri Kosina 
783078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
784078328daSJiri Kosina 	[0x01] = KEY_SELECT,
785078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
786078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
787078328daSJiri Kosina 	[0x04] = BTN_START,
788078328daSJiri Kosina 	[0x05] = KEY_UP,
789078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
790078328daSJiri Kosina 	[0x07] = KEY_DOWN,
791078328daSJiri Kosina 	[0x08] = KEY_LEFT,
792078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
793078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
794078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
795078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
796078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
797078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
798078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
799078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
800078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
801078328daSJiri Kosina 	[0x14] = KEY_ENTER,
802078328daSJiri Kosina };
803078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
804078328daSJiri Kosina 	[0x00] = KEY_1,
805078328daSJiri Kosina 	[0x01] = KEY_2,
806078328daSJiri Kosina 	[0x02] = KEY_3,
807078328daSJiri Kosina 	[0x03] = KEY_4,
808078328daSJiri Kosina 	[0x04] = KEY_5,
809078328daSJiri Kosina 	[0x05] = KEY_6,
810078328daSJiri Kosina 	[0x06] = KEY_7,
811078328daSJiri Kosina 	[0x07] = KEY_8,
812078328daSJiri Kosina 	[0x08] = KEY_9,
813078328daSJiri Kosina 	[0x09] = KEY_0,
814078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
815078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
816078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
817078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
818078328daSJiri Kosina 	[0x28] = KEY_TIME,
819078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
820078328daSJiri Kosina 	[0x31] = KEY_NEXT,
821078328daSJiri Kosina 	[0x32] = KEY_PLAY,
822078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
823078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
824078328daSJiri Kosina 	[0x38] = KEY_STOP,
825078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
826078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
827078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
828078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
829078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
830078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
831078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
832078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
833078328daSJiri Kosina 	[0x80] = KEY_BLUE,
834078328daSJiri Kosina 	[0x81] = KEY_RED,
835078328daSJiri Kosina 	[0x82] = KEY_GREEN,
836078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
837078328daSJiri Kosina };
838078328daSJiri Kosina 
839f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
840ad142b9eSFrank Praznik 	/*
841ad142b9eSFrank Praznik 	 * The controller has 4 remote buzzers, each with one LED and 5
842f04d5140SColin Leitner 	 * buttons.
843f04d5140SColin Leitner 	 *
844f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
845f04d5140SColin Leitner 	 *
846f04d5140SColin Leitner 	 * Key          Offset
847f04d5140SColin Leitner 	 * -------------------
848f04d5140SColin Leitner 	 * Buzz              1
849f04d5140SColin Leitner 	 * Blue              5
850f04d5140SColin Leitner 	 * Orange            4
851f04d5140SColin Leitner 	 * Green             3
852f04d5140SColin Leitner 	 * Yellow            2
853f04d5140SColin Leitner 	 *
854f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
855f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
856f04d5140SColin Leitner 	 */
857f04d5140SColin Leitner 	[ 1] = BTN_TRIGGER_HAPPY1,
858f04d5140SColin Leitner 	[ 2] = BTN_TRIGGER_HAPPY2,
859f04d5140SColin Leitner 	[ 3] = BTN_TRIGGER_HAPPY3,
860f04d5140SColin Leitner 	[ 4] = BTN_TRIGGER_HAPPY4,
861f04d5140SColin Leitner 	[ 5] = BTN_TRIGGER_HAPPY5,
862f04d5140SColin Leitner 	[ 6] = BTN_TRIGGER_HAPPY6,
863f04d5140SColin Leitner 	[ 7] = BTN_TRIGGER_HAPPY7,
864f04d5140SColin Leitner 	[ 8] = BTN_TRIGGER_HAPPY8,
865f04d5140SColin Leitner 	[ 9] = BTN_TRIGGER_HAPPY9,
866f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
867f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
868f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
869f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
870f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
871f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
872f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
873f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
874f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
875f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
876f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
877f04d5140SColin Leitner };
878f04d5140SColin Leitner 
879d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
880d902f472SFrank Praznik 	POWER_SUPPLY_PROP_PRESENT,
881d902f472SFrank Praznik 	POWER_SUPPLY_PROP_CAPACITY,
882d902f472SFrank Praznik 	POWER_SUPPLY_PROP_SCOPE,
883d902f472SFrank Praznik 	POWER_SUPPLY_PROP_STATUS,
884d902f472SFrank Praznik };
885d902f472SFrank Praznik 
88655d3b664SFrank Praznik struct sixaxis_led {
88755d3b664SFrank Praznik 	__u8 time_enabled; /* the total time the led is active (0xff means forever) */
88855d3b664SFrank Praznik 	__u8 duty_length;  /* how long a cycle is in deciseconds (0 means "really fast") */
88955d3b664SFrank Praznik 	__u8 enabled;
89055d3b664SFrank Praznik 	__u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
89155d3b664SFrank Praznik 	__u8 duty_on;  /* % of duty_length the led is on (0xff mean 100%) */
89255d3b664SFrank Praznik } __packed;
89355d3b664SFrank Praznik 
89455d3b664SFrank Praznik struct sixaxis_rumble {
89555d3b664SFrank Praznik 	__u8 padding;
89655d3b664SFrank Praznik 	__u8 right_duration; /* Right motor duration (0xff means forever) */
89755d3b664SFrank Praznik 	__u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
89855d3b664SFrank Praznik 	__u8 left_duration;    /* Left motor duration (0xff means forever) */
89955d3b664SFrank Praznik 	__u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
90055d3b664SFrank Praznik } __packed;
90155d3b664SFrank Praznik 
90255d3b664SFrank Praznik struct sixaxis_output_report {
90355d3b664SFrank Praznik 	__u8 report_id;
90455d3b664SFrank Praznik 	struct sixaxis_rumble rumble;
90555d3b664SFrank Praznik 	__u8 padding[4];
90655d3b664SFrank Praznik 	__u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
90755d3b664SFrank Praznik 	struct sixaxis_led led[4];    /* LEDx at (4 - x) */
90855d3b664SFrank Praznik 	struct sixaxis_led _reserved; /* LED5, not actually soldered */
90955d3b664SFrank Praznik } __packed;
91055d3b664SFrank Praznik 
91155d3b664SFrank Praznik union sixaxis_output_report_01 {
91255d3b664SFrank Praznik 	struct sixaxis_output_report data;
91355d3b664SFrank Praznik 	__u8 buf[36];
91455d3b664SFrank Praznik };
91555d3b664SFrank Praznik 
916c5e0c1c4SFrank Praznik struct motion_output_report_02 {
917c5e0c1c4SFrank Praznik 	u8 type, zero;
918c5e0c1c4SFrank Praznik 	u8 r, g, b;
919c5e0c1c4SFrank Praznik 	u8 zero2;
920c5e0c1c4SFrank Praznik 	u8 rumble;
921c5e0c1c4SFrank Praznik };
922c5e0c1c4SFrank Praznik 
9239b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37
9249b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32
9259b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78
9269b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7
92729b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
928a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
92941d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
9309b2b5c9aSFrank Praznik 
9318b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
932d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
9338025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
934d2d782fcSFrank Praznik 
935cc6e0bbbSJiri Kosina struct sony_sc {
936d902f472SFrank Praznik 	spinlock_t lock;
937d2d782fcSFrank Praznik 	struct list_head list_node;
9380a286ef2SSven Eckelmann 	struct hid_device *hdev;
93960781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
940cc6e0bbbSJiri Kosina 	unsigned long quirks;
9410a286ef2SSven Eckelmann 	struct work_struct state_worker;
942297d716fSKrzysztof Kozlowski 	struct power_supply *battery;
943297d716fSKrzysztof Kozlowski 	struct power_supply_desc battery_desc;
9448025087aSFrank Praznik 	int device_id;
9459b2b5c9aSFrank Praznik 	__u8 *output_report_dmabuf;
946f04d5140SColin Leitner 
9479f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
9489f323b68SSven Eckelmann 	__u8 left;
9499f323b68SSven Eckelmann 	__u8 right;
9509f323b68SSven Eckelmann #endif
9519f323b68SSven Eckelmann 
952d2d782fcSFrank Praznik 	__u8 mac_address[6];
9535f5750d2SFrank Praznik 	__u8 worker_initialized;
954d902f472SFrank Praznik 	__u8 cable_state;
955d902f472SFrank Praznik 	__u8 battery_charging;
956d902f472SFrank Praznik 	__u8 battery_capacity;
95760781cf4SFrank Praznik 	__u8 led_state[MAX_LEDS];
958b3ed458cSFrank Praznik 	__u8 led_delay_on[MAX_LEDS];
959b3ed458cSFrank Praznik 	__u8 led_delay_off[MAX_LEDS];
96060781cf4SFrank Praznik 	__u8 led_count;
961cc6e0bbbSJiri Kosina };
962cc6e0bbbSJiri Kosina 
963c607fb8dSAntonio Ospite static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc,
964c607fb8dSAntonio Ospite 			     unsigned int *rsize)
965c607fb8dSAntonio Ospite {
966c607fb8dSAntonio Ospite 	*rsize = sizeof(sixaxis_rdesc);
967c607fb8dSAntonio Ospite 	return sixaxis_rdesc;
968c607fb8dSAntonio Ospite }
969c607fb8dSAntonio Ospite 
970c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
971c5e0c1c4SFrank Praznik 			     unsigned int *rsize)
972c5e0c1c4SFrank Praznik {
973c5e0c1c4SFrank Praznik 	*rsize = sizeof(motion_rdesc);
974c5e0c1c4SFrank Praznik 	return motion_rdesc;
975c5e0c1c4SFrank Praznik }
976c5e0c1c4SFrank Praznik 
977078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
978078328daSJiri Kosina 			     unsigned int *rsize)
979078328daSJiri Kosina {
980078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
981078328daSJiri Kosina 	return ps3remote_rdesc;
982078328daSJiri Kosina }
983078328daSJiri Kosina 
984078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
985078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
986078328daSJiri Kosina 			     unsigned long **bit, int *max)
987078328daSJiri Kosina {
988078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
989078328daSJiri Kosina 
990078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
991078328daSJiri Kosina 		return -1;
992078328daSJiri Kosina 
993078328daSJiri Kosina 	switch (usage->collection_index) {
994078328daSJiri Kosina 	case 1:
995078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
996078328daSJiri Kosina 			return -1;
997078328daSJiri Kosina 
998078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
999078328daSJiri Kosina 		if (!key)
1000078328daSJiri Kosina 			return -1;
1001078328daSJiri Kosina 		break;
1002078328daSJiri Kosina 	case 2:
1003078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
1004078328daSJiri Kosina 			return -1;
1005078328daSJiri Kosina 
1006078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
1007078328daSJiri Kosina 		if (!key)
1008078328daSJiri Kosina 			return -1;
1009078328daSJiri Kosina 		break;
1010078328daSJiri Kosina 	default:
1011078328daSJiri Kosina 		return -1;
1012078328daSJiri Kosina 	}
1013078328daSJiri Kosina 
1014078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1015078328daSJiri Kosina 	return 1;
1016078328daSJiri Kosina }
1017078328daSJiri Kosina 
101873e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
101973e4008dSNikolai Kondrashov 		unsigned int *rsize)
1020cc6e0bbbSJiri Kosina {
1021cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
1022cc6e0bbbSJiri Kosina 
102399d24902SFernando Luis Vázquez Cao 	/*
102499d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
102599d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
102699d24902SFernando Luis Vázquez Cao 	 */
102799d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
102899d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
102999d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
103099d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
103199d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
103299d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
103399d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
1034a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
103599d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
1036cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
1037cc6e0bbbSJiri Kosina 	}
103861ab44beSSimon Wood 
1039ed19d8cfSFrank Praznik 	/*
1040ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
1041ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
1042ed19d8cfSFrank Praznik 	 * modified one.
1043ed19d8cfSFrank Praznik 	 */
1044ed19d8cfSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) {
1045ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
1046ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
1047ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
1048d829674dSFrank Praznik 	} else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) {
1049d829674dSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
1050d829674dSFrank Praznik 		rdesc = dualshock4_bt_rdesc;
1051d829674dSFrank Praznik 		*rsize = sizeof(dualshock4_bt_rdesc);
1052ed19d8cfSFrank Praznik 	}
1053ed19d8cfSFrank Praznik 
1054c607fb8dSAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER)
1055c607fb8dSAntonio Ospite 		return sixaxis_fixup(hdev, rdesc, rsize);
1056078328daSJiri Kosina 
1057c5e0c1c4SFrank Praznik 	if (sc->quirks & MOTION_CONTROLLER)
1058c5e0c1c4SFrank Praznik 		return motion_fixup(hdev, rdesc, rsize);
1059c5e0c1c4SFrank Praznik 
1060*4545ee0aSSimon Wood 	if (sc->quirks & NAVIGATION_CONTROLLER)
1061*4545ee0aSSimon Wood 		return sixaxis_fixup(hdev, rdesc, rsize);
1062*4545ee0aSSimon Wood 
1063078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1064078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
1065078328daSJiri Kosina 
106673e4008dSNikolai Kondrashov 	return rdesc;
1067cc6e0bbbSJiri Kosina }
1068cc6e0bbbSJiri Kosina 
1069d902f472SFrank Praznik static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
1070d902f472SFrank Praznik {
1071d902f472SFrank Praznik 	static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
1072d902f472SFrank Praznik 	unsigned long flags;
107312e9a6d7SSimon Wood 	int offset;
1074d902f472SFrank Praznik 	__u8 cable_state, battery_capacity, battery_charging;
1075d902f472SFrank Praznik 
1076ad142b9eSFrank Praznik 	/*
1077ad142b9eSFrank Praznik 	 * The sixaxis is charging if the battery value is 0xee
1078d902f472SFrank Praznik 	 * and it is fully charged if the value is 0xef.
1079d902f472SFrank Praznik 	 * It does not report the actual level while charging so it
1080d902f472SFrank Praznik 	 * is set to 100% while charging is in progress.
1081d902f472SFrank Praznik 	 */
108212e9a6d7SSimon Wood 	offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
108312e9a6d7SSimon Wood 
108412e9a6d7SSimon Wood 	if (rd[offset] >= 0xee) {
1085d902f472SFrank Praznik 		battery_capacity = 100;
108612e9a6d7SSimon Wood 		battery_charging = !(rd[offset] & 0x01);
10879fddd74aSFrank Praznik 		cable_state = 1;
1088d902f472SFrank Praznik 	} else {
108912e9a6d7SSimon Wood 		__u8 index = rd[offset] <= 5 ? rd[offset] : 5;
1090ac3c9a94SFrank Praznik 		battery_capacity = sixaxis_battery_capacity[index];
1091d902f472SFrank Praznik 		battery_charging = 0;
10929fddd74aSFrank Praznik 		cable_state = 0;
1093d902f472SFrank Praznik 	}
1094d902f472SFrank Praznik 
1095d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1096d902f472SFrank Praznik 	sc->cable_state = cable_state;
1097d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1098d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1099d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1100d902f472SFrank Praznik }
1101d902f472SFrank Praznik 
1102d902f472SFrank Praznik static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
1103d902f472SFrank Praznik {
1104e5606230SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1105e5606230SFrank Praznik 						struct hid_input, list);
1106e5606230SFrank Praznik 	struct input_dev *input_dev = hidinput->input;
1107d902f472SFrank Praznik 	unsigned long flags;
11086c5f860dSFrank Praznik 	int n, offset;
1109d902f472SFrank Praznik 	__u8 cable_state, battery_capacity, battery_charging;
1110d902f472SFrank Praznik 
1111ad142b9eSFrank Praznik 	/*
1112ad142b9eSFrank Praznik 	 * Battery and touchpad data starts at byte 30 in the USB report and
11136c5f860dSFrank Praznik 	 * 32 in Bluetooth report.
11146c5f860dSFrank Praznik 	 */
11156c5f860dSFrank Praznik 	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
11166c5f860dSFrank Praznik 
1117ad142b9eSFrank Praznik 	/*
1118ad142b9eSFrank Praznik 	 * The lower 4 bits of byte 30 contain the battery level
1119d902f472SFrank Praznik 	 * and the 5th bit contains the USB cable state.
1120d902f472SFrank Praznik 	 */
11216c5f860dSFrank Praznik 	cable_state = (rd[offset] >> 4) & 0x01;
11226c5f860dSFrank Praznik 	battery_capacity = rd[offset] & 0x0F;
1123d902f472SFrank Praznik 
1124ad142b9eSFrank Praznik 	/*
1125ad142b9eSFrank Praznik 	 * When a USB power source is connected the battery level ranges from
11266c5f860dSFrank Praznik 	 * 0 to 10, and when running on battery power it ranges from 0 to 9.
11276c5f860dSFrank Praznik 	 * A battery level above 10 when plugged in means charge completed.
1128d902f472SFrank Praznik 	 */
11296c5f860dSFrank Praznik 	if (!cable_state || battery_capacity > 10)
1130d902f472SFrank Praznik 		battery_charging = 0;
1131d902f472SFrank Praznik 	else
1132d902f472SFrank Praznik 		battery_charging = 1;
1133d902f472SFrank Praznik 
11346c5f860dSFrank Praznik 	if (!cable_state)
11356c5f860dSFrank Praznik 		battery_capacity++;
1136d902f472SFrank Praznik 	if (battery_capacity > 10)
11376c5f860dSFrank Praznik 		battery_capacity = 10;
11386c5f860dSFrank Praznik 
1139d902f472SFrank Praznik 	battery_capacity *= 10;
1140d902f472SFrank Praznik 
1141d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1142d902f472SFrank Praznik 	sc->cable_state = cable_state;
1143d902f472SFrank Praznik 	sc->battery_capacity = battery_capacity;
1144d902f472SFrank Praznik 	sc->battery_charging = battery_charging;
1145d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1146e5606230SFrank Praznik 
11476c5f860dSFrank Praznik 	offset += 5;
11486c5f860dSFrank Praznik 
1149ad142b9eSFrank Praznik 	/*
1150ad142b9eSFrank Praznik 	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
11516c5f860dSFrank Praznik 	 * and 37 on Bluetooth.
1152e5606230SFrank Praznik 	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
1153e5606230SFrank Praznik 	 * indicator that is 0 when pressed and 1 when not pressed.
1154e5606230SFrank Praznik 	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
1155e5606230SFrank Praznik 	 * The data for the second touch is in the same format and immediatly
1156e5606230SFrank Praznik 	 * follows the data for the first.
1157e5606230SFrank Praznik 	 */
1158e5606230SFrank Praznik 	for (n = 0; n < 2; n++) {
1159e5606230SFrank Praznik 		__u16 x, y;
1160e5606230SFrank Praznik 
1161e5606230SFrank Praznik 		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
1162e5606230SFrank Praznik 		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
1163e5606230SFrank Praznik 
1164e5606230SFrank Praznik 		input_mt_slot(input_dev, n);
1165e5606230SFrank Praznik 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
1166e5606230SFrank Praznik 					!(rd[offset] >> 7));
1167e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
1168e5606230SFrank Praznik 		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
1169e5606230SFrank Praznik 
1170e5606230SFrank Praznik 		offset += 4;
1171e5606230SFrank Praznik 	}
1172d902f472SFrank Praznik }
1173d902f472SFrank Praznik 
1174c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
1175c9e4d877SSimon Wood 		__u8 *rd, int size)
1176c9e4d877SSimon Wood {
1177c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
1178c9e4d877SSimon Wood 
1179ad142b9eSFrank Praznik 	/*
1180ad142b9eSFrank Praznik 	 * Sixaxis HID report has acclerometers/gyro with MSByte first, this
1181c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
1182c9e4d877SSimon Wood 	 */
1183fee4e2d5SFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
1184c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
1185c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
1186c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
1187c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
1188d902f472SFrank Praznik 
1189d902f472SFrank Praznik 		sixaxis_parse_report(sc, rd, size);
119012e9a6d7SSimon Wood 	} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
119112e9a6d7SSimon Wood 		sixaxis_parse_report(sc, rd, size);
1192*4545ee0aSSimon Wood 	} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
1193*4545ee0aSSimon Wood 			size == 49) {
1194*4545ee0aSSimon Wood 		sixaxis_parse_report(sc, rd, size);
119568330d83SFrank Praznik 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
119668330d83SFrank Praznik 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
119768330d83SFrank Praznik 			&& rd[0] == 0x11 && size == 78)) {
1198d902f472SFrank Praznik 		dualshock4_parse_report(sc, rd, size);
1199c9e4d877SSimon Wood 	}
1200c9e4d877SSimon Wood 
1201c9e4d877SSimon Wood 	return 0;
1202c9e4d877SSimon Wood }
1203c9e4d877SSimon Wood 
1204f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
1205f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
1206f04d5140SColin Leitner 			unsigned long **bit, int *max)
1207f04d5140SColin Leitner {
1208f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1209f04d5140SColin Leitner 
1210f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
1211f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
1212f04d5140SColin Leitner 
1213f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
1214f04d5140SColin Leitner 			return -1;
1215f04d5140SColin Leitner 
1216f04d5140SColin Leitner 		switch (usage->collection_index) {
1217f04d5140SColin Leitner 		case 1:
1218f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
1219f04d5140SColin Leitner 				return -1;
1220f04d5140SColin Leitner 
1221f04d5140SColin Leitner 			key = buzz_keymap[key];
1222f04d5140SColin Leitner 			if (!key)
1223f04d5140SColin Leitner 				return -1;
1224f04d5140SColin Leitner 			break;
1225f04d5140SColin Leitner 		default:
1226f04d5140SColin Leitner 			return -1;
1227f04d5140SColin Leitner 		}
1228f04d5140SColin Leitner 
1229f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
1230f04d5140SColin Leitner 		return 1;
1231f04d5140SColin Leitner 	}
1232f04d5140SColin Leitner 
1233078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
1234078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
1235078328daSJiri Kosina 
12366f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
12376f498018SBenjamin Tissoires 	return 0;
1238f04d5140SColin Leitner }
1239f04d5140SColin Leitner 
1240ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count,
1241ce8efc3bSFrank Praznik 					int w, int h)
1242ce8efc3bSFrank Praznik {
1243ce8efc3bSFrank Praznik 	struct input_dev *input_dev = hi->input;
1244ce8efc3bSFrank Praznik 	int ret;
1245ce8efc3bSFrank Praznik 
1246ce8efc3bSFrank Praznik 	ret = input_mt_init_slots(input_dev, touch_count, 0);
1247ce8efc3bSFrank Praznik 	if (ret < 0)
1248ce8efc3bSFrank Praznik 		return ret;
1249ce8efc3bSFrank Praznik 
1250ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
1251ce8efc3bSFrank Praznik 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
1252ce8efc3bSFrank Praznik 
1253ce8efc3bSFrank Praznik 	return 0;
1254ce8efc3bSFrank Praznik }
1255ce8efc3bSFrank Praznik 
1256ce8efc3bSFrank Praznik static void sony_input_configured(struct hid_device *hdev,
1257ce8efc3bSFrank Praznik 					struct hid_input *hidinput)
1258ce8efc3bSFrank Praznik {
1259ce8efc3bSFrank Praznik 	struct sony_sc *sc = hid_get_drvdata(hdev);
1260ce8efc3bSFrank Praznik 
1261ce8efc3bSFrank Praznik 	/*
1262ce8efc3bSFrank Praznik 	 * The Dualshock 4 touchpad supports 2 touches and has a
1263981c5b4aSFrank Praznik 	 * resolution of 1920x942 (44.86 dots/mm).
1264ce8efc3bSFrank Praznik 	 */
1265ce8efc3bSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1266981c5b4aSFrank Praznik 		if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0)
1267ce8efc3bSFrank Praznik 			hid_err(sc->hdev,
1268ce8efc3bSFrank Praznik 				"Unable to initialize multi-touch slots\n");
1269ce8efc3bSFrank Praznik 	}
1270ce8efc3bSFrank Praznik }
1271ce8efc3bSFrank Praznik 
12725710fabfSAntonio Ospite /*
1273bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1274bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
1275bd28ce00SJiri Slaby  * events.
1276bd28ce00SJiri Slaby  */
1277816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1278bd28ce00SJiri Slaby {
1279a85d67b5SAntonio Ospite 	const int buf_size =
1280a85d67b5SAntonio Ospite 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
12812e701a35SAntonio Ospite 	__u8 *buf;
1282bd28ce00SJiri Slaby 	int ret;
1283bd28ce00SJiri Slaby 
12842e701a35SAntonio Ospite 	buf = kmalloc(buf_size, GFP_KERNEL);
1285bd28ce00SJiri Slaby 	if (!buf)
1286bd28ce00SJiri Slaby 		return -ENOMEM;
1287bd28ce00SJiri Slaby 
1288a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1289a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1290a7de9b86SLauri Kasanen 	if (ret < 0) {
1291a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 1\n");
1292a7de9b86SLauri Kasanen 		goto out;
1293a7de9b86SLauri Kasanen 	}
1294f204828aSBenjamin Tissoires 
1295a7de9b86SLauri Kasanen 	/*
1296a7de9b86SLauri Kasanen 	 * Some compatible controllers like the Speedlink Strike FX and
1297a7de9b86SLauri Kasanen 	 * Gasia need another query plus an USB interrupt to get operational.
1298a7de9b86SLauri Kasanen 	 */
1299a85d67b5SAntonio Ospite 	ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1300a85d67b5SAntonio Ospite 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1301a7de9b86SLauri Kasanen 	if (ret < 0) {
1302a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 2\n");
1303a7de9b86SLauri Kasanen 		goto out;
1304a7de9b86SLauri Kasanen 	}
1305a7de9b86SLauri Kasanen 
1306a7de9b86SLauri Kasanen 	ret = hid_hw_output_report(hdev, buf, 1);
1307bd28ce00SJiri Slaby 	if (ret < 0)
1308a7de9b86SLauri Kasanen 		hid_err(hdev, "can't set operational mode: step 3\n");
1309bd28ce00SJiri Slaby 
1310a7de9b86SLauri Kasanen out:
1311bd28ce00SJiri Slaby 	kfree(buf);
1312bd28ce00SJiri Slaby 
1313bd28ce00SJiri Slaby 	return ret;
1314bd28ce00SJiri Slaby }
1315bd28ce00SJiri Slaby 
1316816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1317f9ce7c28SBastien Nocera {
13189b2b5c9aSFrank Praznik 	static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
13199b2b5c9aSFrank Praznik 	__u8 *buf;
13209b2b5c9aSFrank Praznik 	int ret;
13219b2b5c9aSFrank Praznik 
13229b2b5c9aSFrank Praznik 	buf = kmemdup(report, sizeof(report), GFP_KERNEL);
13239b2b5c9aSFrank Praznik 	if (!buf)
13249b2b5c9aSFrank Praznik 		return -ENOMEM;
13259b2b5c9aSFrank Praznik 
13269b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1327b0dd72aaSBenjamin Tissoires 				  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
13289b2b5c9aSFrank Praznik 
13299b2b5c9aSFrank Praznik 	kfree(buf);
13309b2b5c9aSFrank Praznik 
13319b2b5c9aSFrank Praznik 	return ret;
1332f9ce7c28SBastien Nocera }
1333f9ce7c28SBastien Nocera 
1334ad142b9eSFrank Praznik /*
1335ad142b9eSFrank Praznik  * Requesting feature report 0x02 in Bluetooth mode changes the state of the
133668330d83SFrank Praznik  * controller so that it sends full input reports of type 0x11.
133768330d83SFrank Praznik  */
133868330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev)
133968330d83SFrank Praznik {
13409b2b5c9aSFrank Praznik 	__u8 *buf;
13419b2b5c9aSFrank Praznik 	int ret;
134268330d83SFrank Praznik 
13439b2b5c9aSFrank Praznik 	buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);
13449b2b5c9aSFrank Praznik 	if (!buf)
13459b2b5c9aSFrank Praznik 		return -ENOMEM;
13469b2b5c9aSFrank Praznik 
13479b2b5c9aSFrank Praznik 	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,
134868330d83SFrank Praznik 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
13499b2b5c9aSFrank Praznik 
13509b2b5c9aSFrank Praznik 	kfree(buf);
13519b2b5c9aSFrank Praznik 
13529b2b5c9aSFrank Praznik 	return ret;
1353bd28ce00SJiri Slaby }
1354bd28ce00SJiri Slaby 
1355221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
13568025087aSFrank Praznik {
13578025087aSFrank Praznik 	static const __u8 sixaxis_leds[10][4] = {
13588025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x00 },
13598025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x00 },
13608025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x00 },
13618025087aSFrank Praznik 				{ 0x00, 0x00, 0x00, 0x01 },
13628025087aSFrank Praznik 				{ 0x01, 0x00, 0x00, 0x01 },
13638025087aSFrank Praznik 				{ 0x00, 0x01, 0x00, 0x01 },
13648025087aSFrank Praznik 				{ 0x00, 0x00, 0x01, 0x01 },
13658025087aSFrank Praznik 				{ 0x01, 0x00, 0x01, 0x01 },
13668025087aSFrank Praznik 				{ 0x00, 0x01, 0x01, 0x01 },
13678025087aSFrank Praznik 				{ 0x01, 0x01, 0x01, 0x01 }
13688025087aSFrank Praznik 	};
13698025087aSFrank Praznik 
1370221399b3SFrank Praznik 	int id = sc->device_id;
1371221399b3SFrank Praznik 
1372221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
13738025087aSFrank Praznik 
13748025087aSFrank Praznik 	if (id < 0)
13758025087aSFrank Praznik 		return;
13768025087aSFrank Praznik 
13778025087aSFrank Praznik 	id %= 10;
1378221399b3SFrank Praznik 	memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
13798025087aSFrank Praznik }
13808025087aSFrank Praznik 
1381221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc)
13828025087aSFrank Praznik {
13838025087aSFrank Praznik 	/* The first 4 color/index entries match what the PS4 assigns */
13848025087aSFrank Praznik 	static const __u8 color_code[7][3] = {
13858025087aSFrank Praznik 			/* Blue   */	{ 0x00, 0x00, 0x01 },
13868025087aSFrank Praznik 			/* Red	  */	{ 0x01, 0x00, 0x00 },
13878025087aSFrank Praznik 			/* Green  */	{ 0x00, 0x01, 0x00 },
13888025087aSFrank Praznik 			/* Pink   */	{ 0x02, 0x00, 0x01 },
13898025087aSFrank Praznik 			/* Orange */	{ 0x02, 0x01, 0x00 },
13908025087aSFrank Praznik 			/* Teal   */	{ 0x00, 0x01, 0x01 },
13918025087aSFrank Praznik 			/* White  */	{ 0x01, 0x01, 0x01 }
13928025087aSFrank Praznik 	};
13938025087aSFrank Praznik 
1394221399b3SFrank Praznik 	int id = sc->device_id;
1395221399b3SFrank Praznik 
1396221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0]));
13978025087aSFrank Praznik 
13988025087aSFrank Praznik 	if (id < 0)
13998025087aSFrank Praznik 		return;
14008025087aSFrank Praznik 
14018025087aSFrank Praznik 	id %= 7;
1402221399b3SFrank Praznik 	memcpy(sc->led_state, color_code[id], sizeof(color_code[id]));
14038025087aSFrank Praznik }
14048025087aSFrank Praznik 
1405221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1406f04d5140SColin Leitner {
1407221399b3SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1408f04d5140SColin Leitner 	struct list_head *report_list =
1409f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1410f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
1411f04d5140SColin Leitner 		struct hid_report, list);
1412f04d5140SColin Leitner 	__s32 *value = report->field[0]->value;
1413f04d5140SColin Leitner 
1414221399b3SFrank Praznik 	BUILD_BUG_ON(MAX_LEDS < 4);
1415221399b3SFrank Praznik 
1416f04d5140SColin Leitner 	value[0] = 0x00;
1417221399b3SFrank Praznik 	value[1] = sc->led_state[0] ? 0xff : 0x00;
1418221399b3SFrank Praznik 	value[2] = sc->led_state[1] ? 0xff : 0x00;
1419221399b3SFrank Praznik 	value[3] = sc->led_state[2] ? 0xff : 0x00;
1420221399b3SFrank Praznik 	value[4] = sc->led_state[3] ? 0xff : 0x00;
1421f04d5140SColin Leitner 	value[5] = 0x00;
1422f04d5140SColin Leitner 	value[6] = 0x00;
1423f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1424f04d5140SColin Leitner }
1425f04d5140SColin Leitner 
1426221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
14270a286ef2SSven Eckelmann {
1428221399b3SFrank Praznik 	if (!(sc->quirks & BUZZ_CONTROLLER))
1429fa57a810SFrank Praznik 		schedule_work(&sc->state_worker);
1430221399b3SFrank Praznik 	else
1431221399b3SFrank Praznik 		buzz_set_leds(sc);
14320a286ef2SSven Eckelmann }
14330a286ef2SSven Eckelmann 
1434c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1435f04d5140SColin Leitner 				    enum led_brightness value)
1436f04d5140SColin Leitner {
1437f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1438f04d5140SColin Leitner 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1439f04d5140SColin Leitner 	struct sony_sc *drv_data;
1440f04d5140SColin Leitner 
1441f04d5140SColin Leitner 	int n;
1442b3ed458cSFrank Praznik 	int force_update;
1443f04d5140SColin Leitner 
1444f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
14452251b85fSSven Eckelmann 	if (!drv_data) {
1446f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1447f04d5140SColin Leitner 		return;
1448f04d5140SColin Leitner 	}
1449f04d5140SColin Leitner 
1450b3ed458cSFrank Praznik 	/*
1451b3ed458cSFrank Praznik 	 * The Sixaxis on USB will override any LED settings sent to it
1452b3ed458cSFrank Praznik 	 * and keep flashing all of the LEDs until the PS button is pressed.
1453b3ed458cSFrank Praznik 	 * Updates, even if redundant, must be always be sent to the
1454b3ed458cSFrank Praznik 	 * controller to avoid having to toggle the state of an LED just to
1455b3ed458cSFrank Praznik 	 * stop the flashing later on.
1456b3ed458cSFrank Praznik 	 */
1457b3ed458cSFrank Praznik 	force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1458b3ed458cSFrank Praznik 
145960781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1460b3ed458cSFrank Praznik 		if (led == drv_data->leds[n] && (force_update ||
1461b3ed458cSFrank Praznik 			(value != drv_data->led_state[n] ||
1462b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] ||
1463b3ed458cSFrank Praznik 			drv_data->led_delay_off[n]))) {
1464b3ed458cSFrank Praznik 
146560781cf4SFrank Praznik 			drv_data->led_state[n] = value;
1466b3ed458cSFrank Praznik 
1467b3ed458cSFrank Praznik 			/* Setting the brightness stops the blinking */
1468b3ed458cSFrank Praznik 			drv_data->led_delay_on[n] = 0;
1469b3ed458cSFrank Praznik 			drv_data->led_delay_off[n] = 0;
1470b3ed458cSFrank Praznik 
1471221399b3SFrank Praznik 			sony_set_leds(drv_data);
1472f04d5140SColin Leitner 			break;
1473f04d5140SColin Leitner 		}
1474f04d5140SColin Leitner 	}
1475f04d5140SColin Leitner }
1476f04d5140SColin Leitner 
1477c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1478f04d5140SColin Leitner {
1479f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
1480f04d5140SColin Leitner 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1481f04d5140SColin Leitner 	struct sony_sc *drv_data;
1482f04d5140SColin Leitner 
1483f04d5140SColin Leitner 	int n;
1484f04d5140SColin Leitner 
1485f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
14862251b85fSSven Eckelmann 	if (!drv_data) {
1487f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
1488f04d5140SColin Leitner 		return LED_OFF;
1489f04d5140SColin Leitner 	}
1490f04d5140SColin Leitner 
149160781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
14927db7504aSSimon Wood 		if (led == drv_data->leds[n])
14937db7504aSSimon Wood 			return drv_data->led_state[n];
1494f04d5140SColin Leitner 	}
1495f04d5140SColin Leitner 
14967db7504aSSimon Wood 	return LED_OFF;
1497f04d5140SColin Leitner }
1498f04d5140SColin Leitner 
1499b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1500b3ed458cSFrank Praznik 				unsigned long *delay_off)
1501b3ed458cSFrank Praznik {
1502b3ed458cSFrank Praznik 	struct device *dev = led->dev->parent;
1503b3ed458cSFrank Praznik 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1504b3ed458cSFrank Praznik 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
1505b3ed458cSFrank Praznik 	int n;
1506b3ed458cSFrank Praznik 	__u8 new_on, new_off;
1507b3ed458cSFrank Praznik 
1508b3ed458cSFrank Praznik 	if (!drv_data) {
1509b3ed458cSFrank Praznik 		hid_err(hdev, "No device data\n");
1510b3ed458cSFrank Praznik 		return -EINVAL;
1511b3ed458cSFrank Praznik 	}
1512b3ed458cSFrank Praznik 
1513b3ed458cSFrank Praznik 	/* Max delay is 255 deciseconds or 2550 milliseconds */
1514b3ed458cSFrank Praznik 	if (*delay_on > 2550)
1515b3ed458cSFrank Praznik 		*delay_on = 2550;
1516b3ed458cSFrank Praznik 	if (*delay_off > 2550)
1517b3ed458cSFrank Praznik 		*delay_off = 2550;
1518b3ed458cSFrank Praznik 
1519b3ed458cSFrank Praznik 	/* Blink at 1 Hz if both values are zero */
1520b3ed458cSFrank Praznik 	if (!*delay_on && !*delay_off)
1521b3ed458cSFrank Praznik 		*delay_on = *delay_off = 500;
1522b3ed458cSFrank Praznik 
1523b3ed458cSFrank Praznik 	new_on = *delay_on / 10;
1524b3ed458cSFrank Praznik 	new_off = *delay_off / 10;
1525b3ed458cSFrank Praznik 
1526b3ed458cSFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
1527b3ed458cSFrank Praznik 		if (led == drv_data->leds[n])
1528b3ed458cSFrank Praznik 			break;
1529b3ed458cSFrank Praznik 	}
1530b3ed458cSFrank Praznik 
1531b3ed458cSFrank Praznik 	/* This LED is not registered on this device */
1532b3ed458cSFrank Praznik 	if (n >= drv_data->led_count)
1533b3ed458cSFrank Praznik 		return -EINVAL;
1534b3ed458cSFrank Praznik 
1535b3ed458cSFrank Praznik 	/* Don't schedule work if the values didn't change */
1536b3ed458cSFrank Praznik 	if (new_on != drv_data->led_delay_on[n] ||
1537b3ed458cSFrank Praznik 		new_off != drv_data->led_delay_off[n]) {
1538b3ed458cSFrank Praznik 		drv_data->led_delay_on[n] = new_on;
1539b3ed458cSFrank Praznik 		drv_data->led_delay_off[n] = new_off;
1540b3ed458cSFrank Praznik 		schedule_work(&drv_data->state_worker);
1541b3ed458cSFrank Praznik 	}
1542b3ed458cSFrank Praznik 
1543b3ed458cSFrank Praznik 	return 0;
1544b3ed458cSFrank Praznik }
1545b3ed458cSFrank Praznik 
1546fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc)
15470a286ef2SSven Eckelmann {
15480a286ef2SSven Eckelmann 	struct led_classdev *led;
15490a286ef2SSven Eckelmann 	int n;
15500a286ef2SSven Eckelmann 
1551fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
15520a286ef2SSven Eckelmann 
1553fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
1554fa57a810SFrank Praznik 		led = sc->leds[n];
1555fa57a810SFrank Praznik 		sc->leds[n] = NULL;
15560a286ef2SSven Eckelmann 		if (!led)
15570a286ef2SSven Eckelmann 			continue;
15580a286ef2SSven Eckelmann 		led_classdev_unregister(led);
15590a286ef2SSven Eckelmann 		kfree(led);
15600a286ef2SSven Eckelmann 	}
156160781cf4SFrank Praznik 
1562fa57a810SFrank Praznik 	sc->led_count = 0;
15630a286ef2SSven Eckelmann }
15640a286ef2SSven Eckelmann 
1565fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1566f04d5140SColin Leitner {
1567fa57a810SFrank Praznik 	struct hid_device *hdev = sc->hdev;
156840e32ee6SJiri Kosina 	int n, ret = 0;
1569b3ed458cSFrank Praznik 	int use_ds4_names;
157040e32ee6SJiri Kosina 	struct led_classdev *led;
157140e32ee6SJiri Kosina 	size_t name_sz;
157240e32ee6SJiri Kosina 	char *name;
15730a286ef2SSven Eckelmann 	size_t name_len;
15740a286ef2SSven Eckelmann 	const char *name_fmt;
1575b3ed458cSFrank Praznik 	static const char * const ds4_name_str[] = { "red", "green", "blue",
1576b3ed458cSFrank Praznik 						  "global" };
15775607c89aSFrank Praznik 	__u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
1578b3ed458cSFrank Praznik 	__u8 use_hw_blink[MAX_LEDS] = { 0 };
1579f04d5140SColin Leitner 
1580fa57a810SFrank Praznik 	BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1581f04d5140SColin Leitner 
1582fa57a810SFrank Praznik 	if (sc->quirks & BUZZ_CONTROLLER) {
1583fa57a810SFrank Praznik 		sc->led_count = 4;
1584b3ed458cSFrank Praznik 		use_ds4_names = 0;
15850a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
15860a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
15879446edb9SKees Cook 		/* Validate expected report characteristics. */
15889446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
15899446edb9SKees Cook 			return -ENODEV;
1590fa57a810SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
1591221399b3SFrank Praznik 		dualshock4_set_leds_from_id(sc);
1592221399b3SFrank Praznik 		sc->led_state[3] = 1;
1593b3ed458cSFrank Praznik 		sc->led_count = 4;
1594b3ed458cSFrank Praznik 		memset(max_brightness, 255, 3);
1595b3ed458cSFrank Praznik 		use_hw_blink[3] = 1;
1596b3ed458cSFrank Praznik 		use_ds4_names = 1;
159761ebca93SFrank Praznik 		name_len = 0;
159861ebca93SFrank Praznik 		name_fmt = "%s:%s";
1599c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
1600c5e0c1c4SFrank Praznik 		sc->led_count = 3;
1601c5e0c1c4SFrank Praznik 		memset(max_brightness, 255, 3);
1602c5e0c1c4SFrank Praznik 		use_ds4_names = 1;
1603c5e0c1c4SFrank Praznik 		name_len = 0;
1604c5e0c1c4SFrank Praznik 		name_fmt = "%s:%s";
1605*4545ee0aSSimon Wood 	} else if (sc->quirks & NAVIGATION_CONTROLLER) {
1606*4545ee0aSSimon Wood 		static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
1607*4545ee0aSSimon Wood 
1608*4545ee0aSSimon Wood 		memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
1609*4545ee0aSSimon Wood 		sc->led_count = 1;
1610*4545ee0aSSimon Wood 		memset(use_hw_blink, 1, 4);
1611*4545ee0aSSimon Wood 		use_ds4_names = 0;
1612*4545ee0aSSimon Wood 		name_len = strlen("::sony#");
1613*4545ee0aSSimon Wood 		name_fmt = "%s::sony%d";
161460781cf4SFrank Praznik 	} else {
1615221399b3SFrank Praznik 		sixaxis_set_leds_from_id(sc);
1616fa57a810SFrank Praznik 		sc->led_count = 4;
1617b3ed458cSFrank Praznik 		memset(use_hw_blink, 1, 4);
1618b3ed458cSFrank Praznik 		use_ds4_names = 0;
161961ebca93SFrank Praznik 		name_len = strlen("::sony#");
162061ebca93SFrank Praznik 		name_fmt = "%s::sony%d";
162160781cf4SFrank Praznik 	}
162260781cf4SFrank Praznik 
1623ad142b9eSFrank Praznik 	/*
1624ad142b9eSFrank Praznik 	 * Clear LEDs as we have no way of reading their initial state. This is
1625f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
1626ad142b9eSFrank Praznik 	 * LEDs to on
1627ad142b9eSFrank Praznik 	 */
1628221399b3SFrank Praznik 	sony_set_leds(sc);
1629f04d5140SColin Leitner 
16300a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1631f04d5140SColin Leitner 
1632fa57a810SFrank Praznik 	for (n = 0; n < sc->led_count; n++) {
163361ebca93SFrank Praznik 
1634b3ed458cSFrank Praznik 		if (use_ds4_names)
1635b3ed458cSFrank Praznik 			name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
163661ebca93SFrank Praznik 
1637f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1638f04d5140SColin Leitner 		if (!led) {
1639f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
16408cd5fcdaSJulia Lawall 			ret = -ENOMEM;
1641f04d5140SColin Leitner 			goto error_leds;
1642f04d5140SColin Leitner 		}
1643f04d5140SColin Leitner 
1644f04d5140SColin Leitner 		name = (void *)(&led[1]);
1645b3ed458cSFrank Praznik 		if (use_ds4_names)
1646b3ed458cSFrank Praznik 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
1647b3ed458cSFrank Praznik 			ds4_name_str[n]);
164861ebca93SFrank Praznik 		else
16490a286ef2SSven Eckelmann 			snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1650f04d5140SColin Leitner 		led->name = name;
1651221399b3SFrank Praznik 		led->brightness = sc->led_state[n];
1652b3ed458cSFrank Praznik 		led->max_brightness = max_brightness[n];
1653c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
1654c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
1655f04d5140SColin Leitner 
1656b3ed458cSFrank Praznik 		if (use_hw_blink[n])
1657b3ed458cSFrank Praznik 			led->blink_set = sony_led_blink_set;
1658b3ed458cSFrank Praznik 
16598025087aSFrank Praznik 		sc->leds[n] = led;
16608025087aSFrank Praznik 
16618cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
16628cd5fcdaSJulia Lawall 		if (ret) {
1663f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
16648025087aSFrank Praznik 			sc->leds[n] = NULL;
1665f04d5140SColin Leitner 			kfree(led);
1666f04d5140SColin Leitner 			goto error_leds;
1667f04d5140SColin Leitner 		}
1668f04d5140SColin Leitner 	}
1669f04d5140SColin Leitner 
1670f04d5140SColin Leitner 	return ret;
1671f04d5140SColin Leitner 
1672f04d5140SColin Leitner error_leds:
1673fa57a810SFrank Praznik 	sony_leds_remove(sc);
1674f04d5140SColin Leitner 
1675f04d5140SColin Leitner 	return ret;
1676f04d5140SColin Leitner }
1677f04d5140SColin Leitner 
1678cad665a2SFrank Praznik static void sixaxis_state_worker(struct work_struct *work)
1679a08c22c0SSven Eckelmann {
16809b2b5c9aSFrank Praznik 	static const union sixaxis_output_report_01 default_report = {
168155d3b664SFrank Praznik 		.buf = {
1682a08c22c0SSven Eckelmann 			0x01,
1683a08c22c0SSven Eckelmann 			0x00, 0xff, 0x00, 0xff, 0x00,
16840a286ef2SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00,
1685a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1686a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1687a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1688a08c22c0SSven Eckelmann 			0xff, 0x27, 0x10, 0x00, 0x32,
1689a08c22c0SSven Eckelmann 			0x00, 0x00, 0x00, 0x00, 0x00
169055d3b664SFrank Praznik 		}
1691a08c22c0SSven Eckelmann 	};
16929b2b5c9aSFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
16939b2b5c9aSFrank Praznik 	struct sixaxis_output_report *report =
16949b2b5c9aSFrank Praznik 		(struct sixaxis_output_report *)sc->output_report_dmabuf;
16959b2b5c9aSFrank Praznik 	int n;
16969b2b5c9aSFrank Praznik 
16979b2b5c9aSFrank Praznik 	/* Initialize the report with default values */
16989b2b5c9aSFrank Praznik 	memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
16999f323b68SSven Eckelmann 
17000a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
17019b2b5c9aSFrank Praznik 	report->rumble.right_motor_on = sc->right ? 1 : 0;
17029b2b5c9aSFrank Praznik 	report->rumble.left_motor_force = sc->left;
17030a286ef2SSven Eckelmann #endif
17040a286ef2SSven Eckelmann 
17059b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[0] << 1;
17069b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[1] << 2;
17079b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[2] << 3;
17089b2b5c9aSFrank Praznik 	report->leds_bitmap |= sc->led_state[3] << 4;
17099f323b68SSven Eckelmann 
171088f6576fSSimon Wood 	/* Set flag for all leds off, required for 3rd party INTEC controller */
17119b2b5c9aSFrank Praznik 	if ((report->leds_bitmap & 0x1E) == 0)
17129b2b5c9aSFrank Praznik 		report->leds_bitmap |= 0x20;
171388f6576fSSimon Wood 
1714b3ed458cSFrank Praznik 	/*
1715b3ed458cSFrank Praznik 	 * The LEDs in the report are indexed in reverse order to their
1716b3ed458cSFrank Praznik 	 * corresponding light on the controller.
1717b3ed458cSFrank Praznik 	 * Index 0 = LED 4, index 1 = LED 3, etc...
1718b3ed458cSFrank Praznik 	 *
1719b3ed458cSFrank Praznik 	 * In the case of both delay values being zero (blinking disabled) the
1720b3ed458cSFrank Praznik 	 * default report values should be used or the controller LED will be
1721b3ed458cSFrank Praznik 	 * always off.
1722b3ed458cSFrank Praznik 	 */
1723b3ed458cSFrank Praznik 	for (n = 0; n < 4; n++) {
1724b3ed458cSFrank Praznik 		if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
17259b2b5c9aSFrank Praznik 			report->led[3 - n].duty_off = sc->led_delay_off[n];
17269b2b5c9aSFrank Praznik 			report->led[3 - n].duty_on = sc->led_delay_on[n];
1727b3ed458cSFrank Praznik 		}
1728b3ed458cSFrank Praznik 	}
1729b3ed458cSFrank Praznik 
17309b2b5c9aSFrank Praznik 	hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report,
17319b2b5c9aSFrank Praznik 			sizeof(struct sixaxis_output_report),
17329b2b5c9aSFrank Praznik 			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
17339f323b68SSven Eckelmann }
17349f323b68SSven Eckelmann 
17350bd88dd3SFrank Praznik static void dualshock4_state_worker(struct work_struct *work)
17360bd88dd3SFrank Praznik {
17370bd88dd3SFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
17380da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
17399b2b5c9aSFrank Praznik 	__u8 *buf = sc->output_report_dmabuf;
174048220237SFrank Praznik 	int offset;
17410da8ea65SFrank Praznik 
1742fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
17439b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x05_SIZE);
174448220237SFrank Praznik 		buf[0] = 0x05;
1745b3ed458cSFrank Praznik 		buf[1] = 0xFF;
174648220237SFrank Praznik 		offset = 4;
1747fdcf105dSFrank Praznik 	} else {
17489b2b5c9aSFrank Praznik 		memset(buf, 0, DS4_REPORT_0x11_SIZE);
1749fdcf105dSFrank Praznik 		buf[0] = 0x11;
1750fdcf105dSFrank Praznik 		buf[1] = 0xB0;
1751fdcf105dSFrank Praznik 		buf[3] = 0x0F;
1752fdcf105dSFrank Praznik 		offset = 6;
1753fdcf105dSFrank Praznik 	}
17540bd88dd3SFrank Praznik 
17550bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
175648220237SFrank Praznik 	buf[offset++] = sc->right;
175748220237SFrank Praznik 	buf[offset++] = sc->left;
175848220237SFrank Praznik #else
175948220237SFrank Praznik 	offset += 2;
17600bd88dd3SFrank Praznik #endif
17610bd88dd3SFrank Praznik 
1762b3ed458cSFrank Praznik 	/* LED 3 is the global control */
1763b3ed458cSFrank Praznik 	if (sc->led_state[3]) {
176448220237SFrank Praznik 		buf[offset++] = sc->led_state[0];
176548220237SFrank Praznik 		buf[offset++] = sc->led_state[1];
176648220237SFrank Praznik 		buf[offset++] = sc->led_state[2];
1767b3ed458cSFrank Praznik 	} else {
1768b3ed458cSFrank Praznik 		offset += 3;
1769b3ed458cSFrank Praznik 	}
1770b3ed458cSFrank Praznik 
1771b3ed458cSFrank Praznik 	/* If both delay values are zero the DualShock 4 disables blinking. */
1772b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_on[3];
1773b3ed458cSFrank Praznik 	buf[offset++] = sc->led_delay_off[3];
177460781cf4SFrank Praznik 
1775fdcf105dSFrank Praznik 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
17769b2b5c9aSFrank Praznik 		hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);
1777fdcf105dSFrank Praznik 	else
17789b2b5c9aSFrank Praznik 		hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,
1779fdcf105dSFrank Praznik 				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
17800bd88dd3SFrank Praznik }
17810bd88dd3SFrank Praznik 
1782c5e0c1c4SFrank Praznik static void motion_state_worker(struct work_struct *work)
1783c5e0c1c4SFrank Praznik {
1784c5e0c1c4SFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1785c5e0c1c4SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1786c5e0c1c4SFrank Praznik 	struct motion_output_report_02 *report =
1787c5e0c1c4SFrank Praznik 		(struct motion_output_report_02 *)sc->output_report_dmabuf;
1788c5e0c1c4SFrank Praznik 
178941d2d425SSimon Wood 	memset(report, 0, MOTION_REPORT_0x02_SIZE);
1790c5e0c1c4SFrank Praznik 
1791c5e0c1c4SFrank Praznik 	report->type = 0x02; /* set leds */
1792c5e0c1c4SFrank Praznik 	report->r = sc->led_state[0];
1793c5e0c1c4SFrank Praznik 	report->g = sc->led_state[1];
1794c5e0c1c4SFrank Praznik 	report->b = sc->led_state[2];
1795c5e0c1c4SFrank Praznik 
1796c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1797c5e0c1c4SFrank Praznik 	report->rumble = max(sc->right, sc->left);
1798c5e0c1c4SFrank Praznik #endif
1799c5e0c1c4SFrank Praznik 
180041d2d425SSimon Wood 	hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
1801c5e0c1c4SFrank Praznik }
1802c5e0c1c4SFrank Praznik 
18039b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
18049b2b5c9aSFrank Praznik {
1805*4545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
1806*4545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER))
18079b2b5c9aSFrank Praznik 		sc->output_report_dmabuf =
18089b2b5c9aSFrank Praznik 			kmalloc(sizeof(union sixaxis_output_report_01),
18099b2b5c9aSFrank Praznik 				GFP_KERNEL);
18109b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
18119b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,
18129b2b5c9aSFrank Praznik 						GFP_KERNEL);
18139b2b5c9aSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
18149b2b5c9aSFrank Praznik 		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
18159b2b5c9aSFrank Praznik 						GFP_KERNEL);
1816c5e0c1c4SFrank Praznik 	else if (sc->quirks & MOTION_CONTROLLER)
181741d2d425SSimon Wood 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
1818c5e0c1c4SFrank Praznik 						GFP_KERNEL);
18199b2b5c9aSFrank Praznik 	else
18209b2b5c9aSFrank Praznik 		return 0;
18219b2b5c9aSFrank Praznik 
18229b2b5c9aSFrank Praznik 	if (!sc->output_report_dmabuf)
18239b2b5c9aSFrank Praznik 		return -ENOMEM;
18249b2b5c9aSFrank Praznik 
18259b2b5c9aSFrank Praznik 	return 0;
18269b2b5c9aSFrank Praznik }
18279b2b5c9aSFrank Praznik 
18280a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
18299f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
18309f323b68SSven Eckelmann 			    struct ff_effect *effect)
18319f323b68SSven Eckelmann {
1832a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
18339f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
1834a08c22c0SSven Eckelmann 
1835a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
1836a08c22c0SSven Eckelmann 		return 0;
1837a08c22c0SSven Eckelmann 
18389f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
18390bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
1840a08c22c0SSven Eckelmann 
184192b5c411SSven Eckelmann 	schedule_work(&sc->state_worker);
18429f323b68SSven Eckelmann 	return 0;
1843a08c22c0SSven Eckelmann }
1844a08c22c0SSven Eckelmann 
1845fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1846a08c22c0SSven Eckelmann {
1847fa57a810SFrank Praznik 	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
1848a08c22c0SSven Eckelmann 						struct hid_input, list);
1849a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
1850a08c22c0SSven Eckelmann 
1851a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
1852a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
1853a08c22c0SSven Eckelmann }
1854a08c22c0SSven Eckelmann 
1855a08c22c0SSven Eckelmann #else
1856fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1857a08c22c0SSven Eckelmann {
1858a08c22c0SSven Eckelmann 	return 0;
1859a08c22c0SSven Eckelmann }
18609f323b68SSven Eckelmann 
1861a08c22c0SSven Eckelmann #endif
1862a08c22c0SSven Eckelmann 
1863d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
1864d902f472SFrank Praznik 				     enum power_supply_property psp,
1865d902f472SFrank Praznik 				     union power_supply_propval *val)
1866c4e1ddf2SFrank Praznik {
1867297d716fSKrzysztof Kozlowski 	struct sony_sc *sc = power_supply_get_drvdata(psy);
1868d902f472SFrank Praznik 	unsigned long flags;
1869d902f472SFrank Praznik 	int ret = 0;
1870d902f472SFrank Praznik 	u8 battery_charging, battery_capacity, cable_state;
1871c4e1ddf2SFrank Praznik 
1872d902f472SFrank Praznik 	spin_lock_irqsave(&sc->lock, flags);
1873d902f472SFrank Praznik 	battery_charging = sc->battery_charging;
1874d902f472SFrank Praznik 	battery_capacity = sc->battery_capacity;
1875d902f472SFrank Praznik 	cable_state = sc->cable_state;
1876d902f472SFrank Praznik 	spin_unlock_irqrestore(&sc->lock, flags);
1877c4e1ddf2SFrank Praznik 
1878d902f472SFrank Praznik 	switch (psp) {
1879d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_PRESENT:
1880d902f472SFrank Praznik 		val->intval = 1;
1881d902f472SFrank Praznik 		break;
1882d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_SCOPE:
1883d902f472SFrank Praznik 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
1884d902f472SFrank Praznik 		break;
1885d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_CAPACITY:
1886d902f472SFrank Praznik 		val->intval = battery_capacity;
1887d902f472SFrank Praznik 		break;
1888d902f472SFrank Praznik 	case POWER_SUPPLY_PROP_STATUS:
1889d902f472SFrank Praznik 		if (battery_charging)
1890d902f472SFrank Praznik 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
1891d902f472SFrank Praznik 		else
1892d902f472SFrank Praznik 			if (battery_capacity == 100 && cable_state)
1893d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_FULL;
1894d902f472SFrank Praznik 			else
1895d902f472SFrank Praznik 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
1896d902f472SFrank Praznik 		break;
1897d902f472SFrank Praznik 	default:
1898d902f472SFrank Praznik 		ret = -EINVAL;
1899d902f472SFrank Praznik 		break;
1900c4e1ddf2SFrank Praznik 	}
1901d902f472SFrank Praznik 	return ret;
1902d902f472SFrank Praznik }
1903d902f472SFrank Praznik 
1904d902f472SFrank Praznik static int sony_battery_probe(struct sony_sc *sc)
1905d902f472SFrank Praznik {
1906297d716fSKrzysztof Kozlowski 	struct power_supply_config psy_cfg = { .drv_data = sc, };
1907d902f472SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1908d902f472SFrank Praznik 	int ret;
1909d902f472SFrank Praznik 
1910ad142b9eSFrank Praznik 	/*
1911ad142b9eSFrank Praznik 	 * Set the default battery level to 100% to avoid low battery warnings
1912d9a293a9SFrank Praznik 	 * if the battery is polled before the first device report is received.
1913d9a293a9SFrank Praznik 	 */
1914d9a293a9SFrank Praznik 	sc->battery_capacity = 100;
1915d9a293a9SFrank Praznik 
1916297d716fSKrzysztof Kozlowski 	sc->battery_desc.properties = sony_battery_props;
1917297d716fSKrzysztof Kozlowski 	sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
1918297d716fSKrzysztof Kozlowski 	sc->battery_desc.get_property = sony_battery_get_property;
1919297d716fSKrzysztof Kozlowski 	sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
1920297d716fSKrzysztof Kozlowski 	sc->battery_desc.use_for_apm = 0;
1921297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = kasprintf(GFP_KERNEL,
1922297d716fSKrzysztof Kozlowski 					  "sony_controller_battery_%pMR",
1923314531f1SFrank Praznik 					  sc->mac_address);
1924297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
1925d902f472SFrank Praznik 		return -ENOMEM;
1926d902f472SFrank Praznik 
1927297d716fSKrzysztof Kozlowski 	sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
1928297d716fSKrzysztof Kozlowski 					    &psy_cfg);
1929297d716fSKrzysztof Kozlowski 	if (IS_ERR(sc->battery)) {
1930297d716fSKrzysztof Kozlowski 		ret = PTR_ERR(sc->battery);
1931d902f472SFrank Praznik 		hid_err(hdev, "Unable to register battery device\n");
1932d902f472SFrank Praznik 		goto err_free;
1933d902f472SFrank Praznik 	}
1934d902f472SFrank Praznik 
1935297d716fSKrzysztof Kozlowski 	power_supply_powers(sc->battery, &hdev->dev);
1936d902f472SFrank Praznik 	return 0;
1937d902f472SFrank Praznik 
1938d902f472SFrank Praznik err_free:
1939297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
1940297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
1941d902f472SFrank Praznik 	return ret;
1942d902f472SFrank Praznik }
1943d902f472SFrank Praznik 
1944d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc)
1945d902f472SFrank Praznik {
1946297d716fSKrzysztof Kozlowski 	if (!sc->battery_desc.name)
1947d902f472SFrank Praznik 		return;
1948d902f472SFrank Praznik 
1949297d716fSKrzysztof Kozlowski 	power_supply_unregister(sc->battery);
1950297d716fSKrzysztof Kozlowski 	kfree(sc->battery_desc.name);
1951297d716fSKrzysztof Kozlowski 	sc->battery_desc.name = NULL;
1952d902f472SFrank Praznik }
1953d902f472SFrank Praznik 
1954d2d782fcSFrank Praznik /*
1955d2d782fcSFrank Praznik  * If a controller is plugged in via USB while already connected via Bluetooth
1956d2d782fcSFrank Praznik  * it will show up as two devices. A global list of connected controllers and
1957d2d782fcSFrank Praznik  * their MAC addresses is maintained to ensure that a device is only connected
1958d2d782fcSFrank Praznik  * once.
1959d2d782fcSFrank Praznik  */
1960d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
1961d2d782fcSFrank Praznik {
1962d2d782fcSFrank Praznik 	struct sony_sc *entry;
1963d2d782fcSFrank Praznik 	unsigned long flags;
1964d2d782fcSFrank Praznik 	int ret;
1965d2d782fcSFrank Praznik 
1966d2d782fcSFrank Praznik 	spin_lock_irqsave(&sony_dev_list_lock, flags);
1967d2d782fcSFrank Praznik 
1968d2d782fcSFrank Praznik 	list_for_each_entry(entry, &sony_device_list, list_node) {
1969d2d782fcSFrank Praznik 		ret = memcmp(sc->mac_address, entry->mac_address,
1970d2d782fcSFrank Praznik 				sizeof(sc->mac_address));
1971d2d782fcSFrank Praznik 		if (!ret) {
1972d2d782fcSFrank Praznik 			ret = -EEXIST;
1973d2d782fcSFrank Praznik 			hid_info(sc->hdev, "controller with MAC address %pMR already connected\n",
1974d2d782fcSFrank Praznik 				sc->mac_address);
1975d2d782fcSFrank Praznik 			goto unlock;
1976d2d782fcSFrank Praznik 		}
1977c4e1ddf2SFrank Praznik 	}
1978c4e1ddf2SFrank Praznik 
1979d2d782fcSFrank Praznik 	ret = 0;
1980d2d782fcSFrank Praznik 	list_add(&(sc->list_node), &sony_device_list);
1981c4e1ddf2SFrank Praznik 
1982d2d782fcSFrank Praznik unlock:
1983d2d782fcSFrank Praznik 	spin_unlock_irqrestore(&sony_dev_list_lock, flags);
1984d2d782fcSFrank Praznik 	return ret;
1985d2d782fcSFrank Praznik }
1986d2d782fcSFrank Praznik 
1987d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
1988d2d782fcSFrank Praznik {
1989d2d782fcSFrank Praznik 	unsigned long flags;
1990d2d782fcSFrank Praznik 
1991d2d782fcSFrank Praznik 	if (sc->list_node.next) {
1992d2d782fcSFrank Praznik 		spin_lock_irqsave(&sony_dev_list_lock, flags);
1993d2d782fcSFrank Praznik 		list_del(&(sc->list_node));
1994d2d782fcSFrank Praznik 		spin_unlock_irqrestore(&sony_dev_list_lock, flags);
1995d2d782fcSFrank Praznik 	}
1996d2d782fcSFrank Praznik }
1997d2d782fcSFrank Praznik 
1998d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
1999d2d782fcSFrank Praznik {
2000d2d782fcSFrank Praznik 	int ret;
2001d2d782fcSFrank Praznik 
2002d2d782fcSFrank Praznik 	/* HIDP stores the device MAC address as a string in the uniq field. */
2003d2d782fcSFrank Praznik 	ret = strlen(sc->hdev->uniq);
2004d2d782fcSFrank Praznik 	if (ret != 17)
2005c4e1ddf2SFrank Praznik 		return -EINVAL;
2006d2d782fcSFrank Praznik 
2007d2d782fcSFrank Praznik 	ret = sscanf(sc->hdev->uniq,
2008d2d782fcSFrank Praznik 		"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2009d2d782fcSFrank Praznik 		&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
2010d2d782fcSFrank Praznik 		&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
2011d2d782fcSFrank Praznik 
2012d2d782fcSFrank Praznik 	if (ret != 6)
2013d2d782fcSFrank Praznik 		return -EINVAL;
2014d2d782fcSFrank Praznik 
2015d2d782fcSFrank Praznik 	return 0;
2016c4e1ddf2SFrank Praznik }
2017c4e1ddf2SFrank Praznik 
2018d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
2019d2d782fcSFrank Praznik {
20209b2b5c9aSFrank Praznik 	__u8 *buf = NULL;
2021d2d782fcSFrank Praznik 	int n, ret;
2022d2d782fcSFrank Praznik 
2023d2d782fcSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
202412e9a6d7SSimon Wood 	    (sc->quirks & MOTION_CONTROLLER_BT) ||
2025*4545ee0aSSimon Wood 	    (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
2026d2d782fcSFrank Praznik 	    (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
2027d2d782fcSFrank Praznik 		/*
2028d2d782fcSFrank Praznik 		 * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
2029d2d782fcSFrank Praznik 		 * address from the uniq string where HIDP stores it.
2030d2d782fcSFrank Praznik 		 * As uniq cannot be guaranteed to be a MAC address in all cases
2031d2d782fcSFrank Praznik 		 * a failure of this function should not prevent the connection.
2032d2d782fcSFrank Praznik 		 */
2033d2d782fcSFrank Praznik 		if (sony_get_bt_devaddr(sc) < 0) {
2034d2d782fcSFrank Praznik 			hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
2035d2d782fcSFrank Praznik 			return 0;
2036d2d782fcSFrank Praznik 		}
2037d2d782fcSFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
20389b2b5c9aSFrank Praznik 		buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);
20399b2b5c9aSFrank Praznik 		if (!buf)
20409b2b5c9aSFrank Praznik 			return -ENOMEM;
2041d2d782fcSFrank Praznik 
2042d2d782fcSFrank Praznik 		/*
2043d2d782fcSFrank Praznik 		 * The MAC address of a DS4 controller connected via USB can be
2044d2d782fcSFrank Praznik 		 * retrieved with feature report 0x81. The address begins at
2045d2d782fcSFrank Praznik 		 * offset 1.
2046d2d782fcSFrank Praznik 		 */
20479b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
20489b2b5c9aSFrank Praznik 				DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
20499b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2050d2d782fcSFrank Praznik 
20519b2b5c9aSFrank Praznik 		if (ret != DS4_REPORT_0x81_SIZE) {
2052d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
20539b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
20549b2b5c9aSFrank Praznik 			goto out_free;
2055d2d782fcSFrank Praznik 		}
2056d2d782fcSFrank Praznik 
2057d2d782fcSFrank Praznik 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
2058*4545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
2059*4545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
20609b2b5c9aSFrank Praznik 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
20619b2b5c9aSFrank Praznik 		if (!buf)
20629b2b5c9aSFrank Praznik 			return -ENOMEM;
2063d2d782fcSFrank Praznik 
2064d2d782fcSFrank Praznik 		/*
2065d2d782fcSFrank Praznik 		 * The MAC address of a Sixaxis controller connected via USB can
2066d2d782fcSFrank Praznik 		 * be retrieved with feature report 0xf2. The address begins at
2067d2d782fcSFrank Praznik 		 * offset 4.
2068d2d782fcSFrank Praznik 		 */
20699b2b5c9aSFrank Praznik 		ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
20709b2b5c9aSFrank Praznik 				SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
20719b2b5c9aSFrank Praznik 				HID_REQ_GET_REPORT);
2072d2d782fcSFrank Praznik 
20739b2b5c9aSFrank Praznik 		if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
2074d2d782fcSFrank Praznik 			hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
20759b2b5c9aSFrank Praznik 			ret = ret < 0 ? ret : -EINVAL;
20769b2b5c9aSFrank Praznik 			goto out_free;
2077d2d782fcSFrank Praznik 		}
2078d2d782fcSFrank Praznik 
2079d2d782fcSFrank Praznik 		/*
2080d2d782fcSFrank Praznik 		 * The Sixaxis device MAC in the report is big-endian and must
2081d2d782fcSFrank Praznik 		 * be byte-swapped.
2082d2d782fcSFrank Praznik 		 */
2083d2d782fcSFrank Praznik 		for (n = 0; n < 6; n++)
2084d2d782fcSFrank Praznik 			sc->mac_address[5-n] = buf[4+n];
2085d2d782fcSFrank Praznik 	} else {
2086d2d782fcSFrank Praznik 		return 0;
2087d2d782fcSFrank Praznik 	}
2088d2d782fcSFrank Praznik 
20899b2b5c9aSFrank Praznik 	ret = sony_check_add_dev_list(sc);
20909b2b5c9aSFrank Praznik 
20919b2b5c9aSFrank Praznik out_free:
20929b2b5c9aSFrank Praznik 
20939b2b5c9aSFrank Praznik 	kfree(buf);
20949b2b5c9aSFrank Praznik 
20959b2b5c9aSFrank Praznik 	return ret;
2096d2d782fcSFrank Praznik }
2097d2d782fcSFrank Praznik 
20988025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
20998025087aSFrank Praznik {
21008025087aSFrank Praznik 	int ret;
21018025087aSFrank Praznik 
21028025087aSFrank Praznik 	/*
21038025087aSFrank Praznik 	 * Only DualShock 4 or Sixaxis controllers get an id.
21048025087aSFrank Praznik 	 * All others are set to -1.
21058025087aSFrank Praznik 	 */
21068025087aSFrank Praznik 	if ((sc->quirks & SIXAXIS_CONTROLLER) ||
21078025087aSFrank Praznik 	    (sc->quirks & DUALSHOCK4_CONTROLLER)) {
21088025087aSFrank Praznik 		ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
21098025087aSFrank Praznik 					GFP_KERNEL);
21108025087aSFrank Praznik 		if (ret < 0) {
21118025087aSFrank Praznik 			sc->device_id = -1;
21128025087aSFrank Praznik 			return ret;
21138025087aSFrank Praznik 		}
21148025087aSFrank Praznik 		sc->device_id = ret;
21158025087aSFrank Praznik 	} else {
21168025087aSFrank Praznik 		sc->device_id = -1;
21178025087aSFrank Praznik 	}
21188025087aSFrank Praznik 
21198025087aSFrank Praznik 	return 0;
21208025087aSFrank Praznik }
21218025087aSFrank Praznik 
21228025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
21238025087aSFrank Praznik {
21248025087aSFrank Praznik 	if (sc->device_id >= 0) {
21258025087aSFrank Praznik 		ida_simple_remove(&sony_device_id_allocator, sc->device_id);
21268025087aSFrank Praznik 		sc->device_id = -1;
21278025087aSFrank Praznik 	}
21288025087aSFrank Praznik }
21298025087aSFrank Praznik 
213046262047SFrank Praznik static inline void sony_init_work(struct sony_sc *sc,
213146262047SFrank Praznik 					void (*worker)(struct work_struct *))
213246262047SFrank Praznik {
213346262047SFrank Praznik 	if (!sc->worker_initialized)
213446262047SFrank Praznik 		INIT_WORK(&sc->state_worker, worker);
213546262047SFrank Praznik 
213646262047SFrank Praznik 	sc->worker_initialized = 1;
213746262047SFrank Praznik }
213846262047SFrank Praznik 
213946262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
214046262047SFrank Praznik {
214146262047SFrank Praznik 	if (sc->worker_initialized)
214246262047SFrank Praznik 		cancel_work_sync(&sc->state_worker);
214346262047SFrank Praznik }
2144d2d782fcSFrank Praznik 
2145bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2146bd28ce00SJiri Slaby {
2147bd28ce00SJiri Slaby 	int ret;
2148cc6e0bbbSJiri Kosina 	unsigned long quirks = id->driver_data;
2149cc6e0bbbSJiri Kosina 	struct sony_sc *sc;
2150f04d5140SColin Leitner 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
2151cc6e0bbbSJiri Kosina 
2152abf832bfSBenjamin Tissoires 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2153cc6e0bbbSJiri Kosina 	if (sc == NULL) {
21544291ee30SJoe Perches 		hid_err(hdev, "can't alloc sony descriptor\n");
2155cc6e0bbbSJiri Kosina 		return -ENOMEM;
2156cc6e0bbbSJiri Kosina 	}
2157cc6e0bbbSJiri Kosina 
2158b94993f6SFrank Praznik 	spin_lock_init(&sc->lock);
2159b94993f6SFrank Praznik 
2160cc6e0bbbSJiri Kosina 	sc->quirks = quirks;
2161cc6e0bbbSJiri Kosina 	hid_set_drvdata(hdev, sc);
21620a286ef2SSven Eckelmann 	sc->hdev = hdev;
2163bd28ce00SJiri Slaby 
2164bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
2165bd28ce00SJiri Slaby 	if (ret) {
21664291ee30SJoe Perches 		hid_err(hdev, "parse failed\n");
2167abf832bfSBenjamin Tissoires 		return ret;
2168bd28ce00SJiri Slaby 	}
2169bd28ce00SJiri Slaby 
2170f04d5140SColin Leitner 	if (sc->quirks & VAIO_RDESC_CONSTANT)
2171f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
217250764650SAntonio Ospite 	else if (sc->quirks & SIXAXIS_CONTROLLER)
2173f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2174f04d5140SColin Leitner 
2175f04d5140SColin Leitner 	ret = hid_hw_start(hdev, connect_mask);
2176bd28ce00SJiri Slaby 	if (ret) {
21774291ee30SJoe Perches 		hid_err(hdev, "hw start failed\n");
2178abf832bfSBenjamin Tissoires 		return ret;
2179bd28ce00SJiri Slaby 	}
2180bd28ce00SJiri Slaby 
21818025087aSFrank Praznik 	ret = sony_set_device_id(sc);
21828025087aSFrank Praznik 	if (ret < 0) {
21838025087aSFrank Praznik 		hid_err(hdev, "failed to allocate the device id\n");
21848025087aSFrank Praznik 		goto err_stop;
21858025087aSFrank Praznik 	}
21868025087aSFrank Praznik 
2187131a8a9aSFrank Praznik 	ret = sony_allocate_output_report(sc);
2188131a8a9aSFrank Praznik 	if (ret < 0) {
2189131a8a9aSFrank Praznik 		hid_err(hdev, "failed to allocate the output report buffer\n");
2190131a8a9aSFrank Praznik 		goto err_stop;
2191131a8a9aSFrank Praznik 	}
2192131a8a9aSFrank Praznik 
2193*4545ee0aSSimon Wood 	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
2194*4545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2195e534a935SBenjamin Tissoires 		/*
2196e534a935SBenjamin Tissoires 		 * The Sony Sixaxis does not handle HID Output Reports on the
2197e534a935SBenjamin Tissoires 		 * Interrupt EP like it could, so we need to force HID Output
2198e534a935SBenjamin Tissoires 		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
2199e534a935SBenjamin Tissoires 		 *
2200e534a935SBenjamin Tissoires 		 * There is also another issue about HID Output Reports via USB,
2201e534a935SBenjamin Tissoires 		 * the Sixaxis does not want the report_id as part of the data
2202e534a935SBenjamin Tissoires 		 * packet, so we have to discard buf[0] when sending the actual
2203e534a935SBenjamin Tissoires 		 * control message, even for numbered reports, humpf!
2204e534a935SBenjamin Tissoires 		 */
2205e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2206e534a935SBenjamin Tissoires 		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
2207816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
220846262047SFrank Praznik 		sony_init_work(sc, sixaxis_state_worker);
2209*4545ee0aSSimon Wood 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
2210*4545ee0aSSimon Wood 			(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
22112078b9bbSFrank Praznik 		/*
22122078b9bbSFrank Praznik 		 * The Sixaxis wants output reports sent on the ctrl endpoint
22132078b9bbSFrank Praznik 		 * when connected via Bluetooth.
22142078b9bbSFrank Praznik 		 */
22152078b9bbSFrank Praznik 		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2216816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
221746262047SFrank Praznik 		sony_init_work(sc, sixaxis_state_worker);
2218fee4e2d5SFrank Praznik 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
221968330d83SFrank Praznik 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
22202078b9bbSFrank Praznik 			/*
22212078b9bbSFrank Praznik 			 * The DualShock 4 wants output reports sent on the ctrl
22222078b9bbSFrank Praznik 			 * endpoint when connected via Bluetooth.
22232078b9bbSFrank Praznik 			 */
22242078b9bbSFrank Praznik 			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
222568330d83SFrank Praznik 			ret = dualshock4_set_operational_bt(hdev);
222668330d83SFrank Praznik 			if (ret < 0) {
222768330d83SFrank Praznik 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
222868330d83SFrank Praznik 				goto err_stop;
222968330d83SFrank Praznik 			}
223068330d83SFrank Praznik 		}
2231c4e1ddf2SFrank Praznik 
223246262047SFrank Praznik 		sony_init_work(sc, dualshock4_state_worker);
2233c5e0c1c4SFrank Praznik 	} else if (sc->quirks & MOTION_CONTROLLER) {
2234c5e0c1c4SFrank Praznik 		sony_init_work(sc, motion_state_worker);
22350bd88dd3SFrank Praznik 	} else {
22360bd88dd3SFrank Praznik 		ret = 0;
22370bd88dd3SFrank Praznik 	}
2238f9ce7c28SBastien Nocera 
22394dfdc464SJiri Kosina 	if (ret < 0)
2240bd28ce00SJiri Slaby 		goto err_stop;
2241bd28ce00SJiri Slaby 
2242d2d782fcSFrank Praznik 	ret = sony_check_add(sc);
2243d2d782fcSFrank Praznik 	if (ret < 0)
2244d2d782fcSFrank Praznik 		goto err_stop;
2245d2d782fcSFrank Praznik 
22460a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
2247fa57a810SFrank Praznik 		ret = sony_leds_init(sc);
22480a286ef2SSven Eckelmann 		if (ret < 0)
22490a286ef2SSven Eckelmann 			goto err_stop;
22500a286ef2SSven Eckelmann 	}
22510a286ef2SSven Eckelmann 
2252d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2253d902f472SFrank Praznik 		ret = sony_battery_probe(sc);
2254a08c22c0SSven Eckelmann 		if (ret < 0)
2255a08c22c0SSven Eckelmann 			goto err_stop;
2256a08c22c0SSven Eckelmann 
2257d902f472SFrank Praznik 		/* Open the device to receive reports with battery info */
2258d902f472SFrank Praznik 		ret = hid_hw_open(hdev);
2259d902f472SFrank Praznik 		if (ret < 0) {
2260d902f472SFrank Praznik 			hid_err(hdev, "hw open failed\n");
2261d902f472SFrank Praznik 			goto err_stop;
2262d902f472SFrank Praznik 		}
2263d902f472SFrank Praznik 	}
2264d902f472SFrank Praznik 
2265c8de9dbbSFrank Praznik 	if (sc->quirks & SONY_FF_SUPPORT) {
2266fa57a810SFrank Praznik 		ret = sony_init_ff(sc);
2267d902f472SFrank Praznik 		if (ret < 0)
2268d902f472SFrank Praznik 			goto err_close;
22695f5750d2SFrank Praznik 	}
2270bd28ce00SJiri Slaby 
2271f425458eSH Hartley Sweeten 	return 0;
2272d902f472SFrank Praznik err_close:
2273d902f472SFrank Praznik 	hid_hw_close(hdev);
2274bd28ce00SJiri Slaby err_stop:
22750a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2276fa57a810SFrank Praznik 		sony_leds_remove(sc);
2277d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT)
2278d902f472SFrank Praznik 		sony_battery_remove(sc);
227946262047SFrank Praznik 	sony_cancel_work_sync(sc);
22809b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
2281d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
22828025087aSFrank Praznik 	sony_release_device_id(sc);
2283bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2284bd28ce00SJiri Slaby 	return ret;
2285bd28ce00SJiri Slaby }
2286bd28ce00SJiri Slaby 
2287bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2288bd28ce00SJiri Slaby {
2289bd28ce00SJiri Slaby 	struct sony_sc *sc = hid_get_drvdata(hdev);
2290bd28ce00SJiri Slaby 
22910a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
2292fa57a810SFrank Praznik 		sony_leds_remove(sc);
2293bd28ce00SJiri Slaby 
2294d902f472SFrank Praznik 	if (sc->quirks & SONY_BATTERY_SUPPORT) {
2295d902f472SFrank Praznik 		hid_hw_close(hdev);
2296d902f472SFrank Praznik 		sony_battery_remove(sc);
2297d902f472SFrank Praznik 	}
2298d902f472SFrank Praznik 
229946262047SFrank Praznik 	sony_cancel_work_sync(sc);
23009f323b68SSven Eckelmann 
23019b2b5c9aSFrank Praznik 	kfree(sc->output_report_dmabuf);
23029b2b5c9aSFrank Praznik 
2303d2d782fcSFrank Praznik 	sony_remove_dev_list(sc);
2304bd28ce00SJiri Slaby 
23058025087aSFrank Praznik 	sony_release_device_id(sc);
23068025087aSFrank Praznik 
2307bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
2308bd28ce00SJiri Slaby }
2309bd28ce00SJiri Slaby 
2310bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2311bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2312bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_USB },
2313bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
2314*4545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_USB },
23156eabaaa0SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
2316*4545ee0aSSimon Wood 		.driver_data = NAVIGATION_CONTROLLER_BT },
2317c5e0c1c4SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2318b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_USB },
2319a4afa854SSimon Wood 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2320b3bca326SSimon Wood 		.driver_data = MOTION_CONTROLLER_BT },
2321bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2322bd28ce00SJiri Slaby 		.driver_data = SIXAXIS_CONTROLLER_BT },
2323bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2324bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2325bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2326bd28ce00SJiri Slaby 		.driver_data = VAIO_RDESC_CONSTANT },
2327bd28ce00SJiri Slaby 	/* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2328bd28ce00SJiri Slaby 	 * Logitech joystick from the device descriptor. */
2329bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2330bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2331bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2332bd28ce00SJiri Slaby 		.driver_data = BUZZ_CONTROLLER },
2333bd28ce00SJiri Slaby 	/* PS3 BD Remote Control */
2334bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2335bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
2336bd28ce00SJiri Slaby 	/* Logitech Harmony Adapter for PS3 */
2337bd28ce00SJiri Slaby 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2338bd28ce00SJiri Slaby 		.driver_data = PS3REMOTE },
233968a49e51SFrank Praznik 	/* SMK-Link PS3 BD Remote Control */
234068a49e51SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
234168a49e51SFrank Praznik 		.driver_data = PS3REMOTE },
23420bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
23430bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
23448ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
23450bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
23468ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
2347bd28ce00SJiri Slaby 	{ }
2348bd28ce00SJiri Slaby };
2349bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2350bd28ce00SJiri Slaby 
2351bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2352bd28ce00SJiri Slaby 	.name             = "sony",
2353bd28ce00SJiri Slaby 	.id_table         = sony_devices,
2354bd28ce00SJiri Slaby 	.input_mapping    = sony_mapping,
2355ce8efc3bSFrank Praznik 	.input_configured = sony_input_configured,
2356bd28ce00SJiri Slaby 	.probe            = sony_probe,
2357bd28ce00SJiri Slaby 	.remove           = sony_remove,
2358bd28ce00SJiri Slaby 	.report_fixup     = sony_report_fixup,
2359bd28ce00SJiri Slaby 	.raw_event        = sony_raw_event
2360bd28ce00SJiri Slaby };
23618025087aSFrank Praznik 
23628025087aSFrank Praznik static int __init sony_init(void)
23638025087aSFrank Praznik {
23648025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
23658025087aSFrank Praznik 
23668025087aSFrank Praznik 	return hid_register_driver(&sony_driver);
23678025087aSFrank Praznik }
23688025087aSFrank Praznik 
23698025087aSFrank Praznik static void __exit sony_exit(void)
23708025087aSFrank Praznik {
23718025087aSFrank Praznik 	dbg_hid("Sony:%s\n", __func__);
23728025087aSFrank Praznik 
23738025087aSFrank Praznik 	hid_unregister_driver(&sony_driver);
23746c40065fSAntonio Ospite 	ida_destroy(&sony_device_id_allocator);
23758025087aSFrank Praznik }
23768025087aSFrank Praznik module_init(sony_init);
23778025087aSFrank Praznik module_exit(sony_exit);
2378bd28ce00SJiri Slaby 
2379bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2380