xref: /linux/drivers/hid/hid-sony.c (revision 58d7027b7f92b1c4d883126a54782c656a76cafd)
1bd28ce00SJiri Slaby /*
2078328daSJiri Kosina  *  HID driver for Sony / PS2 / PS3 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>
11bd28ce00SJiri Slaby  */
12bd28ce00SJiri Slaby 
13bd28ce00SJiri Slaby /*
14bd28ce00SJiri Slaby  * This program is free software; you can redistribute it and/or modify it
15bd28ce00SJiri Slaby  * under the terms of the GNU General Public License as published by the Free
16bd28ce00SJiri Slaby  * Software Foundation; either version 2 of the License, or (at your option)
17bd28ce00SJiri Slaby  * any later version.
18bd28ce00SJiri Slaby  */
19bd28ce00SJiri Slaby 
20078328daSJiri Kosina /* NOTE: in order for the Sony PS3 BD Remote Control to be found by
21078328daSJiri Kosina  * a Bluetooth host, the key combination Start+Enter has to be kept pressed
22078328daSJiri Kosina  * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
23078328daSJiri Kosina  *
24078328daSJiri Kosina  * There will be no PIN request from the device.
25078328daSJiri Kosina  */
26078328daSJiri Kosina 
27bd28ce00SJiri Slaby #include <linux/device.h>
28bd28ce00SJiri Slaby #include <linux/hid.h>
29bd28ce00SJiri Slaby #include <linux/module.h>
305a0e3ad6STejun Heo #include <linux/slab.h>
31bd28ce00SJiri Slaby #include <linux/usb.h>
3240e32ee6SJiri Kosina #include <linux/leds.h>
33bd28ce00SJiri Slaby 
34bd28ce00SJiri Slaby #include "hid-ids.h"
35bd28ce00SJiri Slaby 
36f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT       BIT(0)
37f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB    BIT(1)
38f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT     BIT(2)
39f1c458caSSven Eckelmann #define BUZZ_CONTROLLER           BIT(3)
40f1c458caSSven Eckelmann #define PS3REMOTE                 BIT(4)
418ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5)
428ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
43cc6e0bbbSJiri Kosina 
448ab1676bSFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB)
4560781cf4SFrank Praznik 
4660781cf4SFrank Praznik #define MAX_LEDS 4
470a286ef2SSven Eckelmann 
4861ab44beSSimon Wood static const u8 sixaxis_rdesc_fixup[] = {
4961ab44beSSimon Wood 	0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
5061ab44beSSimon Wood 	0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
5161ab44beSSimon Wood 	0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02
5261ab44beSSimon Wood };
5361ab44beSSimon Wood 
54e57a67daSMauro Carvalho Chehab static const u8 sixaxis_rdesc_fixup2[] = {
55e57a67daSMauro Carvalho Chehab 	0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02,
56e57a67daSMauro Carvalho Chehab 	0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00,
57e57a67daSMauro Carvalho Chehab 	0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95,
58e57a67daSMauro Carvalho Chehab 	0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45,
59e57a67daSMauro Carvalho Chehab 	0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81,
60e57a67daSMauro Carvalho Chehab 	0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff,
61e57a67daSMauro Carvalho Chehab 	0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
62e57a67daSMauro Carvalho Chehab 	0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95,
63e57a67daSMauro Carvalho Chehab 	0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30,
64e57a67daSMauro Carvalho Chehab 	0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02,
65e57a67daSMauro Carvalho Chehab 	0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81,
66e57a67daSMauro Carvalho Chehab 	0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95,
67e57a67daSMauro Carvalho Chehab 	0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09,
68e57a67daSMauro Carvalho Chehab 	0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02,
69e57a67daSMauro Carvalho Chehab 	0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02,
70e57a67daSMauro Carvalho Chehab 	0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95,
71e57a67daSMauro Carvalho Chehab 	0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02,
72e57a67daSMauro Carvalho Chehab 	0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01,
73e57a67daSMauro Carvalho Chehab 	0xb1, 0x02, 0xc0, 0xc0,
74e57a67daSMauro Carvalho Chehab };
75e57a67daSMauro Carvalho Chehab 
76*58d7027bSFrank Praznik /* The default descriptor doesn't provide mapping for the accelerometers
77*58d7027bSFrank Praznik  * or orientation sensors.  This fixed descriptor maps the accelerometers
78*58d7027bSFrank Praznik  * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
79*58d7027bSFrank Praznik  * to usage values 0x43, 0x44 and 0x45.
80*58d7027bSFrank Praznik  */
81ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = {
82*58d7027bSFrank Praznik 	0x05, 0x01,         /*  Usage Page (Desktop),               */
83*58d7027bSFrank Praznik 	0x09, 0x05,         /*  Usage (Gamepad),                    */
84*58d7027bSFrank Praznik 	0xA1, 0x01,         /*  Collection (Application),           */
85*58d7027bSFrank Praznik 	0x85, 0x01,         /*      Report ID (1),                  */
86*58d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (X),                      */
87*58d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (Y),                      */
88*58d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (Z),                      */
89*58d7027bSFrank Praznik 	0x09, 0x35,         /*      Usage (Rz),                     */
90*58d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
91*58d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
92*58d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
93*58d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
94*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
95*58d7027bSFrank Praznik 	0x09, 0x39,         /*      Usage (Hat Switch),             */
96*58d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
97*58d7027bSFrank Praznik 	0x25, 0x07,         /*      Logical Maximum (7),            */
98*58d7027bSFrank Praznik 	0x35, 0x00,         /*      Physical Minimum (0),           */
99*58d7027bSFrank Praznik 	0x46, 0x3B, 0x01,   /*      Physical Maximum (315),         */
100*58d7027bSFrank Praznik 	0x65, 0x14,         /*      Unit (Degrees),                 */
101*58d7027bSFrank Praznik 	0x75, 0x04,         /*      Report Size (4),                */
102*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
103*58d7027bSFrank Praznik 	0x81, 0x42,         /*      Input (Variable, Null State),   */
104*58d7027bSFrank Praznik 	0x65, 0x00,         /*      Unit,                           */
105*58d7027bSFrank Praznik 	0x05, 0x09,         /*      Usage Page (Button),            */
106*58d7027bSFrank Praznik 	0x19, 0x01,         /*      Usage Minimum (01h),            */
107*58d7027bSFrank Praznik 	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
108*58d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
109*58d7027bSFrank Praznik 	0x25, 0x01,         /*      Logical Maximum (1),            */
110*58d7027bSFrank Praznik 	0x75, 0x01,         /*      Report Size (1),                */
111*58d7027bSFrank Praznik 	0x95, 0x0E,         /*      Report Count (14),              */
112*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
113*58d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
114*58d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
115*58d7027bSFrank Praznik 	0x75, 0x06,         /*      Report Size (6),                */
116*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
117*58d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
118*58d7027bSFrank Praznik 	0x25, 0x7F,         /*      Logical Maximum (127),          */
119*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
120*58d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
121*58d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (Rx),                     */
122*58d7027bSFrank Praznik 	0x09, 0x34,         /*      Usage (Ry),                     */
123*58d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
124*58d7027bSFrank Praznik 	0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
125*58d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
126*58d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
127*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
128*58d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
129*58d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
130*58d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
131*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
132*58d7027bSFrank Praznik 	0x05, 0x01,         /*      Usage Page (Desktop),           */
133*58d7027bSFrank Praznik 	0x19, 0x40,         /*      Usage Minimum (40h),            */
134*58d7027bSFrank Praznik 	0x29, 0x42,         /*      Usage Maximum (42h),            */
135*58d7027bSFrank Praznik 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
136*58d7027bSFrank Praznik 	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
137*58d7027bSFrank Praznik 	0x75, 0x10,         /*      Report Size (16),               */
138*58d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
139*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
140*58d7027bSFrank Praznik 	0x19, 0x43,         /*      Usage Minimum (43h),            */
141*58d7027bSFrank Praznik 	0x29, 0x45,         /*      Usage Maximum (45h),            */
142*58d7027bSFrank Praznik 	0x16, 0xFF, 0xBF,   /*      Logical Minimum (-16385),       */
143*58d7027bSFrank Praznik 	0x26, 0x00, 0x40,   /*      Logical Maximum (16384),        */
144*58d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
145*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
146*58d7027bSFrank Praznik 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
147*58d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
148*58d7027bSFrank Praznik 	0x15, 0x00,         /*      Logical Minimum (0),            */
149*58d7027bSFrank Praznik 	0x25, 0xFF,         /*      Logical Maximum (255),          */
150*58d7027bSFrank Praznik 	0x75, 0x08,         /*      Report Size (8),                */
151*58d7027bSFrank Praznik 	0x95, 0x27,         /*      Report Count (39),              */
152*58d7027bSFrank Praznik 	0x81, 0x02,         /*      Input (Variable),               */
153*58d7027bSFrank Praznik 	0x85, 0x05,         /*      Report ID (5),                  */
154*58d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
155*58d7027bSFrank Praznik 	0x95, 0x1F,         /*      Report Count (31),              */
156*58d7027bSFrank Praznik 	0x91, 0x02,         /*      Output (Variable),              */
157*58d7027bSFrank Praznik 	0x85, 0x04,         /*      Report ID (4),                  */
158*58d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
159*58d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
160*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
161*58d7027bSFrank Praznik 	0x85, 0x02,         /*      Report ID (2),                  */
162*58d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
163*58d7027bSFrank Praznik 	0x95, 0x24,         /*      Report Count (36),              */
164*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
165*58d7027bSFrank Praznik 	0x85, 0x08,         /*      Report ID (8),                  */
166*58d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
167*58d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
168*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
169*58d7027bSFrank Praznik 	0x85, 0x10,         /*      Report ID (16),                 */
170*58d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
171*58d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
172*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
173*58d7027bSFrank Praznik 	0x85, 0x11,         /*      Report ID (17),                 */
174*58d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
175*58d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
176*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
177*58d7027bSFrank Praznik 	0x85, 0x12,         /*      Report ID (18),                 */
178*58d7027bSFrank Praznik 	0x06, 0x02, 0xFF,   /*      Usage Page (FF02h),             */
179*58d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
180*58d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
181*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
182*58d7027bSFrank Praznik 	0x85, 0x13,         /*      Report ID (19),                 */
183*58d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
184*58d7027bSFrank Praznik 	0x95, 0x16,         /*      Report Count (22),              */
185*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
186*58d7027bSFrank Praznik 	0x85, 0x14,         /*      Report ID (20),                 */
187*58d7027bSFrank Praznik 	0x06, 0x05, 0xFF,   /*      Usage Page (FF05h),             */
188*58d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
189*58d7027bSFrank Praznik 	0x95, 0x10,         /*      Report Count (16),              */
190*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
191*58d7027bSFrank Praznik 	0x85, 0x15,         /*      Report ID (21),                 */
192*58d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
193*58d7027bSFrank Praznik 	0x95, 0x2C,         /*      Report Count (44),              */
194*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
195*58d7027bSFrank Praznik 	0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
196*58d7027bSFrank Praznik 	0x85, 0x80,         /*      Report ID (128),                */
197*58d7027bSFrank Praznik 	0x09, 0x20,         /*      Usage (20h),                    */
198*58d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
199*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
200*58d7027bSFrank Praznik 	0x85, 0x81,         /*      Report ID (129),                */
201*58d7027bSFrank Praznik 	0x09, 0x21,         /*      Usage (21h),                    */
202*58d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
203*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
204*58d7027bSFrank Praznik 	0x85, 0x82,         /*      Report ID (130),                */
205*58d7027bSFrank Praznik 	0x09, 0x22,         /*      Usage (22h),                    */
206*58d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
207*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
208*58d7027bSFrank Praznik 	0x85, 0x83,         /*      Report ID (131),                */
209*58d7027bSFrank Praznik 	0x09, 0x23,         /*      Usage (23h),                    */
210*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
211*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
212*58d7027bSFrank Praznik 	0x85, 0x84,         /*      Report ID (132),                */
213*58d7027bSFrank Praznik 	0x09, 0x24,         /*      Usage (24h),                    */
214*58d7027bSFrank Praznik 	0x95, 0x04,         /*      Report Count (4),               */
215*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
216*58d7027bSFrank Praznik 	0x85, 0x85,         /*      Report ID (133),                */
217*58d7027bSFrank Praznik 	0x09, 0x25,         /*      Usage (25h),                    */
218*58d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
219*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
220*58d7027bSFrank Praznik 	0x85, 0x86,         /*      Report ID (134),                */
221*58d7027bSFrank Praznik 	0x09, 0x26,         /*      Usage (26h),                    */
222*58d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
223*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
224*58d7027bSFrank Praznik 	0x85, 0x87,         /*      Report ID (135),                */
225*58d7027bSFrank Praznik 	0x09, 0x27,         /*      Usage (27h),                    */
226*58d7027bSFrank Praznik 	0x95, 0x23,         /*      Report Count (35),              */
227*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
228*58d7027bSFrank Praznik 	0x85, 0x88,         /*      Report ID (136),                */
229*58d7027bSFrank Praznik 	0x09, 0x28,         /*      Usage (28h),                    */
230*58d7027bSFrank Praznik 	0x95, 0x22,         /*      Report Count (34),              */
231*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
232*58d7027bSFrank Praznik 	0x85, 0x89,         /*      Report ID (137),                */
233*58d7027bSFrank Praznik 	0x09, 0x29,         /*      Usage (29h),                    */
234*58d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
235*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
236*58d7027bSFrank Praznik 	0x85, 0x90,         /*      Report ID (144),                */
237*58d7027bSFrank Praznik 	0x09, 0x30,         /*      Usage (30h),                    */
238*58d7027bSFrank Praznik 	0x95, 0x05,         /*      Report Count (5),               */
239*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
240*58d7027bSFrank Praznik 	0x85, 0x91,         /*      Report ID (145),                */
241*58d7027bSFrank Praznik 	0x09, 0x31,         /*      Usage (31h),                    */
242*58d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
243*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
244*58d7027bSFrank Praznik 	0x85, 0x92,         /*      Report ID (146),                */
245*58d7027bSFrank Praznik 	0x09, 0x32,         /*      Usage (32h),                    */
246*58d7027bSFrank Praznik 	0x95, 0x03,         /*      Report Count (3),               */
247*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
248*58d7027bSFrank Praznik 	0x85, 0x93,         /*      Report ID (147),                */
249*58d7027bSFrank Praznik 	0x09, 0x33,         /*      Usage (33h),                    */
250*58d7027bSFrank Praznik 	0x95, 0x0C,         /*      Report Count (12),              */
251*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
252*58d7027bSFrank Praznik 	0x85, 0xA0,         /*      Report ID (160),                */
253*58d7027bSFrank Praznik 	0x09, 0x40,         /*      Usage (40h),                    */
254*58d7027bSFrank Praznik 	0x95, 0x06,         /*      Report Count (6),               */
255*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
256*58d7027bSFrank Praznik 	0x85, 0xA1,         /*      Report ID (161),                */
257*58d7027bSFrank Praznik 	0x09, 0x41,         /*      Usage (41h),                    */
258*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
259*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
260*58d7027bSFrank Praznik 	0x85, 0xA2,         /*      Report ID (162),                */
261*58d7027bSFrank Praznik 	0x09, 0x42,         /*      Usage (42h),                    */
262*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
263*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
264*58d7027bSFrank Praznik 	0x85, 0xA3,         /*      Report ID (163),                */
265*58d7027bSFrank Praznik 	0x09, 0x43,         /*      Usage (43h),                    */
266*58d7027bSFrank Praznik 	0x95, 0x30,         /*      Report Count (48),              */
267*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
268*58d7027bSFrank Praznik 	0x85, 0xA4,         /*      Report ID (164),                */
269*58d7027bSFrank Praznik 	0x09, 0x44,         /*      Usage (44h),                    */
270*58d7027bSFrank Praznik 	0x95, 0x0D,         /*      Report Count (13),              */
271*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
272*58d7027bSFrank Praznik 	0x85, 0xA5,         /*      Report ID (165),                */
273*58d7027bSFrank Praznik 	0x09, 0x45,         /*      Usage (45h),                    */
274*58d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
275*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
276*58d7027bSFrank Praznik 	0x85, 0xA6,         /*      Report ID (166),                */
277*58d7027bSFrank Praznik 	0x09, 0x46,         /*      Usage (46h),                    */
278*58d7027bSFrank Praznik 	0x95, 0x15,         /*      Report Count (21),              */
279*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
280*58d7027bSFrank Praznik 	0x85, 0xF0,         /*      Report ID (240),                */
281*58d7027bSFrank Praznik 	0x09, 0x47,         /*      Usage (47h),                    */
282*58d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
283*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
284*58d7027bSFrank Praznik 	0x85, 0xF1,         /*      Report ID (241),                */
285*58d7027bSFrank Praznik 	0x09, 0x48,         /*      Usage (48h),                    */
286*58d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
287*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
288*58d7027bSFrank Praznik 	0x85, 0xF2,         /*      Report ID (242),                */
289*58d7027bSFrank Praznik 	0x09, 0x49,         /*      Usage (49h),                    */
290*58d7027bSFrank Praznik 	0x95, 0x0F,         /*      Report Count (15),              */
291*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
292*58d7027bSFrank Praznik 	0x85, 0xA7,         /*      Report ID (167),                */
293*58d7027bSFrank Praznik 	0x09, 0x4A,         /*      Usage (4Ah),                    */
294*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
295*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
296*58d7027bSFrank Praznik 	0x85, 0xA8,         /*      Report ID (168),                */
297*58d7027bSFrank Praznik 	0x09, 0x4B,         /*      Usage (4Bh),                    */
298*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
299*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
300*58d7027bSFrank Praznik 	0x85, 0xA9,         /*      Report ID (169),                */
301*58d7027bSFrank Praznik 	0x09, 0x4C,         /*      Usage (4Ch),                    */
302*58d7027bSFrank Praznik 	0x95, 0x08,         /*      Report Count (8),               */
303*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
304*58d7027bSFrank Praznik 	0x85, 0xAA,         /*      Report ID (170),                */
305*58d7027bSFrank Praznik 	0x09, 0x4E,         /*      Usage (4Eh),                    */
306*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
307*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
308*58d7027bSFrank Praznik 	0x85, 0xAB,         /*      Report ID (171),                */
309*58d7027bSFrank Praznik 	0x09, 0x4F,         /*      Usage (4Fh),                    */
310*58d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
311*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
312*58d7027bSFrank Praznik 	0x85, 0xAC,         /*      Report ID (172),                */
313*58d7027bSFrank Praznik 	0x09, 0x50,         /*      Usage (50h),                    */
314*58d7027bSFrank Praznik 	0x95, 0x39,         /*      Report Count (57),              */
315*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
316*58d7027bSFrank Praznik 	0x85, 0xAD,         /*      Report ID (173),                */
317*58d7027bSFrank Praznik 	0x09, 0x51,         /*      Usage (51h),                    */
318*58d7027bSFrank Praznik 	0x95, 0x0B,         /*      Report Count (11),              */
319*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
320*58d7027bSFrank Praznik 	0x85, 0xAE,         /*      Report ID (174),                */
321*58d7027bSFrank Praznik 	0x09, 0x52,         /*      Usage (52h),                    */
322*58d7027bSFrank Praznik 	0x95, 0x01,         /*      Report Count (1),               */
323*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
324*58d7027bSFrank Praznik 	0x85, 0xAF,         /*      Report ID (175),                */
325*58d7027bSFrank Praznik 	0x09, 0x53,         /*      Usage (53h),                    */
326*58d7027bSFrank Praznik 	0x95, 0x02,         /*      Report Count (2),               */
327*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
328*58d7027bSFrank Praznik 	0x85, 0xB0,         /*      Report ID (176),                */
329*58d7027bSFrank Praznik 	0x09, 0x54,         /*      Usage (54h),                    */
330*58d7027bSFrank Praznik 	0x95, 0x3F,         /*      Report Count (63),              */
331*58d7027bSFrank Praznik 	0xB1, 0x02,         /*      Feature (Variable),             */
332*58d7027bSFrank Praznik 	0xC0                /*  End Collection                      */
333ed19d8cfSFrank Praznik };
334ed19d8cfSFrank Praznik 
335078328daSJiri Kosina static __u8 ps3remote_rdesc[] = {
336078328daSJiri Kosina 	0x05, 0x01,          /* GUsagePage Generic Desktop */
337078328daSJiri Kosina 	0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
338078328daSJiri Kosina 	0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
339078328daSJiri Kosina 
340078328daSJiri Kosina 	 /* Use collection 1 for joypad buttons */
341078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
342078328daSJiri Kosina 
343078328daSJiri Kosina 	  /* Ignore the 1st byte, maybe it is used for a controller
344078328daSJiri Kosina 	   * number but it's not needed for correct operation */
345078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
346078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
347078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
348078328daSJiri Kosina 
349078328daSJiri Kosina 	  /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
350078328daSJiri Kosina 	   * buttons multiple keypresses are allowed */
351078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
352078328daSJiri Kosina 	  0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
353078328daSJiri Kosina 	  0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
354078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
355078328daSJiri Kosina 	  0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
356078328daSJiri Kosina 	  0x75, 0x01,        /* GReportSize 0x01 [1] */
357078328daSJiri Kosina 	  0x95, 0x18,        /* GReportCount 0x18 [24] */
358078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
359078328daSJiri Kosina 
360078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
361078328daSJiri Kosina 
362078328daSJiri Kosina 	 /* Use collection 2 for remote control buttons */
363078328daSJiri Kosina 	 0xA1, 0x02,         /* MCollection Logical (interrelated data) */
364078328daSJiri Kosina 
365078328daSJiri Kosina 	  /* 5th byte is used for remote control buttons */
366078328daSJiri Kosina 	  0x05, 0x09,        /* GUsagePage Button */
367078328daSJiri Kosina 	  0x18,              /* LUsageMinimum [No button pressed] */
368078328daSJiri Kosina 	  0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
369078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
370078328daSJiri Kosina 	  0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
371078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
372078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
373078328daSJiri Kosina 	  0x80,              /* MInput  */
374078328daSJiri Kosina 
375078328daSJiri Kosina 	  /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
376078328daSJiri Kosina 	   * 0xff and 11th is for press indication */
377078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
378078328daSJiri Kosina 	  0x95, 0x06,        /* GReportCount 0x06 [6] */
379078328daSJiri Kosina 	  0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
380078328daSJiri Kosina 
381078328daSJiri Kosina 	  /* 12th byte is for battery strength */
382078328daSJiri Kosina 	  0x05, 0x06,        /* GUsagePage Generic Device Controls */
383078328daSJiri Kosina 	  0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
384078328daSJiri Kosina 	  0x14,              /* GLogicalMinimum [0] */
385078328daSJiri Kosina 	  0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
386078328daSJiri Kosina 	  0x75, 0x08,        /* GReportSize 0x08 [8] */
387078328daSJiri Kosina 	  0x95, 0x01,        /* GReportCount 0x01 [1] */
388078328daSJiri Kosina 	  0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
389078328daSJiri Kosina 
390078328daSJiri Kosina 	  0xC0,              /* MEndCollection */
391078328daSJiri Kosina 
392078328daSJiri Kosina 	 0xC0                /* MEndCollection [Game Pad] */
393078328daSJiri Kosina };
394078328daSJiri Kosina 
395078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
396078328daSJiri Kosina 	[0x01] = KEY_SELECT,
397078328daSJiri Kosina 	[0x02] = BTN_THUMBL,		/* L3 */
398078328daSJiri Kosina 	[0x03] = BTN_THUMBR,		/* R3 */
399078328daSJiri Kosina 	[0x04] = BTN_START,
400078328daSJiri Kosina 	[0x05] = KEY_UP,
401078328daSJiri Kosina 	[0x06] = KEY_RIGHT,
402078328daSJiri Kosina 	[0x07] = KEY_DOWN,
403078328daSJiri Kosina 	[0x08] = KEY_LEFT,
404078328daSJiri Kosina 	[0x09] = BTN_TL2,		/* L2 */
405078328daSJiri Kosina 	[0x0a] = BTN_TR2,		/* R2 */
406078328daSJiri Kosina 	[0x0b] = BTN_TL,		/* L1 */
407078328daSJiri Kosina 	[0x0c] = BTN_TR,		/* R1 */
408078328daSJiri Kosina 	[0x0d] = KEY_OPTION,		/* options/triangle */
409078328daSJiri Kosina 	[0x0e] = KEY_BACK,		/* back/circle */
410078328daSJiri Kosina 	[0x0f] = BTN_0,			/* cross */
411078328daSJiri Kosina 	[0x10] = KEY_SCREEN,		/* view/square */
412078328daSJiri Kosina 	[0x11] = KEY_HOMEPAGE,		/* PS button */
413078328daSJiri Kosina 	[0x14] = KEY_ENTER,
414078328daSJiri Kosina };
415078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
416078328daSJiri Kosina 	[0x00] = KEY_1,
417078328daSJiri Kosina 	[0x01] = KEY_2,
418078328daSJiri Kosina 	[0x02] = KEY_3,
419078328daSJiri Kosina 	[0x03] = KEY_4,
420078328daSJiri Kosina 	[0x04] = KEY_5,
421078328daSJiri Kosina 	[0x05] = KEY_6,
422078328daSJiri Kosina 	[0x06] = KEY_7,
423078328daSJiri Kosina 	[0x07] = KEY_8,
424078328daSJiri Kosina 	[0x08] = KEY_9,
425078328daSJiri Kosina 	[0x09] = KEY_0,
426078328daSJiri Kosina 	[0x0e] = KEY_ESC,		/* return */
427078328daSJiri Kosina 	[0x0f] = KEY_CLEAR,
428078328daSJiri Kosina 	[0x16] = KEY_EJECTCD,
429078328daSJiri Kosina 	[0x1a] = KEY_MENU,		/* top menu */
430078328daSJiri Kosina 	[0x28] = KEY_TIME,
431078328daSJiri Kosina 	[0x30] = KEY_PREVIOUS,
432078328daSJiri Kosina 	[0x31] = KEY_NEXT,
433078328daSJiri Kosina 	[0x32] = KEY_PLAY,
434078328daSJiri Kosina 	[0x33] = KEY_REWIND,		/* scan back */
435078328daSJiri Kosina 	[0x34] = KEY_FORWARD,		/* scan forward */
436078328daSJiri Kosina 	[0x38] = KEY_STOP,
437078328daSJiri Kosina 	[0x39] = KEY_PAUSE,
438078328daSJiri Kosina 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
439078328daSJiri Kosina 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
440078328daSJiri Kosina 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
441078328daSJiri Kosina 	[0x63] = KEY_SUBTITLE,
442078328daSJiri Kosina 	[0x64] = KEY_AUDIO,
443078328daSJiri Kosina 	[0x65] = KEY_ANGLE,
444078328daSJiri Kosina 	[0x70] = KEY_INFO,		/* display */
445078328daSJiri Kosina 	[0x80] = KEY_BLUE,
446078328daSJiri Kosina 	[0x81] = KEY_RED,
447078328daSJiri Kosina 	[0x82] = KEY_GREEN,
448078328daSJiri Kosina 	[0x83] = KEY_YELLOW,
449078328daSJiri Kosina };
450078328daSJiri Kosina 
451f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
452f04d5140SColin Leitner 	/* The controller has 4 remote buzzers, each with one LED and 5
453f04d5140SColin Leitner 	 * buttons.
454f04d5140SColin Leitner 	 *
455f04d5140SColin Leitner 	 * We use the mapping chosen by the controller, which is:
456f04d5140SColin Leitner 	 *
457f04d5140SColin Leitner 	 * Key          Offset
458f04d5140SColin Leitner 	 * -------------------
459f04d5140SColin Leitner 	 * Buzz              1
460f04d5140SColin Leitner 	 * Blue              5
461f04d5140SColin Leitner 	 * Orange            4
462f04d5140SColin Leitner 	 * Green             3
463f04d5140SColin Leitner 	 * Yellow            2
464f04d5140SColin Leitner 	 *
465f04d5140SColin Leitner 	 * So, for example, the orange button on the third buzzer is mapped to
466f04d5140SColin Leitner 	 * BTN_TRIGGER_HAPPY14
467f04d5140SColin Leitner 	 */
468f04d5140SColin Leitner 	[ 1] = BTN_TRIGGER_HAPPY1,
469f04d5140SColin Leitner 	[ 2] = BTN_TRIGGER_HAPPY2,
470f04d5140SColin Leitner 	[ 3] = BTN_TRIGGER_HAPPY3,
471f04d5140SColin Leitner 	[ 4] = BTN_TRIGGER_HAPPY4,
472f04d5140SColin Leitner 	[ 5] = BTN_TRIGGER_HAPPY5,
473f04d5140SColin Leitner 	[ 6] = BTN_TRIGGER_HAPPY6,
474f04d5140SColin Leitner 	[ 7] = BTN_TRIGGER_HAPPY7,
475f04d5140SColin Leitner 	[ 8] = BTN_TRIGGER_HAPPY8,
476f04d5140SColin Leitner 	[ 9] = BTN_TRIGGER_HAPPY9,
477f04d5140SColin Leitner 	[10] = BTN_TRIGGER_HAPPY10,
478f04d5140SColin Leitner 	[11] = BTN_TRIGGER_HAPPY11,
479f04d5140SColin Leitner 	[12] = BTN_TRIGGER_HAPPY12,
480f04d5140SColin Leitner 	[13] = BTN_TRIGGER_HAPPY13,
481f04d5140SColin Leitner 	[14] = BTN_TRIGGER_HAPPY14,
482f04d5140SColin Leitner 	[15] = BTN_TRIGGER_HAPPY15,
483f04d5140SColin Leitner 	[16] = BTN_TRIGGER_HAPPY16,
484f04d5140SColin Leitner 	[17] = BTN_TRIGGER_HAPPY17,
485f04d5140SColin Leitner 	[18] = BTN_TRIGGER_HAPPY18,
486f04d5140SColin Leitner 	[19] = BTN_TRIGGER_HAPPY19,
487f04d5140SColin Leitner 	[20] = BTN_TRIGGER_HAPPY20,
488f04d5140SColin Leitner };
489f04d5140SColin Leitner 
490cc6e0bbbSJiri Kosina struct sony_sc {
4910a286ef2SSven Eckelmann 	struct hid_device *hdev;
49260781cf4SFrank Praznik 	struct led_classdev *leds[MAX_LEDS];
493c4e1ddf2SFrank Praznik 	struct hid_report *output_report;
494cc6e0bbbSJiri Kosina 	unsigned long quirks;
4950a286ef2SSven Eckelmann 	struct work_struct state_worker;
496f04d5140SColin Leitner 
4979f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
4989f323b68SSven Eckelmann 	__u8 left;
4999f323b68SSven Eckelmann 	__u8 right;
5009f323b68SSven Eckelmann #endif
5019f323b68SSven Eckelmann 
50260781cf4SFrank Praznik 	__u8 led_state[MAX_LEDS];
50360781cf4SFrank Praznik 	__u8 led_count;
504cc6e0bbbSJiri Kosina };
505cc6e0bbbSJiri Kosina 
506078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
507078328daSJiri Kosina 			     unsigned int *rsize)
508078328daSJiri Kosina {
509078328daSJiri Kosina 	*rsize = sizeof(ps3remote_rdesc);
510078328daSJiri Kosina 	return ps3remote_rdesc;
511078328daSJiri Kosina }
512078328daSJiri Kosina 
513078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
514078328daSJiri Kosina 			     struct hid_field *field, struct hid_usage *usage,
515078328daSJiri Kosina 			     unsigned long **bit, int *max)
516078328daSJiri Kosina {
517078328daSJiri Kosina 	unsigned int key = usage->hid & HID_USAGE;
518078328daSJiri Kosina 
519078328daSJiri Kosina 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
520078328daSJiri Kosina 		return -1;
521078328daSJiri Kosina 
522078328daSJiri Kosina 	switch (usage->collection_index) {
523078328daSJiri Kosina 	case 1:
524078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
525078328daSJiri Kosina 			return -1;
526078328daSJiri Kosina 
527078328daSJiri Kosina 		key = ps3remote_keymap_joypad_buttons[key];
528078328daSJiri Kosina 		if (!key)
529078328daSJiri Kosina 			return -1;
530078328daSJiri Kosina 		break;
531078328daSJiri Kosina 	case 2:
532078328daSJiri Kosina 		if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
533078328daSJiri Kosina 			return -1;
534078328daSJiri Kosina 
535078328daSJiri Kosina 		key = ps3remote_keymap_remote_buttons[key];
536078328daSJiri Kosina 		if (!key)
537078328daSJiri Kosina 			return -1;
538078328daSJiri Kosina 		break;
539078328daSJiri Kosina 	default:
540078328daSJiri Kosina 		return -1;
541078328daSJiri Kosina 	}
542078328daSJiri Kosina 
543078328daSJiri Kosina 	hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
544078328daSJiri Kosina 	return 1;
545078328daSJiri Kosina }
546078328daSJiri Kosina 
547078328daSJiri Kosina 
548cc6e0bbbSJiri Kosina /* Sony Vaio VGX has wrongly mouse pointer declared as constant */
54973e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
55073e4008dSNikolai Kondrashov 		unsigned int *rsize)
551cc6e0bbbSJiri Kosina {
552cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
553cc6e0bbbSJiri Kosina 
55499d24902SFernando Luis Vázquez Cao 	/*
55599d24902SFernando Luis Vázquez Cao 	 * Some Sony RF receivers wrongly declare the mouse pointer as a
55699d24902SFernando Luis Vázquez Cao 	 * a constant non-data variable.
55799d24902SFernando Luis Vázquez Cao 	 */
55899d24902SFernando Luis Vázquez Cao 	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
55999d24902SFernando Luis Vázquez Cao 	    /* usage page: generic desktop controls */
56099d24902SFernando Luis Vázquez Cao 	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
56199d24902SFernando Luis Vázquez Cao 	    /* usage: mouse */
56299d24902SFernando Luis Vázquez Cao 	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
56399d24902SFernando Luis Vázquez Cao 	    /* input (usage page for x,y axes): constant, variable, relative */
56499d24902SFernando Luis Vázquez Cao 	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
565a4649184SFernando Luis Vázquez Cao 		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
56699d24902SFernando Luis Vázquez Cao 		/* input: data, variable, relative */
567cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
568cc6e0bbbSJiri Kosina 	}
56961ab44beSSimon Wood 
570ed19d8cfSFrank Praznik 	/*
571ed19d8cfSFrank Praznik 	 * The default Dualshock 4 USB descriptor doesn't assign
572ed19d8cfSFrank Praznik 	 * the gyroscope values to corresponding axes so we need a
573ed19d8cfSFrank Praznik 	 * modified one.
574ed19d8cfSFrank Praznik 	 */
575ed19d8cfSFrank Praznik 	if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) {
576ed19d8cfSFrank Praznik 		hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
577ed19d8cfSFrank Praznik 		rdesc = dualshock4_usb_rdesc;
578ed19d8cfSFrank Praznik 		*rsize = sizeof(dualshock4_usb_rdesc);
579ed19d8cfSFrank Praznik 	}
580ed19d8cfSFrank Praznik 
58161ab44beSSimon Wood 	/* The HID descriptor exposed over BT has a trailing zero byte */
58261ab44beSSimon Wood 	if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
58361ab44beSSimon Wood 			((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
58461ab44beSSimon Wood 			rdesc[83] == 0x75) {
58561ab44beSSimon Wood 		hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
58661ab44beSSimon Wood 		memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
58761ab44beSSimon Wood 			sizeof(sixaxis_rdesc_fixup));
588e57a67daSMauro Carvalho Chehab 	} else if (sc->quirks & SIXAXIS_CONTROLLER_USB &&
589e57a67daSMauro Carvalho Chehab 		   *rsize > sizeof(sixaxis_rdesc_fixup2)) {
590e57a67daSMauro Carvalho Chehab 		hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n",
591e57a67daSMauro Carvalho Chehab 			 *rsize, (int)sizeof(sixaxis_rdesc_fixup2));
592e57a67daSMauro Carvalho Chehab 		*rsize = sizeof(sixaxis_rdesc_fixup2);
593e57a67daSMauro Carvalho Chehab 		memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
59461ab44beSSimon Wood 	}
595078328daSJiri Kosina 
596078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
597078328daSJiri Kosina 		return ps3remote_fixup(hdev, rdesc, rsize);
598078328daSJiri Kosina 
59973e4008dSNikolai Kondrashov 	return rdesc;
600cc6e0bbbSJiri Kosina }
601cc6e0bbbSJiri Kosina 
602c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
603c9e4d877SSimon Wood 		__u8 *rd, int size)
604c9e4d877SSimon Wood {
605c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
606c9e4d877SSimon Wood 
607c9e4d877SSimon Wood 	/* Sixaxis HID report has acclerometers/gyro with MSByte first, this
608c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
609c9e4d877SSimon Wood 	 */
610c9e4d877SSimon Wood 	if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
611c9e4d877SSimon Wood 			rd[0] == 0x01 && size == 49) {
612c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
613c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
614c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
615c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
616c9e4d877SSimon Wood 	}
617c9e4d877SSimon Wood 
618c9e4d877SSimon Wood 	return 0;
619c9e4d877SSimon Wood }
620c9e4d877SSimon Wood 
621f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
622f04d5140SColin Leitner 			struct hid_field *field, struct hid_usage *usage,
623f04d5140SColin Leitner 			unsigned long **bit, int *max)
624f04d5140SColin Leitner {
625f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
626f04d5140SColin Leitner 
627f04d5140SColin Leitner 	if (sc->quirks & BUZZ_CONTROLLER) {
628f04d5140SColin Leitner 		unsigned int key = usage->hid & HID_USAGE;
629f04d5140SColin Leitner 
630f04d5140SColin Leitner 		if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
631f04d5140SColin Leitner 			return -1;
632f04d5140SColin Leitner 
633f04d5140SColin Leitner 		switch (usage->collection_index) {
634f04d5140SColin Leitner 		case 1:
635f04d5140SColin Leitner 			if (key >= ARRAY_SIZE(buzz_keymap))
636f04d5140SColin Leitner 				return -1;
637f04d5140SColin Leitner 
638f04d5140SColin Leitner 			key = buzz_keymap[key];
639f04d5140SColin Leitner 			if (!key)
640f04d5140SColin Leitner 				return -1;
641f04d5140SColin Leitner 			break;
642f04d5140SColin Leitner 		default:
643f04d5140SColin Leitner 			return -1;
644f04d5140SColin Leitner 		}
645f04d5140SColin Leitner 
646f04d5140SColin Leitner 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
647f04d5140SColin Leitner 		return 1;
648f04d5140SColin Leitner 	}
649f04d5140SColin Leitner 
650078328daSJiri Kosina 	if (sc->quirks & PS3REMOTE)
651078328daSJiri Kosina 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
652078328daSJiri Kosina 
6536f498018SBenjamin Tissoires 	/* Let hid-core decide for the others */
6546f498018SBenjamin Tissoires 	return 0;
655f04d5140SColin Leitner }
656f04d5140SColin Leitner 
6575710fabfSAntonio Ospite /*
6585710fabfSAntonio Ospite  * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
6595710fabfSAntonio Ospite  * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
6605710fabfSAntonio Ospite  * so we need to override that forcing HID Output Reports on the Control EP.
6615710fabfSAntonio Ospite  *
6625710fabfSAntonio Ospite  * There is also another issue about HID Output Reports via USB, the Sixaxis
6635710fabfSAntonio Ospite  * does not want the report_id as part of the data packet, so we have to
6645710fabfSAntonio Ospite  * discard buf[0] when sending the actual control message, even for numbered
6655710fabfSAntonio Ospite  * reports, humpf!
6665710fabfSAntonio Ospite  */
667569b10a5SAntonio Ospite static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
668569b10a5SAntonio Ospite 		size_t count, unsigned char report_type)
669569b10a5SAntonio Ospite {
670569b10a5SAntonio Ospite 	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
671569b10a5SAntonio Ospite 	struct usb_device *dev = interface_to_usbdev(intf);
672569b10a5SAntonio Ospite 	struct usb_host_interface *interface = intf->cur_altsetting;
673569b10a5SAntonio Ospite 	int report_id = buf[0];
674569b10a5SAntonio Ospite 	int ret;
675569b10a5SAntonio Ospite 
6765710fabfSAntonio Ospite 	if (report_type == HID_OUTPUT_REPORT) {
6775710fabfSAntonio Ospite 		/* Don't send the Report ID */
6785710fabfSAntonio Ospite 		buf++;
6795710fabfSAntonio Ospite 		count--;
6805710fabfSAntonio Ospite 	}
6815710fabfSAntonio Ospite 
682569b10a5SAntonio Ospite 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
683569b10a5SAntonio Ospite 		HID_REQ_SET_REPORT,
684569b10a5SAntonio Ospite 		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
685569b10a5SAntonio Ospite 		((report_type + 1) << 8) | report_id,
686569b10a5SAntonio Ospite 		interface->desc.bInterfaceNumber, buf, count,
687569b10a5SAntonio Ospite 		USB_CTRL_SET_TIMEOUT);
688569b10a5SAntonio Ospite 
6895710fabfSAntonio Ospite 	/* Count also the Report ID, in case of an Output report. */
6905710fabfSAntonio Ospite 	if (ret > 0 && report_type == HID_OUTPUT_REPORT)
6915710fabfSAntonio Ospite 		ret++;
6925710fabfSAntonio Ospite 
693569b10a5SAntonio Ospite 	return ret;
694569b10a5SAntonio Ospite }
695569b10a5SAntonio Ospite 
696bd28ce00SJiri Slaby /*
697bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
698bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
699bd28ce00SJiri Slaby  * events.
700bd28ce00SJiri Slaby  */
701816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
702bd28ce00SJiri Slaby {
703bd28ce00SJiri Slaby 	int ret;
704bd28ce00SJiri Slaby 	char *buf = kmalloc(18, GFP_KERNEL);
705bd28ce00SJiri Slaby 
706bd28ce00SJiri Slaby 	if (!buf)
707bd28ce00SJiri Slaby 		return -ENOMEM;
708bd28ce00SJiri Slaby 
709f204828aSBenjamin Tissoires 	ret = hdev->hid_get_raw_report(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT);
710f204828aSBenjamin Tissoires 
711bd28ce00SJiri Slaby 	if (ret < 0)
7124291ee30SJoe Perches 		hid_err(hdev, "can't set operational mode\n");
713bd28ce00SJiri Slaby 
714bd28ce00SJiri Slaby 	kfree(buf);
715bd28ce00SJiri Slaby 
716bd28ce00SJiri Slaby 	return ret;
717bd28ce00SJiri Slaby }
718bd28ce00SJiri Slaby 
719816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
720f9ce7c28SBastien Nocera {
721fddb33f2SAntonio Ospite 	unsigned char buf[] = { 0xf4,  0x42, 0x03, 0x00, 0x00 };
722f9ce7c28SBastien Nocera 	return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
723f9ce7c28SBastien Nocera }
724f9ce7c28SBastien Nocera 
72560781cf4SFrank Praznik static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds)
726f04d5140SColin Leitner {
727f04d5140SColin Leitner 	struct list_head *report_list =
728f04d5140SColin Leitner 		&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
729f04d5140SColin Leitner 	struct hid_report *report = list_entry(report_list->next,
730f04d5140SColin Leitner 		struct hid_report, list);
731f04d5140SColin Leitner 	__s32 *value = report->field[0]->value;
732f04d5140SColin Leitner 
733f04d5140SColin Leitner 	value[0] = 0x00;
73460781cf4SFrank Praznik 	value[1] = leds[0] ? 0xff : 0x00;
73560781cf4SFrank Praznik 	value[2] = leds[1] ? 0xff : 0x00;
73660781cf4SFrank Praznik 	value[3] = leds[2] ? 0xff : 0x00;
73760781cf4SFrank Praznik 	value[4] = leds[3] ? 0xff : 0x00;
738f04d5140SColin Leitner 	value[5] = 0x00;
739f04d5140SColin Leitner 	value[6] = 0x00;
740f04d5140SColin Leitner 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
741f04d5140SColin Leitner }
742f04d5140SColin Leitner 
74360781cf4SFrank Praznik static void sony_set_leds(struct hid_device *hdev, const __u8 *leds, int count)
7440a286ef2SSven Eckelmann {
7450a286ef2SSven Eckelmann 	struct sony_sc *drv_data = hid_get_drvdata(hdev);
74660781cf4SFrank Praznik 	int n;
7470a286ef2SSven Eckelmann 
74860781cf4SFrank Praznik 	BUG_ON(count > MAX_LEDS);
74960781cf4SFrank Praznik 
75060781cf4SFrank Praznik 	if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) {
7510a286ef2SSven Eckelmann 		buzz_set_leds(hdev, leds);
75260781cf4SFrank Praznik 	} else if ((drv_data->quirks & SIXAXIS_CONTROLLER_USB) ||
7538ab1676bSFrank Praznik 		   (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB)) {
75460781cf4SFrank Praznik 		for (n = 0; n < count; n++)
75560781cf4SFrank Praznik 			drv_data->led_state[n] = leds[n];
7560a286ef2SSven Eckelmann 		schedule_work(&drv_data->state_worker);
7570a286ef2SSven Eckelmann 	}
7580a286ef2SSven Eckelmann }
7590a286ef2SSven Eckelmann 
760c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
761f04d5140SColin Leitner 				    enum led_brightness value)
762f04d5140SColin Leitner {
763f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
764f04d5140SColin Leitner 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
765f04d5140SColin Leitner 	struct sony_sc *drv_data;
766f04d5140SColin Leitner 
767f04d5140SColin Leitner 	int n;
768f04d5140SColin Leitner 
769f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
7702251b85fSSven Eckelmann 	if (!drv_data) {
771f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
772f04d5140SColin Leitner 		return;
773f04d5140SColin Leitner 	}
774f04d5140SColin Leitner 
77560781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
7762251b85fSSven Eckelmann 		if (led == drv_data->leds[n]) {
77760781cf4SFrank Praznik 			if (value != drv_data->led_state[n]) {
77860781cf4SFrank Praznik 				drv_data->led_state[n] = value;
77960781cf4SFrank Praznik 				sony_set_leds(hdev, drv_data->led_state, drv_data->led_count);
780f04d5140SColin Leitner 			}
781f04d5140SColin Leitner 			break;
782f04d5140SColin Leitner 		}
783f04d5140SColin Leitner 	}
784f04d5140SColin Leitner }
785f04d5140SColin Leitner 
786c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
787f04d5140SColin Leitner {
788f04d5140SColin Leitner 	struct device *dev = led->dev->parent;
789f04d5140SColin Leitner 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
790f04d5140SColin Leitner 	struct sony_sc *drv_data;
791f04d5140SColin Leitner 
792f04d5140SColin Leitner 	int n;
793f04d5140SColin Leitner 	int on = 0;
794f04d5140SColin Leitner 
795f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
7962251b85fSSven Eckelmann 	if (!drv_data) {
797f04d5140SColin Leitner 		hid_err(hdev, "No device data\n");
798f04d5140SColin Leitner 		return LED_OFF;
799f04d5140SColin Leitner 	}
800f04d5140SColin Leitner 
80160781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
8022251b85fSSven Eckelmann 		if (led == drv_data->leds[n]) {
80360781cf4SFrank Praznik 			on = !!(drv_data->led_state[n]);
804f04d5140SColin Leitner 			break;
805f04d5140SColin Leitner 		}
806f04d5140SColin Leitner 	}
807f04d5140SColin Leitner 
808f04d5140SColin Leitner 	return on ? LED_FULL : LED_OFF;
809f04d5140SColin Leitner }
810f04d5140SColin Leitner 
8110a286ef2SSven Eckelmann static void sony_leds_remove(struct hid_device *hdev)
8120a286ef2SSven Eckelmann {
8130a286ef2SSven Eckelmann 	struct sony_sc *drv_data;
8140a286ef2SSven Eckelmann 	struct led_classdev *led;
8150a286ef2SSven Eckelmann 	int n;
8160a286ef2SSven Eckelmann 
8170a286ef2SSven Eckelmann 	drv_data = hid_get_drvdata(hdev);
8180a286ef2SSven Eckelmann 	BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
8190a286ef2SSven Eckelmann 
82060781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
8210a286ef2SSven Eckelmann 		led = drv_data->leds[n];
8220a286ef2SSven Eckelmann 		drv_data->leds[n] = NULL;
8230a286ef2SSven Eckelmann 		if (!led)
8240a286ef2SSven Eckelmann 			continue;
8250a286ef2SSven Eckelmann 		led_classdev_unregister(led);
8260a286ef2SSven Eckelmann 		kfree(led);
8270a286ef2SSven Eckelmann 	}
82860781cf4SFrank Praznik 
82960781cf4SFrank Praznik 	drv_data->led_count = 0;
8300a286ef2SSven Eckelmann }
8310a286ef2SSven Eckelmann 
832c5382519SSven Eckelmann static int sony_leds_init(struct hid_device *hdev)
833f04d5140SColin Leitner {
834f04d5140SColin Leitner 	struct sony_sc *drv_data;
83540e32ee6SJiri Kosina 	int n, ret = 0;
83660781cf4SFrank Praznik 	int max_brightness;
83740e32ee6SJiri Kosina 	struct led_classdev *led;
83840e32ee6SJiri Kosina 	size_t name_sz;
83940e32ee6SJiri Kosina 	char *name;
8400a286ef2SSven Eckelmann 	size_t name_len;
8410a286ef2SSven Eckelmann 	const char *name_fmt;
84260781cf4SFrank Praznik 	static const __u8 initial_values[MAX_LEDS] = { 0x00, 0x00, 0x00, 0x00 };
843f04d5140SColin Leitner 
844f04d5140SColin Leitner 	drv_data = hid_get_drvdata(hdev);
8450a286ef2SSven Eckelmann 	BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
846f04d5140SColin Leitner 
8470a286ef2SSven Eckelmann 	if (drv_data->quirks & BUZZ_CONTROLLER) {
8480a286ef2SSven Eckelmann 		name_len = strlen("::buzz#");
8490a286ef2SSven Eckelmann 		name_fmt = "%s::buzz%d";
8509446edb9SKees Cook 		/* Validate expected report characteristics. */
8519446edb9SKees Cook 		if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
8529446edb9SKees Cook 			return -ENODEV;
8530a286ef2SSven Eckelmann 	} else {
8540a286ef2SSven Eckelmann 		name_len = strlen("::sony#");
8550a286ef2SSven Eckelmann 		name_fmt = "%s::sony%d";
8560a286ef2SSven Eckelmann 	}
8579446edb9SKees Cook 
8588ab1676bSFrank Praznik 	if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) {
85960781cf4SFrank Praznik 		drv_data->led_count = 3;
86060781cf4SFrank Praznik 		max_brightness = 255;
86160781cf4SFrank Praznik 	} else {
86260781cf4SFrank Praznik 		drv_data->led_count = 4;
86360781cf4SFrank Praznik 		max_brightness = 1;
86460781cf4SFrank Praznik 	}
86560781cf4SFrank Praznik 
866f04d5140SColin Leitner 	/* Clear LEDs as we have no way of reading their initial state. This is
867f04d5140SColin Leitner 	 * only relevant if the driver is loaded after somebody actively set the
868f04d5140SColin Leitner 	 * LEDs to on */
86960781cf4SFrank Praznik 	sony_set_leds(hdev, initial_values, drv_data->led_count);
870f04d5140SColin Leitner 
8710a286ef2SSven Eckelmann 	name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
872f04d5140SColin Leitner 
87360781cf4SFrank Praznik 	for (n = 0; n < drv_data->led_count; n++) {
874f04d5140SColin Leitner 		led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
875f04d5140SColin Leitner 		if (!led) {
876f04d5140SColin Leitner 			hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
8778cd5fcdaSJulia Lawall 			ret = -ENOMEM;
878f04d5140SColin Leitner 			goto error_leds;
879f04d5140SColin Leitner 		}
880f04d5140SColin Leitner 
881f04d5140SColin Leitner 		name = (void *)(&led[1]);
8820a286ef2SSven Eckelmann 		snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
883f04d5140SColin Leitner 		led->name = name;
884f04d5140SColin Leitner 		led->brightness = 0;
88560781cf4SFrank Praznik 		led->max_brightness = max_brightness;
886c5382519SSven Eckelmann 		led->brightness_get = sony_led_get_brightness;
887c5382519SSven Eckelmann 		led->brightness_set = sony_led_set_brightness;
888f04d5140SColin Leitner 
8898cd5fcdaSJulia Lawall 		ret = led_classdev_register(&hdev->dev, led);
8908cd5fcdaSJulia Lawall 		if (ret) {
891f04d5140SColin Leitner 			hid_err(hdev, "Failed to register LED %d\n", n);
892f04d5140SColin Leitner 			kfree(led);
893f04d5140SColin Leitner 			goto error_leds;
894f04d5140SColin Leitner 		}
895f04d5140SColin Leitner 
8962251b85fSSven Eckelmann 		drv_data->leds[n] = led;
897f04d5140SColin Leitner 	}
898f04d5140SColin Leitner 
899f04d5140SColin Leitner 	return ret;
900f04d5140SColin Leitner 
901f04d5140SColin Leitner error_leds:
9020a286ef2SSven Eckelmann 	sony_leds_remove(hdev);
903f04d5140SColin Leitner 
904f04d5140SColin Leitner 	return ret;
905f04d5140SColin Leitner }
906f04d5140SColin Leitner 
907cad665a2SFrank Praznik static void sixaxis_state_worker(struct work_struct *work)
908a08c22c0SSven Eckelmann {
90992b5c411SSven Eckelmann 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
910a08c22c0SSven Eckelmann 	unsigned char buf[] = {
911a08c22c0SSven Eckelmann 		0x01,
912a08c22c0SSven Eckelmann 		0x00, 0xff, 0x00, 0xff, 0x00,
9130a286ef2SSven Eckelmann 		0x00, 0x00, 0x00, 0x00, 0x00,
914a08c22c0SSven Eckelmann 		0xff, 0x27, 0x10, 0x00, 0x32,
915a08c22c0SSven Eckelmann 		0xff, 0x27, 0x10, 0x00, 0x32,
916a08c22c0SSven Eckelmann 		0xff, 0x27, 0x10, 0x00, 0x32,
917a08c22c0SSven Eckelmann 		0xff, 0x27, 0x10, 0x00, 0x32,
918a08c22c0SSven Eckelmann 		0x00, 0x00, 0x00, 0x00, 0x00
919a08c22c0SSven Eckelmann 	};
9209f323b68SSven Eckelmann 
9210a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
9220bd88dd3SFrank Praznik 	buf[3] = sc->right ? 1 : 0;
9239f323b68SSven Eckelmann 	buf[5] = sc->left;
9240a286ef2SSven Eckelmann #endif
9250a286ef2SSven Eckelmann 
92660781cf4SFrank Praznik 	buf[10] |= sc->led_state[0] << 1;
92760781cf4SFrank Praznik 	buf[10] |= sc->led_state[1] << 2;
92860781cf4SFrank Praznik 	buf[10] |= sc->led_state[2] << 3;
92960781cf4SFrank Praznik 	buf[10] |= sc->led_state[3] << 4;
9309f323b68SSven Eckelmann 
9319f323b68SSven Eckelmann 	sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
9329f323b68SSven Eckelmann 					HID_OUTPUT_REPORT);
9339f323b68SSven Eckelmann }
9349f323b68SSven Eckelmann 
9350bd88dd3SFrank Praznik static void dualshock4_state_worker(struct work_struct *work)
9360bd88dd3SFrank Praznik {
9370bd88dd3SFrank Praznik 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
9380da8ea65SFrank Praznik 	struct hid_device *hdev = sc->hdev;
939c4e1ddf2SFrank Praznik 	struct hid_report *report = sc->output_report;
940c4e1ddf2SFrank Praznik 	__s32 *value = report->field[0]->value;
9410da8ea65SFrank Praznik 
9420da8ea65SFrank Praznik 	value[0] = 0x03;
9430bd88dd3SFrank Praznik 
9440bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF
9450da8ea65SFrank Praznik 	value[3] = sc->right;
9460da8ea65SFrank Praznik 	value[4] = sc->left;
9470bd88dd3SFrank Praznik #endif
9480bd88dd3SFrank Praznik 
9490da8ea65SFrank Praznik 	value[5] = sc->led_state[0];
9500da8ea65SFrank Praznik 	value[6] = sc->led_state[1];
9510da8ea65SFrank Praznik 	value[7] = sc->led_state[2];
95260781cf4SFrank Praznik 
9530da8ea65SFrank Praznik 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
9540bd88dd3SFrank Praznik }
9550bd88dd3SFrank Praznik 
9560a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
9579f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
9589f323b68SSven Eckelmann 			    struct ff_effect *effect)
9599f323b68SSven Eckelmann {
960a08c22c0SSven Eckelmann 	struct hid_device *hid = input_get_drvdata(dev);
9619f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hid);
962a08c22c0SSven Eckelmann 
963a08c22c0SSven Eckelmann 	if (effect->type != FF_RUMBLE)
964a08c22c0SSven Eckelmann 		return 0;
965a08c22c0SSven Eckelmann 
9669f323b68SSven Eckelmann 	sc->left = effect->u.rumble.strong_magnitude / 256;
9670bd88dd3SFrank Praznik 	sc->right = effect->u.rumble.weak_magnitude / 256;
968a08c22c0SSven Eckelmann 
96992b5c411SSven Eckelmann 	schedule_work(&sc->state_worker);
9709f323b68SSven Eckelmann 	return 0;
971a08c22c0SSven Eckelmann }
972a08c22c0SSven Eckelmann 
973a08c22c0SSven Eckelmann static int sony_init_ff(struct hid_device *hdev)
974a08c22c0SSven Eckelmann {
975a08c22c0SSven Eckelmann 	struct hid_input *hidinput = list_entry(hdev->inputs.next,
976a08c22c0SSven Eckelmann 						struct hid_input, list);
977a08c22c0SSven Eckelmann 	struct input_dev *input_dev = hidinput->input;
978a08c22c0SSven Eckelmann 
979a08c22c0SSven Eckelmann 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
980a08c22c0SSven Eckelmann 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
981a08c22c0SSven Eckelmann }
982a08c22c0SSven Eckelmann 
9839f323b68SSven Eckelmann static void sony_destroy_ff(struct hid_device *hdev)
9849f323b68SSven Eckelmann {
9859f323b68SSven Eckelmann 	struct sony_sc *sc = hid_get_drvdata(hdev);
9869f323b68SSven Eckelmann 
98792b5c411SSven Eckelmann 	cancel_work_sync(&sc->state_worker);
9889f323b68SSven Eckelmann }
9899f323b68SSven Eckelmann 
990a08c22c0SSven Eckelmann #else
991a08c22c0SSven Eckelmann static int sony_init_ff(struct hid_device *hdev)
992a08c22c0SSven Eckelmann {
993a08c22c0SSven Eckelmann 	return 0;
994a08c22c0SSven Eckelmann }
9959f323b68SSven Eckelmann 
9969f323b68SSven Eckelmann static void sony_destroy_ff(struct hid_device *hdev)
9979f323b68SSven Eckelmann {
9989f323b68SSven Eckelmann }
999a08c22c0SSven Eckelmann #endif
1000a08c22c0SSven Eckelmann 
1001c4e1ddf2SFrank Praznik static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size)
1002c4e1ddf2SFrank Praznik {
1003c4e1ddf2SFrank Praznik 	struct list_head *head, *list;
1004c4e1ddf2SFrank Praznik 	struct hid_report *report;
1005c4e1ddf2SFrank Praznik 	struct hid_device *hdev = sc->hdev;
1006c4e1ddf2SFrank Praznik 
1007c4e1ddf2SFrank Praznik 	list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1008c4e1ddf2SFrank Praznik 
1009c4e1ddf2SFrank Praznik 	list_for_each(head, list) {
1010c4e1ddf2SFrank Praznik 		report = list_entry(head, struct hid_report, list);
1011c4e1ddf2SFrank Praznik 
1012c4e1ddf2SFrank Praznik 		if (report->id == req_id) {
1013c4e1ddf2SFrank Praznik 			if (report->size < req_size) {
1014c4e1ddf2SFrank Praznik 				hid_err(hdev, "Output report 0x%02x (%i bits) is smaller than requested size (%i bits)\n",
1015c4e1ddf2SFrank Praznik 					req_id, report->size, req_size);
1016c4e1ddf2SFrank Praznik 				return -EINVAL;
1017c4e1ddf2SFrank Praznik 			}
1018c4e1ddf2SFrank Praznik 			sc->output_report = report;
1019c4e1ddf2SFrank Praznik 			return 0;
1020c4e1ddf2SFrank Praznik 		}
1021c4e1ddf2SFrank Praznik 	}
1022c4e1ddf2SFrank Praznik 
1023c4e1ddf2SFrank Praznik 	hid_err(hdev, "Unable to locate output report 0x%02x\n", req_id);
1024c4e1ddf2SFrank Praznik 
1025c4e1ddf2SFrank Praznik 	return -EINVAL;
1026c4e1ddf2SFrank Praznik }
1027c4e1ddf2SFrank Praznik 
1028bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
1029bd28ce00SJiri Slaby {
1030bd28ce00SJiri Slaby 	int ret;
1031cc6e0bbbSJiri Kosina 	unsigned long quirks = id->driver_data;
1032cc6e0bbbSJiri Kosina 	struct sony_sc *sc;
1033f04d5140SColin Leitner 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
1034cc6e0bbbSJiri Kosina 
1035abf832bfSBenjamin Tissoires 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
1036cc6e0bbbSJiri Kosina 	if (sc == NULL) {
10374291ee30SJoe Perches 		hid_err(hdev, "can't alloc sony descriptor\n");
1038cc6e0bbbSJiri Kosina 		return -ENOMEM;
1039cc6e0bbbSJiri Kosina 	}
1040cc6e0bbbSJiri Kosina 
1041cc6e0bbbSJiri Kosina 	sc->quirks = quirks;
1042cc6e0bbbSJiri Kosina 	hid_set_drvdata(hdev, sc);
10430a286ef2SSven Eckelmann 	sc->hdev = hdev;
1044bd28ce00SJiri Slaby 
1045bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
1046bd28ce00SJiri Slaby 	if (ret) {
10474291ee30SJoe Perches 		hid_err(hdev, "parse failed\n");
1048abf832bfSBenjamin Tissoires 		return ret;
1049bd28ce00SJiri Slaby 	}
1050bd28ce00SJiri Slaby 
1051f04d5140SColin Leitner 	if (sc->quirks & VAIO_RDESC_CONSTANT)
1052f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
1053f04d5140SColin Leitner 	else if (sc->quirks & SIXAXIS_CONTROLLER_USB)
1054f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
1055f04d5140SColin Leitner 	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
1056f04d5140SColin Leitner 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
1057f04d5140SColin Leitner 
1058f04d5140SColin Leitner 	ret = hid_hw_start(hdev, connect_mask);
1059bd28ce00SJiri Slaby 	if (ret) {
10604291ee30SJoe Perches 		hid_err(hdev, "hw start failed\n");
1061abf832bfSBenjamin Tissoires 		return ret;
1062bd28ce00SJiri Slaby 	}
1063bd28ce00SJiri Slaby 
1064569b10a5SAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
1065569b10a5SAntonio Ospite 		hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
1066816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
1067cad665a2SFrank Praznik 		INIT_WORK(&sc->state_worker, sixaxis_state_worker);
1068569b10a5SAntonio Ospite 	}
1069816651a7SAntonio Ospite 	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
1070816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
10718ab1676bSFrank Praznik 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
1072c4e1ddf2SFrank Praznik 		/* Report 5 (31 bytes) is used to send data to the controller via USB */
1073c4e1ddf2SFrank Praznik 		ret = sony_set_output_report(sc, 0x05, 248);
1074c4e1ddf2SFrank Praznik 		if (ret < 0)
1075c4e1ddf2SFrank Praznik 			goto err_stop;
1076c4e1ddf2SFrank Praznik 
10770bd88dd3SFrank Praznik 		INIT_WORK(&sc->state_worker, dualshock4_state_worker);
10780bd88dd3SFrank Praznik 	} else {
10790bd88dd3SFrank Praznik 		ret = 0;
10800bd88dd3SFrank Praznik 	}
1081f9ce7c28SBastien Nocera 
10824dfdc464SJiri Kosina 	if (ret < 0)
1083bd28ce00SJiri Slaby 		goto err_stop;
1084bd28ce00SJiri Slaby 
10850a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT) {
10860a286ef2SSven Eckelmann 		ret = sony_leds_init(hdev);
10870a286ef2SSven Eckelmann 		if (ret < 0)
10880a286ef2SSven Eckelmann 			goto err_stop;
10890a286ef2SSven Eckelmann 	}
10900a286ef2SSven Eckelmann 
1091a08c22c0SSven Eckelmann 	ret = sony_init_ff(hdev);
1092a08c22c0SSven Eckelmann 	if (ret < 0)
1093a08c22c0SSven Eckelmann 		goto err_stop;
1094a08c22c0SSven Eckelmann 
1095bd28ce00SJiri Slaby 	return 0;
1096bd28ce00SJiri Slaby err_stop:
10970a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
10980a286ef2SSven Eckelmann 		sony_leds_remove(hdev);
1099bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
1100bd28ce00SJiri Slaby 	return ret;
1101bd28ce00SJiri Slaby }
1102bd28ce00SJiri Slaby 
1103cc6e0bbbSJiri Kosina static void sony_remove(struct hid_device *hdev)
1104cc6e0bbbSJiri Kosina {
1105f04d5140SColin Leitner 	struct sony_sc *sc = hid_get_drvdata(hdev);
1106f04d5140SColin Leitner 
11070a286ef2SSven Eckelmann 	if (sc->quirks & SONY_LED_SUPPORT)
1108c5382519SSven Eckelmann 		sony_leds_remove(hdev);
1109f04d5140SColin Leitner 
11109f323b68SSven Eckelmann 	sony_destroy_ff(hdev);
11119f323b68SSven Eckelmann 
1112cc6e0bbbSJiri Kosina 	hid_hw_stop(hdev);
1113cc6e0bbbSJiri Kosina }
1114cc6e0bbbSJiri Kosina 
1115bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
1116816651a7SAntonio Ospite 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
1117816651a7SAntonio Ospite 		.driver_data = SIXAXIS_CONTROLLER_USB },
111835dca5b4SJiri Kosina 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
111935dca5b4SJiri Kosina 		.driver_data = SIXAXIS_CONTROLLER_USB },
1120816651a7SAntonio Ospite 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
1121816651a7SAntonio Ospite 		.driver_data = SIXAXIS_CONTROLLER_BT },
1122cc6e0bbbSJiri Kosina 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
1123cc6e0bbbSJiri Kosina 		.driver_data = VAIO_RDESC_CONSTANT },
1124a4649184SFernando Luis Vázquez Cao 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
1125a4649184SFernando Luis Vázquez Cao 		.driver_data = VAIO_RDESC_CONSTANT },
1126f04d5140SColin Leitner 	/* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
1127f04d5140SColin Leitner 	 * Logitech joystick from the device descriptor. */
1128f04d5140SColin Leitner 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
1129f04d5140SColin Leitner 		.driver_data = BUZZ_CONTROLLER },
1130f04d5140SColin Leitner 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
1131f04d5140SColin Leitner 		.driver_data = BUZZ_CONTROLLER },
1132078328daSJiri Kosina 	/* PS3 BD Remote Control */
1133078328daSJiri Kosina 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
1134078328daSJiri Kosina 		.driver_data = PS3REMOTE },
1135078328daSJiri Kosina 	/* Logitech Harmony Adapter for PS3 */
1136078328daSJiri Kosina 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
1137078328daSJiri Kosina 		.driver_data = PS3REMOTE },
11380bd88dd3SFrank Praznik 	/* Sony Dualshock 4 controllers for PS4 */
11390bd88dd3SFrank Praznik 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
11408ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
11410bd88dd3SFrank Praznik 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
11428ab1676bSFrank Praznik 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
1143bd28ce00SJiri Slaby 	{ }
1144bd28ce00SJiri Slaby };
1145bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
1146bd28ce00SJiri Slaby 
1147bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
1148bd28ce00SJiri Slaby 	.name          = "sony",
1149bd28ce00SJiri Slaby 	.id_table      = sony_devices,
1150f04d5140SColin Leitner 	.input_mapping = sony_mapping,
1151bd28ce00SJiri Slaby 	.probe         = sony_probe,
1152cc6e0bbbSJiri Kosina 	.remove        = sony_remove,
1153cc6e0bbbSJiri Kosina 	.report_fixup  = sony_report_fixup,
1154c9e4d877SSimon Wood 	.raw_event     = sony_raw_event
1155bd28ce00SJiri Slaby };
1156f425458eSH Hartley Sweeten module_hid_driver(sony_driver);
1157bd28ce00SJiri Slaby 
1158bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
1159