1bd28ce00SJiri Slaby /* 2077147a3SFrank Praznik * HID driver for Sony / PS2 / PS3 / PS4 BD devices. 3bd28ce00SJiri Slaby * 4bd28ce00SJiri Slaby * Copyright (c) 1999 Andreas Gal 5bd28ce00SJiri Slaby * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 6bd28ce00SJiri Slaby * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 7bd28ce00SJiri Slaby * Copyright (c) 2008 Jiri Slaby 8078328daSJiri Kosina * Copyright (c) 2012 David Dillow <dave@thedillows.org> 9078328daSJiri Kosina * Copyright (c) 2006-2013 Jiri Kosina 10f04d5140SColin Leitner * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> 11c4425c8fSFrank Praznik * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com> 12bd28ce00SJiri Slaby */ 13bd28ce00SJiri Slaby 14bd28ce00SJiri Slaby /* 15bd28ce00SJiri Slaby * This program is free software; you can redistribute it and/or modify it 16bd28ce00SJiri Slaby * under the terms of the GNU General Public License as published by the Free 17bd28ce00SJiri Slaby * Software Foundation; either version 2 of the License, or (at your option) 18bd28ce00SJiri Slaby * any later version. 19bd28ce00SJiri Slaby */ 20bd28ce00SJiri Slaby 21ad142b9eSFrank Praznik /* 22ad142b9eSFrank Praznik * NOTE: in order for the Sony PS3 BD Remote Control to be found by 23078328daSJiri Kosina * a Bluetooth host, the key combination Start+Enter has to be kept pressed 24078328daSJiri Kosina * for about 7 seconds with the Bluetooth Host Controller in discovering mode. 25078328daSJiri Kosina * 26078328daSJiri Kosina * There will be no PIN request from the device. 27078328daSJiri Kosina */ 28078328daSJiri Kosina 29bd28ce00SJiri Slaby #include <linux/device.h> 30bd28ce00SJiri Slaby #include <linux/hid.h> 31bd28ce00SJiri Slaby #include <linux/module.h> 325a0e3ad6STejun Heo #include <linux/slab.h> 3340e32ee6SJiri Kosina #include <linux/leds.h> 34d902f472SFrank Praznik #include <linux/power_supply.h> 35d902f472SFrank Praznik #include <linux/spinlock.h> 36d2d782fcSFrank Praznik #include <linux/list.h> 378025087aSFrank Praznik #include <linux/idr.h> 38e5606230SFrank Praznik #include <linux/input/mt.h> 3949b9ca6cSRoderick Colenbrander #include <linux/crc32.h> 4049b9ca6cSRoderick Colenbrander #include <asm/unaligned.h> 41bd28ce00SJiri Slaby 42bd28ce00SJiri Slaby #include "hid-ids.h" 43bd28ce00SJiri Slaby 44f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT BIT(0) 45f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB BIT(1) 46f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT BIT(2) 47f1c458caSSven Eckelmann #define BUZZ_CONTROLLER BIT(3) 48f1c458caSSven Eckelmann #define PS3REMOTE BIT(4) 498ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5) 508ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT BIT(6) 51b3bca326SSimon Wood #define MOTION_CONTROLLER_USB BIT(7) 52b3bca326SSimon Wood #define MOTION_CONTROLLER_BT BIT(8) 534545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9) 544545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT BIT(10) 5574500cc8SScott Moreau #define SINO_LITE_CONTROLLER BIT(11) 564ba1eeebSMikko Perttunen #define FUTUREMAX_DANCE_MAT BIT(12) 57cc6e0bbbSJiri Kosina 58fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) 59b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) 604545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\ 614545ee0aSSimon Wood NAVIGATION_CONTROLLER_BT) 6268330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ 6368330d83SFrank Praznik DUALSHOCK4_CONTROLLER_BT) 64fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ 654545ee0aSSimon Wood DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\ 664545ee0aSSimon Wood NAVIGATION_CONTROLLER) 6712e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 684545ee0aSSimon Wood MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) 69c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 70c5e0c1c4SFrank Praznik MOTION_CONTROLLER) 710f398230SFrank Praznik #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\ 720f398230SFrank Praznik MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT) 7360781cf4SFrank Praznik 7460781cf4SFrank Praznik #define MAX_LEDS 4 750a286ef2SSven Eckelmann 764c3e8298SFrank Praznik /* 774c3e8298SFrank Praznik * The Sixaxis reports both digital and analog values for each button on the 784c3e8298SFrank Praznik * controller except for Start, Select and the PS button. The controller ends 794c3e8298SFrank Praznik * up reporting 27 axes which causes them to spill over into the multi-touch 804c3e8298SFrank Praznik * axis values. Additionally, the controller only has 20 actual, physical axes 814c3e8298SFrank Praznik * so there are several unused axes in between the used ones. 824c3e8298SFrank Praznik */ 831adf904eSPavel Machek static u8 sixaxis_rdesc[] = { 84fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 854c3e8298SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */ 86fb705a6dSAntonio Ospite 0xA1, 0x01, /* Collection (Application), */ 87fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 88fb705a6dSAntonio Ospite 0x85, 0x01, /* Report ID (1), */ 89fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 90fb705a6dSAntonio Ospite 0x95, 0x01, /* Report Count (1), */ 91fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 92fb705a6dSAntonio Ospite 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 93fb705a6dSAntonio Ospite 0x81, 0x03, /* Input (Constant, Variable), */ 94fb705a6dSAntonio Ospite 0x75, 0x01, /* Report Size (1), */ 95fb705a6dSAntonio Ospite 0x95, 0x13, /* Report Count (19), */ 96fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 97fb705a6dSAntonio Ospite 0x25, 0x01, /* Logical Maximum (1), */ 98fb705a6dSAntonio Ospite 0x35, 0x00, /* Physical Minimum (0), */ 99fb705a6dSAntonio Ospite 0x45, 0x01, /* Physical Maximum (1), */ 100fb705a6dSAntonio Ospite 0x05, 0x09, /* Usage Page (Button), */ 101fb705a6dSAntonio Ospite 0x19, 0x01, /* Usage Minimum (01h), */ 102fb705a6dSAntonio Ospite 0x29, 0x13, /* Usage Maximum (13h), */ 103fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 104fb705a6dSAntonio Ospite 0x75, 0x01, /* Report Size (1), */ 105fb705a6dSAntonio Ospite 0x95, 0x0D, /* Report Count (13), */ 106fb705a6dSAntonio Ospite 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 107fb705a6dSAntonio Ospite 0x81, 0x03, /* Input (Constant, Variable), */ 108fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 109fb705a6dSAntonio Ospite 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 110fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 111fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 112fb705a6dSAntonio Ospite 0xA1, 0x00, /* Collection (Physical), */ 113fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 114fb705a6dSAntonio Ospite 0x95, 0x04, /* Report Count (4), */ 115fb705a6dSAntonio Ospite 0x35, 0x00, /* Physical Minimum (0), */ 116fb705a6dSAntonio Ospite 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 117fb705a6dSAntonio Ospite 0x09, 0x30, /* Usage (X), */ 118fb705a6dSAntonio Ospite 0x09, 0x31, /* Usage (Y), */ 119fb705a6dSAntonio Ospite 0x09, 0x32, /* Usage (Z), */ 120fb705a6dSAntonio Ospite 0x09, 0x35, /* Usage (Rz), */ 121fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 122fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 123fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 124fb705a6dSAntonio Ospite 0x95, 0x13, /* Report Count (19), */ 125fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 126fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 127fb705a6dSAntonio Ospite 0x95, 0x0C, /* Report Count (12), */ 128fb705a6dSAntonio Ospite 0x81, 0x01, /* Input (Constant), */ 129fb705a6dSAntonio Ospite 0x75, 0x10, /* Report Size (16), */ 130fb705a6dSAntonio Ospite 0x95, 0x04, /* Report Count (4), */ 131fb705a6dSAntonio Ospite 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 132fb705a6dSAntonio Ospite 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 133fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 134fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 135fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 136fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 137fb705a6dSAntonio Ospite 0x85, 0x02, /* Report ID (2), */ 138fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 139fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 140fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 141fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 142fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 143fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 144fb705a6dSAntonio Ospite 0x85, 0xEE, /* Report ID (238), */ 145fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 146fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 147fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 148fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 149fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 150fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 151fb705a6dSAntonio Ospite 0x85, 0xEF, /* Report ID (239), */ 152fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 153fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 154fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 155fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 156fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 157fb705a6dSAntonio Ospite 0xC0 /* End Collection */ 158e57a67daSMauro Carvalho Chehab }; 159e57a67daSMauro Carvalho Chehab 160c5e0c1c4SFrank Praznik /* PS/3 Motion controller */ 1611adf904eSPavel Machek static u8 motion_rdesc[] = { 162c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 163c5e0c1c4SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */ 164c5e0c1c4SFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 165c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 166c5e0c1c4SFrank Praznik 0x85, 0x01, /* Report ID (1), */ 167c5e0c1c4SFrank Praznik 0x75, 0x01, /* Report Size (1), */ 1688b2513c3SSimon Wood 0x95, 0x15, /* Report Count (21), */ 169c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 170c5e0c1c4SFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 171c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 172c5e0c1c4SFrank Praznik 0x45, 0x01, /* Physical Maximum (1), */ 173c5e0c1c4SFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 174c5e0c1c4SFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 1758b2513c3SSimon Wood 0x29, 0x15, /* Usage Maximum (15h), */ 1768b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Buttons */ 1778b2513c3SSimon Wood 0x95, 0x0B, /* Report Count (11), */ 178c5e0c1c4SFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 1798b2513c3SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), * Padding */ 180c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 181c5e0c1c4SFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 182c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 183c5e0c1c4SFrank Praznik 0xA1, 0x00, /* Collection (Physical), */ 184c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 1858b2513c3SSimon Wood 0x95, 0x01, /* Report Count (1), */ 186c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 187c5e0c1c4SFrank Praznik 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 188c5e0c1c4SFrank Praznik 0x09, 0x30, /* Usage (X), */ 1898b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Trigger */ 190c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 1918b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 1928b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 1938b2513c3SSimon Wood 0x95, 0x07, /* Report Count (7), * skip 7 bytes */ 1948b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 195c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 196c5e0c1c4SFrank Praznik 0x75, 0x10, /* Report Size (16), */ 1978b2513c3SSimon Wood 0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */ 1988b2513c3SSimon Wood 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */ 1998b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Accels */ 2008b2513c3SSimon Wood 0x09, 0x33, /* Usage (rX), */ 2018b2513c3SSimon Wood 0x09, 0x34, /* Usage (rY), */ 2028b2513c3SSimon Wood 0x09, 0x35, /* Usage (rZ), */ 203c5e0c1c4SFrank Praznik 0x81, 0x02, /* Input (Variable), */ 2048b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 2058b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */ 2068b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2078b2513c3SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 2088b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 2098b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Gyros */ 2108b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2118b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 2128b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */ 2138b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2148b2513c3SSimon Wood 0x75, 0x0C, /* Report Size (12), */ 2158b2513c3SSimon Wood 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */ 2168b2513c3SSimon Wood 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */ 2178b2513c3SSimon Wood 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */ 2188b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2198b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 2208b2513c3SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 2218b2513c3SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 2228b2513c3SSimon Wood 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */ 2238b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2248b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 2258b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */ 2268b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 2278b2513c3SSimon Wood 0x91, 0x02, /* Output (Variable), */ 2288b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 2298b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */ 2308b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 2318b2513c3SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 232c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 233c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 234c5e0c1c4SFrank Praznik 0x85, 0x02, /* Report ID (2), */ 235c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 236c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 237c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 238c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 239c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 240c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 241c5e0c1c4SFrank Praznik 0x85, 0xEE, /* Report ID (238), */ 242c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 243c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 244c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 245c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 246c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 247c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 248c5e0c1c4SFrank Praznik 0x85, 0xEF, /* Report ID (239), */ 249c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 250c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 251c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 252c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 253c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 254c5e0c1c4SFrank Praznik 0xC0 /* End Collection */ 255c5e0c1c4SFrank Praznik }; 256c5e0c1c4SFrank Praznik 257b2723eb7SSimon Wood /* PS/3 Navigation controller */ 2581adf904eSPavel Machek static u8 navigation_rdesc[] = { 259b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 260d542176fSAntonio Ospite 0x09, 0x04, /* Usage (Joystick), */ 261b2723eb7SSimon Wood 0xA1, 0x01, /* Collection (Application), */ 262b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 263b2723eb7SSimon Wood 0x85, 0x01, /* Report ID (1), */ 264b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 265b2723eb7SSimon Wood 0x95, 0x01, /* Report Count (1), */ 266b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 267b2723eb7SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 268b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 269b2723eb7SSimon Wood 0x75, 0x01, /* Report Size (1), */ 270b2723eb7SSimon Wood 0x95, 0x13, /* Report Count (19), */ 271b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 272b2723eb7SSimon Wood 0x25, 0x01, /* Logical Maximum (1), */ 273b2723eb7SSimon Wood 0x35, 0x00, /* Physical Minimum (0), */ 274b2723eb7SSimon Wood 0x45, 0x01, /* Physical Maximum (1), */ 275b2723eb7SSimon Wood 0x05, 0x09, /* Usage Page (Button), */ 276b2723eb7SSimon Wood 0x19, 0x01, /* Usage Minimum (01h), */ 277b2723eb7SSimon Wood 0x29, 0x13, /* Usage Maximum (13h), */ 278b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 279b2723eb7SSimon Wood 0x75, 0x01, /* Report Size (1), */ 280b2723eb7SSimon Wood 0x95, 0x0D, /* Report Count (13), */ 281b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 282b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 283b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 284b2723eb7SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 285b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 286b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 287b2723eb7SSimon Wood 0xA1, 0x00, /* Collection (Physical), */ 288b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 289b2723eb7SSimon Wood 0x95, 0x02, /* Report Count (2), */ 290b2723eb7SSimon Wood 0x35, 0x00, /* Physical Minimum (0), */ 291b2723eb7SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 292b2723eb7SSimon Wood 0x09, 0x30, /* Usage (X), */ 293b2723eb7SSimon Wood 0x09, 0x31, /* Usage (Y), */ 294b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 295b2723eb7SSimon Wood 0xC0, /* End Collection, */ 296b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 297b2723eb7SSimon Wood 0x95, 0x06, /* Report Count (6), */ 298b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 299b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 300b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 301b2723eb7SSimon Wood 0x95, 0x05, /* Report Count (5), */ 302b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 303b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 304b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 3052259b5bbSSimon Wood 0x95, 0x01, /* Report Count (1), */ 3062259b5bbSSimon Wood 0x81, 0x02, /* Input (Variable), */ 3072259b5bbSSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 3082259b5bbSSimon Wood 0x95, 0x01, /* Report Count (1), */ 3092259b5bbSSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 3102259b5bbSSimon Wood 0x81, 0x02, /* Input (Variable), */ 3112259b5bbSSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 3122259b5bbSSimon Wood 0x95, 0x1E, /* Report Count (24), */ 313b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 314b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 315b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 316b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 317b2723eb7SSimon Wood 0x91, 0x02, /* Output (Variable), */ 318b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 319b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 320b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 321b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 322b2723eb7SSimon Wood 0xC0, /* End Collection, */ 323b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 324b2723eb7SSimon Wood 0x85, 0x02, /* Report ID (2), */ 325b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 326b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 327b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 328b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 329b2723eb7SSimon Wood 0xC0, /* End Collection, */ 330b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 331b2723eb7SSimon Wood 0x85, 0xEE, /* Report ID (238), */ 332b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 333b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 334b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 335b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 336b2723eb7SSimon Wood 0xC0, /* End Collection, */ 337b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 338b2723eb7SSimon Wood 0x85, 0xEF, /* Report ID (239), */ 339b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 340b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 341b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 342b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 343b2723eb7SSimon Wood 0xC0, /* End Collection, */ 344b2723eb7SSimon Wood 0xC0 /* End Collection */ 345b2723eb7SSimon Wood }; 346c5e0c1c4SFrank Praznik 347ad142b9eSFrank Praznik /* 348ad142b9eSFrank Praznik * The default descriptor doesn't provide mapping for the accelerometers 34958d7027bSFrank Praznik * or orientation sensors. This fixed descriptor maps the accelerometers 35058d7027bSFrank Praznik * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors 35158d7027bSFrank Praznik * to usage values 0x43, 0x44 and 0x45. 35258d7027bSFrank Praznik */ 353ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = { 35458d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 35558d7027bSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 35658d7027bSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 35758d7027bSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 35858d7027bSFrank Praznik 0x09, 0x30, /* Usage (X), */ 35958d7027bSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 36058d7027bSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 36158d7027bSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 36258d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 36358d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 36458d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 36558d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 36658d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 36758d7027bSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 36858d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 36958d7027bSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 37058d7027bSFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 37158d7027bSFrank Praznik 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 37258d7027bSFrank Praznik 0x65, 0x14, /* Unit (Degrees), */ 37358d7027bSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 37458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 37558d7027bSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 37658d7027bSFrank Praznik 0x65, 0x00, /* Unit, */ 37758d7027bSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 37858d7027bSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 379ac797b95SRoderick Colenbrander 0x29, 0x0D, /* Usage Maximum (0Dh), */ 38058d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 38158d7027bSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 38258d7027bSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 38358d7027bSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 38458d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 38558d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 38658d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 38758d7027bSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 38858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 38958d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 390fb291cbdSFrank Praznik 0x25, 0x3F, /* Logical Maximum (63), */ 39158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 39258d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 39358d7027bSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 39458d7027bSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 39558d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 39658d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 39758d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 39858d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 39958d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 40058d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 40158d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 40258d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 40358d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 40458d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 40558d7027bSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 40658d7027bSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 40758d7027bSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 408bdae9e0eSRoderick Colenbrander 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 40958d7027bSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 41058d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 41158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 41258d7027bSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 41358d7027bSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 414bdae9e0eSRoderick Colenbrander 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 415bdae9e0eSRoderick Colenbrander 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 41658d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 41758d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 41858d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 41958d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 42058d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 421fb291cbdSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 42258d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 42358d7027bSFrank Praznik 0x95, 0x27, /* Report Count (39), */ 42458d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 42558d7027bSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 42658d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 42758d7027bSFrank Praznik 0x95, 0x1F, /* Report Count (31), */ 42858d7027bSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 42958d7027bSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 43058d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 43158d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 43258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43358d7027bSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 43458d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 43558d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 43658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43758d7027bSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 43858d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 43958d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 44058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44158d7027bSFrank Praznik 0x85, 0x10, /* Report ID (16), */ 44258d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 44358d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 44458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44558d7027bSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 44658d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 44758d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 44858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44958d7027bSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 45058d7027bSFrank Praznik 0x06, 0x02, 0xFF, /* Usage Page (FF02h), */ 45158d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 45258d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 45358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45458d7027bSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 45558d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 45658d7027bSFrank Praznik 0x95, 0x16, /* Report Count (22), */ 45758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45858d7027bSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 45958d7027bSFrank Praznik 0x06, 0x05, 0xFF, /* Usage Page (FF05h), */ 46058d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 46158d7027bSFrank Praznik 0x95, 0x10, /* Report Count (16), */ 46258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46358d7027bSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 46458d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 46558d7027bSFrank Praznik 0x95, 0x2C, /* Report Count (44), */ 46658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46758d7027bSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 46858d7027bSFrank Praznik 0x85, 0x80, /* Report ID (128), */ 46958d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 47058d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 47158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47258d7027bSFrank Praznik 0x85, 0x81, /* Report ID (129), */ 47358d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 47458d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 47558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47658d7027bSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 47758d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 47858d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 47958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48058d7027bSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 48158d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 48258d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 48358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48458d7027bSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 48558d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 48658d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 48758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48858d7027bSFrank Praznik 0x85, 0x85, /* Report ID (133), */ 48958d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 49058d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 49158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49258d7027bSFrank Praznik 0x85, 0x86, /* Report ID (134), */ 49358d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 49458d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 49558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49658d7027bSFrank Praznik 0x85, 0x87, /* Report ID (135), */ 49758d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 49858d7027bSFrank Praznik 0x95, 0x23, /* Report Count (35), */ 49958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50058d7027bSFrank Praznik 0x85, 0x88, /* Report ID (136), */ 50158d7027bSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 50258d7027bSFrank Praznik 0x95, 0x22, /* Report Count (34), */ 50358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50458d7027bSFrank Praznik 0x85, 0x89, /* Report ID (137), */ 50558d7027bSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 50658d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 50758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50858d7027bSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 50958d7027bSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 51058d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 51158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51258d7027bSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 51358d7027bSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 51458d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 51558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51658d7027bSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 51758d7027bSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 51858d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 51958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52058d7027bSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 52158d7027bSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 52258d7027bSFrank Praznik 0x95, 0x0C, /* Report Count (12), */ 52358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52458d7027bSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 52558d7027bSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 52658d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 52758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52858d7027bSFrank Praznik 0x85, 0xA1, /* Report ID (161), */ 52958d7027bSFrank Praznik 0x09, 0x41, /* Usage (41h), */ 53058d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 53158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53258d7027bSFrank Praznik 0x85, 0xA2, /* Report ID (162), */ 53358d7027bSFrank Praznik 0x09, 0x42, /* Usage (42h), */ 53458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 53558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53658d7027bSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 53758d7027bSFrank Praznik 0x09, 0x43, /* Usage (43h), */ 53858d7027bSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 53958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54058d7027bSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 54158d7027bSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 54258d7027bSFrank Praznik 0x95, 0x0D, /* Report Count (13), */ 54358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54458d7027bSFrank Praznik 0x85, 0xA5, /* Report ID (165), */ 54558d7027bSFrank Praznik 0x09, 0x45, /* Usage (45h), */ 54658d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 54758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54858d7027bSFrank Praznik 0x85, 0xA6, /* Report ID (166), */ 54958d7027bSFrank Praznik 0x09, 0x46, /* Usage (46h), */ 55058d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 55158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55258d7027bSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 55358d7027bSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 55458d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 55558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55658d7027bSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 55758d7027bSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 55858d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 55958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56058d7027bSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 56158d7027bSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 56258d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 56358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56458d7027bSFrank Praznik 0x85, 0xA7, /* Report ID (167), */ 56558d7027bSFrank Praznik 0x09, 0x4A, /* Usage (4Ah), */ 56658d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 56758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56858d7027bSFrank Praznik 0x85, 0xA8, /* Report ID (168), */ 56958d7027bSFrank Praznik 0x09, 0x4B, /* Usage (4Bh), */ 57058d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 57158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57258d7027bSFrank Praznik 0x85, 0xA9, /* Report ID (169), */ 57358d7027bSFrank Praznik 0x09, 0x4C, /* Usage (4Ch), */ 57458d7027bSFrank Praznik 0x95, 0x08, /* Report Count (8), */ 57558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57658d7027bSFrank Praznik 0x85, 0xAA, /* Report ID (170), */ 57758d7027bSFrank Praznik 0x09, 0x4E, /* Usage (4Eh), */ 57858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 57958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58058d7027bSFrank Praznik 0x85, 0xAB, /* Report ID (171), */ 58158d7027bSFrank Praznik 0x09, 0x4F, /* Usage (4Fh), */ 58258d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 58358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58458d7027bSFrank Praznik 0x85, 0xAC, /* Report ID (172), */ 58558d7027bSFrank Praznik 0x09, 0x50, /* Usage (50h), */ 58658d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 58758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58858d7027bSFrank Praznik 0x85, 0xAD, /* Report ID (173), */ 58958d7027bSFrank Praznik 0x09, 0x51, /* Usage (51h), */ 59058d7027bSFrank Praznik 0x95, 0x0B, /* Report Count (11), */ 59158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 59258d7027bSFrank Praznik 0x85, 0xAE, /* Report ID (174), */ 59358d7027bSFrank Praznik 0x09, 0x52, /* Usage (52h), */ 59458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 59558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 59658d7027bSFrank Praznik 0x85, 0xAF, /* Report ID (175), */ 59758d7027bSFrank Praznik 0x09, 0x53, /* Usage (53h), */ 59858d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 59958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 60058d7027bSFrank Praznik 0x85, 0xB0, /* Report ID (176), */ 60158d7027bSFrank Praznik 0x09, 0x54, /* Usage (54h), */ 60258d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 60358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 60458d7027bSFrank Praznik 0xC0 /* End Collection */ 605ed19d8cfSFrank Praznik }; 606ed19d8cfSFrank Praznik 607ad142b9eSFrank Praznik /* 608ad142b9eSFrank Praznik * The default behavior of the Dualshock 4 is to send reports using report 609077147a3SFrank Praznik * type 1 when running over Bluetooth. However, when feature report 2 is 610077147a3SFrank Praznik * requested during the controller initialization it starts sending input 611077147a3SFrank Praznik * reports in report 17. Since report 17 is undefined in the default HID 612d829674dSFrank Praznik * descriptor the button and axis definitions must be moved to report 17 or 613077147a3SFrank Praznik * the HID layer won't process the received input. 614d829674dSFrank Praznik */ 615d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = { 616d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 617d829674dSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 618d829674dSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 619d829674dSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 620d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 621d829674dSFrank Praznik 0x95, 0x0A, /* Report Count (9), */ 622d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 623d829674dSFrank Praznik 0x06, 0x04, 0xFF, /* Usage Page (FF04h), */ 624d829674dSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 625d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 626d829674dSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 627d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 628d829674dSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 629d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 630d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 631d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 632d829674dSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 633d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 634d829674dSFrank Praznik 0x95, 0x28, /* Report Count (40), */ 635d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 636d829674dSFrank Praznik 0x85, 0x06, /* Report ID (6), */ 637d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 638d829674dSFrank Praznik 0x95, 0x34, /* Report Count (52), */ 639d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 640d829674dSFrank Praznik 0x85, 0x07, /* Report ID (7), */ 641d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 642d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 643d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 644d829674dSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 645d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 646d829674dSFrank Praznik 0x95, 0x2F, /* Report Count (47), */ 647d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 648d829674dSFrank Praznik 0x06, 0x03, 0xFF, /* Usage Page (FF03h), */ 649d829674dSFrank Praznik 0x85, 0x03, /* Report ID (3), */ 650d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 651d829674dSFrank Praznik 0x95, 0x26, /* Report Count (38), */ 652d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 653d829674dSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 654d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 655d829674dSFrank Praznik 0x95, 0x2E, /* Report Count (46), */ 656d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 657d829674dSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 658d829674dSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 659d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 660d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 661d829674dSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 662d829674dSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 663d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 664d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 665d829674dSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 666d829674dSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 667d829674dSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 668d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 669d829674dSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 670d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 671d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 672d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 673d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 674d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 675d829674dSFrank Praznik 0x09, 0x30, /* Usage (X), */ 676d829674dSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 677d829674dSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 678d829674dSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 679d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 680d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 681d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 682d829674dSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 683d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 684d829674dSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 685d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 686d829674dSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 687d829674dSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 688d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 689d829674dSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 690d829674dSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 691d829674dSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 692ac797b95SRoderick Colenbrander 0x29, 0x0D, /* Usage Maximum (0Dh), */ 693d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 694d829674dSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 695d829674dSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 696d829674dSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 697d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 698d829674dSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 699d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 700d829674dSFrank Praznik 0x81, 0x01, /* Input (Constant), */ 701d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 702d829674dSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 703d829674dSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 704d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 705d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 706d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 707d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 708d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 709d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 710d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 711d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 712d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 713d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 714d829674dSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 715d829674dSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 716d829674dSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 717bdae9e0eSRoderick Colenbrander 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 718d829674dSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 719d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 720d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 721d829674dSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 722d829674dSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 723bdae9e0eSRoderick Colenbrander 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 724bdae9e0eSRoderick Colenbrander 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 725d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 726d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 727d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 728d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 729d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 730d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 731d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 732d829674dSFrank Praznik 0x95, 0x31, /* Report Count (51), */ 733d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 734d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 735d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 736d829674dSFrank Praznik 0x95, 0x4D, /* Report Count (77), */ 737d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 738d829674dSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 739d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 740d829674dSFrank Praznik 0x95, 0x8D, /* Report Count (141), */ 741d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 742d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 743d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 744d829674dSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 745d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 746d829674dSFrank Praznik 0x95, 0xCD, /* Report Count (205), */ 747d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 748d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 749d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 750d829674dSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 751d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 752d829674dSFrank Praznik 0x96, 0x0D, 0x01, /* Report Count (269), */ 753d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 754d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 755d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 756d829674dSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 757d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 758d829674dSFrank Praznik 0x96, 0x4D, 0x01, /* Report Count (333), */ 759d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 760d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 761d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 762d829674dSFrank Praznik 0x85, 0x16, /* Report ID (22), */ 763d829674dSFrank Praznik 0x09, 0x2A, /* Usage (2Ah), */ 764d829674dSFrank Praznik 0x96, 0x8D, 0x01, /* Report Count (397), */ 765d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 766d829674dSFrank Praznik 0x09, 0x2B, /* Usage (2Bh), */ 767d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 768d829674dSFrank Praznik 0x85, 0x17, /* Report ID (23), */ 769d829674dSFrank Praznik 0x09, 0x2C, /* Usage (2Ch), */ 770d829674dSFrank Praznik 0x96, 0xCD, 0x01, /* Report Count (461), */ 771d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 772d829674dSFrank Praznik 0x09, 0x2D, /* Usage (2Dh), */ 773d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 774d829674dSFrank Praznik 0x85, 0x18, /* Report ID (24), */ 775d829674dSFrank Praznik 0x09, 0x2E, /* Usage (2Eh), */ 776d829674dSFrank Praznik 0x96, 0x0D, 0x02, /* Report Count (525), */ 777d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 778d829674dSFrank Praznik 0x09, 0x2F, /* Usage (2Fh), */ 779d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 780d829674dSFrank Praznik 0x85, 0x19, /* Report ID (25), */ 781d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 782d829674dSFrank Praznik 0x96, 0x22, 0x02, /* Report Count (546), */ 783d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 784d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 785d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 786d829674dSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 787d829674dSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 788d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 789d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 790d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 791d829674dSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 792d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 793d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 794d829674dSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 795d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 796d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 797d829674dSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 798d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 799d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 800d829674dSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 801d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 802d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 803d829674dSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 804d829674dSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 805d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 806d829674dSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 807d829674dSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 808d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 809d829674dSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 810d829674dSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 811d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 812d829674dSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 813d829674dSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 814d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 815d829674dSFrank Praznik 0xC0 /* End Collection */ 816d829674dSFrank Praznik }; 817d829674dSFrank Praznik 8181adf904eSPavel Machek static u8 ps3remote_rdesc[] = { 819078328daSJiri Kosina 0x05, 0x01, /* GUsagePage Generic Desktop */ 820078328daSJiri Kosina 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 821078328daSJiri Kosina 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ 822078328daSJiri Kosina 823078328daSJiri Kosina /* Use collection 1 for joypad buttons */ 824078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 825078328daSJiri Kosina 826ef916ef5SAntonio Ospite /* 827ef916ef5SAntonio Ospite * Ignore the 1st byte, maybe it is used for a controller 828ef916ef5SAntonio Ospite * number but it's not needed for correct operation 829ef916ef5SAntonio Ospite */ 830078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 831078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 832078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 833078328daSJiri Kosina 834ef916ef5SAntonio Ospite /* 835ef916ef5SAntonio Ospite * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these 836ef916ef5SAntonio Ospite * buttons multiple keypresses are allowed 837ef916ef5SAntonio Ospite */ 838078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 839078328daSJiri Kosina 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ 840078328daSJiri Kosina 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ 841078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 842078328daSJiri Kosina 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ 843078328daSJiri Kosina 0x75, 0x01, /* GReportSize 0x01 [1] */ 844078328daSJiri Kosina 0x95, 0x18, /* GReportCount 0x18 [24] */ 845078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 846078328daSJiri Kosina 847078328daSJiri Kosina 0xC0, /* MEndCollection */ 848078328daSJiri Kosina 849078328daSJiri Kosina /* Use collection 2 for remote control buttons */ 850078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 851078328daSJiri Kosina 852078328daSJiri Kosina /* 5th byte is used for remote control buttons */ 853078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 854078328daSJiri Kosina 0x18, /* LUsageMinimum [No button pressed] */ 855078328daSJiri Kosina 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ 856078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 857078328daSJiri Kosina 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ 858078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 859078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 860078328daSJiri Kosina 0x80, /* MInput */ 861078328daSJiri Kosina 862ef916ef5SAntonio Ospite /* 863ef916ef5SAntonio Ospite * Ignore bytes from 6th to 11th, 6th to 10th are always constant at 864ef916ef5SAntonio Ospite * 0xff and 11th is for press indication 865ef916ef5SAntonio Ospite */ 866078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 867078328daSJiri Kosina 0x95, 0x06, /* GReportCount 0x06 [6] */ 868078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 869078328daSJiri Kosina 870078328daSJiri Kosina /* 12th byte is for battery strength */ 871078328daSJiri Kosina 0x05, 0x06, /* GUsagePage Generic Device Controls */ 872078328daSJiri Kosina 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ 873078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 874078328daSJiri Kosina 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ 875078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 876078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 877078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 878078328daSJiri Kosina 879078328daSJiri Kosina 0xC0, /* MEndCollection */ 880078328daSJiri Kosina 881078328daSJiri Kosina 0xC0 /* MEndCollection [Game Pad] */ 882078328daSJiri Kosina }; 883078328daSJiri Kosina 884078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = { 885078328daSJiri Kosina [0x01] = KEY_SELECT, 886078328daSJiri Kosina [0x02] = BTN_THUMBL, /* L3 */ 887078328daSJiri Kosina [0x03] = BTN_THUMBR, /* R3 */ 888078328daSJiri Kosina [0x04] = BTN_START, 889078328daSJiri Kosina [0x05] = KEY_UP, 890078328daSJiri Kosina [0x06] = KEY_RIGHT, 891078328daSJiri Kosina [0x07] = KEY_DOWN, 892078328daSJiri Kosina [0x08] = KEY_LEFT, 893078328daSJiri Kosina [0x09] = BTN_TL2, /* L2 */ 894078328daSJiri Kosina [0x0a] = BTN_TR2, /* R2 */ 895078328daSJiri Kosina [0x0b] = BTN_TL, /* L1 */ 896078328daSJiri Kosina [0x0c] = BTN_TR, /* R1 */ 897078328daSJiri Kosina [0x0d] = KEY_OPTION, /* options/triangle */ 898078328daSJiri Kosina [0x0e] = KEY_BACK, /* back/circle */ 899078328daSJiri Kosina [0x0f] = BTN_0, /* cross */ 900078328daSJiri Kosina [0x10] = KEY_SCREEN, /* view/square */ 901078328daSJiri Kosina [0x11] = KEY_HOMEPAGE, /* PS button */ 902078328daSJiri Kosina [0x14] = KEY_ENTER, 903078328daSJiri Kosina }; 904078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = { 905078328daSJiri Kosina [0x00] = KEY_1, 906078328daSJiri Kosina [0x01] = KEY_2, 907078328daSJiri Kosina [0x02] = KEY_3, 908078328daSJiri Kosina [0x03] = KEY_4, 909078328daSJiri Kosina [0x04] = KEY_5, 910078328daSJiri Kosina [0x05] = KEY_6, 911078328daSJiri Kosina [0x06] = KEY_7, 912078328daSJiri Kosina [0x07] = KEY_8, 913078328daSJiri Kosina [0x08] = KEY_9, 914078328daSJiri Kosina [0x09] = KEY_0, 915078328daSJiri Kosina [0x0e] = KEY_ESC, /* return */ 916078328daSJiri Kosina [0x0f] = KEY_CLEAR, 917078328daSJiri Kosina [0x16] = KEY_EJECTCD, 918078328daSJiri Kosina [0x1a] = KEY_MENU, /* top menu */ 919078328daSJiri Kosina [0x28] = KEY_TIME, 920078328daSJiri Kosina [0x30] = KEY_PREVIOUS, 921078328daSJiri Kosina [0x31] = KEY_NEXT, 922078328daSJiri Kosina [0x32] = KEY_PLAY, 923078328daSJiri Kosina [0x33] = KEY_REWIND, /* scan back */ 924078328daSJiri Kosina [0x34] = KEY_FORWARD, /* scan forward */ 925078328daSJiri Kosina [0x38] = KEY_STOP, 926078328daSJiri Kosina [0x39] = KEY_PAUSE, 927078328daSJiri Kosina [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ 928078328daSJiri Kosina [0x60] = KEY_FRAMEBACK, /* slow/step back */ 929078328daSJiri Kosina [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ 930078328daSJiri Kosina [0x63] = KEY_SUBTITLE, 931078328daSJiri Kosina [0x64] = KEY_AUDIO, 932078328daSJiri Kosina [0x65] = KEY_ANGLE, 933078328daSJiri Kosina [0x70] = KEY_INFO, /* display */ 934078328daSJiri Kosina [0x80] = KEY_BLUE, 935078328daSJiri Kosina [0x81] = KEY_RED, 936078328daSJiri Kosina [0x82] = KEY_GREEN, 937078328daSJiri Kosina [0x83] = KEY_YELLOW, 938078328daSJiri Kosina }; 939078328daSJiri Kosina 940f04d5140SColin Leitner static const unsigned int buzz_keymap[] = { 941ad142b9eSFrank Praznik /* 942ad142b9eSFrank Praznik * The controller has 4 remote buzzers, each with one LED and 5 943f04d5140SColin Leitner * buttons. 944f04d5140SColin Leitner * 945f04d5140SColin Leitner * We use the mapping chosen by the controller, which is: 946f04d5140SColin Leitner * 947f04d5140SColin Leitner * Key Offset 948f04d5140SColin Leitner * ------------------- 949f04d5140SColin Leitner * Buzz 1 950f04d5140SColin Leitner * Blue 5 951f04d5140SColin Leitner * Orange 4 952f04d5140SColin Leitner * Green 3 953f04d5140SColin Leitner * Yellow 2 954f04d5140SColin Leitner * 955f04d5140SColin Leitner * So, for example, the orange button on the third buzzer is mapped to 956f04d5140SColin Leitner * BTN_TRIGGER_HAPPY14 957f04d5140SColin Leitner */ 958f04d5140SColin Leitner [1] = BTN_TRIGGER_HAPPY1, 959f04d5140SColin Leitner [2] = BTN_TRIGGER_HAPPY2, 960f04d5140SColin Leitner [3] = BTN_TRIGGER_HAPPY3, 961f04d5140SColin Leitner [4] = BTN_TRIGGER_HAPPY4, 962f04d5140SColin Leitner [5] = BTN_TRIGGER_HAPPY5, 963f04d5140SColin Leitner [6] = BTN_TRIGGER_HAPPY6, 964f04d5140SColin Leitner [7] = BTN_TRIGGER_HAPPY7, 965f04d5140SColin Leitner [8] = BTN_TRIGGER_HAPPY8, 966f04d5140SColin Leitner [9] = BTN_TRIGGER_HAPPY9, 967f04d5140SColin Leitner [10] = BTN_TRIGGER_HAPPY10, 968f04d5140SColin Leitner [11] = BTN_TRIGGER_HAPPY11, 969f04d5140SColin Leitner [12] = BTN_TRIGGER_HAPPY12, 970f04d5140SColin Leitner [13] = BTN_TRIGGER_HAPPY13, 971f04d5140SColin Leitner [14] = BTN_TRIGGER_HAPPY14, 972f04d5140SColin Leitner [15] = BTN_TRIGGER_HAPPY15, 973f04d5140SColin Leitner [16] = BTN_TRIGGER_HAPPY16, 974f04d5140SColin Leitner [17] = BTN_TRIGGER_HAPPY17, 975f04d5140SColin Leitner [18] = BTN_TRIGGER_HAPPY18, 976f04d5140SColin Leitner [19] = BTN_TRIGGER_HAPPY19, 977f04d5140SColin Leitner [20] = BTN_TRIGGER_HAPPY20, 978f04d5140SColin Leitner }; 979f04d5140SColin Leitner 9809131f8ccSRoderick Colenbrander static const unsigned int ds4_absmap[] = { 9819131f8ccSRoderick Colenbrander [0x30] = ABS_X, 9829131f8ccSRoderick Colenbrander [0x31] = ABS_Y, 9839131f8ccSRoderick Colenbrander [0x32] = ABS_RX, /* right stick X */ 9849131f8ccSRoderick Colenbrander [0x33] = ABS_Z, /* L2 */ 9859131f8ccSRoderick Colenbrander [0x34] = ABS_RZ, /* R2 */ 9869131f8ccSRoderick Colenbrander [0x35] = ABS_RY, /* right stick Y */ 9879131f8ccSRoderick Colenbrander }; 9889131f8ccSRoderick Colenbrander 9899131f8ccSRoderick Colenbrander static const unsigned int ds4_keymap[] = { 9909131f8ccSRoderick Colenbrander [0x1] = BTN_WEST, /* Square */ 9919131f8ccSRoderick Colenbrander [0x2] = BTN_SOUTH, /* Cross */ 9929131f8ccSRoderick Colenbrander [0x3] = BTN_EAST, /* Circle */ 9939131f8ccSRoderick Colenbrander [0x4] = BTN_NORTH, /* Triangle */ 9949131f8ccSRoderick Colenbrander [0x5] = BTN_TL, /* L1 */ 9959131f8ccSRoderick Colenbrander [0x6] = BTN_TR, /* R1 */ 9969131f8ccSRoderick Colenbrander [0x7] = BTN_TL2, /* L2 */ 9979131f8ccSRoderick Colenbrander [0x8] = BTN_TR2, /* R2 */ 9989131f8ccSRoderick Colenbrander [0x9] = BTN_SELECT, /* Share */ 9999131f8ccSRoderick Colenbrander [0xa] = BTN_START, /* Options */ 10009131f8ccSRoderick Colenbrander [0xb] = BTN_THUMBL, /* L3 */ 10019131f8ccSRoderick Colenbrander [0xc] = BTN_THUMBR, /* R3 */ 10029131f8ccSRoderick Colenbrander [0xd] = BTN_MODE, /* PS */ 10039131f8ccSRoderick Colenbrander }; 10049131f8ccSRoderick Colenbrander 10059131f8ccSRoderick Colenbrander 1006d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = { 1007d902f472SFrank Praznik POWER_SUPPLY_PROP_PRESENT, 1008d902f472SFrank Praznik POWER_SUPPLY_PROP_CAPACITY, 1009d902f472SFrank Praznik POWER_SUPPLY_PROP_SCOPE, 1010d902f472SFrank Praznik POWER_SUPPLY_PROP_STATUS, 1011d902f472SFrank Praznik }; 1012d902f472SFrank Praznik 101355d3b664SFrank Praznik struct sixaxis_led { 10141adf904eSPavel Machek u8 time_enabled; /* the total time the led is active (0xff means forever) */ 10151adf904eSPavel Machek u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ 10161adf904eSPavel Machek u8 enabled; 10171adf904eSPavel Machek u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ 10181adf904eSPavel Machek u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ 101955d3b664SFrank Praznik } __packed; 102055d3b664SFrank Praznik 102155d3b664SFrank Praznik struct sixaxis_rumble { 10221adf904eSPavel Machek u8 padding; 10231adf904eSPavel Machek u8 right_duration; /* Right motor duration (0xff means forever) */ 10241adf904eSPavel Machek u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ 10251adf904eSPavel Machek u8 left_duration; /* Left motor duration (0xff means forever) */ 10261adf904eSPavel Machek u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ 102755d3b664SFrank Praznik } __packed; 102855d3b664SFrank Praznik 102955d3b664SFrank Praznik struct sixaxis_output_report { 10301adf904eSPavel Machek u8 report_id; 103155d3b664SFrank Praznik struct sixaxis_rumble rumble; 10321adf904eSPavel Machek u8 padding[4]; 10331adf904eSPavel Machek u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ 103455d3b664SFrank Praznik struct sixaxis_led led[4]; /* LEDx at (4 - x) */ 103555d3b664SFrank Praznik struct sixaxis_led _reserved; /* LED5, not actually soldered */ 103655d3b664SFrank Praznik } __packed; 103755d3b664SFrank Praznik 103855d3b664SFrank Praznik union sixaxis_output_report_01 { 103955d3b664SFrank Praznik struct sixaxis_output_report data; 10401adf904eSPavel Machek u8 buf[36]; 104155d3b664SFrank Praznik }; 104255d3b664SFrank Praznik 1043c5e0c1c4SFrank Praznik struct motion_output_report_02 { 1044c5e0c1c4SFrank Praznik u8 type, zero; 1045c5e0c1c4SFrank Praznik u8 r, g, b; 1046c5e0c1c4SFrank Praznik u8 zero2; 1047c5e0c1c4SFrank Praznik u8 rumble; 1048c5e0c1c4SFrank Praznik }; 1049c5e0c1c4SFrank Praznik 10502c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x02_SIZE 37 10512c159de0SRoderick Colenbrander #define DS4_FEATURE_REPORT_0x81_SIZE 7 105249b9ca6cSRoderick Colenbrander #define DS4_INPUT_REPORT_0x11_SIZE 78 10532c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x05_SIZE 32 10542c159de0SRoderick Colenbrander #define DS4_OUTPUT_REPORT_0x11_SIZE 78 105529b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17 1056a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8 105741d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49 10589b2b5c9aSFrank Praznik 1059cdc1c021SRoderick Colenbrander /* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an 1060cdc1c021SRoderick Colenbrander * additional +2. 1061cdc1c021SRoderick Colenbrander */ 1062ac797b95SRoderick Colenbrander #define DS4_INPUT_REPORT_BUTTON_OFFSET 5 1063cdc1c021SRoderick Colenbrander #define DS4_INPUT_REPORT_BATTERY_OFFSET 30 1064cdc1c021SRoderick Colenbrander #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 1065cdc1c021SRoderick Colenbrander 1066ac797b95SRoderick Colenbrander #define DS4_TOUCHPAD_SUFFIX " Touchpad" 1067ac797b95SRoderick Colenbrander 10688b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock); 1069d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list); 10708025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator); 1071d2d782fcSFrank Praznik 1072cc6e0bbbSJiri Kosina struct sony_sc { 1073d902f472SFrank Praznik spinlock_t lock; 1074d2d782fcSFrank Praznik struct list_head list_node; 10750a286ef2SSven Eckelmann struct hid_device *hdev; 1076ac797b95SRoderick Colenbrander struct input_dev *touchpad; 107760781cf4SFrank Praznik struct led_classdev *leds[MAX_LEDS]; 1078cc6e0bbbSJiri Kosina unsigned long quirks; 10790a286ef2SSven Eckelmann struct work_struct state_worker; 1080d8aaccdaSFrank Praznik void (*send_output_report)(struct sony_sc *); 1081297d716fSKrzysztof Kozlowski struct power_supply *battery; 1082297d716fSKrzysztof Kozlowski struct power_supply_desc battery_desc; 10838025087aSFrank Praznik int device_id; 10841adf904eSPavel Machek u8 *output_report_dmabuf; 1085f04d5140SColin Leitner 10869f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF 10871adf904eSPavel Machek u8 left; 10881adf904eSPavel Machek u8 right; 10899f323b68SSven Eckelmann #endif 10909f323b68SSven Eckelmann 10911adf904eSPavel Machek u8 mac_address[6]; 10921adf904eSPavel Machek u8 worker_initialized; 10932a242932SFrank Praznik u8 defer_initialization; 10941adf904eSPavel Machek u8 cable_state; 10951adf904eSPavel Machek u8 battery_charging; 10961adf904eSPavel Machek u8 battery_capacity; 10971adf904eSPavel Machek u8 led_state[MAX_LEDS]; 10981adf904eSPavel Machek u8 resume_led_state[MAX_LEDS]; 10991adf904eSPavel Machek u8 led_delay_on[MAX_LEDS]; 11001adf904eSPavel Machek u8 led_delay_off[MAX_LEDS]; 11011adf904eSPavel Machek u8 led_count; 1102cc6e0bbbSJiri Kosina }; 1103cc6e0bbbSJiri Kosina 11042a242932SFrank Praznik static inline void sony_schedule_work(struct sony_sc *sc) 11052a242932SFrank Praznik { 11062a242932SFrank Praznik if (!sc->defer_initialization) 11072a242932SFrank Praznik schedule_work(&sc->state_worker); 11082a242932SFrank Praznik } 11092a242932SFrank Praznik 11101adf904eSPavel Machek static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc, 1111c607fb8dSAntonio Ospite unsigned int *rsize) 1112c607fb8dSAntonio Ospite { 1113c607fb8dSAntonio Ospite *rsize = sizeof(sixaxis_rdesc); 1114c607fb8dSAntonio Ospite return sixaxis_rdesc; 1115c607fb8dSAntonio Ospite } 1116c607fb8dSAntonio Ospite 1117c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, 1118c5e0c1c4SFrank Praznik unsigned int *rsize) 1119c5e0c1c4SFrank Praznik { 1120c5e0c1c4SFrank Praznik *rsize = sizeof(motion_rdesc); 1121c5e0c1c4SFrank Praznik return motion_rdesc; 1122c5e0c1c4SFrank Praznik } 1123c5e0c1c4SFrank Praznik 1124b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc, 1125b2723eb7SSimon Wood unsigned int *rsize) 1126b2723eb7SSimon Wood { 1127b2723eb7SSimon Wood *rsize = sizeof(navigation_rdesc); 1128b2723eb7SSimon Wood return navigation_rdesc; 1129b2723eb7SSimon Wood } 1130b2723eb7SSimon Wood 11311adf904eSPavel Machek static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc, 1132078328daSJiri Kosina unsigned int *rsize) 1133078328daSJiri Kosina { 1134078328daSJiri Kosina *rsize = sizeof(ps3remote_rdesc); 1135078328daSJiri Kosina return ps3remote_rdesc; 1136078328daSJiri Kosina } 1137078328daSJiri Kosina 1138078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, 1139078328daSJiri Kosina struct hid_field *field, struct hid_usage *usage, 1140078328daSJiri Kosina unsigned long **bit, int *max) 1141078328daSJiri Kosina { 1142078328daSJiri Kosina unsigned int key = usage->hid & HID_USAGE; 1143078328daSJiri Kosina 1144078328daSJiri Kosina if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1145078328daSJiri Kosina return -1; 1146078328daSJiri Kosina 1147078328daSJiri Kosina switch (usage->collection_index) { 1148078328daSJiri Kosina case 1: 1149078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) 1150078328daSJiri Kosina return -1; 1151078328daSJiri Kosina 1152078328daSJiri Kosina key = ps3remote_keymap_joypad_buttons[key]; 1153078328daSJiri Kosina if (!key) 1154078328daSJiri Kosina return -1; 1155078328daSJiri Kosina break; 1156078328daSJiri Kosina case 2: 1157078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) 1158078328daSJiri Kosina return -1; 1159078328daSJiri Kosina 1160078328daSJiri Kosina key = ps3remote_keymap_remote_buttons[key]; 1161078328daSJiri Kosina if (!key) 1162078328daSJiri Kosina return -1; 1163078328daSJiri Kosina break; 1164078328daSJiri Kosina default: 1165078328daSJiri Kosina return -1; 1166078328daSJiri Kosina } 1167078328daSJiri Kosina 1168078328daSJiri Kosina hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1169078328daSJiri Kosina return 1; 1170078328daSJiri Kosina } 1171078328daSJiri Kosina 11729131f8ccSRoderick Colenbrander static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi, 11739131f8ccSRoderick Colenbrander struct hid_field *field, struct hid_usage *usage, 11749131f8ccSRoderick Colenbrander unsigned long **bit, int *max) 11759131f8ccSRoderick Colenbrander { 11769131f8ccSRoderick Colenbrander if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { 11779131f8ccSRoderick Colenbrander unsigned int key = usage->hid & HID_USAGE; 11789131f8ccSRoderick Colenbrander 11799131f8ccSRoderick Colenbrander if (key >= ARRAY_SIZE(ds4_keymap)) 11809131f8ccSRoderick Colenbrander return -1; 11819131f8ccSRoderick Colenbrander 11829131f8ccSRoderick Colenbrander key = ds4_keymap[key]; 11839131f8ccSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 11849131f8ccSRoderick Colenbrander return 1; 11859131f8ccSRoderick Colenbrander } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { 11869131f8ccSRoderick Colenbrander unsigned int abs = usage->hid & HID_USAGE; 11879131f8ccSRoderick Colenbrander 11889131f8ccSRoderick Colenbrander /* Let the HID parser deal with the HAT. */ 11899131f8ccSRoderick Colenbrander if (usage->hid == HID_GD_HATSWITCH) 11909131f8ccSRoderick Colenbrander return 0; 11919131f8ccSRoderick Colenbrander 11929131f8ccSRoderick Colenbrander if (abs >= ARRAY_SIZE(ds4_absmap)) 11939131f8ccSRoderick Colenbrander return -1; 11949131f8ccSRoderick Colenbrander 11959131f8ccSRoderick Colenbrander abs = ds4_absmap[abs]; 11969131f8ccSRoderick Colenbrander hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); 11979131f8ccSRoderick Colenbrander return 1; 11989131f8ccSRoderick Colenbrander } 11999131f8ccSRoderick Colenbrander 12009131f8ccSRoderick Colenbrander return 0; 12019131f8ccSRoderick Colenbrander } 12029131f8ccSRoderick Colenbrander 12031adf904eSPavel Machek static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, 120473e4008dSNikolai Kondrashov unsigned int *rsize) 1205cc6e0bbbSJiri Kosina { 1206cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev); 1207cc6e0bbbSJiri Kosina 12084ba1eeebSMikko Perttunen if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT)) 120974500cc8SScott Moreau return rdesc; 121074500cc8SScott Moreau 121199d24902SFernando Luis Vázquez Cao /* 121299d24902SFernando Luis Vázquez Cao * Some Sony RF receivers wrongly declare the mouse pointer as a 121399d24902SFernando Luis Vázquez Cao * a constant non-data variable. 121499d24902SFernando Luis Vázquez Cao */ 121599d24902SFernando Luis Vázquez Cao if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 && 121699d24902SFernando Luis Vázquez Cao /* usage page: generic desktop controls */ 121799d24902SFernando Luis Vázquez Cao /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */ 121899d24902SFernando Luis Vázquez Cao /* usage: mouse */ 121999d24902SFernando Luis Vázquez Cao rdesc[2] == 0x09 && rdesc[3] == 0x02 && 122099d24902SFernando Luis Vázquez Cao /* input (usage page for x,y axes): constant, variable, relative */ 122199d24902SFernando Luis Vázquez Cao rdesc[54] == 0x81 && rdesc[55] == 0x07) { 1222a4649184SFernando Luis Vázquez Cao hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n"); 122399d24902SFernando Luis Vázquez Cao /* input: data, variable, relative */ 1224cc6e0bbbSJiri Kosina rdesc[55] = 0x06; 1225cc6e0bbbSJiri Kosina } 122661ab44beSSimon Wood 1227ed19d8cfSFrank Praznik /* 1228ed19d8cfSFrank Praznik * The default Dualshock 4 USB descriptor doesn't assign 1229ed19d8cfSFrank Praznik * the gyroscope values to corresponding axes so we need a 1230ed19d8cfSFrank Praznik * modified one. 1231ed19d8cfSFrank Praznik */ 1232b71b5578SFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 1233ed19d8cfSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); 1234ed19d8cfSFrank Praznik rdesc = dualshock4_usb_rdesc; 1235ed19d8cfSFrank Praznik *rsize = sizeof(dualshock4_usb_rdesc); 1236b71b5578SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { 1237d829674dSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n"); 1238d829674dSFrank Praznik rdesc = dualshock4_bt_rdesc; 1239d829674dSFrank Praznik *rsize = sizeof(dualshock4_bt_rdesc); 1240ed19d8cfSFrank Praznik } 1241ed19d8cfSFrank Praznik 1242c607fb8dSAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER) 1243c607fb8dSAntonio Ospite return sixaxis_fixup(hdev, rdesc, rsize); 1244078328daSJiri Kosina 1245c5e0c1c4SFrank Praznik if (sc->quirks & MOTION_CONTROLLER) 1246c5e0c1c4SFrank Praznik return motion_fixup(hdev, rdesc, rsize); 1247c5e0c1c4SFrank Praznik 12484545ee0aSSimon Wood if (sc->quirks & NAVIGATION_CONTROLLER) 1249b2723eb7SSimon Wood return navigation_fixup(hdev, rdesc, rsize); 12504545ee0aSSimon Wood 1251078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1252078328daSJiri Kosina return ps3remote_fixup(hdev, rdesc, rsize); 1253078328daSJiri Kosina 125473e4008dSNikolai Kondrashov return rdesc; 1255cc6e0bbbSJiri Kosina } 1256cc6e0bbbSJiri Kosina 12571adf904eSPavel Machek static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) 1258d902f472SFrank Praznik { 12591adf904eSPavel Machek static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; 1260d902f472SFrank Praznik unsigned long flags; 126112e9a6d7SSimon Wood int offset; 12621adf904eSPavel Machek u8 cable_state, battery_capacity, battery_charging; 1263d902f472SFrank Praznik 1264ad142b9eSFrank Praznik /* 1265ad142b9eSFrank Praznik * The sixaxis is charging if the battery value is 0xee 1266d902f472SFrank Praznik * and it is fully charged if the value is 0xef. 1267d902f472SFrank Praznik * It does not report the actual level while charging so it 1268d902f472SFrank Praznik * is set to 100% while charging is in progress. 1269d902f472SFrank Praznik */ 127012e9a6d7SSimon Wood offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30; 127112e9a6d7SSimon Wood 127212e9a6d7SSimon Wood if (rd[offset] >= 0xee) { 1273d902f472SFrank Praznik battery_capacity = 100; 127412e9a6d7SSimon Wood battery_charging = !(rd[offset] & 0x01); 12759fddd74aSFrank Praznik cable_state = 1; 1276d902f472SFrank Praznik } else { 12771adf904eSPavel Machek u8 index = rd[offset] <= 5 ? rd[offset] : 5; 1278ac3c9a94SFrank Praznik battery_capacity = sixaxis_battery_capacity[index]; 1279d902f472SFrank Praznik battery_charging = 0; 12809fddd74aSFrank Praznik cable_state = 0; 1281d902f472SFrank Praznik } 1282d902f472SFrank Praznik 1283d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1284d902f472SFrank Praznik sc->cable_state = cable_state; 1285d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1286d902f472SFrank Praznik sc->battery_charging = battery_charging; 1287d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1288d902f472SFrank Praznik } 1289d902f472SFrank Praznik 12901adf904eSPavel Machek static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) 1291d902f472SFrank Praznik { 1292d902f472SFrank Praznik unsigned long flags; 1293cdc1c021SRoderick Colenbrander int n, m, offset, num_touch_data, max_touch_data; 12941adf904eSPavel Machek u8 cable_state, battery_capacity, battery_charging; 1295d902f472SFrank Praznik 1296cdc1c021SRoderick Colenbrander /* When using Bluetooth the header is 2 bytes longer, so skip these. */ 1297cdc1c021SRoderick Colenbrander int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2; 12986c5f860dSFrank Praznik 1299ac797b95SRoderick Colenbrander /* Second bit of third button byte is for the touchpad button. */ 1300ac797b95SRoderick Colenbrander offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET; 1301ac797b95SRoderick Colenbrander input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2); 1302ac797b95SRoderick Colenbrander 1303ad142b9eSFrank Praznik /* 1304cdc1c021SRoderick Colenbrander * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level 1305d902f472SFrank Praznik * and the 5th bit contains the USB cable state. 1306d902f472SFrank Praznik */ 1307cdc1c021SRoderick Colenbrander offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET; 13086c5f860dSFrank Praznik cable_state = (rd[offset] >> 4) & 0x01; 13096c5f860dSFrank Praznik battery_capacity = rd[offset] & 0x0F; 1310d902f472SFrank Praznik 1311ad142b9eSFrank Praznik /* 1312ad142b9eSFrank Praznik * When a USB power source is connected the battery level ranges from 13136c5f860dSFrank Praznik * 0 to 10, and when running on battery power it ranges from 0 to 9. 13146c5f860dSFrank Praznik * A battery level above 10 when plugged in means charge completed. 1315d902f472SFrank Praznik */ 13166c5f860dSFrank Praznik if (!cable_state || battery_capacity > 10) 1317d902f472SFrank Praznik battery_charging = 0; 1318d902f472SFrank Praznik else 1319d902f472SFrank Praznik battery_charging = 1; 1320d902f472SFrank Praznik 13216c5f860dSFrank Praznik if (!cable_state) 13226c5f860dSFrank Praznik battery_capacity++; 1323d902f472SFrank Praznik if (battery_capacity > 10) 13246c5f860dSFrank Praznik battery_capacity = 10; 13256c5f860dSFrank Praznik 1326d902f472SFrank Praznik battery_capacity *= 10; 1327d902f472SFrank Praznik 1328d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1329d902f472SFrank Praznik sc->cable_state = cable_state; 1330d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1331d902f472SFrank Praznik sc->battery_charging = battery_charging; 1332d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1333e5606230SFrank Praznik 1334cdc1c021SRoderick Colenbrander /* 1335cdc1c021SRoderick Colenbrander * The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB 1336cdc1c021SRoderick Colenbrander * and 35 on Bluetooth. 1337cdc1c021SRoderick Colenbrander * The first byte indicates the number of touch data in the report. 1338cdc1c021SRoderick Colenbrander * Trackpad data starts 2 bytes later (e.g. 35 for USB). 1339cdc1c021SRoderick Colenbrander */ 1340cdc1c021SRoderick Colenbrander offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET; 1341cdc1c021SRoderick Colenbrander max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4; 1342cdc1c021SRoderick Colenbrander if (rd[offset] > 0 && rd[offset] <= max_touch_data) 1343cdc1c021SRoderick Colenbrander num_touch_data = rd[offset]; 1344cdc1c021SRoderick Colenbrander else 1345cdc1c021SRoderick Colenbrander num_touch_data = 1; 1346cdc1c021SRoderick Colenbrander offset += 1; 1347cdc1c021SRoderick Colenbrander 1348cdc1c021SRoderick Colenbrander for (m = 0; m < num_touch_data; m++) { 1349cdc1c021SRoderick Colenbrander /* Skip past timestamp */ 1350cdc1c021SRoderick Colenbrander offset += 1; 13516c5f860dSFrank Praznik 1352ad142b9eSFrank Praznik /* 1353cdc1c021SRoderick Colenbrander * The first 7 bits of the first byte is a counter and bit 8 is 1354cdc1c021SRoderick Colenbrander * a touch indicator that is 0 when pressed and 1 when not 1355cdc1c021SRoderick Colenbrander * pressed. 1356e5606230SFrank Praznik * The next 3 bytes are two 12 bit touch coordinates, X and Y. 1357cdc1c021SRoderick Colenbrander * The data for the second touch is in the same format and 1358cdc1c021SRoderick Colenbrander * immediately follows the data for the first. 1359e5606230SFrank Praznik */ 1360e5606230SFrank Praznik for (n = 0; n < 2; n++) { 13611adf904eSPavel Machek u16 x, y; 1362cdc1c021SRoderick Colenbrander bool active; 1363e5606230SFrank Praznik 1364e5606230SFrank Praznik x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); 1365e5606230SFrank Praznik y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); 1366e5606230SFrank Praznik 1367cdc1c021SRoderick Colenbrander active = !(rd[offset] >> 7); 1368ac797b95SRoderick Colenbrander input_mt_slot(sc->touchpad, n); 1369ac797b95SRoderick Colenbrander input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active); 1370cdc1c021SRoderick Colenbrander 1371cdc1c021SRoderick Colenbrander if (active) { 1372ac797b95SRoderick Colenbrander input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x); 1373ac797b95SRoderick Colenbrander input_report_abs(sc->touchpad, ABS_MT_POSITION_Y, y); 1374cdc1c021SRoderick Colenbrander } 1375e5606230SFrank Praznik 1376e5606230SFrank Praznik offset += 4; 1377e5606230SFrank Praznik } 1378ac797b95SRoderick Colenbrander input_mt_sync_frame(sc->touchpad); 1379ac797b95SRoderick Colenbrander input_sync(sc->touchpad); 1380cdc1c021SRoderick Colenbrander } 1381d902f472SFrank Praznik } 1382d902f472SFrank Praznik 1383c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, 13841adf904eSPavel Machek u8 *rd, int size) 1385c9e4d877SSimon Wood { 1386c9e4d877SSimon Wood struct sony_sc *sc = hid_get_drvdata(hdev); 1387c9e4d877SSimon Wood 1388ad142b9eSFrank Praznik /* 1389ad142b9eSFrank Praznik * Sixaxis HID report has acclerometers/gyro with MSByte first, this 1390c9e4d877SSimon Wood * has to be BYTE_SWAPPED before passing up to joystick interface 1391c9e4d877SSimon Wood */ 1392fee4e2d5SFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { 13938f5f0bc2SFrank Praznik /* 13948f5f0bc2SFrank Praznik * When connected via Bluetooth the Sixaxis occasionally sends 13958f5f0bc2SFrank Praznik * a report with the second byte 0xff and the rest zeroed. 13968f5f0bc2SFrank Praznik * 13978f5f0bc2SFrank Praznik * This report does not reflect the actual state of the 13988f5f0bc2SFrank Praznik * controller must be ignored to avoid generating false input 13998f5f0bc2SFrank Praznik * events. 14008f5f0bc2SFrank Praznik */ 14018f5f0bc2SFrank Praznik if (rd[1] == 0xff) 14028f5f0bc2SFrank Praznik return -EINVAL; 14038f5f0bc2SFrank Praznik 1404c9e4d877SSimon Wood swap(rd[41], rd[42]); 1405c9e4d877SSimon Wood swap(rd[43], rd[44]); 1406c9e4d877SSimon Wood swap(rd[45], rd[46]); 1407c9e4d877SSimon Wood swap(rd[47], rd[48]); 1408d902f472SFrank Praznik 1409d902f472SFrank Praznik sixaxis_parse_report(sc, rd, size); 141012e9a6d7SSimon Wood } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { 141112e9a6d7SSimon Wood sixaxis_parse_report(sc, rd, size); 14124545ee0aSSimon Wood } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && 14134545ee0aSSimon Wood size == 49) { 14144545ee0aSSimon Wood sixaxis_parse_report(sc, rd, size); 141568330d83SFrank Praznik } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && 141668330d83SFrank Praznik size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) 141768330d83SFrank Praznik && rd[0] == 0x11 && size == 78)) { 141849b9ca6cSRoderick Colenbrander if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { 141949b9ca6cSRoderick Colenbrander /* CRC check */ 142049b9ca6cSRoderick Colenbrander u8 bthdr = 0xA1; 142149b9ca6cSRoderick Colenbrander u32 crc; 142249b9ca6cSRoderick Colenbrander u32 report_crc; 142349b9ca6cSRoderick Colenbrander 142449b9ca6cSRoderick Colenbrander crc = crc32_le(0xFFFFFFFF, &bthdr, 1); 142549b9ca6cSRoderick Colenbrander crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); 142649b9ca6cSRoderick Colenbrander report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); 142749b9ca6cSRoderick Colenbrander if (crc != report_crc) { 142849b9ca6cSRoderick Colenbrander hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", 142949b9ca6cSRoderick Colenbrander report_crc, crc); 143049b9ca6cSRoderick Colenbrander return -EILSEQ; 143149b9ca6cSRoderick Colenbrander } 143249b9ca6cSRoderick Colenbrander } 1433d902f472SFrank Praznik dualshock4_parse_report(sc, rd, size); 1434c9e4d877SSimon Wood } 1435c9e4d877SSimon Wood 14362a242932SFrank Praznik if (sc->defer_initialization) { 14372a242932SFrank Praznik sc->defer_initialization = 0; 14382a242932SFrank Praznik sony_schedule_work(sc); 14392a242932SFrank Praznik } 14402a242932SFrank Praznik 1441c9e4d877SSimon Wood return 0; 1442c9e4d877SSimon Wood } 1443c9e4d877SSimon Wood 1444f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, 1445f04d5140SColin Leitner struct hid_field *field, struct hid_usage *usage, 1446f04d5140SColin Leitner unsigned long **bit, int *max) 1447f04d5140SColin Leitner { 1448f04d5140SColin Leitner struct sony_sc *sc = hid_get_drvdata(hdev); 1449f04d5140SColin Leitner 1450f04d5140SColin Leitner if (sc->quirks & BUZZ_CONTROLLER) { 1451f04d5140SColin Leitner unsigned int key = usage->hid & HID_USAGE; 1452f04d5140SColin Leitner 1453f04d5140SColin Leitner if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1454f04d5140SColin Leitner return -1; 1455f04d5140SColin Leitner 1456f04d5140SColin Leitner switch (usage->collection_index) { 1457f04d5140SColin Leitner case 1: 1458f04d5140SColin Leitner if (key >= ARRAY_SIZE(buzz_keymap)) 1459f04d5140SColin Leitner return -1; 1460f04d5140SColin Leitner 1461f04d5140SColin Leitner key = buzz_keymap[key]; 1462f04d5140SColin Leitner if (!key) 1463f04d5140SColin Leitner return -1; 1464f04d5140SColin Leitner break; 1465f04d5140SColin Leitner default: 1466f04d5140SColin Leitner return -1; 1467f04d5140SColin Leitner } 1468f04d5140SColin Leitner 1469f04d5140SColin Leitner hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1470f04d5140SColin Leitner return 1; 1471f04d5140SColin Leitner } 1472f04d5140SColin Leitner 1473078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1474078328daSJiri Kosina return ps3remote_mapping(hdev, hi, field, usage, bit, max); 1475078328daSJiri Kosina 14769131f8ccSRoderick Colenbrander 14779131f8ccSRoderick Colenbrander if (sc->quirks & DUALSHOCK4_CONTROLLER) 14789131f8ccSRoderick Colenbrander return ds4_mapping(hdev, hi, field, usage, bit, max); 14799131f8ccSRoderick Colenbrander 14806f498018SBenjamin Tissoires /* Let hid-core decide for the others */ 14816f498018SBenjamin Tissoires return 0; 1482f04d5140SColin Leitner } 1483f04d5140SColin Leitner 1484ac797b95SRoderick Colenbrander static int sony_register_touchpad(struct sony_sc *sc, int touch_count, 1485ce8efc3bSFrank Praznik int w, int h) 1486ce8efc3bSFrank Praznik { 1487ac797b95SRoderick Colenbrander size_t name_sz; 1488ac797b95SRoderick Colenbrander char *name; 1489ce8efc3bSFrank Praznik int ret; 1490ce8efc3bSFrank Praznik 1491ac797b95SRoderick Colenbrander sc->touchpad = input_allocate_device(); 1492ac797b95SRoderick Colenbrander if (!sc->touchpad) 1493ac797b95SRoderick Colenbrander return -ENOMEM; 1494ce8efc3bSFrank Praznik 1495ac797b95SRoderick Colenbrander input_set_drvdata(sc->touchpad, sc); 1496ac797b95SRoderick Colenbrander sc->touchpad->dev.parent = &sc->hdev->dev; 1497ac797b95SRoderick Colenbrander sc->touchpad->phys = sc->hdev->phys; 1498ac797b95SRoderick Colenbrander sc->touchpad->uniq = sc->hdev->uniq; 1499ac797b95SRoderick Colenbrander sc->touchpad->id.bustype = sc->hdev->bus; 1500ac797b95SRoderick Colenbrander sc->touchpad->id.vendor = sc->hdev->vendor; 1501ac797b95SRoderick Colenbrander sc->touchpad->id.product = sc->hdev->product; 1502ac797b95SRoderick Colenbrander sc->touchpad->id.version = sc->hdev->version; 1503ac797b95SRoderick Colenbrander 1504ac797b95SRoderick Colenbrander /* Append a suffix to the controller name as there are various 1505ac797b95SRoderick Colenbrander * DS4 compatible non-Sony devices with different names. 1506ac797b95SRoderick Colenbrander */ 1507ac797b95SRoderick Colenbrander name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX); 1508ac797b95SRoderick Colenbrander name = kzalloc(name_sz, GFP_KERNEL); 1509ac797b95SRoderick Colenbrander if (!name) { 1510ac797b95SRoderick Colenbrander ret = -ENOMEM; 1511ac797b95SRoderick Colenbrander goto err; 1512ac797b95SRoderick Colenbrander } 1513ac797b95SRoderick Colenbrander snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name); 1514ac797b95SRoderick Colenbrander sc->touchpad->name = name; 1515ac797b95SRoderick Colenbrander 1516ac797b95SRoderick Colenbrander ret = input_mt_init_slots(sc->touchpad, touch_count, 0); 1517ac797b95SRoderick Colenbrander if (ret < 0) 1518ac797b95SRoderick Colenbrander goto err; 1519ac797b95SRoderick Colenbrander 1520ac797b95SRoderick Colenbrander /* We map the button underneath the touchpad to BTN_LEFT. */ 1521ac797b95SRoderick Colenbrander __set_bit(EV_KEY, sc->touchpad->evbit); 1522ac797b95SRoderick Colenbrander __set_bit(BTN_LEFT, sc->touchpad->keybit); 1523ac797b95SRoderick Colenbrander __set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit); 1524ac797b95SRoderick Colenbrander 1525ac797b95SRoderick Colenbrander input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0); 1526ac797b95SRoderick Colenbrander input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0); 1527ac797b95SRoderick Colenbrander 1528ac797b95SRoderick Colenbrander ret = input_register_device(sc->touchpad); 1529ac797b95SRoderick Colenbrander if (ret < 0) 1530ac797b95SRoderick Colenbrander goto err; 1531ce8efc3bSFrank Praznik 1532ce8efc3bSFrank Praznik return 0; 1533ac797b95SRoderick Colenbrander 1534ac797b95SRoderick Colenbrander err: 1535ac797b95SRoderick Colenbrander kfree(sc->touchpad->name); 1536ac797b95SRoderick Colenbrander sc->touchpad->name = NULL; 1537ac797b95SRoderick Colenbrander 1538ac797b95SRoderick Colenbrander input_free_device(sc->touchpad); 1539ac797b95SRoderick Colenbrander sc->touchpad = NULL; 1540ac797b95SRoderick Colenbrander 1541ac797b95SRoderick Colenbrander return ret; 1542ce8efc3bSFrank Praznik } 1543ce8efc3bSFrank Praznik 1544ac797b95SRoderick Colenbrander static void sony_unregister_touchpad(struct sony_sc *sc) 1545ac797b95SRoderick Colenbrander { 1546ac797b95SRoderick Colenbrander if (!sc->touchpad) 1547ac797b95SRoderick Colenbrander return; 1548ac797b95SRoderick Colenbrander 1549ac797b95SRoderick Colenbrander kfree(sc->touchpad->name); 1550ac797b95SRoderick Colenbrander sc->touchpad->name = NULL; 1551ac797b95SRoderick Colenbrander 1552ac797b95SRoderick Colenbrander input_unregister_device(sc->touchpad); 1553ac797b95SRoderick Colenbrander sc->touchpad = NULL; 1554ac797b95SRoderick Colenbrander } 15559154301aSDmitry Torokhov 15565710fabfSAntonio Ospite /* 1557bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 1558bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any 1559bd28ce00SJiri Slaby * events. 1560bd28ce00SJiri Slaby */ 1561816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev) 1562bd28ce00SJiri Slaby { 1563a85d67b5SAntonio Ospite const int buf_size = 1564a85d67b5SAntonio Ospite max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); 15651adf904eSPavel Machek u8 *buf; 1566bd28ce00SJiri Slaby int ret; 1567bd28ce00SJiri Slaby 15682e701a35SAntonio Ospite buf = kmalloc(buf_size, GFP_KERNEL); 1569bd28ce00SJiri Slaby if (!buf) 1570bd28ce00SJiri Slaby return -ENOMEM; 1571bd28ce00SJiri Slaby 1572a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE, 1573a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1574a7de9b86SLauri Kasanen if (ret < 0) { 1575a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 1\n"); 1576a7de9b86SLauri Kasanen goto out; 1577a7de9b86SLauri Kasanen } 1578f204828aSBenjamin Tissoires 1579a7de9b86SLauri Kasanen /* 1580a7de9b86SLauri Kasanen * Some compatible controllers like the Speedlink Strike FX and 1581a7de9b86SLauri Kasanen * Gasia need another query plus an USB interrupt to get operational. 1582a7de9b86SLauri Kasanen */ 1583a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE, 1584a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1585a7de9b86SLauri Kasanen if (ret < 0) { 1586a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 2\n"); 1587a7de9b86SLauri Kasanen goto out; 1588a7de9b86SLauri Kasanen } 1589a7de9b86SLauri Kasanen 1590a7de9b86SLauri Kasanen ret = hid_hw_output_report(hdev, buf, 1); 159119f4c2baSBenjamin Tissoires if (ret < 0) { 159219f4c2baSBenjamin Tissoires hid_info(hdev, "can't set operational mode: step 3, ignoring\n"); 159319f4c2baSBenjamin Tissoires ret = 0; 159419f4c2baSBenjamin Tissoires } 1595bd28ce00SJiri Slaby 1596a7de9b86SLauri Kasanen out: 1597bd28ce00SJiri Slaby kfree(buf); 1598bd28ce00SJiri Slaby 1599bd28ce00SJiri Slaby return ret; 1600bd28ce00SJiri Slaby } 1601bd28ce00SJiri Slaby 1602816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev) 1603f9ce7c28SBastien Nocera { 16041adf904eSPavel Machek static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 16051adf904eSPavel Machek u8 *buf; 16069b2b5c9aSFrank Praznik int ret; 16079b2b5c9aSFrank Praznik 16089b2b5c9aSFrank Praznik buf = kmemdup(report, sizeof(report), GFP_KERNEL); 16099b2b5c9aSFrank Praznik if (!buf) 16109b2b5c9aSFrank Praznik return -ENOMEM; 16119b2b5c9aSFrank Praznik 16129b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), 1613b0dd72aaSBenjamin Tissoires HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 16149b2b5c9aSFrank Praznik 16159b2b5c9aSFrank Praznik kfree(buf); 16169b2b5c9aSFrank Praznik 16179b2b5c9aSFrank Praznik return ret; 1618f9ce7c28SBastien Nocera } 1619f9ce7c28SBastien Nocera 1620ad142b9eSFrank Praznik /* 1621ad142b9eSFrank Praznik * Requesting feature report 0x02 in Bluetooth mode changes the state of the 162268330d83SFrank Praznik * controller so that it sends full input reports of type 0x11. 162368330d83SFrank Praznik */ 162468330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev) 162568330d83SFrank Praznik { 16261adf904eSPavel Machek u8 *buf; 16279b2b5c9aSFrank Praznik int ret; 162868330d83SFrank Praznik 16292c159de0SRoderick Colenbrander buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); 16309b2b5c9aSFrank Praznik if (!buf) 16319b2b5c9aSFrank Praznik return -ENOMEM; 16329b2b5c9aSFrank Praznik 16332c159de0SRoderick Colenbrander ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE, 163468330d83SFrank Praznik HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 16359b2b5c9aSFrank Praznik 16369b2b5c9aSFrank Praznik kfree(buf); 16379b2b5c9aSFrank Praznik 16389b2b5c9aSFrank Praznik return ret; 1639bd28ce00SJiri Slaby } 1640bd28ce00SJiri Slaby 1641221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc) 16428025087aSFrank Praznik { 16431adf904eSPavel Machek static const u8 sixaxis_leds[10][4] = { 16448025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x00 }, 16458025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x00 }, 16468025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x00 }, 16478025087aSFrank Praznik { 0x00, 0x00, 0x00, 0x01 }, 16488025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x01 }, 16498025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x01 }, 16508025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x01 }, 16518025087aSFrank Praznik { 0x01, 0x00, 0x01, 0x01 }, 16528025087aSFrank Praznik { 0x00, 0x01, 0x01, 0x01 }, 16538025087aSFrank Praznik { 0x01, 0x01, 0x01, 0x01 } 16548025087aSFrank Praznik }; 16558025087aSFrank Praznik 1656221399b3SFrank Praznik int id = sc->device_id; 1657221399b3SFrank Praznik 1658221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); 16598025087aSFrank Praznik 16608025087aSFrank Praznik if (id < 0) 16618025087aSFrank Praznik return; 16628025087aSFrank Praznik 16638025087aSFrank Praznik id %= 10; 1664221399b3SFrank Praznik memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id])); 16658025087aSFrank Praznik } 16668025087aSFrank Praznik 1667221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc) 16688025087aSFrank Praznik { 16698025087aSFrank Praznik /* The first 4 color/index entries match what the PS4 assigns */ 16701adf904eSPavel Machek static const u8 color_code[7][3] = { 16718025087aSFrank Praznik /* Blue */ { 0x00, 0x00, 0x01 }, 16728025087aSFrank Praznik /* Red */ { 0x01, 0x00, 0x00 }, 16738025087aSFrank Praznik /* Green */ { 0x00, 0x01, 0x00 }, 16748025087aSFrank Praznik /* Pink */ { 0x02, 0x00, 0x01 }, 16758025087aSFrank Praznik /* Orange */ { 0x02, 0x01, 0x00 }, 16768025087aSFrank Praznik /* Teal */ { 0x00, 0x01, 0x01 }, 16778025087aSFrank Praznik /* White */ { 0x01, 0x01, 0x01 } 16788025087aSFrank Praznik }; 16798025087aSFrank Praznik 1680221399b3SFrank Praznik int id = sc->device_id; 1681221399b3SFrank Praznik 1682221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); 16838025087aSFrank Praznik 16848025087aSFrank Praznik if (id < 0) 16858025087aSFrank Praznik return; 16868025087aSFrank Praznik 16878025087aSFrank Praznik id %= 7; 1688221399b3SFrank Praznik memcpy(sc->led_state, color_code[id], sizeof(color_code[id])); 16898025087aSFrank Praznik } 16908025087aSFrank Praznik 1691221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc) 1692f04d5140SColin Leitner { 1693221399b3SFrank Praznik struct hid_device *hdev = sc->hdev; 1694f04d5140SColin Leitner struct list_head *report_list = 1695f04d5140SColin Leitner &hdev->report_enum[HID_OUTPUT_REPORT].report_list; 1696f04d5140SColin Leitner struct hid_report *report = list_entry(report_list->next, 1697f04d5140SColin Leitner struct hid_report, list); 16981adf904eSPavel Machek s32 *value = report->field[0]->value; 1699f04d5140SColin Leitner 1700221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < 4); 1701221399b3SFrank Praznik 1702f04d5140SColin Leitner value[0] = 0x00; 1703221399b3SFrank Praznik value[1] = sc->led_state[0] ? 0xff : 0x00; 1704221399b3SFrank Praznik value[2] = sc->led_state[1] ? 0xff : 0x00; 1705221399b3SFrank Praznik value[3] = sc->led_state[2] ? 0xff : 0x00; 1706221399b3SFrank Praznik value[4] = sc->led_state[3] ? 0xff : 0x00; 1707f04d5140SColin Leitner value[5] = 0x00; 1708f04d5140SColin Leitner value[6] = 0x00; 1709f04d5140SColin Leitner hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 1710f04d5140SColin Leitner } 1711f04d5140SColin Leitner 1712221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc) 17130a286ef2SSven Eckelmann { 1714221399b3SFrank Praznik if (!(sc->quirks & BUZZ_CONTROLLER)) 17152a242932SFrank Praznik sony_schedule_work(sc); 1716221399b3SFrank Praznik else 1717221399b3SFrank Praznik buzz_set_leds(sc); 17180a286ef2SSven Eckelmann } 17190a286ef2SSven Eckelmann 1720c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led, 1721f04d5140SColin Leitner enum led_brightness value) 1722f04d5140SColin Leitner { 1723f04d5140SColin Leitner struct device *dev = led->dev->parent; 1724ee79a8f8SGeliang Tang struct hid_device *hdev = to_hid_device(dev); 1725f04d5140SColin Leitner struct sony_sc *drv_data; 1726f04d5140SColin Leitner 1727f04d5140SColin Leitner int n; 1728b3ed458cSFrank Praznik int force_update; 1729f04d5140SColin Leitner 1730f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 17312251b85fSSven Eckelmann if (!drv_data) { 1732f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1733f04d5140SColin Leitner return; 1734f04d5140SColin Leitner } 1735f04d5140SColin Leitner 1736b3ed458cSFrank Praznik /* 1737b3ed458cSFrank Praznik * The Sixaxis on USB will override any LED settings sent to it 1738b3ed458cSFrank Praznik * and keep flashing all of the LEDs until the PS button is pressed. 1739b3ed458cSFrank Praznik * Updates, even if redundant, must be always be sent to the 1740b3ed458cSFrank Praznik * controller to avoid having to toggle the state of an LED just to 1741b3ed458cSFrank Praznik * stop the flashing later on. 1742b3ed458cSFrank Praznik */ 1743b3ed458cSFrank Praznik force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB); 1744b3ed458cSFrank Praznik 174560781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1746b3ed458cSFrank Praznik if (led == drv_data->leds[n] && (force_update || 1747b3ed458cSFrank Praznik (value != drv_data->led_state[n] || 1748b3ed458cSFrank Praznik drv_data->led_delay_on[n] || 1749b3ed458cSFrank Praznik drv_data->led_delay_off[n]))) { 1750b3ed458cSFrank Praznik 175160781cf4SFrank Praznik drv_data->led_state[n] = value; 1752b3ed458cSFrank Praznik 1753b3ed458cSFrank Praznik /* Setting the brightness stops the blinking */ 1754b3ed458cSFrank Praznik drv_data->led_delay_on[n] = 0; 1755b3ed458cSFrank Praznik drv_data->led_delay_off[n] = 0; 1756b3ed458cSFrank Praznik 1757221399b3SFrank Praznik sony_set_leds(drv_data); 1758f04d5140SColin Leitner break; 1759f04d5140SColin Leitner } 1760f04d5140SColin Leitner } 1761f04d5140SColin Leitner } 1762f04d5140SColin Leitner 1763c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led) 1764f04d5140SColin Leitner { 1765f04d5140SColin Leitner struct device *dev = led->dev->parent; 1766ee79a8f8SGeliang Tang struct hid_device *hdev = to_hid_device(dev); 1767f04d5140SColin Leitner struct sony_sc *drv_data; 1768f04d5140SColin Leitner 1769f04d5140SColin Leitner int n; 1770f04d5140SColin Leitner 1771f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 17722251b85fSSven Eckelmann if (!drv_data) { 1773f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1774f04d5140SColin Leitner return LED_OFF; 1775f04d5140SColin Leitner } 1776f04d5140SColin Leitner 177760781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 17787db7504aSSimon Wood if (led == drv_data->leds[n]) 17797db7504aSSimon Wood return drv_data->led_state[n]; 1780f04d5140SColin Leitner } 1781f04d5140SColin Leitner 17827db7504aSSimon Wood return LED_OFF; 1783f04d5140SColin Leitner } 1784f04d5140SColin Leitner 1785b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, 1786b3ed458cSFrank Praznik unsigned long *delay_off) 1787b3ed458cSFrank Praznik { 1788b3ed458cSFrank Praznik struct device *dev = led->dev->parent; 1789ee79a8f8SGeliang Tang struct hid_device *hdev = to_hid_device(dev); 1790b3ed458cSFrank Praznik struct sony_sc *drv_data = hid_get_drvdata(hdev); 1791b3ed458cSFrank Praznik int n; 17921adf904eSPavel Machek u8 new_on, new_off; 1793b3ed458cSFrank Praznik 1794b3ed458cSFrank Praznik if (!drv_data) { 1795b3ed458cSFrank Praznik hid_err(hdev, "No device data\n"); 1796b3ed458cSFrank Praznik return -EINVAL; 1797b3ed458cSFrank Praznik } 1798b3ed458cSFrank Praznik 1799b3ed458cSFrank Praznik /* Max delay is 255 deciseconds or 2550 milliseconds */ 1800b3ed458cSFrank Praznik if (*delay_on > 2550) 1801b3ed458cSFrank Praznik *delay_on = 2550; 1802b3ed458cSFrank Praznik if (*delay_off > 2550) 1803b3ed458cSFrank Praznik *delay_off = 2550; 1804b3ed458cSFrank Praznik 1805b3ed458cSFrank Praznik /* Blink at 1 Hz if both values are zero */ 1806b3ed458cSFrank Praznik if (!*delay_on && !*delay_off) 1807b3ed458cSFrank Praznik *delay_on = *delay_off = 500; 1808b3ed458cSFrank Praznik 1809b3ed458cSFrank Praznik new_on = *delay_on / 10; 1810b3ed458cSFrank Praznik new_off = *delay_off / 10; 1811b3ed458cSFrank Praznik 1812b3ed458cSFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1813b3ed458cSFrank Praznik if (led == drv_data->leds[n]) 1814b3ed458cSFrank Praznik break; 1815b3ed458cSFrank Praznik } 1816b3ed458cSFrank Praznik 1817b3ed458cSFrank Praznik /* This LED is not registered on this device */ 1818b3ed458cSFrank Praznik if (n >= drv_data->led_count) 1819b3ed458cSFrank Praznik return -EINVAL; 1820b3ed458cSFrank Praznik 1821b3ed458cSFrank Praznik /* Don't schedule work if the values didn't change */ 1822b3ed458cSFrank Praznik if (new_on != drv_data->led_delay_on[n] || 1823b3ed458cSFrank Praznik new_off != drv_data->led_delay_off[n]) { 1824b3ed458cSFrank Praznik drv_data->led_delay_on[n] = new_on; 1825b3ed458cSFrank Praznik drv_data->led_delay_off[n] = new_off; 18262a242932SFrank Praznik sony_schedule_work(drv_data); 1827b3ed458cSFrank Praznik } 1828b3ed458cSFrank Praznik 1829b3ed458cSFrank Praznik return 0; 1830b3ed458cSFrank Praznik } 1831b3ed458cSFrank Praznik 1832fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc) 18330a286ef2SSven Eckelmann { 18340a286ef2SSven Eckelmann struct led_classdev *led; 18350a286ef2SSven Eckelmann int n; 18360a286ef2SSven Eckelmann 1837fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 18380a286ef2SSven Eckelmann 1839fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 1840fa57a810SFrank Praznik led = sc->leds[n]; 1841fa57a810SFrank Praznik sc->leds[n] = NULL; 18420a286ef2SSven Eckelmann if (!led) 18430a286ef2SSven Eckelmann continue; 18440a286ef2SSven Eckelmann led_classdev_unregister(led); 18450a286ef2SSven Eckelmann kfree(led); 18460a286ef2SSven Eckelmann } 184760781cf4SFrank Praznik 1848fa57a810SFrank Praznik sc->led_count = 0; 18490a286ef2SSven Eckelmann } 18500a286ef2SSven Eckelmann 1851fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc) 1852f04d5140SColin Leitner { 1853fa57a810SFrank Praznik struct hid_device *hdev = sc->hdev; 185440e32ee6SJiri Kosina int n, ret = 0; 1855b3ed458cSFrank Praznik int use_ds4_names; 185640e32ee6SJiri Kosina struct led_classdev *led; 185740e32ee6SJiri Kosina size_t name_sz; 185840e32ee6SJiri Kosina char *name; 18590a286ef2SSven Eckelmann size_t name_len; 18600a286ef2SSven Eckelmann const char *name_fmt; 1861b3ed458cSFrank Praznik static const char * const ds4_name_str[] = { "red", "green", "blue", 1862b3ed458cSFrank Praznik "global" }; 18631adf904eSPavel Machek u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; 18641adf904eSPavel Machek u8 use_hw_blink[MAX_LEDS] = { 0 }; 1865f04d5140SColin Leitner 1866fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 1867f04d5140SColin Leitner 1868fa57a810SFrank Praznik if (sc->quirks & BUZZ_CONTROLLER) { 1869fa57a810SFrank Praznik sc->led_count = 4; 1870b3ed458cSFrank Praznik use_ds4_names = 0; 18710a286ef2SSven Eckelmann name_len = strlen("::buzz#"); 18720a286ef2SSven Eckelmann name_fmt = "%s::buzz%d"; 18739446edb9SKees Cook /* Validate expected report characteristics. */ 18749446edb9SKees Cook if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) 18759446edb9SKees Cook return -ENODEV; 1876fa57a810SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1877221399b3SFrank Praznik dualshock4_set_leds_from_id(sc); 1878221399b3SFrank Praznik sc->led_state[3] = 1; 1879b3ed458cSFrank Praznik sc->led_count = 4; 1880b3ed458cSFrank Praznik memset(max_brightness, 255, 3); 1881b3ed458cSFrank Praznik use_hw_blink[3] = 1; 1882b3ed458cSFrank Praznik use_ds4_names = 1; 188361ebca93SFrank Praznik name_len = 0; 188461ebca93SFrank Praznik name_fmt = "%s:%s"; 1885c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 1886c5e0c1c4SFrank Praznik sc->led_count = 3; 1887c5e0c1c4SFrank Praznik memset(max_brightness, 255, 3); 1888c5e0c1c4SFrank Praznik use_ds4_names = 1; 1889c5e0c1c4SFrank Praznik name_len = 0; 1890c5e0c1c4SFrank Praznik name_fmt = "%s:%s"; 18914545ee0aSSimon Wood } else if (sc->quirks & NAVIGATION_CONTROLLER) { 18921adf904eSPavel Machek static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; 18934545ee0aSSimon Wood 18944545ee0aSSimon Wood memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds)); 18954545ee0aSSimon Wood sc->led_count = 1; 18964545ee0aSSimon Wood memset(use_hw_blink, 1, 4); 18974545ee0aSSimon Wood use_ds4_names = 0; 18984545ee0aSSimon Wood name_len = strlen("::sony#"); 18994545ee0aSSimon Wood name_fmt = "%s::sony%d"; 190060781cf4SFrank Praznik } else { 1901221399b3SFrank Praznik sixaxis_set_leds_from_id(sc); 1902fa57a810SFrank Praznik sc->led_count = 4; 1903b3ed458cSFrank Praznik memset(use_hw_blink, 1, 4); 1904b3ed458cSFrank Praznik use_ds4_names = 0; 190561ebca93SFrank Praznik name_len = strlen("::sony#"); 190661ebca93SFrank Praznik name_fmt = "%s::sony%d"; 190760781cf4SFrank Praznik } 190860781cf4SFrank Praznik 1909ad142b9eSFrank Praznik /* 1910ad142b9eSFrank Praznik * Clear LEDs as we have no way of reading their initial state. This is 1911f04d5140SColin Leitner * only relevant if the driver is loaded after somebody actively set the 1912ad142b9eSFrank Praznik * LEDs to on 1913ad142b9eSFrank Praznik */ 1914221399b3SFrank Praznik sony_set_leds(sc); 1915f04d5140SColin Leitner 19160a286ef2SSven Eckelmann name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; 1917f04d5140SColin Leitner 1918fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 191961ebca93SFrank Praznik 1920b3ed458cSFrank Praznik if (use_ds4_names) 1921b3ed458cSFrank Praznik name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2; 192261ebca93SFrank Praznik 1923f04d5140SColin Leitner led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); 1924f04d5140SColin Leitner if (!led) { 1925f04d5140SColin Leitner hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); 19268cd5fcdaSJulia Lawall ret = -ENOMEM; 1927f04d5140SColin Leitner goto error_leds; 1928f04d5140SColin Leitner } 1929f04d5140SColin Leitner 1930f04d5140SColin Leitner name = (void *)(&led[1]); 1931b3ed458cSFrank Praznik if (use_ds4_names) 1932b3ed458cSFrank Praznik snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), 1933b3ed458cSFrank Praznik ds4_name_str[n]); 193461ebca93SFrank Praznik else 19350a286ef2SSven Eckelmann snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); 1936f04d5140SColin Leitner led->name = name; 1937221399b3SFrank Praznik led->brightness = sc->led_state[n]; 1938b3ed458cSFrank Praznik led->max_brightness = max_brightness[n]; 1939c5382519SSven Eckelmann led->brightness_get = sony_led_get_brightness; 1940c5382519SSven Eckelmann led->brightness_set = sony_led_set_brightness; 1941f04d5140SColin Leitner 1942b3ed458cSFrank Praznik if (use_hw_blink[n]) 1943b3ed458cSFrank Praznik led->blink_set = sony_led_blink_set; 1944b3ed458cSFrank Praznik 19458025087aSFrank Praznik sc->leds[n] = led; 19468025087aSFrank Praznik 19478cd5fcdaSJulia Lawall ret = led_classdev_register(&hdev->dev, led); 19488cd5fcdaSJulia Lawall if (ret) { 1949f04d5140SColin Leitner hid_err(hdev, "Failed to register LED %d\n", n); 19508025087aSFrank Praznik sc->leds[n] = NULL; 1951f04d5140SColin Leitner kfree(led); 1952f04d5140SColin Leitner goto error_leds; 1953f04d5140SColin Leitner } 1954f04d5140SColin Leitner } 1955f04d5140SColin Leitner 1956f04d5140SColin Leitner return ret; 1957f04d5140SColin Leitner 1958f04d5140SColin Leitner error_leds: 1959fa57a810SFrank Praznik sony_leds_remove(sc); 1960f04d5140SColin Leitner 1961f04d5140SColin Leitner return ret; 1962f04d5140SColin Leitner } 1963f04d5140SColin Leitner 1964d8aaccdaSFrank Praznik static void sixaxis_send_output_report(struct sony_sc *sc) 1965a08c22c0SSven Eckelmann { 19669b2b5c9aSFrank Praznik static const union sixaxis_output_report_01 default_report = { 196755d3b664SFrank Praznik .buf = { 1968a08c22c0SSven Eckelmann 0x01, 1969ad07b7a6SScott Moreau 0x01, 0xff, 0x00, 0xff, 0x00, 19700a286ef2SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00, 1971a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1972a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1973a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1974a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1975a08c22c0SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00 197655d3b664SFrank Praznik } 1977a08c22c0SSven Eckelmann }; 19789b2b5c9aSFrank Praznik struct sixaxis_output_report *report = 19799b2b5c9aSFrank Praznik (struct sixaxis_output_report *)sc->output_report_dmabuf; 19809b2b5c9aSFrank Praznik int n; 19819b2b5c9aSFrank Praznik 19829b2b5c9aSFrank Praznik /* Initialize the report with default values */ 19839b2b5c9aSFrank Praznik memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); 19849f323b68SSven Eckelmann 19850a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 19869b2b5c9aSFrank Praznik report->rumble.right_motor_on = sc->right ? 1 : 0; 19879b2b5c9aSFrank Praznik report->rumble.left_motor_force = sc->left; 19880a286ef2SSven Eckelmann #endif 19890a286ef2SSven Eckelmann 19909b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[0] << 1; 19919b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[1] << 2; 19929b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[2] << 3; 19939b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[3] << 4; 19949f323b68SSven Eckelmann 199588f6576fSSimon Wood /* Set flag for all leds off, required for 3rd party INTEC controller */ 19969b2b5c9aSFrank Praznik if ((report->leds_bitmap & 0x1E) == 0) 19979b2b5c9aSFrank Praznik report->leds_bitmap |= 0x20; 199888f6576fSSimon Wood 1999b3ed458cSFrank Praznik /* 2000b3ed458cSFrank Praznik * The LEDs in the report are indexed in reverse order to their 2001b3ed458cSFrank Praznik * corresponding light on the controller. 2002b3ed458cSFrank Praznik * Index 0 = LED 4, index 1 = LED 3, etc... 2003b3ed458cSFrank Praznik * 2004b3ed458cSFrank Praznik * In the case of both delay values being zero (blinking disabled) the 2005b3ed458cSFrank Praznik * default report values should be used or the controller LED will be 2006b3ed458cSFrank Praznik * always off. 2007b3ed458cSFrank Praznik */ 2008b3ed458cSFrank Praznik for (n = 0; n < 4; n++) { 2009b3ed458cSFrank Praznik if (sc->led_delay_on[n] || sc->led_delay_off[n]) { 20109b2b5c9aSFrank Praznik report->led[3 - n].duty_off = sc->led_delay_off[n]; 20119b2b5c9aSFrank Praznik report->led[3 - n].duty_on = sc->led_delay_on[n]; 2012b3ed458cSFrank Praznik } 2013b3ed458cSFrank Praznik } 2014b3ed458cSFrank Praznik 20151adf904eSPavel Machek hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report, 20169b2b5c9aSFrank Praznik sizeof(struct sixaxis_output_report), 20179b2b5c9aSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 20189f323b68SSven Eckelmann } 20199f323b68SSven Eckelmann 2020d8aaccdaSFrank Praznik static void dualshock4_send_output_report(struct sony_sc *sc) 20210bd88dd3SFrank Praznik { 20220da8ea65SFrank Praznik struct hid_device *hdev = sc->hdev; 20231adf904eSPavel Machek u8 *buf = sc->output_report_dmabuf; 202448220237SFrank Praznik int offset; 20250da8ea65SFrank Praznik 2026c4425c8fSFrank Praznik /* 2027c4425c8fSFrank Praznik * NOTE: The buf[1] field of the Bluetooth report controls 2028c4425c8fSFrank Praznik * the Dualshock 4 reporting rate. 2029c4425c8fSFrank Praznik * 2030c4425c8fSFrank Praznik * Known values include: 2031c4425c8fSFrank Praznik * 2032c4425c8fSFrank Praznik * 0x80 - 1000hz (full speed) 2033c4425c8fSFrank Praznik * 0xA0 - 31hz 2034c4425c8fSFrank Praznik * 0xB0 - 20hz 2035c4425c8fSFrank Praznik * 0xD0 - 66hz 2036c4425c8fSFrank Praznik */ 2037fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 20382c159de0SRoderick Colenbrander memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); 203948220237SFrank Praznik buf[0] = 0x05; 2040b3ed458cSFrank Praznik buf[1] = 0xFF; 204148220237SFrank Praznik offset = 4; 2042fdcf105dSFrank Praznik } else { 20432c159de0SRoderick Colenbrander memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); 2044fdcf105dSFrank Praznik buf[0] = 0x11; 2045e7ef53adSRoderick Colenbrander buf[1] = 0xC0; /* HID + CRC */ 2046fdcf105dSFrank Praznik buf[3] = 0x0F; 2047fdcf105dSFrank Praznik offset = 6; 2048fdcf105dSFrank Praznik } 20490bd88dd3SFrank Praznik 20500bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF 205148220237SFrank Praznik buf[offset++] = sc->right; 205248220237SFrank Praznik buf[offset++] = sc->left; 205348220237SFrank Praznik #else 205448220237SFrank Praznik offset += 2; 20550bd88dd3SFrank Praznik #endif 20560bd88dd3SFrank Praznik 2057b3ed458cSFrank Praznik /* LED 3 is the global control */ 2058b3ed458cSFrank Praznik if (sc->led_state[3]) { 205948220237SFrank Praznik buf[offset++] = sc->led_state[0]; 206048220237SFrank Praznik buf[offset++] = sc->led_state[1]; 206148220237SFrank Praznik buf[offset++] = sc->led_state[2]; 2062b3ed458cSFrank Praznik } else { 2063b3ed458cSFrank Praznik offset += 3; 2064b3ed458cSFrank Praznik } 2065b3ed458cSFrank Praznik 2066b3ed458cSFrank Praznik /* If both delay values are zero the DualShock 4 disables blinking. */ 2067b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_on[3]; 2068b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_off[3]; 206960781cf4SFrank Praznik 2070fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 20712c159de0SRoderick Colenbrander hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); 2072e7ef53adSRoderick Colenbrander else { 2073e7ef53adSRoderick Colenbrander /* CRC generation */ 2074e7ef53adSRoderick Colenbrander u8 bthdr = 0xA2; 2075e7ef53adSRoderick Colenbrander u32 crc; 2076e7ef53adSRoderick Colenbrander 2077e7ef53adSRoderick Colenbrander crc = crc32_le(0xFFFFFFFF, &bthdr, 1); 2078e7ef53adSRoderick Colenbrander crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4); 2079e7ef53adSRoderick Colenbrander put_unaligned_le32(crc, &buf[74]); 2080e7ef53adSRoderick Colenbrander hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE); 2081e7ef53adSRoderick Colenbrander } 20820bd88dd3SFrank Praznik } 20830bd88dd3SFrank Praznik 2084d8aaccdaSFrank Praznik static void motion_send_output_report(struct sony_sc *sc) 2085c5e0c1c4SFrank Praznik { 2086c5e0c1c4SFrank Praznik struct hid_device *hdev = sc->hdev; 2087c5e0c1c4SFrank Praznik struct motion_output_report_02 *report = 2088c5e0c1c4SFrank Praznik (struct motion_output_report_02 *)sc->output_report_dmabuf; 2089c5e0c1c4SFrank Praznik 209041d2d425SSimon Wood memset(report, 0, MOTION_REPORT_0x02_SIZE); 2091c5e0c1c4SFrank Praznik 2092c5e0c1c4SFrank Praznik report->type = 0x02; /* set leds */ 2093c5e0c1c4SFrank Praznik report->r = sc->led_state[0]; 2094c5e0c1c4SFrank Praznik report->g = sc->led_state[1]; 2095c5e0c1c4SFrank Praznik report->b = sc->led_state[2]; 2096c5e0c1c4SFrank Praznik 2097c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF 2098c5e0c1c4SFrank Praznik report->rumble = max(sc->right, sc->left); 2099c5e0c1c4SFrank Praznik #endif 2100c5e0c1c4SFrank Praznik 21011adf904eSPavel Machek hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE); 2102c5e0c1c4SFrank Praznik } 2103c5e0c1c4SFrank Praznik 2104decd946cSFrank Praznik static inline void sony_send_output_report(struct sony_sc *sc) 2105decd946cSFrank Praznik { 2106decd946cSFrank Praznik if (sc->send_output_report) 2107decd946cSFrank Praznik sc->send_output_report(sc); 2108decd946cSFrank Praznik } 2109decd946cSFrank Praznik 2110d8aaccdaSFrank Praznik static void sony_state_worker(struct work_struct *work) 2111d8aaccdaSFrank Praznik { 2112d8aaccdaSFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 2113ef916ef5SAntonio Ospite 2114d8aaccdaSFrank Praznik sc->send_output_report(sc); 2115d8aaccdaSFrank Praznik } 2116d8aaccdaSFrank Praznik 21179b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc) 21189b2b5c9aSFrank Praznik { 21194545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER) || 21204545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER)) 21219b2b5c9aSFrank Praznik sc->output_report_dmabuf = 21229b2b5c9aSFrank Praznik kmalloc(sizeof(union sixaxis_output_report_01), 21239b2b5c9aSFrank Praznik GFP_KERNEL); 21249b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) 21252c159de0SRoderick Colenbrander sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE, 21269b2b5c9aSFrank Praznik GFP_KERNEL); 21279b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 21282c159de0SRoderick Colenbrander sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE, 21299b2b5c9aSFrank Praznik GFP_KERNEL); 2130c5e0c1c4SFrank Praznik else if (sc->quirks & MOTION_CONTROLLER) 213141d2d425SSimon Wood sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, 2132c5e0c1c4SFrank Praznik GFP_KERNEL); 21339b2b5c9aSFrank Praznik else 21349b2b5c9aSFrank Praznik return 0; 21359b2b5c9aSFrank Praznik 21369b2b5c9aSFrank Praznik if (!sc->output_report_dmabuf) 21379b2b5c9aSFrank Praznik return -ENOMEM; 21389b2b5c9aSFrank Praznik 21399b2b5c9aSFrank Praznik return 0; 21409b2b5c9aSFrank Praznik } 21419b2b5c9aSFrank Praznik 21420a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 21439f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data, 21449f323b68SSven Eckelmann struct ff_effect *effect) 21459f323b68SSven Eckelmann { 2146a08c22c0SSven Eckelmann struct hid_device *hid = input_get_drvdata(dev); 21479f323b68SSven Eckelmann struct sony_sc *sc = hid_get_drvdata(hid); 2148a08c22c0SSven Eckelmann 2149a08c22c0SSven Eckelmann if (effect->type != FF_RUMBLE) 2150a08c22c0SSven Eckelmann return 0; 2151a08c22c0SSven Eckelmann 21529f323b68SSven Eckelmann sc->left = effect->u.rumble.strong_magnitude / 256; 21530bd88dd3SFrank Praznik sc->right = effect->u.rumble.weak_magnitude / 256; 2154a08c22c0SSven Eckelmann 21552a242932SFrank Praznik sony_schedule_work(sc); 21569f323b68SSven Eckelmann return 0; 2157a08c22c0SSven Eckelmann } 2158a08c22c0SSven Eckelmann 2159fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 2160a08c22c0SSven Eckelmann { 2161fa57a810SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 2162a08c22c0SSven Eckelmann struct hid_input, list); 2163a08c22c0SSven Eckelmann struct input_dev *input_dev = hidinput->input; 2164a08c22c0SSven Eckelmann 2165a08c22c0SSven Eckelmann input_set_capability(input_dev, EV_FF, FF_RUMBLE); 2166a08c22c0SSven Eckelmann return input_ff_create_memless(input_dev, NULL, sony_play_effect); 2167a08c22c0SSven Eckelmann } 2168a08c22c0SSven Eckelmann 2169a08c22c0SSven Eckelmann #else 2170fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 2171a08c22c0SSven Eckelmann { 2172a08c22c0SSven Eckelmann return 0; 2173a08c22c0SSven Eckelmann } 21749f323b68SSven Eckelmann 2175a08c22c0SSven Eckelmann #endif 2176a08c22c0SSven Eckelmann 2177d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy, 2178d902f472SFrank Praznik enum power_supply_property psp, 2179d902f472SFrank Praznik union power_supply_propval *val) 2180c4e1ddf2SFrank Praznik { 2181297d716fSKrzysztof Kozlowski struct sony_sc *sc = power_supply_get_drvdata(psy); 2182d902f472SFrank Praznik unsigned long flags; 2183d902f472SFrank Praznik int ret = 0; 2184d902f472SFrank Praznik u8 battery_charging, battery_capacity, cable_state; 2185c4e1ddf2SFrank Praznik 2186d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 2187d902f472SFrank Praznik battery_charging = sc->battery_charging; 2188d902f472SFrank Praznik battery_capacity = sc->battery_capacity; 2189d902f472SFrank Praznik cable_state = sc->cable_state; 2190d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 2191c4e1ddf2SFrank Praznik 2192d902f472SFrank Praznik switch (psp) { 2193d902f472SFrank Praznik case POWER_SUPPLY_PROP_PRESENT: 2194d902f472SFrank Praznik val->intval = 1; 2195d902f472SFrank Praznik break; 2196d902f472SFrank Praznik case POWER_SUPPLY_PROP_SCOPE: 2197d902f472SFrank Praznik val->intval = POWER_SUPPLY_SCOPE_DEVICE; 2198d902f472SFrank Praznik break; 2199d902f472SFrank Praznik case POWER_SUPPLY_PROP_CAPACITY: 2200d902f472SFrank Praznik val->intval = battery_capacity; 2201d902f472SFrank Praznik break; 2202d902f472SFrank Praznik case POWER_SUPPLY_PROP_STATUS: 2203d902f472SFrank Praznik if (battery_charging) 2204d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_CHARGING; 2205d902f472SFrank Praznik else 2206d902f472SFrank Praznik if (battery_capacity == 100 && cable_state) 2207d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_FULL; 2208d902f472SFrank Praznik else 2209d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 2210d902f472SFrank Praznik break; 2211d902f472SFrank Praznik default: 2212d902f472SFrank Praznik ret = -EINVAL; 2213d902f472SFrank Praznik break; 2214c4e1ddf2SFrank Praznik } 2215d902f472SFrank Praznik return ret; 2216d902f472SFrank Praznik } 2217d902f472SFrank Praznik 22180f398230SFrank Praznik static int sony_battery_probe(struct sony_sc *sc, int append_dev_id) 2219d902f472SFrank Praznik { 22200f398230SFrank Praznik const char *battery_str_fmt = append_dev_id ? 22210f398230SFrank Praznik "sony_controller_battery_%pMR_%i" : 22220f398230SFrank Praznik "sony_controller_battery_%pMR"; 2223297d716fSKrzysztof Kozlowski struct power_supply_config psy_cfg = { .drv_data = sc, }; 2224d902f472SFrank Praznik struct hid_device *hdev = sc->hdev; 2225d902f472SFrank Praznik int ret; 2226d902f472SFrank Praznik 2227ad142b9eSFrank Praznik /* 2228ad142b9eSFrank Praznik * Set the default battery level to 100% to avoid low battery warnings 2229d9a293a9SFrank Praznik * if the battery is polled before the first device report is received. 2230d9a293a9SFrank Praznik */ 2231d9a293a9SFrank Praznik sc->battery_capacity = 100; 2232d9a293a9SFrank Praznik 2233297d716fSKrzysztof Kozlowski sc->battery_desc.properties = sony_battery_props; 2234297d716fSKrzysztof Kozlowski sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props); 2235297d716fSKrzysztof Kozlowski sc->battery_desc.get_property = sony_battery_get_property; 2236297d716fSKrzysztof Kozlowski sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 2237297d716fSKrzysztof Kozlowski sc->battery_desc.use_for_apm = 0; 22380f398230SFrank Praznik sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt, 22390f398230SFrank Praznik sc->mac_address, sc->device_id); 2240297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 2241d902f472SFrank Praznik return -ENOMEM; 2242d902f472SFrank Praznik 2243297d716fSKrzysztof Kozlowski sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc, 2244297d716fSKrzysztof Kozlowski &psy_cfg); 2245297d716fSKrzysztof Kozlowski if (IS_ERR(sc->battery)) { 2246297d716fSKrzysztof Kozlowski ret = PTR_ERR(sc->battery); 2247d902f472SFrank Praznik hid_err(hdev, "Unable to register battery device\n"); 2248d902f472SFrank Praznik goto err_free; 2249d902f472SFrank Praznik } 2250d902f472SFrank Praznik 2251297d716fSKrzysztof Kozlowski power_supply_powers(sc->battery, &hdev->dev); 2252d902f472SFrank Praznik return 0; 2253d902f472SFrank Praznik 2254d902f472SFrank Praznik err_free: 2255297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 2256297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 2257d902f472SFrank Praznik return ret; 2258d902f472SFrank Praznik } 2259d902f472SFrank Praznik 2260d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc) 2261d902f472SFrank Praznik { 2262297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 2263d902f472SFrank Praznik return; 2264d902f472SFrank Praznik 2265297d716fSKrzysztof Kozlowski power_supply_unregister(sc->battery); 2266297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 2267297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 2268d902f472SFrank Praznik } 2269d902f472SFrank Praznik 2270d2d782fcSFrank Praznik /* 2271d2d782fcSFrank Praznik * If a controller is plugged in via USB while already connected via Bluetooth 2272d2d782fcSFrank Praznik * it will show up as two devices. A global list of connected controllers and 2273d2d782fcSFrank Praznik * their MAC addresses is maintained to ensure that a device is only connected 2274d2d782fcSFrank Praznik * once. 22750f398230SFrank Praznik * 22760f398230SFrank Praznik * Some USB-only devices masquerade as Sixaxis controllers and all have the 22770f398230SFrank Praznik * same dummy Bluetooth address, so a comparison of the connection type is 22780f398230SFrank Praznik * required. Devices are only rejected in the case where two devices have 22790f398230SFrank Praznik * matching Bluetooth addresses on different bus types. 2280d2d782fcSFrank Praznik */ 22810f398230SFrank Praznik static inline int sony_compare_connection_type(struct sony_sc *sc0, 22820f398230SFrank Praznik struct sony_sc *sc1) 22830f398230SFrank Praznik { 22840f398230SFrank Praznik const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE); 22850f398230SFrank Praznik const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE); 22860f398230SFrank Praznik 22870f398230SFrank Praznik return sc0_not_bt == sc1_not_bt; 22880f398230SFrank Praznik } 22890f398230SFrank Praznik 2290d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc) 2291d2d782fcSFrank Praznik { 2292d2d782fcSFrank Praznik struct sony_sc *entry; 2293d2d782fcSFrank Praznik unsigned long flags; 2294d2d782fcSFrank Praznik int ret; 2295d2d782fcSFrank Praznik 2296d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 2297d2d782fcSFrank Praznik 2298d2d782fcSFrank Praznik list_for_each_entry(entry, &sony_device_list, list_node) { 2299d2d782fcSFrank Praznik ret = memcmp(sc->mac_address, entry->mac_address, 2300d2d782fcSFrank Praznik sizeof(sc->mac_address)); 2301d2d782fcSFrank Praznik if (!ret) { 23020f398230SFrank Praznik if (sony_compare_connection_type(sc, entry)) { 23030f398230SFrank Praznik ret = 1; 23040f398230SFrank Praznik } else { 2305d2d782fcSFrank Praznik ret = -EEXIST; 23060f398230SFrank Praznik hid_info(sc->hdev, 23070f398230SFrank Praznik "controller with MAC address %pMR already connected\n", 2308d2d782fcSFrank Praznik sc->mac_address); 23090f398230SFrank Praznik } 2310d2d782fcSFrank Praznik goto unlock; 2311d2d782fcSFrank Praznik } 2312c4e1ddf2SFrank Praznik } 2313c4e1ddf2SFrank Praznik 2314d2d782fcSFrank Praznik ret = 0; 2315d2d782fcSFrank Praznik list_add(&(sc->list_node), &sony_device_list); 2316c4e1ddf2SFrank Praznik 2317d2d782fcSFrank Praznik unlock: 2318d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 2319d2d782fcSFrank Praznik return ret; 2320d2d782fcSFrank Praznik } 2321d2d782fcSFrank Praznik 2322d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc) 2323d2d782fcSFrank Praznik { 2324d2d782fcSFrank Praznik unsigned long flags; 2325d2d782fcSFrank Praznik 2326d2d782fcSFrank Praznik if (sc->list_node.next) { 2327d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 2328d2d782fcSFrank Praznik list_del(&(sc->list_node)); 2329d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 2330d2d782fcSFrank Praznik } 2331d2d782fcSFrank Praznik } 2332d2d782fcSFrank Praznik 2333d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc) 2334d2d782fcSFrank Praznik { 2335d2d782fcSFrank Praznik int ret; 2336d2d782fcSFrank Praznik 2337d2d782fcSFrank Praznik /* HIDP stores the device MAC address as a string in the uniq field. */ 2338d2d782fcSFrank Praznik ret = strlen(sc->hdev->uniq); 2339d2d782fcSFrank Praznik if (ret != 17) 2340c4e1ddf2SFrank Praznik return -EINVAL; 2341d2d782fcSFrank Praznik 2342d2d782fcSFrank Praznik ret = sscanf(sc->hdev->uniq, 2343d2d782fcSFrank Praznik "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 2344d2d782fcSFrank Praznik &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3], 2345d2d782fcSFrank Praznik &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]); 2346d2d782fcSFrank Praznik 2347d2d782fcSFrank Praznik if (ret != 6) 2348d2d782fcSFrank Praznik return -EINVAL; 2349d2d782fcSFrank Praznik 2350d2d782fcSFrank Praznik return 0; 2351c4e1ddf2SFrank Praznik } 2352c4e1ddf2SFrank Praznik 2353d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc) 2354d2d782fcSFrank Praznik { 23551adf904eSPavel Machek u8 *buf = NULL; 2356d2d782fcSFrank Praznik int n, ret; 2357d2d782fcSFrank Praznik 2358d2d782fcSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || 235912e9a6d7SSimon Wood (sc->quirks & MOTION_CONTROLLER_BT) || 23604545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT) || 2361d2d782fcSFrank Praznik (sc->quirks & SIXAXIS_CONTROLLER_BT)) { 2362d2d782fcSFrank Praznik /* 2363d2d782fcSFrank Praznik * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC 2364d2d782fcSFrank Praznik * address from the uniq string where HIDP stores it. 2365d2d782fcSFrank Praznik * As uniq cannot be guaranteed to be a MAC address in all cases 2366d2d782fcSFrank Praznik * a failure of this function should not prevent the connection. 2367d2d782fcSFrank Praznik */ 2368d2d782fcSFrank Praznik if (sony_get_bt_devaddr(sc) < 0) { 2369d2d782fcSFrank Praznik hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); 2370d2d782fcSFrank Praznik return 0; 2371d2d782fcSFrank Praznik } 2372d2d782fcSFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 23732c159de0SRoderick Colenbrander buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); 23749b2b5c9aSFrank Praznik if (!buf) 23759b2b5c9aSFrank Praznik return -ENOMEM; 2376d2d782fcSFrank Praznik 2377d2d782fcSFrank Praznik /* 2378d2d782fcSFrank Praznik * The MAC address of a DS4 controller connected via USB can be 2379d2d782fcSFrank Praznik * retrieved with feature report 0x81. The address begins at 2380d2d782fcSFrank Praznik * offset 1. 2381d2d782fcSFrank Praznik */ 23829b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0x81, buf, 23832c159de0SRoderick Colenbrander DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, 23849b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2385d2d782fcSFrank Praznik 23862c159de0SRoderick Colenbrander if (ret != DS4_FEATURE_REPORT_0x81_SIZE) { 2387d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); 23889b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 23899b2b5c9aSFrank Praznik goto out_free; 2390d2d782fcSFrank Praznik } 2391d2d782fcSFrank Praznik 2392d2d782fcSFrank Praznik memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); 23934545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 23944545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 23959b2b5c9aSFrank Praznik buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); 23969b2b5c9aSFrank Praznik if (!buf) 23979b2b5c9aSFrank Praznik return -ENOMEM; 2398d2d782fcSFrank Praznik 2399d2d782fcSFrank Praznik /* 2400d2d782fcSFrank Praznik * The MAC address of a Sixaxis controller connected via USB can 2401d2d782fcSFrank Praznik * be retrieved with feature report 0xf2. The address begins at 2402d2d782fcSFrank Praznik * offset 4. 2403d2d782fcSFrank Praznik */ 24049b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, 24059b2b5c9aSFrank Praznik SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, 24069b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2407d2d782fcSFrank Praznik 24089b2b5c9aSFrank Praznik if (ret != SIXAXIS_REPORT_0xF2_SIZE) { 2409d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); 24109b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 24119b2b5c9aSFrank Praznik goto out_free; 2412d2d782fcSFrank Praznik } 2413d2d782fcSFrank Praznik 2414d2d782fcSFrank Praznik /* 2415d2d782fcSFrank Praznik * The Sixaxis device MAC in the report is big-endian and must 2416d2d782fcSFrank Praznik * be byte-swapped. 2417d2d782fcSFrank Praznik */ 2418d2d782fcSFrank Praznik for (n = 0; n < 6; n++) 2419d2d782fcSFrank Praznik sc->mac_address[5-n] = buf[4+n]; 2420d2d782fcSFrank Praznik } else { 2421d2d782fcSFrank Praznik return 0; 2422d2d782fcSFrank Praznik } 2423d2d782fcSFrank Praznik 24249b2b5c9aSFrank Praznik ret = sony_check_add_dev_list(sc); 24259b2b5c9aSFrank Praznik 24269b2b5c9aSFrank Praznik out_free: 24279b2b5c9aSFrank Praznik 24289b2b5c9aSFrank Praznik kfree(buf); 24299b2b5c9aSFrank Praznik 24309b2b5c9aSFrank Praznik return ret; 2431d2d782fcSFrank Praznik } 2432d2d782fcSFrank Praznik 24338025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc) 24348025087aSFrank Praznik { 24358025087aSFrank Praznik int ret; 24368025087aSFrank Praznik 24378025087aSFrank Praznik /* 24388025087aSFrank Praznik * Only DualShock 4 or Sixaxis controllers get an id. 24398025087aSFrank Praznik * All others are set to -1. 24408025087aSFrank Praznik */ 24418025087aSFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) || 24428025087aSFrank Praznik (sc->quirks & DUALSHOCK4_CONTROLLER)) { 24438025087aSFrank Praznik ret = ida_simple_get(&sony_device_id_allocator, 0, 0, 24448025087aSFrank Praznik GFP_KERNEL); 24458025087aSFrank Praznik if (ret < 0) { 24468025087aSFrank Praznik sc->device_id = -1; 24478025087aSFrank Praznik return ret; 24488025087aSFrank Praznik } 24498025087aSFrank Praznik sc->device_id = ret; 24508025087aSFrank Praznik } else { 24518025087aSFrank Praznik sc->device_id = -1; 24528025087aSFrank Praznik } 24538025087aSFrank Praznik 24548025087aSFrank Praznik return 0; 24558025087aSFrank Praznik } 24568025087aSFrank Praznik 24578025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc) 24588025087aSFrank Praznik { 24598025087aSFrank Praznik if (sc->device_id >= 0) { 24608025087aSFrank Praznik ida_simple_remove(&sony_device_id_allocator, sc->device_id); 24618025087aSFrank Praznik sc->device_id = -1; 24628025087aSFrank Praznik } 24638025087aSFrank Praznik } 24648025087aSFrank Praznik 2465d8aaccdaSFrank Praznik static inline void sony_init_output_report(struct sony_sc *sc, 2466d8aaccdaSFrank Praznik void (*send_output_report)(struct sony_sc *)) 246746262047SFrank Praznik { 2468d8aaccdaSFrank Praznik sc->send_output_report = send_output_report; 2469d8aaccdaSFrank Praznik 247046262047SFrank Praznik if (!sc->worker_initialized) 2471d8aaccdaSFrank Praznik INIT_WORK(&sc->state_worker, sony_state_worker); 247246262047SFrank Praznik 247346262047SFrank Praznik sc->worker_initialized = 1; 247446262047SFrank Praznik } 247546262047SFrank Praznik 247646262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc) 247746262047SFrank Praznik { 247846262047SFrank Praznik if (sc->worker_initialized) 247946262047SFrank Praznik cancel_work_sync(&sc->state_worker); 248046262047SFrank Praznik } 2481d2d782fcSFrank Praznik 2482e1bc84d0SRoderick Colenbrander static int sony_input_configured(struct hid_device *hdev, 2483e1bc84d0SRoderick Colenbrander struct hid_input *hidinput) 2484bd28ce00SJiri Slaby { 2485e1bc84d0SRoderick Colenbrander struct sony_sc *sc = hid_get_drvdata(hdev); 24860f398230SFrank Praznik int append_dev_id; 2487e1bc84d0SRoderick Colenbrander int ret; 2488bd28ce00SJiri Slaby 24898025087aSFrank Praznik ret = sony_set_device_id(sc); 24908025087aSFrank Praznik if (ret < 0) { 24918025087aSFrank Praznik hid_err(hdev, "failed to allocate the device id\n"); 24928025087aSFrank Praznik goto err_stop; 24938025087aSFrank Praznik } 24948025087aSFrank Praznik 2495131a8a9aSFrank Praznik ret = sony_allocate_output_report(sc); 2496131a8a9aSFrank Praznik if (ret < 0) { 2497131a8a9aSFrank Praznik hid_err(hdev, "failed to allocate the output report buffer\n"); 2498131a8a9aSFrank Praznik goto err_stop; 2499131a8a9aSFrank Praznik } 2500131a8a9aSFrank Praznik 25014545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 25024545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 2503e534a935SBenjamin Tissoires /* 2504e534a935SBenjamin Tissoires * The Sony Sixaxis does not handle HID Output Reports on the 2505e534a935SBenjamin Tissoires * Interrupt EP like it could, so we need to force HID Output 2506e534a935SBenjamin Tissoires * Reports to use HID_REQ_SET_REPORT on the Control EP. 2507e534a935SBenjamin Tissoires * 2508e534a935SBenjamin Tissoires * There is also another issue about HID Output Reports via USB, 2509e534a935SBenjamin Tissoires * the Sixaxis does not want the report_id as part of the data 2510e534a935SBenjamin Tissoires * packet, so we have to discard buf[0] when sending the actual 2511e534a935SBenjamin Tissoires * control message, even for numbered reports, humpf! 25122a242932SFrank Praznik * 25132a242932SFrank Praznik * Additionally, the Sixaxis on USB isn't properly initialized 25142a242932SFrank Praznik * until the PS logo button is pressed and as such won't retain 25152a242932SFrank Praznik * any state set by an output report, so the initial 25162a242932SFrank Praznik * configuration report is deferred until the first input 25172a242932SFrank Praznik * report arrives. 2518e534a935SBenjamin Tissoires */ 2519e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2520e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; 25212a242932SFrank Praznik sc->defer_initialization = 1; 2522816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev); 2523d8aaccdaSFrank Praznik sony_init_output_report(sc, sixaxis_send_output_report); 25244545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || 25254545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT)) { 25262078b9bbSFrank Praznik /* 25272078b9bbSFrank Praznik * The Sixaxis wants output reports sent on the ctrl endpoint 25282078b9bbSFrank Praznik * when connected via Bluetooth. 25292078b9bbSFrank Praznik */ 25302078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2531816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev); 2532d8aaccdaSFrank Praznik sony_init_output_report(sc, sixaxis_send_output_report); 2533fee4e2d5SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 253468330d83SFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { 253568330d83SFrank Praznik ret = dualshock4_set_operational_bt(hdev); 253668330d83SFrank Praznik if (ret < 0) { 253768330d83SFrank Praznik hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); 253868330d83SFrank Praznik goto err_stop; 253968330d83SFrank Praznik } 254068330d83SFrank Praznik } 2541c4e1ddf2SFrank Praznik 2542e1bc84d0SRoderick Colenbrander /* 2543e1bc84d0SRoderick Colenbrander * The Dualshock 4 touchpad supports 2 touches and has a 2544e1bc84d0SRoderick Colenbrander * resolution of 1920x942 (44.86 dots/mm). 2545e1bc84d0SRoderick Colenbrander */ 2546ac797b95SRoderick Colenbrander ret = sony_register_touchpad(sc, 2, 1920, 942); 2547e1bc84d0SRoderick Colenbrander if (ret) { 2548e1bc84d0SRoderick Colenbrander hid_err(sc->hdev, 2549e1bc84d0SRoderick Colenbrander "Unable to initialize multi-touch slots: %d\n", 2550e1bc84d0SRoderick Colenbrander ret); 2551e1bc84d0SRoderick Colenbrander return ret; 2552e1bc84d0SRoderick Colenbrander } 2553e1bc84d0SRoderick Colenbrander 2554d8aaccdaSFrank Praznik sony_init_output_report(sc, dualshock4_send_output_report); 2555c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 2556d8aaccdaSFrank Praznik sony_init_output_report(sc, motion_send_output_report); 25570bd88dd3SFrank Praznik } else { 25580bd88dd3SFrank Praznik ret = 0; 25590bd88dd3SFrank Praznik } 2560f9ce7c28SBastien Nocera 25614dfdc464SJiri Kosina if (ret < 0) 2562bd28ce00SJiri Slaby goto err_stop; 2563bd28ce00SJiri Slaby 25640f398230SFrank Praznik ret = append_dev_id = sony_check_add(sc); 2565d2d782fcSFrank Praznik if (ret < 0) 2566d2d782fcSFrank Praznik goto err_stop; 2567d2d782fcSFrank Praznik 25680a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) { 2569fa57a810SFrank Praznik ret = sony_leds_init(sc); 25700a286ef2SSven Eckelmann if (ret < 0) 25710a286ef2SSven Eckelmann goto err_stop; 25720a286ef2SSven Eckelmann } 25730a286ef2SSven Eckelmann 2574d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 25750f398230SFrank Praznik ret = sony_battery_probe(sc, append_dev_id); 2576a08c22c0SSven Eckelmann if (ret < 0) 2577a08c22c0SSven Eckelmann goto err_stop; 2578a08c22c0SSven Eckelmann 2579d902f472SFrank Praznik /* Open the device to receive reports with battery info */ 2580d902f472SFrank Praznik ret = hid_hw_open(hdev); 2581d902f472SFrank Praznik if (ret < 0) { 2582d902f472SFrank Praznik hid_err(hdev, "hw open failed\n"); 2583d902f472SFrank Praznik goto err_stop; 2584d902f472SFrank Praznik } 2585d902f472SFrank Praznik } 2586d902f472SFrank Praznik 2587c8de9dbbSFrank Praznik if (sc->quirks & SONY_FF_SUPPORT) { 2588fa57a810SFrank Praznik ret = sony_init_ff(sc); 2589d902f472SFrank Praznik if (ret < 0) 2590d902f472SFrank Praznik goto err_close; 25915f5750d2SFrank Praznik } 2592bd28ce00SJiri Slaby 2593f425458eSH Hartley Sweeten return 0; 2594d902f472SFrank Praznik err_close: 2595d902f472SFrank Praznik hid_hw_close(hdev); 2596bd28ce00SJiri Slaby err_stop: 25970a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2598fa57a810SFrank Praznik sony_leds_remove(sc); 2599d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) 2600d902f472SFrank Praznik sony_battery_remove(sc); 260146262047SFrank Praznik sony_cancel_work_sync(sc); 26029b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 2603d2d782fcSFrank Praznik sony_remove_dev_list(sc); 26048025087aSFrank Praznik sony_release_device_id(sc); 2605bd28ce00SJiri Slaby hid_hw_stop(hdev); 2606bd28ce00SJiri Slaby return ret; 2607bd28ce00SJiri Slaby } 2608bd28ce00SJiri Slaby 2609e1bc84d0SRoderick Colenbrander static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 2610e1bc84d0SRoderick Colenbrander { 2611e1bc84d0SRoderick Colenbrander int ret; 2612e1bc84d0SRoderick Colenbrander unsigned long quirks = id->driver_data; 2613e1bc84d0SRoderick Colenbrander struct sony_sc *sc; 2614e1bc84d0SRoderick Colenbrander unsigned int connect_mask = HID_CONNECT_DEFAULT; 2615e1bc84d0SRoderick Colenbrander 2616e1bc84d0SRoderick Colenbrander if (!strcmp(hdev->name, "FutureMax Dance Mat")) 2617e1bc84d0SRoderick Colenbrander quirks |= FUTUREMAX_DANCE_MAT; 2618e1bc84d0SRoderick Colenbrander 2619e1bc84d0SRoderick Colenbrander sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); 2620e1bc84d0SRoderick Colenbrander if (sc == NULL) { 2621e1bc84d0SRoderick Colenbrander hid_err(hdev, "can't alloc sony descriptor\n"); 2622e1bc84d0SRoderick Colenbrander return -ENOMEM; 2623e1bc84d0SRoderick Colenbrander } 2624e1bc84d0SRoderick Colenbrander 2625e1bc84d0SRoderick Colenbrander spin_lock_init(&sc->lock); 2626e1bc84d0SRoderick Colenbrander 2627e1bc84d0SRoderick Colenbrander sc->quirks = quirks; 2628e1bc84d0SRoderick Colenbrander hid_set_drvdata(hdev, sc); 2629e1bc84d0SRoderick Colenbrander sc->hdev = hdev; 2630e1bc84d0SRoderick Colenbrander 2631e1bc84d0SRoderick Colenbrander ret = hid_parse(hdev); 2632e1bc84d0SRoderick Colenbrander if (ret) { 2633e1bc84d0SRoderick Colenbrander hid_err(hdev, "parse failed\n"); 2634e1bc84d0SRoderick Colenbrander return ret; 2635e1bc84d0SRoderick Colenbrander } 2636e1bc84d0SRoderick Colenbrander 2637e1bc84d0SRoderick Colenbrander if (sc->quirks & VAIO_RDESC_CONSTANT) 2638e1bc84d0SRoderick Colenbrander connect_mask |= HID_CONNECT_HIDDEV_FORCE; 2639e1bc84d0SRoderick Colenbrander else if (sc->quirks & SIXAXIS_CONTROLLER) 2640e1bc84d0SRoderick Colenbrander connect_mask |= HID_CONNECT_HIDDEV_FORCE; 2641e1bc84d0SRoderick Colenbrander 26429131f8ccSRoderick Colenbrander /* Patch the hw version on DS4 compatible devices, so applications can 26439131f8ccSRoderick Colenbrander * distinguish between the default HID mappings and the mappings defined 26449131f8ccSRoderick Colenbrander * by the Linux game controller spec. This is important for the SDL2 26459131f8ccSRoderick Colenbrander * library, which has a game controller database, which uses device ids 26469131f8ccSRoderick Colenbrander * in combination with version as a key. 26479131f8ccSRoderick Colenbrander */ 26489131f8ccSRoderick Colenbrander if (sc->quirks & DUALSHOCK4_CONTROLLER) 26499131f8ccSRoderick Colenbrander hdev->version |= 0x8000; 26509131f8ccSRoderick Colenbrander 2651e1bc84d0SRoderick Colenbrander ret = hid_hw_start(hdev, connect_mask); 2652e1bc84d0SRoderick Colenbrander if (ret) { 2653e1bc84d0SRoderick Colenbrander hid_err(hdev, "hw start failed\n"); 2654e1bc84d0SRoderick Colenbrander return ret; 2655e1bc84d0SRoderick Colenbrander } 2656e1bc84d0SRoderick Colenbrander 26574f967f6dSRoderick Colenbrander /* sony_input_configured can fail, but this doesn't result 26584f967f6dSRoderick Colenbrander * in hid_hw_start failures (intended). Check whether 26594f967f6dSRoderick Colenbrander * the HID layer claimed the device else fail. 26604f967f6dSRoderick Colenbrander * We don't know the actual reason for the failure, most 26614f967f6dSRoderick Colenbrander * likely it is due to EEXIST in case of double connection 26624f967f6dSRoderick Colenbrander * of USB and Bluetooth, but could have been due to ENOMEM 26634f967f6dSRoderick Colenbrander * or other reasons as well. 26644f967f6dSRoderick Colenbrander */ 26654f967f6dSRoderick Colenbrander if (!(hdev->claimed & HID_CLAIMED_INPUT)) { 26664f967f6dSRoderick Colenbrander hid_err(hdev, "failed to claim input\n"); 26674f967f6dSRoderick Colenbrander return -ENODEV; 26684f967f6dSRoderick Colenbrander } 26694f967f6dSRoderick Colenbrander 2670e1bc84d0SRoderick Colenbrander return ret; 2671e1bc84d0SRoderick Colenbrander } 2672e1bc84d0SRoderick Colenbrander 2673bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev) 2674bd28ce00SJiri Slaby { 2675bd28ce00SJiri Slaby struct sony_sc *sc = hid_get_drvdata(hdev); 2676bd28ce00SJiri Slaby 2677ac797b95SRoderick Colenbrander hid_hw_close(hdev); 2678ac797b95SRoderick Colenbrander 26790a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2680fa57a810SFrank Praznik sony_leds_remove(sc); 2681bd28ce00SJiri Slaby 2682ac797b95SRoderick Colenbrander if (sc->quirks & SONY_BATTERY_SUPPORT) 2683d902f472SFrank Praznik sony_battery_remove(sc); 2684ac797b95SRoderick Colenbrander 2685ac797b95SRoderick Colenbrander if (sc->touchpad) 2686ac797b95SRoderick Colenbrander sony_unregister_touchpad(sc); 2687d902f472SFrank Praznik 268846262047SFrank Praznik sony_cancel_work_sync(sc); 26899f323b68SSven Eckelmann 26909b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 26919b2b5c9aSFrank Praznik 2692d2d782fcSFrank Praznik sony_remove_dev_list(sc); 2693bd28ce00SJiri Slaby 26948025087aSFrank Praznik sony_release_device_id(sc); 26958025087aSFrank Praznik 2696bd28ce00SJiri Slaby hid_hw_stop(hdev); 2697bd28ce00SJiri Slaby } 2698bd28ce00SJiri Slaby 2699decd946cSFrank Praznik #ifdef CONFIG_PM 2700decd946cSFrank Praznik 2701decd946cSFrank Praznik static int sony_suspend(struct hid_device *hdev, pm_message_t message) 2702decd946cSFrank Praznik { 2703decd946cSFrank Praznik /* 2704decd946cSFrank Praznik * On suspend save the current LED state, 2705decd946cSFrank Praznik * stop running force-feedback and blank the LEDS. 2706decd946cSFrank Praznik */ 2707decd946cSFrank Praznik if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) { 2708decd946cSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev); 2709decd946cSFrank Praznik 2710decd946cSFrank Praznik #ifdef CONFIG_SONY_FF 2711decd946cSFrank Praznik sc->left = sc->right = 0; 2712decd946cSFrank Praznik #endif 2713decd946cSFrank Praznik 2714decd946cSFrank Praznik memcpy(sc->resume_led_state, sc->led_state, 2715decd946cSFrank Praznik sizeof(sc->resume_led_state)); 2716decd946cSFrank Praznik memset(sc->led_state, 0, sizeof(sc->led_state)); 2717decd946cSFrank Praznik 2718decd946cSFrank Praznik sony_send_output_report(sc); 2719decd946cSFrank Praznik } 2720decd946cSFrank Praznik 2721decd946cSFrank Praznik return 0; 2722decd946cSFrank Praznik } 2723decd946cSFrank Praznik 2724decd946cSFrank Praznik static int sony_resume(struct hid_device *hdev) 2725decd946cSFrank Praznik { 2726decd946cSFrank Praznik /* Restore the state of controller LEDs on resume */ 2727decd946cSFrank Praznik if (SONY_LED_SUPPORT) { 2728decd946cSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev); 2729decd946cSFrank Praznik 2730decd946cSFrank Praznik memcpy(sc->led_state, sc->resume_led_state, 2731decd946cSFrank Praznik sizeof(sc->led_state)); 2732decd946cSFrank Praznik 2733decd946cSFrank Praznik /* 2734decd946cSFrank Praznik * The Sixaxis and navigation controllers on USB need to be 2735decd946cSFrank Praznik * reinitialized on resume or they won't behave properly. 2736decd946cSFrank Praznik */ 2737decd946cSFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 27382a242932SFrank Praznik (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 2739decd946cSFrank Praznik sixaxis_set_operational_usb(sc->hdev); 27402a242932SFrank Praznik sc->defer_initialization = 1; 27412a242932SFrank Praznik } 2742decd946cSFrank Praznik 2743decd946cSFrank Praznik sony_set_leds(sc); 2744decd946cSFrank Praznik } 2745decd946cSFrank Praznik 2746decd946cSFrank Praznik return 0; 2747decd946cSFrank Praznik } 2748decd946cSFrank Praznik 2749decd946cSFrank Praznik #endif 2750decd946cSFrank Praznik 2751bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = { 2752bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2753bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_USB }, 2754bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 27554545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_USB }, 27566eabaaa0SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 27574545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_BT }, 2758c5e0c1c4SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2759b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_USB }, 2760a4afa854SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2761b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_BT }, 2762bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2763bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_BT }, 2764bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 2765bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2766bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), 2767bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2768ef916ef5SAntonio Ospite /* 2769ef916ef5SAntonio Ospite * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as 2770ef916ef5SAntonio Ospite * Logitech joystick from the device descriptor. 2771ef916ef5SAntonio Ospite */ 2772bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), 2773bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2774bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), 2775bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2776bd28ce00SJiri Slaby /* PS3 BD Remote Control */ 2777bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), 2778bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 2779bd28ce00SJiri Slaby /* Logitech Harmony Adapter for PS3 */ 2780bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), 2781bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 278268a49e51SFrank Praznik /* SMK-Link PS3 BD Remote Control */ 278368a49e51SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), 278468a49e51SFrank Praznik .driver_data = PS3REMOTE }, 27850bd88dd3SFrank Praznik /* Sony Dualshock 4 controllers for PS4 */ 27860bd88dd3SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 27878ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_USB }, 27880bd88dd3SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 27898ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_BT }, 2790cf1015d6SRoderick Colenbrander { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), 2791cf1015d6SRoderick Colenbrander .driver_data = DUALSHOCK4_CONTROLLER_USB }, 2792cf1015d6SRoderick Colenbrander { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), 2793cf1015d6SRoderick Colenbrander .driver_data = DUALSHOCK4_CONTROLLER_BT }, 2794*de66a1a0SRoderick Colenbrander { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE), 2795*de66a1a0SRoderick Colenbrander .driver_data = DUALSHOCK4_CONTROLLER_USB }, 279674500cc8SScott Moreau /* Nyko Core Controller for PS3 */ 279774500cc8SScott Moreau { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), 279874500cc8SScott Moreau .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, 2799bd28ce00SJiri Slaby { } 2800bd28ce00SJiri Slaby }; 2801bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices); 2802bd28ce00SJiri Slaby 2803bd28ce00SJiri Slaby static struct hid_driver sony_driver = { 2804bd28ce00SJiri Slaby .name = "sony", 2805bd28ce00SJiri Slaby .id_table = sony_devices, 2806bd28ce00SJiri Slaby .input_mapping = sony_mapping, 2807ce8efc3bSFrank Praznik .input_configured = sony_input_configured, 2808bd28ce00SJiri Slaby .probe = sony_probe, 2809bd28ce00SJiri Slaby .remove = sony_remove, 2810bd28ce00SJiri Slaby .report_fixup = sony_report_fixup, 2811decd946cSFrank Praznik .raw_event = sony_raw_event, 2812decd946cSFrank Praznik 2813decd946cSFrank Praznik #ifdef CONFIG_PM 2814decd946cSFrank Praznik .suspend = sony_suspend, 2815decd946cSFrank Praznik .resume = sony_resume, 2816decd946cSFrank Praznik .reset_resume = sony_resume, 2817decd946cSFrank Praznik #endif 2818bd28ce00SJiri Slaby }; 28198025087aSFrank Praznik 28208025087aSFrank Praznik static int __init sony_init(void) 28218025087aSFrank Praznik { 28228025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 28238025087aSFrank Praznik 28248025087aSFrank Praznik return hid_register_driver(&sony_driver); 28258025087aSFrank Praznik } 28268025087aSFrank Praznik 28278025087aSFrank Praznik static void __exit sony_exit(void) 28288025087aSFrank Praznik { 28298025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 28308025087aSFrank Praznik 28318025087aSFrank Praznik hid_unregister_driver(&sony_driver); 28326c40065fSAntonio Ospite ida_destroy(&sony_device_id_allocator); 28338025087aSFrank Praznik } 28348025087aSFrank Praznik module_init(sony_init); 28358025087aSFrank Praznik module_exit(sony_exit); 2836bd28ce00SJiri Slaby 2837bd28ce00SJiri Slaby MODULE_LICENSE("GPL"); 2838