12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2bd28ce00SJiri Slaby /*
3077147a3SFrank Praznik * HID driver for Sony / PS2 / PS3 / PS4 BD devices.
4bd28ce00SJiri Slaby *
5bd28ce00SJiri Slaby * Copyright (c) 1999 Andreas Gal
6bd28ce00SJiri Slaby * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
7bd28ce00SJiri Slaby * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
8bd28ce00SJiri Slaby * Copyright (c) 2008 Jiri Slaby
9078328daSJiri Kosina * Copyright (c) 2012 David Dillow <dave@thedillows.org>
10078328daSJiri Kosina * Copyright (c) 2006-2013 Jiri Kosina
11f04d5140SColin Leitner * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
12c4425c8fSFrank Praznik * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>
13b7289cb1STodd Kelner * Copyright (c) 2018 Todd Kelner
14a4bfe13fSDaniel Nguyen * Copyright (c) 2020-2021 Pascal Giard <pascal.giard@etsmtl.ca>
1532e411d0SSanjay Govind * Copyright (c) 2020 Sanjay Govind <sanjay.govind9@gmail.com>
16a4bfe13fSDaniel Nguyen * Copyright (c) 2021 Daniel Nguyen <daniel.nguyen.1@ens.etsmtl.ca>
17bd28ce00SJiri Slaby */
18bd28ce00SJiri Slaby
19bd28ce00SJiri Slaby /*
20bd28ce00SJiri Slaby */
21bd28ce00SJiri Slaby
22ad142b9eSFrank Praznik /*
23ad142b9eSFrank Praznik * NOTE: in order for the Sony PS3 BD Remote Control to be found by
24078328daSJiri Kosina * a Bluetooth host, the key combination Start+Enter has to be kept pressed
25078328daSJiri Kosina * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
26078328daSJiri Kosina *
27078328daSJiri Kosina * There will be no PIN request from the device.
28078328daSJiri Kosina */
29078328daSJiri Kosina
30bd28ce00SJiri Slaby #include <linux/device.h>
31bd28ce00SJiri Slaby #include <linux/hid.h>
32bd28ce00SJiri Slaby #include <linux/module.h>
335a0e3ad6STejun Heo #include <linux/slab.h>
3440e32ee6SJiri Kosina #include <linux/leds.h>
35d902f472SFrank Praznik #include <linux/power_supply.h>
36d902f472SFrank Praznik #include <linux/spinlock.h>
37d2d782fcSFrank Praznik #include <linux/list.h>
388025087aSFrank Praznik #include <linux/idr.h>
39e5606230SFrank Praznik #include <linux/input/mt.h>
4049b9ca6cSRoderick Colenbrander #include <linux/crc32.h>
41cc894ac5SPascal Giard #include <linux/usb.h>
42cc894ac5SPascal Giard #include <linux/timer.h>
43*5f60d5f6SAl Viro #include <linux/unaligned.h>
44bd28ce00SJiri Slaby
45bd28ce00SJiri Slaby #include "hid-ids.h"
46bd28ce00SJiri Slaby
47f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT BIT(0)
48f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB BIT(1)
49f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT BIT(2)
50f1c458caSSven Eckelmann #define BUZZ_CONTROLLER BIT(3)
51f1c458caSSven Eckelmann #define PS3REMOTE BIT(4)
524f1f3918SRoderick Colenbrander #define MOTION_CONTROLLER_USB BIT(5)
534f1f3918SRoderick Colenbrander #define MOTION_CONTROLLER_BT BIT(6)
544f1f3918SRoderick Colenbrander #define NAVIGATION_CONTROLLER_USB BIT(7)
554f1f3918SRoderick Colenbrander #define NAVIGATION_CONTROLLER_BT BIT(8)
564f1f3918SRoderick Colenbrander #define SINO_LITE_CONTROLLER BIT(9)
574f1f3918SRoderick Colenbrander #define FUTUREMAX_DANCE_MAT BIT(10)
584f1f3918SRoderick Colenbrander #define NSG_MR5U_REMOTE_BT BIT(11)
594f1f3918SRoderick Colenbrander #define NSG_MR7U_REMOTE_BT BIT(12)
604f1f3918SRoderick Colenbrander #define SHANWAN_GAMEPAD BIT(13)
614f1f3918SRoderick Colenbrander #define GH_GUITAR_CONTROLLER BIT(14)
624f1f3918SRoderick Colenbrander #define GHL_GUITAR_PS3WIIU BIT(15)
634f1f3918SRoderick Colenbrander #define GHL_GUITAR_PS4 BIT(16)
64cc6e0bbbSJiri Kosina
65fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
66b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
674545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\
684545ee0aSSimon Wood NAVIGATION_CONTROLLER_BT)
69fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
704f1f3918SRoderick Colenbrander MOTION_CONTROLLER | NAVIGATION_CONTROLLER)
714f1f3918SRoderick Colenbrander #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
724f1f3918SRoderick Colenbrander #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | MOTION_CONTROLLER)
734f1f3918SRoderick Colenbrander #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT)
74b7289cb1STodd Kelner #define NSG_MRXU_REMOTE (NSG_MR5U_REMOTE_BT | NSG_MR7U_REMOTE_BT)
7560781cf4SFrank Praznik
7660781cf4SFrank Praznik #define MAX_LEDS 4
77b7289cb1STodd Kelner #define NSG_MRXU_MAX_X 1667
78b7289cb1STodd Kelner #define NSG_MRXU_MAX_Y 1868
790a286ef2SSven Eckelmann
80a4bfe13fSDaniel Nguyen /* The PS3/Wii U dongles require a poke every 10 seconds, but the PS4
81a4bfe13fSDaniel Nguyen * requires one every 8 seconds. Using 8 seconds for all for simplicity.
82a4bfe13fSDaniel Nguyen */
83a4bfe13fSDaniel Nguyen #define GHL_GUITAR_POKE_INTERVAL 8 /* In seconds */
8432e411d0SSanjay Govind #define GUITAR_TILT_USAGE 44
85cc894ac5SPascal Giard
86a4bfe13fSDaniel Nguyen /* Magic data taken from GHLtarUtility:
87cc894ac5SPascal Giard * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs
88cc894ac5SPascal Giard * Note: The Wii U and PS3 dongles happen to share the same!
89cc894ac5SPascal Giard */
90cc894ac5SPascal Giard static const char ghl_ps3wiiu_magic_data[] = {
91cc894ac5SPascal Giard 0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00
92cc894ac5SPascal Giard };
93e57a67daSMauro Carvalho Chehab
94a4bfe13fSDaniel Nguyen /* Magic data for the PS4 dongles sniffed with a USB protocol
95a4bfe13fSDaniel Nguyen * analyzer.
96a4bfe13fSDaniel Nguyen */
97a4bfe13fSDaniel Nguyen static const char ghl_ps4_magic_data[] = {
98a4bfe13fSDaniel Nguyen 0x30, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00
99a4bfe13fSDaniel Nguyen };
100a4bfe13fSDaniel Nguyen
101c5e0c1c4SFrank Praznik /* PS/3 Motion controller */
102d4781a27SThomas Weißschuh static const u8 motion_rdesc[] = {
103c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */
104c5e0c1c4SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */
105c5e0c1c4SFrank Praznik 0xA1, 0x01, /* Collection (Application), */
106c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */
107c5e0c1c4SFrank Praznik 0x85, 0x01, /* Report ID (1), */
108c5e0c1c4SFrank Praznik 0x75, 0x01, /* Report Size (1), */
1098b2513c3SSimon Wood 0x95, 0x15, /* Report Count (21), */
110c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */
111c5e0c1c4SFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */
112c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */
113c5e0c1c4SFrank Praznik 0x45, 0x01, /* Physical Maximum (1), */
114c5e0c1c4SFrank Praznik 0x05, 0x09, /* Usage Page (Button), */
115c5e0c1c4SFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */
1168b2513c3SSimon Wood 0x29, 0x15, /* Usage Maximum (15h), */
1178b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Buttons */
1188b2513c3SSimon Wood 0x95, 0x0B, /* Report Count (11), */
119c5e0c1c4SFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
1208b2513c3SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), * Padding */
121c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */
122c5e0c1c4SFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
123c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */
124c5e0c1c4SFrank Praznik 0xA1, 0x00, /* Collection (Physical), */
125c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */
1268b2513c3SSimon Wood 0x95, 0x01, /* Report Count (1), */
127c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */
128c5e0c1c4SFrank Praznik 0x46, 0xFF, 0x00, /* Physical Maximum (255), */
129c5e0c1c4SFrank Praznik 0x09, 0x30, /* Usage (X), */
1308b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Trigger */
131c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */
1328b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
1338b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */
1348b2513c3SSimon Wood 0x95, 0x07, /* Report Count (7), * skip 7 bytes */
1358b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */
136c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */
137c5e0c1c4SFrank Praznik 0x75, 0x10, /* Report Size (16), */
1388b2513c3SSimon Wood 0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */
1398b2513c3SSimon Wood 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */
1408b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Accels */
1418b2513c3SSimon Wood 0x09, 0x33, /* Usage (rX), */
1428b2513c3SSimon Wood 0x09, 0x34, /* Usage (rY), */
1438b2513c3SSimon Wood 0x09, 0x35, /* Usage (rZ), */
144c5e0c1c4SFrank Praznik 0x81, 0x02, /* Input (Variable), */
1458b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
1468b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */
1478b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */
1488b2513c3SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */
1498b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */
1508b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Gyros */
1518b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */
1528b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
1538b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */
1548b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */
1558b2513c3SSimon Wood 0x75, 0x0C, /* Report Size (12), */
1568b2513c3SSimon Wood 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */
1578b2513c3SSimon Wood 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */
1588b2513c3SSimon Wood 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */
1598b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */
1608b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */
1618b2513c3SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */
1628b2513c3SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
1638b2513c3SSimon Wood 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */
1648b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */
1658b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */
1668b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */
1678b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */
1688b2513c3SSimon Wood 0x91, 0x02, /* Output (Variable), */
1698b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */
1708b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */
1718b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */
1728b2513c3SSimon Wood 0xB1, 0x02, /* Feature (Variable), */
173c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */
174c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */
175c5e0c1c4SFrank Praznik 0x85, 0x02, /* Report ID (2), */
176c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */
177c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */
178c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */
179c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */
180c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */
181c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */
182c5e0c1c4SFrank Praznik 0x85, 0xEE, /* Report ID (238), */
183c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */
184c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */
185c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */
186c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */
187c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */
188c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */
189c5e0c1c4SFrank Praznik 0x85, 0xEF, /* Report ID (239), */
190c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */
191c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */
192c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */
193c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */
194c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */
195c5e0c1c4SFrank Praznik 0xC0 /* End Collection */
196c5e0c1c4SFrank Praznik };
197c5e0c1c4SFrank Praznik
198d4781a27SThomas Weißschuh static const u8 ps3remote_rdesc[] = {
199078328daSJiri Kosina 0x05, 0x01, /* GUsagePage Generic Desktop */
200078328daSJiri Kosina 0x09, 0x05, /* LUsage 0x05 [Game Pad] */
201078328daSJiri Kosina 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */
202078328daSJiri Kosina
203078328daSJiri Kosina /* Use collection 1 for joypad buttons */
204078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */
205078328daSJiri Kosina
206ef916ef5SAntonio Ospite /*
207ef916ef5SAntonio Ospite * Ignore the 1st byte, maybe it is used for a controller
208ef916ef5SAntonio Ospite * number but it's not needed for correct operation
209ef916ef5SAntonio Ospite */
210078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */
211078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */
212078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
213078328daSJiri Kosina
214ef916ef5SAntonio Ospite /*
215ef916ef5SAntonio Ospite * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
216ef916ef5SAntonio Ospite * buttons multiple keypresses are allowed
217ef916ef5SAntonio Ospite */
218078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */
219078328daSJiri Kosina 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
220078328daSJiri Kosina 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */
221078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */
222078328daSJiri Kosina 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */
223078328daSJiri Kosina 0x75, 0x01, /* GReportSize 0x01 [1] */
224078328daSJiri Kosina 0x95, 0x18, /* GReportCount 0x18 [24] */
225078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
226078328daSJiri Kosina
227078328daSJiri Kosina 0xC0, /* MEndCollection */
228078328daSJiri Kosina
229078328daSJiri Kosina /* Use collection 2 for remote control buttons */
230078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */
231078328daSJiri Kosina
232078328daSJiri Kosina /* 5th byte is used for remote control buttons */
233078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */
234078328daSJiri Kosina 0x18, /* LUsageMinimum [No button pressed] */
235078328daSJiri Kosina 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */
236078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */
237078328daSJiri Kosina 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */
238078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */
239078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */
240078328daSJiri Kosina 0x80, /* MInput */
241078328daSJiri Kosina
242ef916ef5SAntonio Ospite /*
243ef916ef5SAntonio Ospite * Ignore bytes from 6th to 11th, 6th to 10th are always constant at
244ef916ef5SAntonio Ospite * 0xff and 11th is for press indication
245ef916ef5SAntonio Ospite */
246078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */
247078328daSJiri Kosina 0x95, 0x06, /* GReportCount 0x06 [6] */
248078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
249078328daSJiri Kosina
250078328daSJiri Kosina /* 12th byte is for battery strength */
251078328daSJiri Kosina 0x05, 0x06, /* GUsagePage Generic Device Controls */
252078328daSJiri Kosina 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */
253078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */
254078328daSJiri Kosina 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */
255078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */
256078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */
257078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
258078328daSJiri Kosina
259078328daSJiri Kosina 0xC0, /* MEndCollection */
260078328daSJiri Kosina
261078328daSJiri Kosina 0xC0 /* MEndCollection [Game Pad] */
262078328daSJiri Kosina };
263078328daSJiri Kosina
264078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = {
265078328daSJiri Kosina [0x01] = KEY_SELECT,
266078328daSJiri Kosina [0x02] = BTN_THUMBL, /* L3 */
267078328daSJiri Kosina [0x03] = BTN_THUMBR, /* R3 */
268078328daSJiri Kosina [0x04] = BTN_START,
269078328daSJiri Kosina [0x05] = KEY_UP,
270078328daSJiri Kosina [0x06] = KEY_RIGHT,
271078328daSJiri Kosina [0x07] = KEY_DOWN,
272078328daSJiri Kosina [0x08] = KEY_LEFT,
273078328daSJiri Kosina [0x09] = BTN_TL2, /* L2 */
274078328daSJiri Kosina [0x0a] = BTN_TR2, /* R2 */
275078328daSJiri Kosina [0x0b] = BTN_TL, /* L1 */
276078328daSJiri Kosina [0x0c] = BTN_TR, /* R1 */
277078328daSJiri Kosina [0x0d] = KEY_OPTION, /* options/triangle */
278078328daSJiri Kosina [0x0e] = KEY_BACK, /* back/circle */
279078328daSJiri Kosina [0x0f] = BTN_0, /* cross */
280078328daSJiri Kosina [0x10] = KEY_SCREEN, /* view/square */
281078328daSJiri Kosina [0x11] = KEY_HOMEPAGE, /* PS button */
282078328daSJiri Kosina [0x14] = KEY_ENTER,
283078328daSJiri Kosina };
284078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = {
285078328daSJiri Kosina [0x00] = KEY_1,
286078328daSJiri Kosina [0x01] = KEY_2,
287078328daSJiri Kosina [0x02] = KEY_3,
288078328daSJiri Kosina [0x03] = KEY_4,
289078328daSJiri Kosina [0x04] = KEY_5,
290078328daSJiri Kosina [0x05] = KEY_6,
291078328daSJiri Kosina [0x06] = KEY_7,
292078328daSJiri Kosina [0x07] = KEY_8,
293078328daSJiri Kosina [0x08] = KEY_9,
294078328daSJiri Kosina [0x09] = KEY_0,
295078328daSJiri Kosina [0x0e] = KEY_ESC, /* return */
296078328daSJiri Kosina [0x0f] = KEY_CLEAR,
297078328daSJiri Kosina [0x16] = KEY_EJECTCD,
298078328daSJiri Kosina [0x1a] = KEY_MENU, /* top menu */
299078328daSJiri Kosina [0x28] = KEY_TIME,
300078328daSJiri Kosina [0x30] = KEY_PREVIOUS,
301078328daSJiri Kosina [0x31] = KEY_NEXT,
302078328daSJiri Kosina [0x32] = KEY_PLAY,
303078328daSJiri Kosina [0x33] = KEY_REWIND, /* scan back */
304078328daSJiri Kosina [0x34] = KEY_FORWARD, /* scan forward */
305078328daSJiri Kosina [0x38] = KEY_STOP,
306078328daSJiri Kosina [0x39] = KEY_PAUSE,
307078328daSJiri Kosina [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
308078328daSJiri Kosina [0x60] = KEY_FRAMEBACK, /* slow/step back */
309078328daSJiri Kosina [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */
310078328daSJiri Kosina [0x63] = KEY_SUBTITLE,
311078328daSJiri Kosina [0x64] = KEY_AUDIO,
312078328daSJiri Kosina [0x65] = KEY_ANGLE,
313078328daSJiri Kosina [0x70] = KEY_INFO, /* display */
314078328daSJiri Kosina [0x80] = KEY_BLUE,
315078328daSJiri Kosina [0x81] = KEY_RED,
316078328daSJiri Kosina [0x82] = KEY_GREEN,
317078328daSJiri Kosina [0x83] = KEY_YELLOW,
318078328daSJiri Kosina };
319078328daSJiri Kosina
320f04d5140SColin Leitner static const unsigned int buzz_keymap[] = {
321ad142b9eSFrank Praznik /*
322ad142b9eSFrank Praznik * The controller has 4 remote buzzers, each with one LED and 5
323f04d5140SColin Leitner * buttons.
324f04d5140SColin Leitner *
325f04d5140SColin Leitner * We use the mapping chosen by the controller, which is:
326f04d5140SColin Leitner *
327f04d5140SColin Leitner * Key Offset
328f04d5140SColin Leitner * -------------------
329f04d5140SColin Leitner * Buzz 1
330f04d5140SColin Leitner * Blue 5
331f04d5140SColin Leitner * Orange 4
332f04d5140SColin Leitner * Green 3
333f04d5140SColin Leitner * Yellow 2
334f04d5140SColin Leitner *
335f04d5140SColin Leitner * So, for example, the orange button on the third buzzer is mapped to
336f04d5140SColin Leitner * BTN_TRIGGER_HAPPY14
337f04d5140SColin Leitner */
338f04d5140SColin Leitner [1] = BTN_TRIGGER_HAPPY1,
339f04d5140SColin Leitner [2] = BTN_TRIGGER_HAPPY2,
340f04d5140SColin Leitner [3] = BTN_TRIGGER_HAPPY3,
341f04d5140SColin Leitner [4] = BTN_TRIGGER_HAPPY4,
342f04d5140SColin Leitner [5] = BTN_TRIGGER_HAPPY5,
343f04d5140SColin Leitner [6] = BTN_TRIGGER_HAPPY6,
344f04d5140SColin Leitner [7] = BTN_TRIGGER_HAPPY7,
345f04d5140SColin Leitner [8] = BTN_TRIGGER_HAPPY8,
346f04d5140SColin Leitner [9] = BTN_TRIGGER_HAPPY9,
347f04d5140SColin Leitner [10] = BTN_TRIGGER_HAPPY10,
348f04d5140SColin Leitner [11] = BTN_TRIGGER_HAPPY11,
349f04d5140SColin Leitner [12] = BTN_TRIGGER_HAPPY12,
350f04d5140SColin Leitner [13] = BTN_TRIGGER_HAPPY13,
351f04d5140SColin Leitner [14] = BTN_TRIGGER_HAPPY14,
352f04d5140SColin Leitner [15] = BTN_TRIGGER_HAPPY15,
353f04d5140SColin Leitner [16] = BTN_TRIGGER_HAPPY16,
354f04d5140SColin Leitner [17] = BTN_TRIGGER_HAPPY17,
355f04d5140SColin Leitner [18] = BTN_TRIGGER_HAPPY18,
356f04d5140SColin Leitner [19] = BTN_TRIGGER_HAPPY19,
357f04d5140SColin Leitner [20] = BTN_TRIGGER_HAPPY20,
358f04d5140SColin Leitner };
359f04d5140SColin Leitner
360b8f0970dSRoderick Colenbrander /* The Navigation controller is a partial DS3 and uses the same HID report
361454d243aSShaomin Deng * and hence the same keymap indices, however not all axes/buttons
362b8f0970dSRoderick Colenbrander * are physically present. We use the same axis and button mapping as
363b8f0970dSRoderick Colenbrander * the DS3, which uses the Linux gamepad spec.
364b8f0970dSRoderick Colenbrander */
365b8f0970dSRoderick Colenbrander static const unsigned int navigation_absmap[] = {
366b8f0970dSRoderick Colenbrander [0x30] = ABS_X,
367b8f0970dSRoderick Colenbrander [0x31] = ABS_Y,
368b8f0970dSRoderick Colenbrander [0x33] = ABS_Z, /* L2 */
369b8f0970dSRoderick Colenbrander };
370b8f0970dSRoderick Colenbrander
371b8f0970dSRoderick Colenbrander /* Buttons not physically available on the device, but still available
372b8f0970dSRoderick Colenbrander * in the reports are explicitly set to 0 for documentation purposes.
373b8f0970dSRoderick Colenbrander */
374b8f0970dSRoderick Colenbrander static const unsigned int navigation_keymap[] = {
375b8f0970dSRoderick Colenbrander [0x01] = 0, /* Select */
376b8f0970dSRoderick Colenbrander [0x02] = BTN_THUMBL, /* L3 */
377b8f0970dSRoderick Colenbrander [0x03] = 0, /* R3 */
378b8f0970dSRoderick Colenbrander [0x04] = 0, /* Start */
379b8f0970dSRoderick Colenbrander [0x05] = BTN_DPAD_UP, /* Up */
380b8f0970dSRoderick Colenbrander [0x06] = BTN_DPAD_RIGHT, /* Right */
381b8f0970dSRoderick Colenbrander [0x07] = BTN_DPAD_DOWN, /* Down */
382b8f0970dSRoderick Colenbrander [0x08] = BTN_DPAD_LEFT, /* Left */
383b8f0970dSRoderick Colenbrander [0x09] = BTN_TL2, /* L2 */
384b8f0970dSRoderick Colenbrander [0x0a] = 0, /* R2 */
385b8f0970dSRoderick Colenbrander [0x0b] = BTN_TL, /* L1 */
386b8f0970dSRoderick Colenbrander [0x0c] = 0, /* R1 */
387b8f0970dSRoderick Colenbrander [0x0d] = BTN_NORTH, /* Triangle */
388b8f0970dSRoderick Colenbrander [0x0e] = BTN_EAST, /* Circle */
389b8f0970dSRoderick Colenbrander [0x0f] = BTN_SOUTH, /* Cross */
390b8f0970dSRoderick Colenbrander [0x10] = BTN_WEST, /* Square */
391b8f0970dSRoderick Colenbrander [0x11] = BTN_MODE, /* PS */
392b8f0970dSRoderick Colenbrander };
393b8f0970dSRoderick Colenbrander
394e19a267bSRoderick Colenbrander static const unsigned int sixaxis_absmap[] = {
395e19a267bSRoderick Colenbrander [0x30] = ABS_X,
396e19a267bSRoderick Colenbrander [0x31] = ABS_Y,
397e19a267bSRoderick Colenbrander [0x32] = ABS_RX, /* right stick X */
398e19a267bSRoderick Colenbrander [0x35] = ABS_RY, /* right stick Y */
399e19a267bSRoderick Colenbrander };
400e19a267bSRoderick Colenbrander
401e19a267bSRoderick Colenbrander static const unsigned int sixaxis_keymap[] = {
402e19a267bSRoderick Colenbrander [0x01] = BTN_SELECT, /* Select */
403e19a267bSRoderick Colenbrander [0x02] = BTN_THUMBL, /* L3 */
404e19a267bSRoderick Colenbrander [0x03] = BTN_THUMBR, /* R3 */
405e19a267bSRoderick Colenbrander [0x04] = BTN_START, /* Start */
406e19a267bSRoderick Colenbrander [0x05] = BTN_DPAD_UP, /* Up */
407e19a267bSRoderick Colenbrander [0x06] = BTN_DPAD_RIGHT, /* Right */
408e19a267bSRoderick Colenbrander [0x07] = BTN_DPAD_DOWN, /* Down */
409e19a267bSRoderick Colenbrander [0x08] = BTN_DPAD_LEFT, /* Left */
410e19a267bSRoderick Colenbrander [0x09] = BTN_TL2, /* L2 */
411e19a267bSRoderick Colenbrander [0x0a] = BTN_TR2, /* R2 */
412e19a267bSRoderick Colenbrander [0x0b] = BTN_TL, /* L1 */
413e19a267bSRoderick Colenbrander [0x0c] = BTN_TR, /* R1 */
414e19a267bSRoderick Colenbrander [0x0d] = BTN_NORTH, /* Triangle */
415e19a267bSRoderick Colenbrander [0x0e] = BTN_EAST, /* Circle */
416e19a267bSRoderick Colenbrander [0x0f] = BTN_SOUTH, /* Cross */
417e19a267bSRoderick Colenbrander [0x10] = BTN_WEST, /* Square */
418e19a267bSRoderick Colenbrander [0x11] = BTN_MODE, /* PS */
419e19a267bSRoderick Colenbrander };
420e19a267bSRoderick Colenbrander
421d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = {
422d902f472SFrank Praznik POWER_SUPPLY_PROP_PRESENT,
423d902f472SFrank Praznik POWER_SUPPLY_PROP_CAPACITY,
424d902f472SFrank Praznik POWER_SUPPLY_PROP_SCOPE,
425d902f472SFrank Praznik POWER_SUPPLY_PROP_STATUS,
426d902f472SFrank Praznik };
427d902f472SFrank Praznik
42855d3b664SFrank Praznik struct sixaxis_led {
4291adf904eSPavel Machek u8 time_enabled; /* the total time the led is active (0xff means forever) */
4301adf904eSPavel Machek u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */
4311adf904eSPavel Machek u8 enabled;
4321adf904eSPavel Machek u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
4331adf904eSPavel Machek u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */
43455d3b664SFrank Praznik } __packed;
43555d3b664SFrank Praznik
43655d3b664SFrank Praznik struct sixaxis_rumble {
4371adf904eSPavel Machek u8 padding;
4381adf904eSPavel Machek u8 right_duration; /* Right motor duration (0xff means forever) */
4391adf904eSPavel Machek u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
4401adf904eSPavel Machek u8 left_duration; /* Left motor duration (0xff means forever) */
4411adf904eSPavel Machek u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
44255d3b664SFrank Praznik } __packed;
44355d3b664SFrank Praznik
44455d3b664SFrank Praznik struct sixaxis_output_report {
4451adf904eSPavel Machek u8 report_id;
44655d3b664SFrank Praznik struct sixaxis_rumble rumble;
4471adf904eSPavel Machek u8 padding[4];
4481adf904eSPavel Machek u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
44955d3b664SFrank Praznik struct sixaxis_led led[4]; /* LEDx at (4 - x) */
45055d3b664SFrank Praznik struct sixaxis_led _reserved; /* LED5, not actually soldered */
45155d3b664SFrank Praznik } __packed;
45255d3b664SFrank Praznik
45355d3b664SFrank Praznik union sixaxis_output_report_01 {
45455d3b664SFrank Praznik struct sixaxis_output_report data;
4551adf904eSPavel Machek u8 buf[36];
45655d3b664SFrank Praznik };
45755d3b664SFrank Praznik
458c5e0c1c4SFrank Praznik struct motion_output_report_02 {
459c5e0c1c4SFrank Praznik u8 type, zero;
460c5e0c1c4SFrank Praznik u8 r, g, b;
461c5e0c1c4SFrank Praznik u8 zero2;
462c5e0c1c4SFrank Praznik u8 rumble;
463c5e0c1c4SFrank Praznik };
464c5e0c1c4SFrank Praznik
46529b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17
466a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8
46741d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49
4689b2b5c9aSFrank Praznik
469510c8b7cSRoderick Colenbrander #define SENSOR_SUFFIX " Motion Sensors"
4704f1f3918SRoderick Colenbrander #define TOUCHPAD_SUFFIX " Touchpad"
47155a07d62SRoderick Colenbrander
472510c8b7cSRoderick Colenbrander #define SIXAXIS_INPUT_REPORT_ACC_X_OFFSET 41
473510c8b7cSRoderick Colenbrander #define SIXAXIS_ACC_RES_PER_G 113
474510c8b7cSRoderick Colenbrander
4758b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock);
476d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list);
4778025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator);
478d2d782fcSFrank Praznik
479b5322736SRoderick Colenbrander enum sony_worker {
4804f1f3918SRoderick Colenbrander SONY_WORKER_STATE
481b5322736SRoderick Colenbrander };
482b5322736SRoderick Colenbrander
483cc6e0bbbSJiri Kosina struct sony_sc {
484d902f472SFrank Praznik spinlock_t lock;
485d2d782fcSFrank Praznik struct list_head list_node;
4860a286ef2SSven Eckelmann struct hid_device *hdev;
487ac797b95SRoderick Colenbrander struct input_dev *touchpad;
488227c011bSRoderick Colenbrander struct input_dev *sensor_dev;
48960781cf4SFrank Praznik struct led_classdev *leds[MAX_LEDS];
490cc6e0bbbSJiri Kosina unsigned long quirks;
4910a286ef2SSven Eckelmann struct work_struct state_worker;
492d8aaccdaSFrank Praznik void (*send_output_report)(struct sony_sc *);
493297d716fSKrzysztof Kozlowski struct power_supply *battery;
494297d716fSKrzysztof Kozlowski struct power_supply_desc battery_desc;
4958025087aSFrank Praznik int device_id;
4961adf904eSPavel Machek u8 *output_report_dmabuf;
497f04d5140SColin Leitner
4989f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF
4991adf904eSPavel Machek u8 left;
5001adf904eSPavel Machek u8 right;
5019f323b68SSven Eckelmann #endif
5029f323b68SSven Eckelmann
5031adf904eSPavel Machek u8 mac_address[6];
504b5322736SRoderick Colenbrander u8 state_worker_initialized;
5052a242932SFrank Praznik u8 defer_initialization;
5061adf904eSPavel Machek u8 battery_capacity;
507a76a6c18SRoderick Colenbrander int battery_status;
5081adf904eSPavel Machek u8 led_state[MAX_LEDS];
5091adf904eSPavel Machek u8 led_delay_on[MAX_LEDS];
5101adf904eSPavel Machek u8 led_delay_off[MAX_LEDS];
5111adf904eSPavel Machek u8 led_count;
51280786eb9SRoderick Colenbrander
513cc894ac5SPascal Giard /* GH Live */
514fb1a79a6SPascal Giard struct urb *ghl_urb;
515cc894ac5SPascal Giard struct timer_list ghl_poke_timer;
516cc6e0bbbSJiri Kosina };
517cc6e0bbbSJiri Kosina
518405182c2SRoderick Colenbrander static void sony_set_leds(struct sony_sc *sc);
519405182c2SRoderick Colenbrander
sony_schedule_work(struct sony_sc * sc,enum sony_worker which)520b5322736SRoderick Colenbrander static inline void sony_schedule_work(struct sony_sc *sc,
521b5322736SRoderick Colenbrander enum sony_worker which)
5222a242932SFrank Praznik {
523e0f6974aSRoderick Colenbrander unsigned long flags;
524e0f6974aSRoderick Colenbrander
525b5322736SRoderick Colenbrander switch (which) {
526b5322736SRoderick Colenbrander case SONY_WORKER_STATE:
527e0f6974aSRoderick Colenbrander spin_lock_irqsave(&sc->lock, flags);
528e0f6974aSRoderick Colenbrander if (!sc->defer_initialization && sc->state_worker_initialized)
5292a242932SFrank Praznik schedule_work(&sc->state_worker);
530e0f6974aSRoderick Colenbrander spin_unlock_irqrestore(&sc->lock, flags);
531f2f47c38SRoderick Colenbrander break;
5322a242932SFrank Praznik }
5332a242932SFrank Praznik }
5342a242932SFrank Praznik
ghl_magic_poke_cb(struct urb * urb)535cc894ac5SPascal Giard static void ghl_magic_poke_cb(struct urb *urb)
536cc894ac5SPascal Giard {
537fb1a79a6SPascal Giard struct sony_sc *sc = urb->context;
538fb1a79a6SPascal Giard
539fb1a79a6SPascal Giard if (urb->status < 0)
540fb1a79a6SPascal Giard hid_err(sc->hdev, "URB transfer failed : %d", urb->status);
541fb1a79a6SPascal Giard
542fb1a79a6SPascal Giard mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
543cc894ac5SPascal Giard }
544cc894ac5SPascal Giard
ghl_magic_poke(struct timer_list * t)545cc894ac5SPascal Giard static void ghl_magic_poke(struct timer_list *t)
546cc894ac5SPascal Giard {
547fb1a79a6SPascal Giard int ret;
548cc894ac5SPascal Giard struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer);
549cc894ac5SPascal Giard
550fb1a79a6SPascal Giard ret = usb_submit_urb(sc->ghl_urb, GFP_ATOMIC);
551fb1a79a6SPascal Giard if (ret < 0)
552fb1a79a6SPascal Giard hid_err(sc->hdev, "usb_submit_urb failed: %d", ret);
553fb1a79a6SPascal Giard }
554cc894ac5SPascal Giard
ghl_init_urb(struct sony_sc * sc,struct usb_device * usbdev,const char ghl_magic_data[],u16 poke_size)555a4bfe13fSDaniel Nguyen static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev,
556a4bfe13fSDaniel Nguyen const char ghl_magic_data[], u16 poke_size)
557fb1a79a6SPascal Giard {
558fb1a79a6SPascal Giard struct usb_ctrlrequest *cr;
559fb1a79a6SPascal Giard u8 *databuf;
560fb1a79a6SPascal Giard unsigned int pipe;
561a4bfe13fSDaniel Nguyen u16 ghl_magic_value = (((HID_OUTPUT_REPORT + 1) << 8) | ghl_magic_data[0]);
562fb1a79a6SPascal Giard
563cc894ac5SPascal Giard pipe = usb_sndctrlpipe(usbdev, 0);
564cc894ac5SPascal Giard
565fb1a79a6SPascal Giard cr = devm_kzalloc(&sc->hdev->dev, sizeof(*cr), GFP_ATOMIC);
566fb1a79a6SPascal Giard if (cr == NULL)
567fb1a79a6SPascal Giard return -ENOMEM;
568cc894ac5SPascal Giard
569fb1a79a6SPascal Giard databuf = devm_kzalloc(&sc->hdev->dev, poke_size, GFP_ATOMIC);
570fb1a79a6SPascal Giard if (databuf == NULL)
571fb1a79a6SPascal Giard return -ENOMEM;
572cc894ac5SPascal Giard
573fb1a79a6SPascal Giard cr->bRequestType =
574cc894ac5SPascal Giard USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT;
575fb1a79a6SPascal Giard cr->bRequest = USB_REQ_SET_CONFIGURATION;
576a4bfe13fSDaniel Nguyen cr->wValue = cpu_to_le16(ghl_magic_value);
577fb1a79a6SPascal Giard cr->wIndex = 0;
578fb1a79a6SPascal Giard cr->wLength = cpu_to_le16(poke_size);
579a4bfe13fSDaniel Nguyen memcpy(databuf, ghl_magic_data, poke_size);
580cc894ac5SPascal Giard usb_fill_control_urb(
581fb1a79a6SPascal Giard sc->ghl_urb, usbdev, pipe,
582fb1a79a6SPascal Giard (unsigned char *) cr, databuf, poke_size,
583fb1a79a6SPascal Giard ghl_magic_poke_cb, sc);
584fb1a79a6SPascal Giard return 0;
585cc894ac5SPascal Giard }
586cc894ac5SPascal Giard
guitar_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)587cc894ac5SPascal Giard static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
588cc894ac5SPascal Giard struct hid_field *field, struct hid_usage *usage,
589cc894ac5SPascal Giard unsigned long **bit, int *max)
590cc894ac5SPascal Giard {
591cc894ac5SPascal Giard if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) {
592cc894ac5SPascal Giard unsigned int abs = usage->hid & HID_USAGE;
593cc894ac5SPascal Giard
59432e411d0SSanjay Govind if (abs == GUITAR_TILT_USAGE) {
595cc894ac5SPascal Giard hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RY);
596cc894ac5SPascal Giard return 1;
597cc894ac5SPascal Giard }
598cc894ac5SPascal Giard }
599cc894ac5SPascal Giard return 0;
600cc894ac5SPascal Giard }
601cc894ac5SPascal Giard
motion_fixup(struct hid_device * hdev,u8 * rdesc,unsigned int * rsize)602d4781a27SThomas Weißschuh static const u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
603c5e0c1c4SFrank Praznik unsigned int *rsize)
604c5e0c1c4SFrank Praznik {
605c5e0c1c4SFrank Praznik *rsize = sizeof(motion_rdesc);
606c5e0c1c4SFrank Praznik return motion_rdesc;
607c5e0c1c4SFrank Praznik }
608c5e0c1c4SFrank Praznik
ps3remote_fixup(struct hid_device * hdev,u8 * rdesc,unsigned int * rsize)609d4781a27SThomas Weißschuh static const u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc,
610078328daSJiri Kosina unsigned int *rsize)
611078328daSJiri Kosina {
612078328daSJiri Kosina *rsize = sizeof(ps3remote_rdesc);
613078328daSJiri Kosina return ps3remote_rdesc;
614078328daSJiri Kosina }
615078328daSJiri Kosina
ps3remote_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)616078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
617078328daSJiri Kosina struct hid_field *field, struct hid_usage *usage,
618078328daSJiri Kosina unsigned long **bit, int *max)
619078328daSJiri Kosina {
620078328daSJiri Kosina unsigned int key = usage->hid & HID_USAGE;
621078328daSJiri Kosina
622078328daSJiri Kosina if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
623078328daSJiri Kosina return -1;
624078328daSJiri Kosina
625078328daSJiri Kosina switch (usage->collection_index) {
626078328daSJiri Kosina case 1:
627078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
628078328daSJiri Kosina return -1;
629078328daSJiri Kosina
630078328daSJiri Kosina key = ps3remote_keymap_joypad_buttons[key];
631078328daSJiri Kosina if (!key)
632078328daSJiri Kosina return -1;
633078328daSJiri Kosina break;
634078328daSJiri Kosina case 2:
635078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
636078328daSJiri Kosina return -1;
637078328daSJiri Kosina
638078328daSJiri Kosina key = ps3remote_keymap_remote_buttons[key];
639078328daSJiri Kosina if (!key)
640078328daSJiri Kosina return -1;
641078328daSJiri Kosina break;
642078328daSJiri Kosina default:
643078328daSJiri Kosina return -1;
644078328daSJiri Kosina }
645078328daSJiri Kosina
646078328daSJiri Kosina hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
647078328daSJiri Kosina return 1;
648078328daSJiri Kosina }
649078328daSJiri Kosina
navigation_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)650b8f0970dSRoderick Colenbrander static int navigation_mapping(struct hid_device *hdev, struct hid_input *hi,
651b8f0970dSRoderick Colenbrander struct hid_field *field, struct hid_usage *usage,
652b8f0970dSRoderick Colenbrander unsigned long **bit, int *max)
653b8f0970dSRoderick Colenbrander {
654b8f0970dSRoderick Colenbrander if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
655b8f0970dSRoderick Colenbrander unsigned int key = usage->hid & HID_USAGE;
656b8f0970dSRoderick Colenbrander
657b8f0970dSRoderick Colenbrander if (key >= ARRAY_SIZE(sixaxis_keymap))
658b8f0970dSRoderick Colenbrander return -1;
659b8f0970dSRoderick Colenbrander
660b8f0970dSRoderick Colenbrander key = navigation_keymap[key];
661b8f0970dSRoderick Colenbrander if (!key)
662b8f0970dSRoderick Colenbrander return -1;
663b8f0970dSRoderick Colenbrander
664b8f0970dSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
665b8f0970dSRoderick Colenbrander return 1;
666b8f0970dSRoderick Colenbrander } else if (usage->hid == HID_GD_POINTER) {
667b8f0970dSRoderick Colenbrander /* See comment in sixaxis_mapping, basically the L2 (and R2)
668b8f0970dSRoderick Colenbrander * triggers are reported through GD Pointer.
669b8f0970dSRoderick Colenbrander * In addition we ignore any analog button 'axes' and only
670b8f0970dSRoderick Colenbrander * support digital buttons.
671b8f0970dSRoderick Colenbrander */
672b8f0970dSRoderick Colenbrander switch (usage->usage_index) {
673b8f0970dSRoderick Colenbrander case 8: /* L2 */
674b8f0970dSRoderick Colenbrander usage->hid = HID_GD_Z;
675b8f0970dSRoderick Colenbrander break;
676b8f0970dSRoderick Colenbrander default:
677b8f0970dSRoderick Colenbrander return -1;
678b8f0970dSRoderick Colenbrander }
679b8f0970dSRoderick Colenbrander
680b8f0970dSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf);
681b8f0970dSRoderick Colenbrander return 1;
682b8f0970dSRoderick Colenbrander } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
683b8f0970dSRoderick Colenbrander unsigned int abs = usage->hid & HID_USAGE;
684b8f0970dSRoderick Colenbrander
685b8f0970dSRoderick Colenbrander if (abs >= ARRAY_SIZE(navigation_absmap))
686b8f0970dSRoderick Colenbrander return -1;
687b8f0970dSRoderick Colenbrander
688b8f0970dSRoderick Colenbrander abs = navigation_absmap[abs];
689b8f0970dSRoderick Colenbrander
690b8f0970dSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
691b8f0970dSRoderick Colenbrander return 1;
692b8f0970dSRoderick Colenbrander }
693b8f0970dSRoderick Colenbrander
694b8f0970dSRoderick Colenbrander return -1;
695b8f0970dSRoderick Colenbrander }
696b8f0970dSRoderick Colenbrander
697b8f0970dSRoderick Colenbrander
sixaxis_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)698e19a267bSRoderick Colenbrander static int sixaxis_mapping(struct hid_device *hdev, struct hid_input *hi,
699e19a267bSRoderick Colenbrander struct hid_field *field, struct hid_usage *usage,
700e19a267bSRoderick Colenbrander unsigned long **bit, int *max)
701e19a267bSRoderick Colenbrander {
702e19a267bSRoderick Colenbrander if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
703e19a267bSRoderick Colenbrander unsigned int key = usage->hid & HID_USAGE;
704e19a267bSRoderick Colenbrander
705e19a267bSRoderick Colenbrander if (key >= ARRAY_SIZE(sixaxis_keymap))
706e19a267bSRoderick Colenbrander return -1;
707e19a267bSRoderick Colenbrander
708e19a267bSRoderick Colenbrander key = sixaxis_keymap[key];
709e19a267bSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
710e19a267bSRoderick Colenbrander return 1;
711e19a267bSRoderick Colenbrander } else if (usage->hid == HID_GD_POINTER) {
712e19a267bSRoderick Colenbrander /* The DS3 provides analog values for most buttons and even
713e19a267bSRoderick Colenbrander * for HAT axes through GD Pointer. L2 and R2 are reported
714e19a267bSRoderick Colenbrander * among these as well instead of as GD Z / RZ. Remap L2
715e19a267bSRoderick Colenbrander * and R2 and ignore other analog 'button axes' as there is
716e19a267bSRoderick Colenbrander * no good way for reporting them.
717e19a267bSRoderick Colenbrander */
718e19a267bSRoderick Colenbrander switch (usage->usage_index) {
719e19a267bSRoderick Colenbrander case 8: /* L2 */
720e19a267bSRoderick Colenbrander usage->hid = HID_GD_Z;
721e19a267bSRoderick Colenbrander break;
722e19a267bSRoderick Colenbrander case 9: /* R2 */
723e19a267bSRoderick Colenbrander usage->hid = HID_GD_RZ;
724e19a267bSRoderick Colenbrander break;
725e19a267bSRoderick Colenbrander default:
726e19a267bSRoderick Colenbrander return -1;
727e19a267bSRoderick Colenbrander }
728e19a267bSRoderick Colenbrander
729e19a267bSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf);
730e19a267bSRoderick Colenbrander return 1;
731e19a267bSRoderick Colenbrander } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
732e19a267bSRoderick Colenbrander unsigned int abs = usage->hid & HID_USAGE;
733e19a267bSRoderick Colenbrander
734e19a267bSRoderick Colenbrander if (abs >= ARRAY_SIZE(sixaxis_absmap))
735e19a267bSRoderick Colenbrander return -1;
736e19a267bSRoderick Colenbrander
737e19a267bSRoderick Colenbrander abs = sixaxis_absmap[abs];
738e19a267bSRoderick Colenbrander
739e19a267bSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
740e19a267bSRoderick Colenbrander return 1;
741e19a267bSRoderick Colenbrander }
742e19a267bSRoderick Colenbrander
743e19a267bSRoderick Colenbrander return -1;
744e19a267bSRoderick Colenbrander }
745e19a267bSRoderick Colenbrander
sony_report_fixup(struct hid_device * hdev,u8 * rdesc,unsigned int * rsize)746fe73965dSThomas Weißschuh static const u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
74773e4008dSNikolai Kondrashov unsigned int *rsize)
748cc6e0bbbSJiri Kosina {
749cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev);
750cc6e0bbbSJiri Kosina
7514ba1eeebSMikko Perttunen if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
75274500cc8SScott Moreau return rdesc;
75374500cc8SScott Moreau
75499d24902SFernando Luis Vázquez Cao /*
75599d24902SFernando Luis Vázquez Cao * Some Sony RF receivers wrongly declare the mouse pointer as a
75699d24902SFernando Luis Vázquez Cao * a constant non-data variable.
75799d24902SFernando Luis Vázquez Cao */
75899d24902SFernando Luis Vázquez Cao if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
75999d24902SFernando Luis Vázquez Cao /* usage page: generic desktop controls */
76099d24902SFernando Luis Vázquez Cao /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
76199d24902SFernando Luis Vázquez Cao /* usage: mouse */
76299d24902SFernando Luis Vázquez Cao rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
76399d24902SFernando Luis Vázquez Cao /* input (usage page for x,y axes): constant, variable, relative */
76499d24902SFernando Luis Vázquez Cao rdesc[54] == 0x81 && rdesc[55] == 0x07) {
765a4649184SFernando Luis Vázquez Cao hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
76699d24902SFernando Luis Vázquez Cao /* input: data, variable, relative */
767cc6e0bbbSJiri Kosina rdesc[55] = 0x06;
768cc6e0bbbSJiri Kosina }
76961ab44beSSimon Wood
770c5e0c1c4SFrank Praznik if (sc->quirks & MOTION_CONTROLLER)
771c5e0c1c4SFrank Praznik return motion_fixup(hdev, rdesc, rsize);
772c5e0c1c4SFrank Praznik
773078328daSJiri Kosina if (sc->quirks & PS3REMOTE)
774078328daSJiri Kosina return ps3remote_fixup(hdev, rdesc, rsize);
775078328daSJiri Kosina
776e72455b8SScott Shumate /*
777e72455b8SScott Shumate * Some knock-off USB dongles incorrectly report their button count
778e72455b8SScott Shumate * as 13 instead of 16 causing three non-functional buttons.
779e72455b8SScott Shumate */
780e72455b8SScott Shumate if ((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize >= 45 &&
781e72455b8SScott Shumate /* Report Count (13) */
782e72455b8SScott Shumate rdesc[23] == 0x95 && rdesc[24] == 0x0D &&
783e72455b8SScott Shumate /* Usage Maximum (13) */
784e72455b8SScott Shumate rdesc[37] == 0x29 && rdesc[38] == 0x0D &&
785e72455b8SScott Shumate /* Report Count (3) */
786e72455b8SScott Shumate rdesc[43] == 0x95 && rdesc[44] == 0x03) {
787e72455b8SScott Shumate hid_info(hdev, "Fixing up USB dongle report descriptor\n");
788e72455b8SScott Shumate rdesc[24] = 0x10;
789e72455b8SScott Shumate rdesc[38] = 0x10;
790e72455b8SScott Shumate rdesc[44] = 0x00;
791e72455b8SScott Shumate }
792e72455b8SScott Shumate
79373e4008dSNikolai Kondrashov return rdesc;
794cc6e0bbbSJiri Kosina }
795cc6e0bbbSJiri Kosina
sixaxis_parse_report(struct sony_sc * sc,u8 * rd,int size)7961adf904eSPavel Machek static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
797d902f472SFrank Praznik {
7981adf904eSPavel Machek static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
799d902f472SFrank Praznik unsigned long flags;
80012e9a6d7SSimon Wood int offset;
801a76a6c18SRoderick Colenbrander u8 battery_capacity;
802a76a6c18SRoderick Colenbrander int battery_status;
803d902f472SFrank Praznik
804ad142b9eSFrank Praznik /*
805ad142b9eSFrank Praznik * The sixaxis is charging if the battery value is 0xee
806d902f472SFrank Praznik * and it is fully charged if the value is 0xef.
807d902f472SFrank Praznik * It does not report the actual level while charging so it
808d902f472SFrank Praznik * is set to 100% while charging is in progress.
809d902f472SFrank Praznik */
81012e9a6d7SSimon Wood offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
81112e9a6d7SSimon Wood
81212e9a6d7SSimon Wood if (rd[offset] >= 0xee) {
813d902f472SFrank Praznik battery_capacity = 100;
814a76a6c18SRoderick Colenbrander battery_status = (rd[offset] & 0x01) ? POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING;
815d902f472SFrank Praznik } else {
8161adf904eSPavel Machek u8 index = rd[offset] <= 5 ? rd[offset] : 5;
817ac3c9a94SFrank Praznik battery_capacity = sixaxis_battery_capacity[index];
818a76a6c18SRoderick Colenbrander battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
819d902f472SFrank Praznik }
820d902f472SFrank Praznik
821d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags);
822d902f472SFrank Praznik sc->battery_capacity = battery_capacity;
823a76a6c18SRoderick Colenbrander sc->battery_status = battery_status;
824d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags);
825510c8b7cSRoderick Colenbrander
826510c8b7cSRoderick Colenbrander if (sc->quirks & SIXAXIS_CONTROLLER) {
827510c8b7cSRoderick Colenbrander int val;
828510c8b7cSRoderick Colenbrander
829510c8b7cSRoderick Colenbrander offset = SIXAXIS_INPUT_REPORT_ACC_X_OFFSET;
830510c8b7cSRoderick Colenbrander val = ((rd[offset+1] << 8) | rd[offset]) - 511;
831510c8b7cSRoderick Colenbrander input_report_abs(sc->sensor_dev, ABS_X, val);
832510c8b7cSRoderick Colenbrander
833510c8b7cSRoderick Colenbrander /* Y and Z are swapped and inversed */
834510c8b7cSRoderick Colenbrander val = 511 - ((rd[offset+5] << 8) | rd[offset+4]);
835510c8b7cSRoderick Colenbrander input_report_abs(sc->sensor_dev, ABS_Y, val);
836510c8b7cSRoderick Colenbrander
837510c8b7cSRoderick Colenbrander val = 511 - ((rd[offset+3] << 8) | rd[offset+2]);
838510c8b7cSRoderick Colenbrander input_report_abs(sc->sensor_dev, ABS_Z, val);
839510c8b7cSRoderick Colenbrander
840510c8b7cSRoderick Colenbrander input_sync(sc->sensor_dev);
841510c8b7cSRoderick Colenbrander }
842d902f472SFrank Praznik }
843d902f472SFrank Praznik
nsg_mrxu_parse_report(struct sony_sc * sc,u8 * rd,int size)844b7289cb1STodd Kelner static void nsg_mrxu_parse_report(struct sony_sc *sc, u8 *rd, int size)
845b7289cb1STodd Kelner {
846b7289cb1STodd Kelner int n, offset, relx, rely;
847b7289cb1STodd Kelner u8 active;
848b7289cb1STodd Kelner
849b7289cb1STodd Kelner /*
850b7289cb1STodd Kelner * The NSG-MRxU multi-touch trackpad data starts at offset 1 and
851b7289cb1STodd Kelner * the touch-related data starts at offset 2.
852b7289cb1STodd Kelner * For the first byte, bit 0 is set when touchpad button is pressed.
853b7289cb1STodd Kelner * Bit 2 is set when a touch is active and the drag (Fn) key is pressed.
854b7289cb1STodd Kelner * This drag key is mapped to BTN_LEFT. It is operational only when a
855b7289cb1STodd Kelner * touch point is active.
856b7289cb1STodd Kelner * Bit 4 is set when only the first touch point is active.
857b7289cb1STodd Kelner * Bit 6 is set when only the second touch point is active.
858b7289cb1STodd Kelner * Bits 5 and 7 are set when both touch points are active.
859b7289cb1STodd Kelner * The next 3 bytes are two 12 bit X/Y coordinates for the first touch.
860b7289cb1STodd Kelner * The following byte, offset 5, has the touch width and length.
861b7289cb1STodd Kelner * Bits 0-4=X (width), bits 5-7=Y (length).
862b7289cb1STodd Kelner * A signed relative X coordinate is at offset 6.
863b7289cb1STodd Kelner * The bytes at offset 7-9 are the second touch X/Y coordinates.
864b7289cb1STodd Kelner * Offset 10 has the second touch width and length.
865b7289cb1STodd Kelner * Offset 11 has the relative Y coordinate.
866b7289cb1STodd Kelner */
867b7289cb1STodd Kelner offset = 1;
868b7289cb1STodd Kelner
869b7289cb1STodd Kelner input_report_key(sc->touchpad, BTN_LEFT, rd[offset] & 0x0F);
870b7289cb1STodd Kelner active = (rd[offset] >> 4);
871b7289cb1STodd Kelner relx = (s8) rd[offset+5];
872b7289cb1STodd Kelner rely = ((s8) rd[offset+10]) * -1;
873b7289cb1STodd Kelner
874b7289cb1STodd Kelner offset++;
875b7289cb1STodd Kelner
876b7289cb1STodd Kelner for (n = 0; n < 2; n++) {
877b7289cb1STodd Kelner u16 x, y;
878b7289cb1STodd Kelner u8 contactx, contacty;
879b7289cb1STodd Kelner
880b7289cb1STodd Kelner x = rd[offset] | ((rd[offset+1] & 0x0F) << 8);
881b7289cb1STodd Kelner y = ((rd[offset+1] & 0xF0) >> 4) | (rd[offset+2] << 4);
882b7289cb1STodd Kelner
883b7289cb1STodd Kelner input_mt_slot(sc->touchpad, n);
884b7289cb1STodd Kelner input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active & 0x03);
885b7289cb1STodd Kelner
886b7289cb1STodd Kelner if (active & 0x03) {
887b7289cb1STodd Kelner contactx = rd[offset+3] & 0x0F;
888b7289cb1STodd Kelner contacty = rd[offset+3] >> 4;
889b7289cb1STodd Kelner input_report_abs(sc->touchpad, ABS_MT_TOUCH_MAJOR,
890b7289cb1STodd Kelner max(contactx, contacty));
891b7289cb1STodd Kelner input_report_abs(sc->touchpad, ABS_MT_TOUCH_MINOR,
892b7289cb1STodd Kelner min(contactx, contacty));
893b7289cb1STodd Kelner input_report_abs(sc->touchpad, ABS_MT_ORIENTATION,
894b7289cb1STodd Kelner (bool) (contactx > contacty));
895b7289cb1STodd Kelner input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x);
896b7289cb1STodd Kelner input_report_abs(sc->touchpad, ABS_MT_POSITION_Y,
897b7289cb1STodd Kelner NSG_MRXU_MAX_Y - y);
898b7289cb1STodd Kelner /*
899b7289cb1STodd Kelner * The relative coordinates belong to the first touch
900b7289cb1STodd Kelner * point, when present, or to the second touch point
901b7289cb1STodd Kelner * when the first is not active.
902b7289cb1STodd Kelner */
903b7289cb1STodd Kelner if ((n == 0) || ((n == 1) && (active & 0x01))) {
904b7289cb1STodd Kelner input_report_rel(sc->touchpad, REL_X, relx);
905b7289cb1STodd Kelner input_report_rel(sc->touchpad, REL_Y, rely);
906b7289cb1STodd Kelner }
907b7289cb1STodd Kelner }
908b7289cb1STodd Kelner
909b7289cb1STodd Kelner offset += 5;
910b7289cb1STodd Kelner active >>= 2;
911b7289cb1STodd Kelner }
912b7289cb1STodd Kelner
913b7289cb1STodd Kelner input_mt_sync_frame(sc->touchpad);
914b7289cb1STodd Kelner
915b7289cb1STodd Kelner input_sync(sc->touchpad);
916b7289cb1STodd Kelner }
917b7289cb1STodd Kelner
sony_raw_event(struct hid_device * hdev,struct hid_report * report,u8 * rd,int size)918c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
9191adf904eSPavel Machek u8 *rd, int size)
920c9e4d877SSimon Wood {
921c9e4d877SSimon Wood struct sony_sc *sc = hid_get_drvdata(hdev);
922c9e4d877SSimon Wood
923ad142b9eSFrank Praznik /*
924ad142b9eSFrank Praznik * Sixaxis HID report has acclerometers/gyro with MSByte first, this
925c9e4d877SSimon Wood * has to be BYTE_SWAPPED before passing up to joystick interface
926c9e4d877SSimon Wood */
927fee4e2d5SFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
9288f5f0bc2SFrank Praznik /*
9298f5f0bc2SFrank Praznik * When connected via Bluetooth the Sixaxis occasionally sends
9308f5f0bc2SFrank Praznik * a report with the second byte 0xff and the rest zeroed.
9318f5f0bc2SFrank Praznik *
9328f5f0bc2SFrank Praznik * This report does not reflect the actual state of the
9338f5f0bc2SFrank Praznik * controller must be ignored to avoid generating false input
9348f5f0bc2SFrank Praznik * events.
9358f5f0bc2SFrank Praznik */
9368f5f0bc2SFrank Praznik if (rd[1] == 0xff)
9378f5f0bc2SFrank Praznik return -EINVAL;
9388f5f0bc2SFrank Praznik
939c9e4d877SSimon Wood swap(rd[41], rd[42]);
940c9e4d877SSimon Wood swap(rd[43], rd[44]);
941c9e4d877SSimon Wood swap(rd[45], rd[46]);
942c9e4d877SSimon Wood swap(rd[47], rd[48]);
943d902f472SFrank Praznik
944d902f472SFrank Praznik sixaxis_parse_report(sc, rd, size);
94512e9a6d7SSimon Wood } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) {
94612e9a6d7SSimon Wood sixaxis_parse_report(sc, rd, size);
9474545ee0aSSimon Wood } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 &&
9484545ee0aSSimon Wood size == 49) {
9494545ee0aSSimon Wood sixaxis_parse_report(sc, rd, size);
950b7289cb1STodd Kelner } else if ((sc->quirks & NSG_MRXU_REMOTE) && rd[0] == 0x02) {
951b7289cb1STodd Kelner nsg_mrxu_parse_report(sc, rd, size);
952b7289cb1STodd Kelner return 1;
953c9e4d877SSimon Wood }
954c9e4d877SSimon Wood
9552a242932SFrank Praznik if (sc->defer_initialization) {
9562a242932SFrank Praznik sc->defer_initialization = 0;
957b5322736SRoderick Colenbrander sony_schedule_work(sc, SONY_WORKER_STATE);
9582a242932SFrank Praznik }
9592a242932SFrank Praznik
960c9e4d877SSimon Wood return 0;
961c9e4d877SSimon Wood }
962c9e4d877SSimon Wood
sony_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)963f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
964f04d5140SColin Leitner struct hid_field *field, struct hid_usage *usage,
965f04d5140SColin Leitner unsigned long **bit, int *max)
966f04d5140SColin Leitner {
967f04d5140SColin Leitner struct sony_sc *sc = hid_get_drvdata(hdev);
968f04d5140SColin Leitner
969f04d5140SColin Leitner if (sc->quirks & BUZZ_CONTROLLER) {
970f04d5140SColin Leitner unsigned int key = usage->hid & HID_USAGE;
971f04d5140SColin Leitner
972f04d5140SColin Leitner if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
973f04d5140SColin Leitner return -1;
974f04d5140SColin Leitner
975f04d5140SColin Leitner switch (usage->collection_index) {
976f04d5140SColin Leitner case 1:
977f04d5140SColin Leitner if (key >= ARRAY_SIZE(buzz_keymap))
978f04d5140SColin Leitner return -1;
979f04d5140SColin Leitner
980f04d5140SColin Leitner key = buzz_keymap[key];
981f04d5140SColin Leitner if (!key)
982f04d5140SColin Leitner return -1;
983f04d5140SColin Leitner break;
984f04d5140SColin Leitner default:
985f04d5140SColin Leitner return -1;
986f04d5140SColin Leitner }
987f04d5140SColin Leitner
988f04d5140SColin Leitner hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
989f04d5140SColin Leitner return 1;
990f04d5140SColin Leitner }
991f04d5140SColin Leitner
992078328daSJiri Kosina if (sc->quirks & PS3REMOTE)
993078328daSJiri Kosina return ps3remote_mapping(hdev, hi, field, usage, bit, max);
994078328daSJiri Kosina
995b8f0970dSRoderick Colenbrander if (sc->quirks & NAVIGATION_CONTROLLER)
996b8f0970dSRoderick Colenbrander return navigation_mapping(hdev, hi, field, usage, bit, max);
997b8f0970dSRoderick Colenbrander
998e19a267bSRoderick Colenbrander if (sc->quirks & SIXAXIS_CONTROLLER)
999e19a267bSRoderick Colenbrander return sixaxis_mapping(hdev, hi, field, usage, bit, max);
10009131f8ccSRoderick Colenbrander
100132e411d0SSanjay Govind if (sc->quirks & GH_GUITAR_CONTROLLER)
1002cc894ac5SPascal Giard return guitar_mapping(hdev, hi, field, usage, bit, max);
1003e19a267bSRoderick Colenbrander
10046f498018SBenjamin Tissoires /* Let hid-core decide for the others */
10056f498018SBenjamin Tissoires return 0;
1006f04d5140SColin Leitner }
1007f04d5140SColin Leitner
sony_register_touchpad(struct sony_sc * sc,int touch_count,int w,int h,int touch_major,int touch_minor,int orientation)1008ac797b95SRoderick Colenbrander static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
1009b7289cb1STodd Kelner int w, int h, int touch_major, int touch_minor, int orientation)
1010ce8efc3bSFrank Praznik {
1011ac797b95SRoderick Colenbrander size_t name_sz;
1012ac797b95SRoderick Colenbrander char *name;
1013ce8efc3bSFrank Praznik int ret;
1014ce8efc3bSFrank Praznik
1015cc070a84SHanno Zulla sc->touchpad = devm_input_allocate_device(&sc->hdev->dev);
1016ac797b95SRoderick Colenbrander if (!sc->touchpad)
1017ac797b95SRoderick Colenbrander return -ENOMEM;
1018ce8efc3bSFrank Praznik
1019ac797b95SRoderick Colenbrander input_set_drvdata(sc->touchpad, sc);
1020ac797b95SRoderick Colenbrander sc->touchpad->dev.parent = &sc->hdev->dev;
1021ac797b95SRoderick Colenbrander sc->touchpad->phys = sc->hdev->phys;
1022ac797b95SRoderick Colenbrander sc->touchpad->uniq = sc->hdev->uniq;
1023ac797b95SRoderick Colenbrander sc->touchpad->id.bustype = sc->hdev->bus;
1024ac797b95SRoderick Colenbrander sc->touchpad->id.vendor = sc->hdev->vendor;
1025ac797b95SRoderick Colenbrander sc->touchpad->id.product = sc->hdev->product;
1026ac797b95SRoderick Colenbrander sc->touchpad->id.version = sc->hdev->version;
1027ac797b95SRoderick Colenbrander
10284f1f3918SRoderick Colenbrander /* This suffix was originally apended when hid-sony also
10294f1f3918SRoderick Colenbrander * supported DS4 devices. The DS4 was implemented using multiple
10304f1f3918SRoderick Colenbrander * evdev nodes and hence had the need to separete them out using
10314f1f3918SRoderick Colenbrander * a suffix. Other devices which were added later like Sony TV remotes
10324f1f3918SRoderick Colenbrander * inhirited this suffix.
1033ac797b95SRoderick Colenbrander */
10344f1f3918SRoderick Colenbrander name_sz = strlen(sc->hdev->name) + sizeof(TOUCHPAD_SUFFIX);
1035cc070a84SHanno Zulla name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL);
1036cc070a84SHanno Zulla if (!name)
1037cc070a84SHanno Zulla return -ENOMEM;
10384f1f3918SRoderick Colenbrander snprintf(name, name_sz, "%s" TOUCHPAD_SUFFIX, sc->hdev->name);
1039ac797b95SRoderick Colenbrander sc->touchpad->name = name;
1040ac797b95SRoderick Colenbrander
1041ac797b95SRoderick Colenbrander /* We map the button underneath the touchpad to BTN_LEFT. */
1042ac797b95SRoderick Colenbrander __set_bit(EV_KEY, sc->touchpad->evbit);
1043ac797b95SRoderick Colenbrander __set_bit(BTN_LEFT, sc->touchpad->keybit);
1044ac797b95SRoderick Colenbrander __set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit);
1045ac797b95SRoderick Colenbrander
1046ac797b95SRoderick Colenbrander input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0);
1047ac797b95SRoderick Colenbrander input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0);
1048ac797b95SRoderick Colenbrander
1049b7289cb1STodd Kelner if (touch_major > 0) {
1050b7289cb1STodd Kelner input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MAJOR,
1051b7289cb1STodd Kelner 0, touch_major, 0, 0);
1052b7289cb1STodd Kelner if (touch_minor > 0)
1053b7289cb1STodd Kelner input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MINOR,
1054b7289cb1STodd Kelner 0, touch_minor, 0, 0);
1055b7289cb1STodd Kelner if (orientation > 0)
1056b7289cb1STodd Kelner input_set_abs_params(sc->touchpad, ABS_MT_ORIENTATION,
1057b7289cb1STodd Kelner 0, orientation, 0, 0);
1058b7289cb1STodd Kelner }
1059b7289cb1STodd Kelner
1060b7289cb1STodd Kelner if (sc->quirks & NSG_MRXU_REMOTE) {
1061b7289cb1STodd Kelner __set_bit(EV_REL, sc->touchpad->evbit);
1062b7289cb1STodd Kelner }
1063b7289cb1STodd Kelner
1064b7289cb1STodd Kelner ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER);
1065b7289cb1STodd Kelner if (ret < 0)
1066cc070a84SHanno Zulla return ret;
1067b7289cb1STodd Kelner
1068ac797b95SRoderick Colenbrander ret = input_register_device(sc->touchpad);
1069ac797b95SRoderick Colenbrander if (ret < 0)
1070cc070a84SHanno Zulla return ret;
1071ce8efc3bSFrank Praznik
1072ce8efc3bSFrank Praznik return 0;
1073ac797b95SRoderick Colenbrander }
10749154301aSDmitry Torokhov
sony_register_sensors(struct sony_sc * sc)1075227c011bSRoderick Colenbrander static int sony_register_sensors(struct sony_sc *sc)
1076227c011bSRoderick Colenbrander {
1077227c011bSRoderick Colenbrander size_t name_sz;
1078227c011bSRoderick Colenbrander char *name;
1079227c011bSRoderick Colenbrander int ret;
1080227c011bSRoderick Colenbrander
1081ea4a5fdcSHanno Zulla sc->sensor_dev = devm_input_allocate_device(&sc->hdev->dev);
1082227c011bSRoderick Colenbrander if (!sc->sensor_dev)
1083227c011bSRoderick Colenbrander return -ENOMEM;
1084227c011bSRoderick Colenbrander
1085227c011bSRoderick Colenbrander input_set_drvdata(sc->sensor_dev, sc);
1086227c011bSRoderick Colenbrander sc->sensor_dev->dev.parent = &sc->hdev->dev;
1087227c011bSRoderick Colenbrander sc->sensor_dev->phys = sc->hdev->phys;
1088227c011bSRoderick Colenbrander sc->sensor_dev->uniq = sc->hdev->uniq;
1089227c011bSRoderick Colenbrander sc->sensor_dev->id.bustype = sc->hdev->bus;
1090227c011bSRoderick Colenbrander sc->sensor_dev->id.vendor = sc->hdev->vendor;
1091227c011bSRoderick Colenbrander sc->sensor_dev->id.product = sc->hdev->product;
1092227c011bSRoderick Colenbrander sc->sensor_dev->id.version = sc->hdev->version;
1093227c011bSRoderick Colenbrander
1094227c011bSRoderick Colenbrander /* Append a suffix to the controller name as there are various
1095227c011bSRoderick Colenbrander * DS4 compatible non-Sony devices with different names.
1096227c011bSRoderick Colenbrander */
1097510c8b7cSRoderick Colenbrander name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX);
1098ea4a5fdcSHanno Zulla name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL);
1099ea4a5fdcSHanno Zulla if (!name)
1100ea4a5fdcSHanno Zulla return -ENOMEM;
1101510c8b7cSRoderick Colenbrander snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name);
1102227c011bSRoderick Colenbrander sc->sensor_dev->name = name;
1103227c011bSRoderick Colenbrander
1104510c8b7cSRoderick Colenbrander if (sc->quirks & SIXAXIS_CONTROLLER) {
1105510c8b7cSRoderick Colenbrander /* For the DS3 we only support the accelerometer, which works
1106510c8b7cSRoderick Colenbrander * quite well even without calibration. The device also has
1107510c8b7cSRoderick Colenbrander * a 1-axis gyro, but it is very difficult to manage from within
1108510c8b7cSRoderick Colenbrander * the driver even to get data, the sensor is inaccurate and
1109510c8b7cSRoderick Colenbrander * the behavior is very different between hardware revisions.
1110510c8b7cSRoderick Colenbrander */
1111510c8b7cSRoderick Colenbrander input_set_abs_params(sc->sensor_dev, ABS_X, -512, 511, 4, 0);
1112510c8b7cSRoderick Colenbrander input_set_abs_params(sc->sensor_dev, ABS_Y, -512, 511, 4, 0);
1113510c8b7cSRoderick Colenbrander input_set_abs_params(sc->sensor_dev, ABS_Z, -512, 511, 4, 0);
1114510c8b7cSRoderick Colenbrander input_abs_set_res(sc->sensor_dev, ABS_X, SIXAXIS_ACC_RES_PER_G);
1115510c8b7cSRoderick Colenbrander input_abs_set_res(sc->sensor_dev, ABS_Y, SIXAXIS_ACC_RES_PER_G);
1116510c8b7cSRoderick Colenbrander input_abs_set_res(sc->sensor_dev, ABS_Z, SIXAXIS_ACC_RES_PER_G);
1117510c8b7cSRoderick Colenbrander }
1118510c8b7cSRoderick Colenbrander
1119227c011bSRoderick Colenbrander __set_bit(INPUT_PROP_ACCELEROMETER, sc->sensor_dev->propbit);
1120227c011bSRoderick Colenbrander
1121227c011bSRoderick Colenbrander ret = input_register_device(sc->sensor_dev);
1122227c011bSRoderick Colenbrander if (ret < 0)
1123ea4a5fdcSHanno Zulla return ret;
1124227c011bSRoderick Colenbrander
1125227c011bSRoderick Colenbrander return 0;
1126227c011bSRoderick Colenbrander }
1127227c011bSRoderick Colenbrander
11285710fabfSAntonio Ospite /*
1129bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
1130bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any
1131bd28ce00SJiri Slaby * events.
1132bd28ce00SJiri Slaby */
sixaxis_set_operational_usb(struct hid_device * hdev)1133816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
1134bd28ce00SJiri Slaby {
113569481059SHongye Yuan struct sony_sc *sc = hid_get_drvdata(hdev);
1136a85d67b5SAntonio Ospite const int buf_size =
1137a85d67b5SAntonio Ospite max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
11381adf904eSPavel Machek u8 *buf;
1139bd28ce00SJiri Slaby int ret;
1140bd28ce00SJiri Slaby
11412e701a35SAntonio Ospite buf = kmalloc(buf_size, GFP_KERNEL);
1142bd28ce00SJiri Slaby if (!buf)
1143bd28ce00SJiri Slaby return -ENOMEM;
1144bd28ce00SJiri Slaby
1145a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
1146a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1147a7de9b86SLauri Kasanen if (ret < 0) {
1148a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 1\n");
1149a7de9b86SLauri Kasanen goto out;
1150a7de9b86SLauri Kasanen }
1151f204828aSBenjamin Tissoires
1152a7de9b86SLauri Kasanen /*
1153a7de9b86SLauri Kasanen * Some compatible controllers like the Speedlink Strike FX and
1154a7de9b86SLauri Kasanen * Gasia need another query plus an USB interrupt to get operational.
1155a7de9b86SLauri Kasanen */
1156a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
1157a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
1158a7de9b86SLauri Kasanen if (ret < 0) {
1159a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 2\n");
1160a7de9b86SLauri Kasanen goto out;
1161a7de9b86SLauri Kasanen }
1162a7de9b86SLauri Kasanen
1163492ca83cSBastien Nocera /*
1164492ca83cSBastien Nocera * But the USB interrupt would cause SHANWAN controllers to
116569481059SHongye Yuan * start rumbling non-stop, so skip step 3 for these controllers.
1166492ca83cSBastien Nocera */
116769481059SHongye Yuan if (sc->quirks & SHANWAN_GAMEPAD)
116869481059SHongye Yuan goto out;
116969481059SHongye Yuan
1170a7de9b86SLauri Kasanen ret = hid_hw_output_report(hdev, buf, 1);
117119f4c2baSBenjamin Tissoires if (ret < 0) {
117219f4c2baSBenjamin Tissoires hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
117319f4c2baSBenjamin Tissoires ret = 0;
117419f4c2baSBenjamin Tissoires }
1175bd28ce00SJiri Slaby
1176a7de9b86SLauri Kasanen out:
1177bd28ce00SJiri Slaby kfree(buf);
1178bd28ce00SJiri Slaby
1179bd28ce00SJiri Slaby return ret;
1180bd28ce00SJiri Slaby }
1181bd28ce00SJiri Slaby
sixaxis_set_operational_bt(struct hid_device * hdev)1182816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
1183f9ce7c28SBastien Nocera {
11841adf904eSPavel Machek static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
11851adf904eSPavel Machek u8 *buf;
11869b2b5c9aSFrank Praznik int ret;
11879b2b5c9aSFrank Praznik
11889b2b5c9aSFrank Praznik buf = kmemdup(report, sizeof(report), GFP_KERNEL);
11899b2b5c9aSFrank Praznik if (!buf)
11909b2b5c9aSFrank Praznik return -ENOMEM;
11919b2b5c9aSFrank Praznik
11929b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
1193b0dd72aaSBenjamin Tissoires HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
11949b2b5c9aSFrank Praznik
11959b2b5c9aSFrank Praznik kfree(buf);
11969b2b5c9aSFrank Praznik
11979b2b5c9aSFrank Praznik return ret;
1198f9ce7c28SBastien Nocera }
1199f9ce7c28SBastien Nocera
sixaxis_set_leds_from_id(struct sony_sc * sc)1200221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc)
12018025087aSFrank Praznik {
12021adf904eSPavel Machek static const u8 sixaxis_leds[10][4] = {
12038025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x00 },
12048025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x00 },
12058025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x00 },
12068025087aSFrank Praznik { 0x00, 0x00, 0x00, 0x01 },
12078025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x01 },
12088025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x01 },
12098025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x01 },
12108025087aSFrank Praznik { 0x01, 0x00, 0x01, 0x01 },
12118025087aSFrank Praznik { 0x00, 0x01, 0x01, 0x01 },
12128025087aSFrank Praznik { 0x01, 0x01, 0x01, 0x01 }
12138025087aSFrank Praznik };
12148025087aSFrank Praznik
1215221399b3SFrank Praznik int id = sc->device_id;
1216221399b3SFrank Praznik
1217221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0]));
12188025087aSFrank Praznik
12198025087aSFrank Praznik if (id < 0)
12208025087aSFrank Praznik return;
12218025087aSFrank Praznik
12228025087aSFrank Praznik id %= 10;
1223221399b3SFrank Praznik memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
12248025087aSFrank Praznik }
12258025087aSFrank Praznik
buzz_set_leds(struct sony_sc * sc)1226221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc)
1227f04d5140SColin Leitner {
1228221399b3SFrank Praznik struct hid_device *hdev = sc->hdev;
1229f04d5140SColin Leitner struct list_head *report_list =
1230f04d5140SColin Leitner &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
1231f04d5140SColin Leitner struct hid_report *report = list_entry(report_list->next,
1232f04d5140SColin Leitner struct hid_report, list);
12331adf904eSPavel Machek s32 *value = report->field[0]->value;
1234f04d5140SColin Leitner
1235221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < 4);
1236221399b3SFrank Praznik
1237f04d5140SColin Leitner value[0] = 0x00;
1238221399b3SFrank Praznik value[1] = sc->led_state[0] ? 0xff : 0x00;
1239221399b3SFrank Praznik value[2] = sc->led_state[1] ? 0xff : 0x00;
1240221399b3SFrank Praznik value[3] = sc->led_state[2] ? 0xff : 0x00;
1241221399b3SFrank Praznik value[4] = sc->led_state[3] ? 0xff : 0x00;
1242f04d5140SColin Leitner value[5] = 0x00;
1243f04d5140SColin Leitner value[6] = 0x00;
1244f04d5140SColin Leitner hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1245f04d5140SColin Leitner }
1246f04d5140SColin Leitner
sony_set_leds(struct sony_sc * sc)1247221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc)
12480a286ef2SSven Eckelmann {
1249221399b3SFrank Praznik if (!(sc->quirks & BUZZ_CONTROLLER))
1250b5322736SRoderick Colenbrander sony_schedule_work(sc, SONY_WORKER_STATE);
1251221399b3SFrank Praznik else
1252221399b3SFrank Praznik buzz_set_leds(sc);
12530a286ef2SSven Eckelmann }
12540a286ef2SSven Eckelmann
sony_led_set_brightness(struct led_classdev * led,enum led_brightness value)1255c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led,
1256f04d5140SColin Leitner enum led_brightness value)
1257f04d5140SColin Leitner {
1258f04d5140SColin Leitner struct device *dev = led->dev->parent;
1259ee79a8f8SGeliang Tang struct hid_device *hdev = to_hid_device(dev);
1260f04d5140SColin Leitner struct sony_sc *drv_data;
1261f04d5140SColin Leitner
1262f04d5140SColin Leitner int n;
1263b3ed458cSFrank Praznik int force_update;
1264f04d5140SColin Leitner
1265f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev);
12662251b85fSSven Eckelmann if (!drv_data) {
1267f04d5140SColin Leitner hid_err(hdev, "No device data\n");
1268f04d5140SColin Leitner return;
1269f04d5140SColin Leitner }
1270f04d5140SColin Leitner
1271b3ed458cSFrank Praznik /*
1272b3ed458cSFrank Praznik * The Sixaxis on USB will override any LED settings sent to it
1273b3ed458cSFrank Praznik * and keep flashing all of the LEDs until the PS button is pressed.
1274b3ed458cSFrank Praznik * Updates, even if redundant, must be always be sent to the
1275b3ed458cSFrank Praznik * controller to avoid having to toggle the state of an LED just to
1276b3ed458cSFrank Praznik * stop the flashing later on.
1277b3ed458cSFrank Praznik */
1278b3ed458cSFrank Praznik force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
1279b3ed458cSFrank Praznik
128060781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) {
1281b3ed458cSFrank Praznik if (led == drv_data->leds[n] && (force_update ||
1282b3ed458cSFrank Praznik (value != drv_data->led_state[n] ||
1283b3ed458cSFrank Praznik drv_data->led_delay_on[n] ||
1284b3ed458cSFrank Praznik drv_data->led_delay_off[n]))) {
1285b3ed458cSFrank Praznik
128660781cf4SFrank Praznik drv_data->led_state[n] = value;
1287b3ed458cSFrank Praznik
1288b3ed458cSFrank Praznik /* Setting the brightness stops the blinking */
1289b3ed458cSFrank Praznik drv_data->led_delay_on[n] = 0;
1290b3ed458cSFrank Praznik drv_data->led_delay_off[n] = 0;
1291b3ed458cSFrank Praznik
1292221399b3SFrank Praznik sony_set_leds(drv_data);
1293f04d5140SColin Leitner break;
1294f04d5140SColin Leitner }
1295f04d5140SColin Leitner }
1296f04d5140SColin Leitner }
1297f04d5140SColin Leitner
sony_led_get_brightness(struct led_classdev * led)1298c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
1299f04d5140SColin Leitner {
1300f04d5140SColin Leitner struct device *dev = led->dev->parent;
1301ee79a8f8SGeliang Tang struct hid_device *hdev = to_hid_device(dev);
1302f04d5140SColin Leitner struct sony_sc *drv_data;
1303f04d5140SColin Leitner
1304f04d5140SColin Leitner int n;
1305f04d5140SColin Leitner
1306f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev);
13072251b85fSSven Eckelmann if (!drv_data) {
1308f04d5140SColin Leitner hid_err(hdev, "No device data\n");
1309f04d5140SColin Leitner return LED_OFF;
1310f04d5140SColin Leitner }
1311f04d5140SColin Leitner
131260781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) {
13137db7504aSSimon Wood if (led == drv_data->leds[n])
13147db7504aSSimon Wood return drv_data->led_state[n];
1315f04d5140SColin Leitner }
1316f04d5140SColin Leitner
13177db7504aSSimon Wood return LED_OFF;
1318f04d5140SColin Leitner }
1319f04d5140SColin Leitner
sony_led_blink_set(struct led_classdev * led,unsigned long * delay_on,unsigned long * delay_off)1320b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1321b3ed458cSFrank Praznik unsigned long *delay_off)
1322b3ed458cSFrank Praznik {
1323b3ed458cSFrank Praznik struct device *dev = led->dev->parent;
1324ee79a8f8SGeliang Tang struct hid_device *hdev = to_hid_device(dev);
1325b3ed458cSFrank Praznik struct sony_sc *drv_data = hid_get_drvdata(hdev);
1326b3ed458cSFrank Praznik int n;
13271adf904eSPavel Machek u8 new_on, new_off;
1328b3ed458cSFrank Praznik
1329b3ed458cSFrank Praznik if (!drv_data) {
1330b3ed458cSFrank Praznik hid_err(hdev, "No device data\n");
1331b3ed458cSFrank Praznik return -EINVAL;
1332b3ed458cSFrank Praznik }
1333b3ed458cSFrank Praznik
1334b3ed458cSFrank Praznik /* Max delay is 255 deciseconds or 2550 milliseconds */
1335b3ed458cSFrank Praznik if (*delay_on > 2550)
1336b3ed458cSFrank Praznik *delay_on = 2550;
1337b3ed458cSFrank Praznik if (*delay_off > 2550)
1338b3ed458cSFrank Praznik *delay_off = 2550;
1339b3ed458cSFrank Praznik
1340b3ed458cSFrank Praznik /* Blink at 1 Hz if both values are zero */
1341b3ed458cSFrank Praznik if (!*delay_on && !*delay_off)
1342b3ed458cSFrank Praznik *delay_on = *delay_off = 500;
1343b3ed458cSFrank Praznik
1344b3ed458cSFrank Praznik new_on = *delay_on / 10;
1345b3ed458cSFrank Praznik new_off = *delay_off / 10;
1346b3ed458cSFrank Praznik
1347b3ed458cSFrank Praznik for (n = 0; n < drv_data->led_count; n++) {
1348b3ed458cSFrank Praznik if (led == drv_data->leds[n])
1349b3ed458cSFrank Praznik break;
1350b3ed458cSFrank Praznik }
1351b3ed458cSFrank Praznik
1352b3ed458cSFrank Praznik /* This LED is not registered on this device */
1353b3ed458cSFrank Praznik if (n >= drv_data->led_count)
1354b3ed458cSFrank Praznik return -EINVAL;
1355b3ed458cSFrank Praznik
1356b3ed458cSFrank Praznik /* Don't schedule work if the values didn't change */
1357b3ed458cSFrank Praznik if (new_on != drv_data->led_delay_on[n] ||
1358b3ed458cSFrank Praznik new_off != drv_data->led_delay_off[n]) {
1359b3ed458cSFrank Praznik drv_data->led_delay_on[n] = new_on;
1360b3ed458cSFrank Praznik drv_data->led_delay_off[n] = new_off;
1361b5322736SRoderick Colenbrander sony_schedule_work(drv_data, SONY_WORKER_STATE);
1362b3ed458cSFrank Praznik }
1363b3ed458cSFrank Praznik
1364b3ed458cSFrank Praznik return 0;
1365b3ed458cSFrank Praznik }
1366b3ed458cSFrank Praznik
sony_leds_init(struct sony_sc * sc)1367fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc)
1368f04d5140SColin Leitner {
1369fa57a810SFrank Praznik struct hid_device *hdev = sc->hdev;
137040e32ee6SJiri Kosina int n, ret = 0;
13714f1f3918SRoderick Colenbrander int use_color_names;
137240e32ee6SJiri Kosina struct led_classdev *led;
137340e32ee6SJiri Kosina size_t name_sz;
137440e32ee6SJiri Kosina char *name;
13750a286ef2SSven Eckelmann size_t name_len;
13760a286ef2SSven Eckelmann const char *name_fmt;
13774f1f3918SRoderick Colenbrander static const char * const color_name_str[] = { "red", "green", "blue",
1378b3ed458cSFrank Praznik "global" };
13791adf904eSPavel Machek u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
13801adf904eSPavel Machek u8 use_hw_blink[MAX_LEDS] = { 0 };
1381f04d5140SColin Leitner
1382fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
1383f04d5140SColin Leitner
1384fa57a810SFrank Praznik if (sc->quirks & BUZZ_CONTROLLER) {
1385fa57a810SFrank Praznik sc->led_count = 4;
13864f1f3918SRoderick Colenbrander use_color_names = 0;
13870a286ef2SSven Eckelmann name_len = strlen("::buzz#");
13880a286ef2SSven Eckelmann name_fmt = "%s::buzz%d";
13899446edb9SKees Cook /* Validate expected report characteristics. */
13909446edb9SKees Cook if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
13919446edb9SKees Cook return -ENODEV;
1392c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) {
1393c5e0c1c4SFrank Praznik sc->led_count = 3;
1394c5e0c1c4SFrank Praznik memset(max_brightness, 255, 3);
13954f1f3918SRoderick Colenbrander use_color_names = 1;
1396c5e0c1c4SFrank Praznik name_len = 0;
1397c5e0c1c4SFrank Praznik name_fmt = "%s:%s";
13984545ee0aSSimon Wood } else if (sc->quirks & NAVIGATION_CONTROLLER) {
13991adf904eSPavel Machek static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00};
14004545ee0aSSimon Wood
14014545ee0aSSimon Wood memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds));
14024545ee0aSSimon Wood sc->led_count = 1;
14034545ee0aSSimon Wood memset(use_hw_blink, 1, 4);
14044f1f3918SRoderick Colenbrander use_color_names = 0;
14054545ee0aSSimon Wood name_len = strlen("::sony#");
14064545ee0aSSimon Wood name_fmt = "%s::sony%d";
140760781cf4SFrank Praznik } else {
1408221399b3SFrank Praznik sixaxis_set_leds_from_id(sc);
1409fa57a810SFrank Praznik sc->led_count = 4;
1410b3ed458cSFrank Praznik memset(use_hw_blink, 1, 4);
14114f1f3918SRoderick Colenbrander use_color_names = 0;
141261ebca93SFrank Praznik name_len = strlen("::sony#");
141361ebca93SFrank Praznik name_fmt = "%s::sony%d";
141460781cf4SFrank Praznik }
141560781cf4SFrank Praznik
1416ad142b9eSFrank Praznik /*
1417ad142b9eSFrank Praznik * Clear LEDs as we have no way of reading their initial state. This is
1418f04d5140SColin Leitner * only relevant if the driver is loaded after somebody actively set the
1419ad142b9eSFrank Praznik * LEDs to on
1420ad142b9eSFrank Praznik */
1421221399b3SFrank Praznik sony_set_leds(sc);
1422f04d5140SColin Leitner
14230a286ef2SSven Eckelmann name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
1424f04d5140SColin Leitner
1425fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) {
142661ebca93SFrank Praznik
14274f1f3918SRoderick Colenbrander if (use_color_names)
14284f1f3918SRoderick Colenbrander name_sz = strlen(dev_name(&hdev->dev)) + strlen(color_name_str[n]) + 2;
142961ebca93SFrank Praznik
1430f2d98e2cSHanno Zulla led = devm_kzalloc(&hdev->dev, sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
1431f04d5140SColin Leitner if (!led) {
1432f04d5140SColin Leitner hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
1433f2d98e2cSHanno Zulla return -ENOMEM;
1434f04d5140SColin Leitner }
1435f04d5140SColin Leitner
1436f04d5140SColin Leitner name = (void *)(&led[1]);
14374f1f3918SRoderick Colenbrander if (use_color_names)
1438b3ed458cSFrank Praznik snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev),
14394f1f3918SRoderick Colenbrander color_name_str[n]);
144061ebca93SFrank Praznik else
14410a286ef2SSven Eckelmann snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
1442f04d5140SColin Leitner led->name = name;
1443221399b3SFrank Praznik led->brightness = sc->led_state[n];
1444b3ed458cSFrank Praznik led->max_brightness = max_brightness[n];
1445765a1077SFrank Praznik led->flags = LED_CORE_SUSPENDRESUME;
1446c5382519SSven Eckelmann led->brightness_get = sony_led_get_brightness;
1447c5382519SSven Eckelmann led->brightness_set = sony_led_set_brightness;
1448f04d5140SColin Leitner
1449b3ed458cSFrank Praznik if (use_hw_blink[n])
1450b3ed458cSFrank Praznik led->blink_set = sony_led_blink_set;
1451b3ed458cSFrank Praznik
14528025087aSFrank Praznik sc->leds[n] = led;
14538025087aSFrank Praznik
1454f2d98e2cSHanno Zulla ret = devm_led_classdev_register(&hdev->dev, led);
14558cd5fcdaSJulia Lawall if (ret) {
1456f04d5140SColin Leitner hid_err(hdev, "Failed to register LED %d\n", n);
1457f2d98e2cSHanno Zulla return ret;
1458f04d5140SColin Leitner }
1459f04d5140SColin Leitner }
1460f04d5140SColin Leitner
1461f2d98e2cSHanno Zulla return 0;
1462f04d5140SColin Leitner }
1463f04d5140SColin Leitner
sixaxis_send_output_report(struct sony_sc * sc)1464d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc)
1465a08c22c0SSven Eckelmann {
14669b2b5c9aSFrank Praznik static const union sixaxis_output_report_01 default_report = {
146755d3b664SFrank Praznik .buf = {
1468a08c22c0SSven Eckelmann 0x01,
1469ad07b7a6SScott Moreau 0x01, 0xff, 0x00, 0xff, 0x00,
14700a286ef2SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00,
1471a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32,
1472a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32,
1473a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32,
1474a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32,
1475a08c22c0SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00
147655d3b664SFrank Praznik }
1477a08c22c0SSven Eckelmann };
14789b2b5c9aSFrank Praznik struct sixaxis_output_report *report =
14799b2b5c9aSFrank Praznik (struct sixaxis_output_report *)sc->output_report_dmabuf;
14809b2b5c9aSFrank Praznik int n;
14819b2b5c9aSFrank Praznik
14829b2b5c9aSFrank Praznik /* Initialize the report with default values */
14839b2b5c9aSFrank Praznik memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
14849f323b68SSven Eckelmann
14850a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
14869b2b5c9aSFrank Praznik report->rumble.right_motor_on = sc->right ? 1 : 0;
14879b2b5c9aSFrank Praznik report->rumble.left_motor_force = sc->left;
14880a286ef2SSven Eckelmann #endif
14890a286ef2SSven Eckelmann
14909b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[0] << 1;
14919b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[1] << 2;
14929b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[2] << 3;
14939b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[3] << 4;
14949f323b68SSven Eckelmann
149588f6576fSSimon Wood /* Set flag for all leds off, required for 3rd party INTEC controller */
14969b2b5c9aSFrank Praznik if ((report->leds_bitmap & 0x1E) == 0)
14979b2b5c9aSFrank Praznik report->leds_bitmap |= 0x20;
149888f6576fSSimon Wood
1499b3ed458cSFrank Praznik /*
1500b3ed458cSFrank Praznik * The LEDs in the report are indexed in reverse order to their
1501b3ed458cSFrank Praznik * corresponding light on the controller.
1502b3ed458cSFrank Praznik * Index 0 = LED 4, index 1 = LED 3, etc...
1503b3ed458cSFrank Praznik *
1504b3ed458cSFrank Praznik * In the case of both delay values being zero (blinking disabled) the
1505b3ed458cSFrank Praznik * default report values should be used or the controller LED will be
1506b3ed458cSFrank Praznik * always off.
1507b3ed458cSFrank Praznik */
1508b3ed458cSFrank Praznik for (n = 0; n < 4; n++) {
1509b3ed458cSFrank Praznik if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
15109b2b5c9aSFrank Praznik report->led[3 - n].duty_off = sc->led_delay_off[n];
15119b2b5c9aSFrank Praznik report->led[3 - n].duty_on = sc->led_delay_on[n];
1512b3ed458cSFrank Praznik }
1513b3ed458cSFrank Praznik }
1514b3ed458cSFrank Praznik
1515d03213f1SHongye Yuan /* SHANWAN controllers require output reports via intr channel */
1516d03213f1SHongye Yuan if (sc->quirks & SHANWAN_GAMEPAD)
1517d03213f1SHongye Yuan hid_hw_output_report(sc->hdev, (u8 *)report,
1518d03213f1SHongye Yuan sizeof(struct sixaxis_output_report));
1519d03213f1SHongye Yuan else
15201adf904eSPavel Machek hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
15219b2b5c9aSFrank Praznik sizeof(struct sixaxis_output_report),
15229b2b5c9aSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
15239f323b68SSven Eckelmann }
15249f323b68SSven Eckelmann
motion_send_output_report(struct sony_sc * sc)1525d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc)
1526c5e0c1c4SFrank Praznik {
1527c5e0c1c4SFrank Praznik struct hid_device *hdev = sc->hdev;
1528c5e0c1c4SFrank Praznik struct motion_output_report_02 *report =
1529c5e0c1c4SFrank Praznik (struct motion_output_report_02 *)sc->output_report_dmabuf;
1530c5e0c1c4SFrank Praznik
153141d2d425SSimon Wood memset(report, 0, MOTION_REPORT_0x02_SIZE);
1532c5e0c1c4SFrank Praznik
1533c5e0c1c4SFrank Praznik report->type = 0x02; /* set leds */
1534c5e0c1c4SFrank Praznik report->r = sc->led_state[0];
1535c5e0c1c4SFrank Praznik report->g = sc->led_state[1];
1536c5e0c1c4SFrank Praznik report->b = sc->led_state[2];
1537c5e0c1c4SFrank Praznik
1538c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF
1539c5e0c1c4SFrank Praznik report->rumble = max(sc->right, sc->left);
1540c5e0c1c4SFrank Praznik #endif
1541c5e0c1c4SFrank Praznik
15421adf904eSPavel Machek hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE);
1543c5e0c1c4SFrank Praznik }
1544c5e0c1c4SFrank Praznik
154554f27dc5SJosé Expósito #ifdef CONFIG_SONY_FF
sony_send_output_report(struct sony_sc * sc)1546decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc)
1547decd946cSFrank Praznik {
1548decd946cSFrank Praznik if (sc->send_output_report)
1549decd946cSFrank Praznik sc->send_output_report(sc);
1550decd946cSFrank Praznik }
155154f27dc5SJosé Expósito #endif
1552decd946cSFrank Praznik
sony_state_worker(struct work_struct * work)1553d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work)
1554d8aaccdaSFrank Praznik {
1555d8aaccdaSFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
1556ef916ef5SAntonio Ospite
1557d8aaccdaSFrank Praznik sc->send_output_report(sc);
1558d8aaccdaSFrank Praznik }
1559d8aaccdaSFrank Praznik
sony_allocate_output_report(struct sony_sc * sc)15609b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc)
15619b2b5c9aSFrank Praznik {
15624545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER) ||
15634545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER))
15649b2b5c9aSFrank Praznik sc->output_report_dmabuf =
1565ea58c33dSHanno Zulla devm_kmalloc(&sc->hdev->dev,
1566ea58c33dSHanno Zulla sizeof(union sixaxis_output_report_01),
15679b2b5c9aSFrank Praznik GFP_KERNEL);
1568c5e0c1c4SFrank Praznik else if (sc->quirks & MOTION_CONTROLLER)
1569ea58c33dSHanno Zulla sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
1570ea58c33dSHanno Zulla MOTION_REPORT_0x02_SIZE,
1571c5e0c1c4SFrank Praznik GFP_KERNEL);
15729b2b5c9aSFrank Praznik else
15739b2b5c9aSFrank Praznik return 0;
15749b2b5c9aSFrank Praznik
15759b2b5c9aSFrank Praznik if (!sc->output_report_dmabuf)
15769b2b5c9aSFrank Praznik return -ENOMEM;
15779b2b5c9aSFrank Praznik
15789b2b5c9aSFrank Praznik return 0;
15799b2b5c9aSFrank Praznik }
15809b2b5c9aSFrank Praznik
15810a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF
sony_play_effect(struct input_dev * dev,void * data,struct ff_effect * effect)15829f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data,
15839f323b68SSven Eckelmann struct ff_effect *effect)
15849f323b68SSven Eckelmann {
1585a08c22c0SSven Eckelmann struct hid_device *hid = input_get_drvdata(dev);
15869f323b68SSven Eckelmann struct sony_sc *sc = hid_get_drvdata(hid);
1587a08c22c0SSven Eckelmann
1588a08c22c0SSven Eckelmann if (effect->type != FF_RUMBLE)
1589a08c22c0SSven Eckelmann return 0;
1590a08c22c0SSven Eckelmann
15919f323b68SSven Eckelmann sc->left = effect->u.rumble.strong_magnitude / 256;
15920bd88dd3SFrank Praznik sc->right = effect->u.rumble.weak_magnitude / 256;
1593a08c22c0SSven Eckelmann
1594b5322736SRoderick Colenbrander sony_schedule_work(sc, SONY_WORKER_STATE);
15959f323b68SSven Eckelmann return 0;
1596a08c22c0SSven Eckelmann }
1597a08c22c0SSven Eckelmann
sony_init_ff(struct sony_sc * sc)1598fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1599a08c22c0SSven Eckelmann {
1600d9d4b1e4SAlan Stern struct hid_input *hidinput;
1601d9d4b1e4SAlan Stern struct input_dev *input_dev;
1602d9d4b1e4SAlan Stern
1603d9d4b1e4SAlan Stern if (list_empty(&sc->hdev->inputs)) {
1604d9d4b1e4SAlan Stern hid_err(sc->hdev, "no inputs found\n");
1605d9d4b1e4SAlan Stern return -ENODEV;
1606d9d4b1e4SAlan Stern }
1607d9d4b1e4SAlan Stern hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list);
1608d9d4b1e4SAlan Stern input_dev = hidinput->input;
1609a08c22c0SSven Eckelmann
1610a08c22c0SSven Eckelmann input_set_capability(input_dev, EV_FF, FF_RUMBLE);
1611a08c22c0SSven Eckelmann return input_ff_create_memless(input_dev, NULL, sony_play_effect);
1612a08c22c0SSven Eckelmann }
1613a08c22c0SSven Eckelmann
1614a08c22c0SSven Eckelmann #else
sony_init_ff(struct sony_sc * sc)1615fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc)
1616a08c22c0SSven Eckelmann {
1617a08c22c0SSven Eckelmann return 0;
1618a08c22c0SSven Eckelmann }
16199f323b68SSven Eckelmann
1620a08c22c0SSven Eckelmann #endif
1621a08c22c0SSven Eckelmann
sony_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)1622d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy,
1623d902f472SFrank Praznik enum power_supply_property psp,
1624d902f472SFrank Praznik union power_supply_propval *val)
1625c4e1ddf2SFrank Praznik {
1626297d716fSKrzysztof Kozlowski struct sony_sc *sc = power_supply_get_drvdata(psy);
1627d902f472SFrank Praznik unsigned long flags;
1628d902f472SFrank Praznik int ret = 0;
1629a76a6c18SRoderick Colenbrander u8 battery_capacity;
1630a76a6c18SRoderick Colenbrander int battery_status;
1631c4e1ddf2SFrank Praznik
1632d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags);
1633d902f472SFrank Praznik battery_capacity = sc->battery_capacity;
1634a76a6c18SRoderick Colenbrander battery_status = sc->battery_status;
1635d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags);
1636c4e1ddf2SFrank Praznik
1637d902f472SFrank Praznik switch (psp) {
1638d902f472SFrank Praznik case POWER_SUPPLY_PROP_PRESENT:
1639d902f472SFrank Praznik val->intval = 1;
1640d902f472SFrank Praznik break;
1641d902f472SFrank Praznik case POWER_SUPPLY_PROP_SCOPE:
1642d902f472SFrank Praznik val->intval = POWER_SUPPLY_SCOPE_DEVICE;
1643d902f472SFrank Praznik break;
1644d902f472SFrank Praznik case POWER_SUPPLY_PROP_CAPACITY:
1645d902f472SFrank Praznik val->intval = battery_capacity;
1646d902f472SFrank Praznik break;
1647d902f472SFrank Praznik case POWER_SUPPLY_PROP_STATUS:
1648a76a6c18SRoderick Colenbrander val->intval = battery_status;
1649d902f472SFrank Praznik break;
1650d902f472SFrank Praznik default:
1651d902f472SFrank Praznik ret = -EINVAL;
1652d902f472SFrank Praznik break;
1653c4e1ddf2SFrank Praznik }
1654d902f472SFrank Praznik return ret;
1655d902f472SFrank Praznik }
1656d902f472SFrank Praznik
sony_battery_probe(struct sony_sc * sc,int append_dev_id)16570f398230SFrank Praznik static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
1658d902f472SFrank Praznik {
16590f398230SFrank Praznik const char *battery_str_fmt = append_dev_id ?
16600f398230SFrank Praznik "sony_controller_battery_%pMR_%i" :
16610f398230SFrank Praznik "sony_controller_battery_%pMR";
1662297d716fSKrzysztof Kozlowski struct power_supply_config psy_cfg = { .drv_data = sc, };
1663d902f472SFrank Praznik struct hid_device *hdev = sc->hdev;
1664d902f472SFrank Praznik int ret;
1665d902f472SFrank Praznik
1666ad142b9eSFrank Praznik /*
1667ad142b9eSFrank Praznik * Set the default battery level to 100% to avoid low battery warnings
1668d9a293a9SFrank Praznik * if the battery is polled before the first device report is received.
1669d9a293a9SFrank Praznik */
1670d9a293a9SFrank Praznik sc->battery_capacity = 100;
1671d9a293a9SFrank Praznik
1672297d716fSKrzysztof Kozlowski sc->battery_desc.properties = sony_battery_props;
1673297d716fSKrzysztof Kozlowski sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
1674297d716fSKrzysztof Kozlowski sc->battery_desc.get_property = sony_battery_get_property;
1675297d716fSKrzysztof Kozlowski sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
1676297d716fSKrzysztof Kozlowski sc->battery_desc.use_for_apm = 0;
16778082d3f0SHanno Zulla sc->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
16788082d3f0SHanno Zulla battery_str_fmt, sc->mac_address, sc->device_id);
1679297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name)
1680d902f472SFrank Praznik return -ENOMEM;
1681d902f472SFrank Praznik
16828082d3f0SHanno Zulla sc->battery = devm_power_supply_register(&hdev->dev, &sc->battery_desc,
1683297d716fSKrzysztof Kozlowski &psy_cfg);
1684297d716fSKrzysztof Kozlowski if (IS_ERR(sc->battery)) {
1685297d716fSKrzysztof Kozlowski ret = PTR_ERR(sc->battery);
1686d902f472SFrank Praznik hid_err(hdev, "Unable to register battery device\n");
16878082d3f0SHanno Zulla return ret;
1688d902f472SFrank Praznik }
1689d902f472SFrank Praznik
1690297d716fSKrzysztof Kozlowski power_supply_powers(sc->battery, &hdev->dev);
1691d902f472SFrank Praznik return 0;
1692d902f472SFrank Praznik }
1693d902f472SFrank Praznik
1694d2d782fcSFrank Praznik /*
1695d2d782fcSFrank Praznik * If a controller is plugged in via USB while already connected via Bluetooth
1696d2d782fcSFrank Praznik * it will show up as two devices. A global list of connected controllers and
1697d2d782fcSFrank Praznik * their MAC addresses is maintained to ensure that a device is only connected
1698d2d782fcSFrank Praznik * once.
16990f398230SFrank Praznik *
17000f398230SFrank Praznik * Some USB-only devices masquerade as Sixaxis controllers and all have the
17010f398230SFrank Praznik * same dummy Bluetooth address, so a comparison of the connection type is
17020f398230SFrank Praznik * required. Devices are only rejected in the case where two devices have
17030f398230SFrank Praznik * matching Bluetooth addresses on different bus types.
1704d2d782fcSFrank Praznik */
sony_compare_connection_type(struct sony_sc * sc0,struct sony_sc * sc1)17050f398230SFrank Praznik static inline int sony_compare_connection_type(struct sony_sc *sc0,
17060f398230SFrank Praznik struct sony_sc *sc1)
17070f398230SFrank Praznik {
17080f398230SFrank Praznik const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE);
17090f398230SFrank Praznik const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
17100f398230SFrank Praznik
17110f398230SFrank Praznik return sc0_not_bt == sc1_not_bt;
17120f398230SFrank Praznik }
17130f398230SFrank Praznik
sony_check_add_dev_list(struct sony_sc * sc)1714d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc)
1715d2d782fcSFrank Praznik {
1716d2d782fcSFrank Praznik struct sony_sc *entry;
1717d2d782fcSFrank Praznik unsigned long flags;
1718d2d782fcSFrank Praznik int ret;
1719d2d782fcSFrank Praznik
1720d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags);
1721d2d782fcSFrank Praznik
1722d2d782fcSFrank Praznik list_for_each_entry(entry, &sony_device_list, list_node) {
1723d2d782fcSFrank Praznik ret = memcmp(sc->mac_address, entry->mac_address,
1724d2d782fcSFrank Praznik sizeof(sc->mac_address));
1725d2d782fcSFrank Praznik if (!ret) {
17260f398230SFrank Praznik if (sony_compare_connection_type(sc, entry)) {
17270f398230SFrank Praznik ret = 1;
17280f398230SFrank Praznik } else {
1729d2d782fcSFrank Praznik ret = -EEXIST;
17300f398230SFrank Praznik hid_info(sc->hdev,
17310f398230SFrank Praznik "controller with MAC address %pMR already connected\n",
1732d2d782fcSFrank Praznik sc->mac_address);
17330f398230SFrank Praznik }
1734d2d782fcSFrank Praznik goto unlock;
1735d2d782fcSFrank Praznik }
1736c4e1ddf2SFrank Praznik }
1737c4e1ddf2SFrank Praznik
1738d2d782fcSFrank Praznik ret = 0;
1739d2d782fcSFrank Praznik list_add(&(sc->list_node), &sony_device_list);
1740c4e1ddf2SFrank Praznik
1741d2d782fcSFrank Praznik unlock:
1742d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags);
1743d2d782fcSFrank Praznik return ret;
1744d2d782fcSFrank Praznik }
1745d2d782fcSFrank Praznik
sony_remove_dev_list(struct sony_sc * sc)1746d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc)
1747d2d782fcSFrank Praznik {
1748d2d782fcSFrank Praznik unsigned long flags;
1749d2d782fcSFrank Praznik
1750d2d782fcSFrank Praznik if (sc->list_node.next) {
1751d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags);
1752d2d782fcSFrank Praznik list_del(&(sc->list_node));
1753d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags);
1754d2d782fcSFrank Praznik }
1755d2d782fcSFrank Praznik }
1756d2d782fcSFrank Praznik
sony_get_bt_devaddr(struct sony_sc * sc)1757d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc)
1758d2d782fcSFrank Praznik {
1759d2d782fcSFrank Praznik int ret;
1760d2d782fcSFrank Praznik
1761d2d782fcSFrank Praznik /* HIDP stores the device MAC address as a string in the uniq field. */
1762d2d782fcSFrank Praznik ret = strlen(sc->hdev->uniq);
1763d2d782fcSFrank Praznik if (ret != 17)
1764c4e1ddf2SFrank Praznik return -EINVAL;
1765d2d782fcSFrank Praznik
1766d2d782fcSFrank Praznik ret = sscanf(sc->hdev->uniq,
1767d2d782fcSFrank Praznik "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1768d2d782fcSFrank Praznik &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
1769d2d782fcSFrank Praznik &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
1770d2d782fcSFrank Praznik
1771d2d782fcSFrank Praznik if (ret != 6)
1772d2d782fcSFrank Praznik return -EINVAL;
1773d2d782fcSFrank Praznik
1774d2d782fcSFrank Praznik return 0;
1775c4e1ddf2SFrank Praznik }
1776c4e1ddf2SFrank Praznik
sony_check_add(struct sony_sc * sc)1777d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc)
1778d2d782fcSFrank Praznik {
17791adf904eSPavel Machek u8 *buf = NULL;
1780d2d782fcSFrank Praznik int n, ret;
1781d2d782fcSFrank Praznik
17824f1f3918SRoderick Colenbrander if ((sc->quirks & MOTION_CONTROLLER_BT) ||
17834545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT) ||
1784d2d782fcSFrank Praznik (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
1785d2d782fcSFrank Praznik /*
1786d2d782fcSFrank Praznik * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
1787d2d782fcSFrank Praznik * address from the uniq string where HIDP stores it.
1788d2d782fcSFrank Praznik * As uniq cannot be guaranteed to be a MAC address in all cases
1789d2d782fcSFrank Praznik * a failure of this function should not prevent the connection.
1790d2d782fcSFrank Praznik */
1791d2d782fcSFrank Praznik if (sony_get_bt_devaddr(sc) < 0) {
1792d2d782fcSFrank Praznik hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
1793d2d782fcSFrank Praznik return 0;
1794d2d782fcSFrank Praznik }
17954545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
17964545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) {
17979b2b5c9aSFrank Praznik buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
17989b2b5c9aSFrank Praznik if (!buf)
17999b2b5c9aSFrank Praznik return -ENOMEM;
1800d2d782fcSFrank Praznik
1801d2d782fcSFrank Praznik /*
1802d2d782fcSFrank Praznik * The MAC address of a Sixaxis controller connected via USB can
1803d2d782fcSFrank Praznik * be retrieved with feature report 0xf2. The address begins at
1804d2d782fcSFrank Praznik * offset 4.
1805d2d782fcSFrank Praznik */
18069b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
18079b2b5c9aSFrank Praznik SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
18089b2b5c9aSFrank Praznik HID_REQ_GET_REPORT);
1809d2d782fcSFrank Praznik
18109b2b5c9aSFrank Praznik if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
1811d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
18129b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL;
18139b2b5c9aSFrank Praznik goto out_free;
1814d2d782fcSFrank Praznik }
1815d2d782fcSFrank Praznik
1816d2d782fcSFrank Praznik /*
1817d2d782fcSFrank Praznik * The Sixaxis device MAC in the report is big-endian and must
1818d2d782fcSFrank Praznik * be byte-swapped.
1819d2d782fcSFrank Praznik */
1820d2d782fcSFrank Praznik for (n = 0; n < 6; n++)
1821d2d782fcSFrank Praznik sc->mac_address[5-n] = buf[4+n];
18225a144be3SRoderick Colenbrander
18235a144be3SRoderick Colenbrander snprintf(sc->hdev->uniq, sizeof(sc->hdev->uniq),
1824648d4932SAndy Shevchenko "%pMR", sc->mac_address);
1825d2d782fcSFrank Praznik } else {
1826d2d782fcSFrank Praznik return 0;
1827d2d782fcSFrank Praznik }
1828d2d782fcSFrank Praznik
18299b2b5c9aSFrank Praznik ret = sony_check_add_dev_list(sc);
18309b2b5c9aSFrank Praznik
18319b2b5c9aSFrank Praznik out_free:
18329b2b5c9aSFrank Praznik
18339b2b5c9aSFrank Praznik kfree(buf);
18349b2b5c9aSFrank Praznik
18359b2b5c9aSFrank Praznik return ret;
1836d2d782fcSFrank Praznik }
1837d2d782fcSFrank Praznik
sony_set_device_id(struct sony_sc * sc)18388025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc)
18398025087aSFrank Praznik {
18408025087aSFrank Praznik int ret;
18418025087aSFrank Praznik
18428025087aSFrank Praznik /*
18434f1f3918SRoderick Colenbrander * Only Sixaxis controllers get an id.
18448025087aSFrank Praznik * All others are set to -1.
18458025087aSFrank Praznik */
18464f1f3918SRoderick Colenbrander if (sc->quirks & SIXAXIS_CONTROLLER) {
184745bf5eddSChristophe JAILLET ret = ida_alloc(&sony_device_id_allocator, GFP_KERNEL);
18488025087aSFrank Praznik if (ret < 0) {
18498025087aSFrank Praznik sc->device_id = -1;
18508025087aSFrank Praznik return ret;
18518025087aSFrank Praznik }
18528025087aSFrank Praznik sc->device_id = ret;
18538025087aSFrank Praznik } else {
18548025087aSFrank Praznik sc->device_id = -1;
18558025087aSFrank Praznik }
18568025087aSFrank Praznik
18578025087aSFrank Praznik return 0;
18588025087aSFrank Praznik }
18598025087aSFrank Praznik
sony_release_device_id(struct sony_sc * sc)18608025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc)
18618025087aSFrank Praznik {
18628025087aSFrank Praznik if (sc->device_id >= 0) {
186345bf5eddSChristophe JAILLET ida_free(&sony_device_id_allocator, sc->device_id);
18648025087aSFrank Praznik sc->device_id = -1;
18658025087aSFrank Praznik }
18668025087aSFrank Praznik }
18678025087aSFrank Praznik
sony_init_output_report(struct sony_sc * sc,void (* send_output_report)(struct sony_sc *))1868d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc,
1869d8aaccdaSFrank Praznik void (*send_output_report)(struct sony_sc *))
187046262047SFrank Praznik {
1871d8aaccdaSFrank Praznik sc->send_output_report = send_output_report;
1872d8aaccdaSFrank Praznik
1873b5322736SRoderick Colenbrander if (!sc->state_worker_initialized)
1874d8aaccdaSFrank Praznik INIT_WORK(&sc->state_worker, sony_state_worker);
187546262047SFrank Praznik
1876b5322736SRoderick Colenbrander sc->state_worker_initialized = 1;
187746262047SFrank Praznik }
187846262047SFrank Praznik
sony_cancel_work_sync(struct sony_sc * sc)187946262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc)
188046262047SFrank Praznik {
1881e0f6974aSRoderick Colenbrander unsigned long flags;
1882e0f6974aSRoderick Colenbrander
1883e0f6974aSRoderick Colenbrander if (sc->state_worker_initialized) {
1884e0f6974aSRoderick Colenbrander spin_lock_irqsave(&sc->lock, flags);
1885e0f6974aSRoderick Colenbrander sc->state_worker_initialized = 0;
1886e0f6974aSRoderick Colenbrander spin_unlock_irqrestore(&sc->lock, flags);
188746262047SFrank Praznik cancel_work_sync(&sc->state_worker);
188846262047SFrank Praznik }
1889e0f6974aSRoderick Colenbrander }
189077b499e7SRoderick Colenbrander
sony_input_configured(struct hid_device * hdev,struct hid_input * hidinput)1891e1bc84d0SRoderick Colenbrander static int sony_input_configured(struct hid_device *hdev,
1892e1bc84d0SRoderick Colenbrander struct hid_input *hidinput)
1893bd28ce00SJiri Slaby {
1894e1bc84d0SRoderick Colenbrander struct sony_sc *sc = hid_get_drvdata(hdev);
18950f398230SFrank Praznik int append_dev_id;
1896e1bc84d0SRoderick Colenbrander int ret;
1897bd28ce00SJiri Slaby
18988025087aSFrank Praznik ret = sony_set_device_id(sc);
18998025087aSFrank Praznik if (ret < 0) {
19008025087aSFrank Praznik hid_err(hdev, "failed to allocate the device id\n");
19018025087aSFrank Praznik goto err_stop;
19028025087aSFrank Praznik }
19038025087aSFrank Praznik
1904df848bc0SRoderick Colenbrander ret = append_dev_id = sony_check_add(sc);
1905df848bc0SRoderick Colenbrander if (ret < 0)
1906df848bc0SRoderick Colenbrander goto err_stop;
1907df848bc0SRoderick Colenbrander
1908131a8a9aSFrank Praznik ret = sony_allocate_output_report(sc);
1909131a8a9aSFrank Praznik if (ret < 0) {
1910131a8a9aSFrank Praznik hid_err(hdev, "failed to allocate the output report buffer\n");
1911131a8a9aSFrank Praznik goto err_stop;
1912131a8a9aSFrank Praznik }
1913131a8a9aSFrank Praznik
1914510c8b7cSRoderick Colenbrander if (sc->quirks & NAVIGATION_CONTROLLER_USB) {
1915e534a935SBenjamin Tissoires /*
1916e534a935SBenjamin Tissoires * The Sony Sixaxis does not handle HID Output Reports on the
1917e534a935SBenjamin Tissoires * Interrupt EP like it could, so we need to force HID Output
1918e534a935SBenjamin Tissoires * Reports to use HID_REQ_SET_REPORT on the Control EP.
1919e534a935SBenjamin Tissoires *
1920e534a935SBenjamin Tissoires * There is also another issue about HID Output Reports via USB,
1921e534a935SBenjamin Tissoires * the Sixaxis does not want the report_id as part of the data
1922e534a935SBenjamin Tissoires * packet, so we have to discard buf[0] when sending the actual
1923e534a935SBenjamin Tissoires * control message, even for numbered reports, humpf!
19242a242932SFrank Praznik *
19252a242932SFrank Praznik * Additionally, the Sixaxis on USB isn't properly initialized
19262a242932SFrank Praznik * until the PS logo button is pressed and as such won't retain
19272a242932SFrank Praznik * any state set by an output report, so the initial
19282a242932SFrank Praznik * configuration report is deferred until the first input
19292a242932SFrank Praznik * report arrives.
1930e534a935SBenjamin Tissoires */
1931e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
1932e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
19332a242932SFrank Praznik sc->defer_initialization = 1;
193480ecc48cSRoderick Colenbrander
1935816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev);
193680ecc48cSRoderick Colenbrander if (ret < 0) {
193780ecc48cSRoderick Colenbrander hid_err(hdev, "Failed to set controller into operational mode\n");
193880ecc48cSRoderick Colenbrander goto err_stop;
193980ecc48cSRoderick Colenbrander }
194080ecc48cSRoderick Colenbrander
1941d8aaccdaSFrank Praznik sony_init_output_report(sc, sixaxis_send_output_report);
1942510c8b7cSRoderick Colenbrander } else if (sc->quirks & NAVIGATION_CONTROLLER_BT) {
1943510c8b7cSRoderick Colenbrander /*
1944510c8b7cSRoderick Colenbrander * The Navigation controller wants output reports sent on the ctrl
1945510c8b7cSRoderick Colenbrander * endpoint when connected via Bluetooth.
1946510c8b7cSRoderick Colenbrander */
1947510c8b7cSRoderick Colenbrander hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
1948510c8b7cSRoderick Colenbrander
1949510c8b7cSRoderick Colenbrander ret = sixaxis_set_operational_bt(hdev);
1950510c8b7cSRoderick Colenbrander if (ret < 0) {
1951510c8b7cSRoderick Colenbrander hid_err(hdev, "Failed to set controller into operational mode\n");
1952510c8b7cSRoderick Colenbrander goto err_stop;
1953510c8b7cSRoderick Colenbrander }
1954510c8b7cSRoderick Colenbrander
1955510c8b7cSRoderick Colenbrander sony_init_output_report(sc, sixaxis_send_output_report);
1956510c8b7cSRoderick Colenbrander } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
1957510c8b7cSRoderick Colenbrander /*
1958510c8b7cSRoderick Colenbrander * The Sony Sixaxis does not handle HID Output Reports on the
1959510c8b7cSRoderick Colenbrander * Interrupt EP and the device only becomes active when the
1960510c8b7cSRoderick Colenbrander * PS button is pressed. See comment for Navigation controller
1961510c8b7cSRoderick Colenbrander * above for more details.
1962510c8b7cSRoderick Colenbrander */
1963510c8b7cSRoderick Colenbrander hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
1964510c8b7cSRoderick Colenbrander hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
1965510c8b7cSRoderick Colenbrander sc->defer_initialization = 1;
1966510c8b7cSRoderick Colenbrander
1967510c8b7cSRoderick Colenbrander ret = sixaxis_set_operational_usb(hdev);
1968510c8b7cSRoderick Colenbrander if (ret < 0) {
1969510c8b7cSRoderick Colenbrander hid_err(hdev, "Failed to set controller into operational mode\n");
1970510c8b7cSRoderick Colenbrander goto err_stop;
1971510c8b7cSRoderick Colenbrander }
1972510c8b7cSRoderick Colenbrander
1973510c8b7cSRoderick Colenbrander ret = sony_register_sensors(sc);
1974510c8b7cSRoderick Colenbrander if (ret) {
1975510c8b7cSRoderick Colenbrander hid_err(sc->hdev,
1976510c8b7cSRoderick Colenbrander "Unable to initialize motion sensors: %d\n", ret);
1977510c8b7cSRoderick Colenbrander goto err_stop;
1978510c8b7cSRoderick Colenbrander }
1979510c8b7cSRoderick Colenbrander
1980510c8b7cSRoderick Colenbrander sony_init_output_report(sc, sixaxis_send_output_report);
1981510c8b7cSRoderick Colenbrander } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
19822078b9bbSFrank Praznik /*
19832078b9bbSFrank Praznik * The Sixaxis wants output reports sent on the ctrl endpoint
19842078b9bbSFrank Praznik * when connected via Bluetooth.
19852078b9bbSFrank Praznik */
19862078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
198780ecc48cSRoderick Colenbrander
1988816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev);
198968330d83SFrank Praznik if (ret < 0) {
199080ecc48cSRoderick Colenbrander hid_err(hdev, "Failed to set controller into operational mode\n");
199168330d83SFrank Praznik goto err_stop;
199268330d83SFrank Praznik }
199380ecc48cSRoderick Colenbrander
1994510c8b7cSRoderick Colenbrander ret = sony_register_sensors(sc);
1995510c8b7cSRoderick Colenbrander if (ret) {
1996510c8b7cSRoderick Colenbrander hid_err(sc->hdev,
1997510c8b7cSRoderick Colenbrander "Unable to initialize motion sensors: %d\n", ret);
1998510c8b7cSRoderick Colenbrander goto err_stop;
1999510c8b7cSRoderick Colenbrander }
2000510c8b7cSRoderick Colenbrander
2001e5606230SFrank Praznik sony_init_output_report(sc, sixaxis_send_output_report);
2002b7289cb1STodd Kelner } else if (sc->quirks & NSG_MRXU_REMOTE) {
2003b7289cb1STodd Kelner /*
2004b7289cb1STodd Kelner * The NSG-MRxU touchpad supports 2 touches and has a
2005b7289cb1STodd Kelner * resolution of 1667x1868
2006b7289cb1STodd Kelner */
2007b7289cb1STodd Kelner ret = sony_register_touchpad(sc, 2,
2008b7289cb1STodd Kelner NSG_MRXU_MAX_X, NSG_MRXU_MAX_Y, 15, 15, 1);
2009b7289cb1STodd Kelner if (ret) {
2010b7289cb1STodd Kelner hid_err(sc->hdev,
2011b7289cb1STodd Kelner "Unable to initialize multi-touch slots: %d\n",
2012b7289cb1STodd Kelner ret);
2013b7289cb1STodd Kelner goto err_stop;
2014b7289cb1STodd Kelner }
2015b7289cb1STodd Kelner
2016c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) {
2017d8aaccdaSFrank Praznik sony_init_output_report(sc, motion_send_output_report);
20180bd88dd3SFrank Praznik }
2019f9ce7c28SBastien Nocera
20200a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) {
2021fa57a810SFrank Praznik ret = sony_leds_init(sc);
20220a286ef2SSven Eckelmann if (ret < 0)
20230a286ef2SSven Eckelmann goto err_stop;
20240a286ef2SSven Eckelmann }
20250a286ef2SSven Eckelmann
2026d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) {
20270f398230SFrank Praznik ret = sony_battery_probe(sc, append_dev_id);
2028a08c22c0SSven Eckelmann if (ret < 0)
2029a08c22c0SSven Eckelmann goto err_stop;
2030a08c22c0SSven Eckelmann
2031d902f472SFrank Praznik /* Open the device to receive reports with battery info */
2032d902f472SFrank Praznik ret = hid_hw_open(hdev);
2033d902f472SFrank Praznik if (ret < 0) {
2034d902f472SFrank Praznik hid_err(hdev, "hw open failed\n");
2035d902f472SFrank Praznik goto err_stop;
2036d902f472SFrank Praznik }
2037d902f472SFrank Praznik }
2038d902f472SFrank Praznik
2039c8de9dbbSFrank Praznik if (sc->quirks & SONY_FF_SUPPORT) {
2040fa57a810SFrank Praznik ret = sony_init_ff(sc);
2041d902f472SFrank Praznik if (ret < 0)
2042d902f472SFrank Praznik goto err_close;
20435f5750d2SFrank Praznik }
2044bd28ce00SJiri Slaby
2045f425458eSH Hartley Sweeten return 0;
2046d902f472SFrank Praznik err_close:
2047d902f472SFrank Praznik hid_hw_close(hdev);
2048bd28ce00SJiri Slaby err_stop:
204946262047SFrank Praznik sony_cancel_work_sync(sc);
2050d2d782fcSFrank Praznik sony_remove_dev_list(sc);
20518025087aSFrank Praznik sony_release_device_id(sc);
2052bd28ce00SJiri Slaby return ret;
2053bd28ce00SJiri Slaby }
2054bd28ce00SJiri Slaby
sony_probe(struct hid_device * hdev,const struct hid_device_id * id)2055e1bc84d0SRoderick Colenbrander static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2056e1bc84d0SRoderick Colenbrander {
2057e1bc84d0SRoderick Colenbrander int ret;
2058e1bc84d0SRoderick Colenbrander unsigned long quirks = id->driver_data;
2059e1bc84d0SRoderick Colenbrander struct sony_sc *sc;
2060fb1a79a6SPascal Giard struct usb_device *usbdev;
2061e1bc84d0SRoderick Colenbrander unsigned int connect_mask = HID_CONNECT_DEFAULT;
2062e1bc84d0SRoderick Colenbrander
2063e1bc84d0SRoderick Colenbrander if (!strcmp(hdev->name, "FutureMax Dance Mat"))
2064e1bc84d0SRoderick Colenbrander quirks |= FUTUREMAX_DANCE_MAT;
2065e1bc84d0SRoderick Colenbrander
2066bab94e97SUlrich Spörlein if (!strcmp(hdev->name, "SHANWAN PS3 GamePad") ||
2067bab94e97SUlrich Spörlein !strcmp(hdev->name, "ShanWan PS(R) Ga`epad"))
206869481059SHongye Yuan quirks |= SHANWAN_GAMEPAD;
206969481059SHongye Yuan
2070e1bc84d0SRoderick Colenbrander sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
2071e1bc84d0SRoderick Colenbrander if (sc == NULL) {
2072e1bc84d0SRoderick Colenbrander hid_err(hdev, "can't alloc sony descriptor\n");
2073e1bc84d0SRoderick Colenbrander return -ENOMEM;
2074e1bc84d0SRoderick Colenbrander }
2075e1bc84d0SRoderick Colenbrander
2076e1bc84d0SRoderick Colenbrander spin_lock_init(&sc->lock);
2077e1bc84d0SRoderick Colenbrander
2078e1bc84d0SRoderick Colenbrander sc->quirks = quirks;
2079e1bc84d0SRoderick Colenbrander hid_set_drvdata(hdev, sc);
2080e1bc84d0SRoderick Colenbrander sc->hdev = hdev;
2081e1bc84d0SRoderick Colenbrander
2082e1bc84d0SRoderick Colenbrander ret = hid_parse(hdev);
2083e1bc84d0SRoderick Colenbrander if (ret) {
2084e1bc84d0SRoderick Colenbrander hid_err(hdev, "parse failed\n");
2085e1bc84d0SRoderick Colenbrander return ret;
2086e1bc84d0SRoderick Colenbrander }
2087e1bc84d0SRoderick Colenbrander
2088e1bc84d0SRoderick Colenbrander if (sc->quirks & VAIO_RDESC_CONSTANT)
2089e1bc84d0SRoderick Colenbrander connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2090e1bc84d0SRoderick Colenbrander else if (sc->quirks & SIXAXIS_CONTROLLER)
2091e1bc84d0SRoderick Colenbrander connect_mask |= HID_CONNECT_HIDDEV_FORCE;
2092e1bc84d0SRoderick Colenbrander
20934f1f3918SRoderick Colenbrander /* Patch the hw version on DS3 compatible devices, so applications can
20949131f8ccSRoderick Colenbrander * distinguish between the default HID mappings and the mappings defined
20959131f8ccSRoderick Colenbrander * by the Linux game controller spec. This is important for the SDL2
20969131f8ccSRoderick Colenbrander * library, which has a game controller database, which uses device ids
20979131f8ccSRoderick Colenbrander * in combination with version as a key.
20989131f8ccSRoderick Colenbrander */
20994f1f3918SRoderick Colenbrander if (sc->quirks & SIXAXIS_CONTROLLER)
21009131f8ccSRoderick Colenbrander hdev->version |= 0x8000;
21019131f8ccSRoderick Colenbrander
2102e1bc84d0SRoderick Colenbrander ret = hid_hw_start(hdev, connect_mask);
2103e1bc84d0SRoderick Colenbrander if (ret) {
2104e1bc84d0SRoderick Colenbrander hid_err(hdev, "hw start failed\n");
2105e1bc84d0SRoderick Colenbrander return ret;
2106e1bc84d0SRoderick Colenbrander }
2107e1bc84d0SRoderick Colenbrander
21084f967f6dSRoderick Colenbrander /* sony_input_configured can fail, but this doesn't result
21094f967f6dSRoderick Colenbrander * in hid_hw_start failures (intended). Check whether
21104f967f6dSRoderick Colenbrander * the HID layer claimed the device else fail.
21114f967f6dSRoderick Colenbrander * We don't know the actual reason for the failure, most
21124f967f6dSRoderick Colenbrander * likely it is due to EEXIST in case of double connection
21134f967f6dSRoderick Colenbrander * of USB and Bluetooth, but could have been due to ENOMEM
21144f967f6dSRoderick Colenbrander * or other reasons as well.
21154f967f6dSRoderick Colenbrander */
21164f967f6dSRoderick Colenbrander if (!(hdev->claimed & HID_CLAIMED_INPUT)) {
21174f967f6dSRoderick Colenbrander hid_err(hdev, "failed to claim input\n");
21187998193bSBenjamin Tissoires ret = -ENODEV;
21197998193bSBenjamin Tissoires goto err;
21204f967f6dSRoderick Colenbrander }
21214f967f6dSRoderick Colenbrander
2122a4bfe13fSDaniel Nguyen if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) {
21237998193bSBenjamin Tissoires if (!hid_is_usb(hdev)) {
21247998193bSBenjamin Tissoires ret = -EINVAL;
21257998193bSBenjamin Tissoires goto err;
21267998193bSBenjamin Tissoires }
212793020953SGreg Kroah-Hartman
212893020953SGreg Kroah-Hartman usbdev = to_usb_device(sc->hdev->dev.parent->parent);
212993020953SGreg Kroah-Hartman
2130fb1a79a6SPascal Giard sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC);
21317998193bSBenjamin Tissoires if (!sc->ghl_urb) {
21327998193bSBenjamin Tissoires ret = -ENOMEM;
21337998193bSBenjamin Tissoires goto err;
21347998193bSBenjamin Tissoires }
2135a4bfe13fSDaniel Nguyen
2136a4bfe13fSDaniel Nguyen if (sc->quirks & GHL_GUITAR_PS3WIIU)
2137a4bfe13fSDaniel Nguyen ret = ghl_init_urb(sc, usbdev, ghl_ps3wiiu_magic_data,
2138a4bfe13fSDaniel Nguyen ARRAY_SIZE(ghl_ps3wiiu_magic_data));
2139a4bfe13fSDaniel Nguyen else if (sc->quirks & GHL_GUITAR_PS4)
2140a4bfe13fSDaniel Nguyen ret = ghl_init_urb(sc, usbdev, ghl_ps4_magic_data,
2141a4bfe13fSDaniel Nguyen ARRAY_SIZE(ghl_ps4_magic_data));
2142fb1a79a6SPascal Giard if (ret) {
2143fb1a79a6SPascal Giard hid_err(hdev, "error preparing URB\n");
21447998193bSBenjamin Tissoires goto err;
2145fb1a79a6SPascal Giard }
2146fb1a79a6SPascal Giard
2147cc894ac5SPascal Giard timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0);
2148cc894ac5SPascal Giard mod_timer(&sc->ghl_poke_timer,
2149cc894ac5SPascal Giard jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
2150cc894ac5SPascal Giard }
2151cc894ac5SPascal Giard
2152e1bc84d0SRoderick Colenbrander return ret;
21537998193bSBenjamin Tissoires
21547998193bSBenjamin Tissoires err:
2155e1cd4004SChristophe JAILLET usb_free_urb(sc->ghl_urb);
2156e1cd4004SChristophe JAILLET
21577998193bSBenjamin Tissoires hid_hw_stop(hdev);
21587998193bSBenjamin Tissoires return ret;
2159e1bc84d0SRoderick Colenbrander }
2160e1bc84d0SRoderick Colenbrander
sony_remove(struct hid_device * hdev)2161bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev)
2162bd28ce00SJiri Slaby {
2163bd28ce00SJiri Slaby struct sony_sc *sc = hid_get_drvdata(hdev);
2164bd28ce00SJiri Slaby
2165a4bfe13fSDaniel Nguyen if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) {
2166cc894ac5SPascal Giard del_timer_sync(&sc->ghl_poke_timer);
2167fb1a79a6SPascal Giard usb_free_urb(sc->ghl_urb);
2168fb1a79a6SPascal Giard }
2169cc894ac5SPascal Giard
2170ac797b95SRoderick Colenbrander hid_hw_close(hdev);
2171ac797b95SRoderick Colenbrander
217246262047SFrank Praznik sony_cancel_work_sync(sc);
21739f323b68SSven Eckelmann
2174d2d782fcSFrank Praznik sony_remove_dev_list(sc);
2175bd28ce00SJiri Slaby
21768025087aSFrank Praznik sony_release_device_id(sc);
21778025087aSFrank Praznik
2178bd28ce00SJiri Slaby hid_hw_stop(hdev);
2179bd28ce00SJiri Slaby }
2180bd28ce00SJiri Slaby
2181decd946cSFrank Praznik #ifdef CONFIG_PM
2182decd946cSFrank Praznik
sony_suspend(struct hid_device * hdev,pm_message_t message)2183decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2184decd946cSFrank Praznik {
2185765a1077SFrank Praznik #ifdef CONFIG_SONY_FF
2186765a1077SFrank Praznik
2187765a1077SFrank Praznik /* On suspend stop any running force-feedback events */
2188765a1077SFrank Praznik if (SONY_FF_SUPPORT) {
2189decd946cSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev);
2190decd946cSFrank Praznik
2191decd946cSFrank Praznik sc->left = sc->right = 0;
2192decd946cSFrank Praznik sony_send_output_report(sc);
2193decd946cSFrank Praznik }
2194decd946cSFrank Praznik
2195765a1077SFrank Praznik #endif
2196decd946cSFrank Praznik return 0;
2197decd946cSFrank Praznik }
2198decd946cSFrank Praznik
sony_resume(struct hid_device * hdev)2199decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev)
2200decd946cSFrank Praznik {
2201decd946cSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev);
2202decd946cSFrank Praznik
2203decd946cSFrank Praznik /*
2204decd946cSFrank Praznik * The Sixaxis and navigation controllers on USB need to be
2205decd946cSFrank Praznik * reinitialized on resume or they won't behave properly.
2206decd946cSFrank Praznik */
2207decd946cSFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
22082a242932SFrank Praznik (sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2209decd946cSFrank Praznik sixaxis_set_operational_usb(sc->hdev);
22102a242932SFrank Praznik sc->defer_initialization = 1;
22112a242932SFrank Praznik }
2212decd946cSFrank Praznik
2213decd946cSFrank Praznik return 0;
2214decd946cSFrank Praznik }
2215decd946cSFrank Praznik
2216decd946cSFrank Praznik #endif
2217decd946cSFrank Praznik
2218bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
2219bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2220bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_USB },
2221bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
22224545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_USB },
22236eabaaa0SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
22244545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_BT },
2225c5e0c1c4SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2226b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_USB },
2227a4afa854SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER),
2228b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_BT },
2229bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2230bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_BT },
2231bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
2232bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT },
2233bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
2234bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT },
2235ef916ef5SAntonio Ospite /*
2236ef916ef5SAntonio Ospite * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
2237ef916ef5SAntonio Ospite * Logitech joystick from the device descriptor.
2238ef916ef5SAntonio Ospite */
2239bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
2240bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER },
2241bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
2242bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER },
2243bd28ce00SJiri Slaby /* PS3 BD Remote Control */
2244bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
2245bd28ce00SJiri Slaby .driver_data = PS3REMOTE },
2246bd28ce00SJiri Slaby /* Logitech Harmony Adapter for PS3 */
2247bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
2248bd28ce00SJiri Slaby .driver_data = PS3REMOTE },
224968a49e51SFrank Praznik /* SMK-Link PS3 BD Remote Control */
225068a49e51SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
225168a49e51SFrank Praznik .driver_data = PS3REMOTE },
225274500cc8SScott Moreau /* Nyko Core Controller for PS3 */
225374500cc8SScott Moreau { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
225474500cc8SScott Moreau .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
2255b7289cb1STodd Kelner /* SMK-Link NSG-MR5U Remote Control */
2256b7289cb1STodd Kelner { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR5U_REMOTE),
2257b7289cb1STodd Kelner .driver_data = NSG_MR5U_REMOTE_BT },
2258b7289cb1STodd Kelner /* SMK-Link NSG-MR7U Remote Control */
2259b7289cb1STodd Kelner { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE),
2260b7289cb1STodd Kelner .driver_data = NSG_MR7U_REMOTE_BT },
2261cc894ac5SPascal Giard /* Guitar Hero Live PS3 and Wii U guitar dongles */
226232e411d0SSanjay Govind { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE),
226332e411d0SSanjay Govind .driver_data = GHL_GUITAR_PS3WIIU | GH_GUITAR_CONTROLLER },
226432e411d0SSanjay Govind /* Guitar Hero PC Guitar Dongle */
2265a4bfe13fSDaniel Nguyen { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_GUITAR_DONGLE),
226632e411d0SSanjay Govind .driver_data = GH_GUITAR_CONTROLLER },
226732e411d0SSanjay Govind /* Guitar Hero PS3 World Tour Guitar Dongle */
226832e411d0SSanjay Govind { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GUITAR_DONGLE),
226932e411d0SSanjay Govind .driver_data = GH_GUITAR_CONTROLLER },
2270a4bfe13fSDaniel Nguyen /* Guitar Hero Live PS4 guitar dongles */
2271a4bfe13fSDaniel Nguyen { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE),
2272a4bfe13fSDaniel Nguyen .driver_data = GHL_GUITAR_PS4 | GH_GUITAR_CONTROLLER },
2273bd28ce00SJiri Slaby { }
2274bd28ce00SJiri Slaby };
2275bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
2276bd28ce00SJiri Slaby
2277bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
2278bd28ce00SJiri Slaby .name = "sony",
2279bd28ce00SJiri Slaby .id_table = sony_devices,
2280bd28ce00SJiri Slaby .input_mapping = sony_mapping,
2281ce8efc3bSFrank Praznik .input_configured = sony_input_configured,
2282bd28ce00SJiri Slaby .probe = sony_probe,
2283bd28ce00SJiri Slaby .remove = sony_remove,
2284bd28ce00SJiri Slaby .report_fixup = sony_report_fixup,
2285decd946cSFrank Praznik .raw_event = sony_raw_event,
2286decd946cSFrank Praznik
2287decd946cSFrank Praznik #ifdef CONFIG_PM
2288decd946cSFrank Praznik .suspend = sony_suspend,
2289decd946cSFrank Praznik .resume = sony_resume,
2290decd946cSFrank Praznik .reset_resume = sony_resume,
2291decd946cSFrank Praznik #endif
2292bd28ce00SJiri Slaby };
22938025087aSFrank Praznik
sony_init(void)22948025087aSFrank Praznik static int __init sony_init(void)
22958025087aSFrank Praznik {
22968025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__);
22978025087aSFrank Praznik
22988025087aSFrank Praznik return hid_register_driver(&sony_driver);
22998025087aSFrank Praznik }
23008025087aSFrank Praznik
sony_exit(void)23018025087aSFrank Praznik static void __exit sony_exit(void)
23028025087aSFrank Praznik {
23038025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__);
23048025087aSFrank Praznik
23058025087aSFrank Praznik hid_unregister_driver(&sony_driver);
23066c40065fSAntonio Ospite ida_destroy(&sony_device_id_allocator);
23078025087aSFrank Praznik }
23088025087aSFrank Praznik module_init(sony_init);
23098025087aSFrank Praznik module_exit(sony_exit);
2310bd28ce00SJiri Slaby
23119d262f35SJeff Johnson MODULE_DESCRIPTION("HID driver for Sony / PS2 / PS3 / PS4 BD devices");
2312bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
2313