1bd28ce00SJiri Slaby /* 2077147a3SFrank Praznik * HID driver for Sony / PS2 / PS3 / PS4 BD devices. 3bd28ce00SJiri Slaby * 4bd28ce00SJiri Slaby * Copyright (c) 1999 Andreas Gal 5bd28ce00SJiri Slaby * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 6bd28ce00SJiri Slaby * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 7bd28ce00SJiri Slaby * Copyright (c) 2008 Jiri Slaby 8078328daSJiri Kosina * Copyright (c) 2012 David Dillow <dave@thedillows.org> 9078328daSJiri Kosina * Copyright (c) 2006-2013 Jiri Kosina 10f04d5140SColin Leitner * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> 11077147a3SFrank Praznik * Copyright (c) 2014 Frank Praznik <frank.praznik@gmail.com> 12bd28ce00SJiri Slaby */ 13bd28ce00SJiri Slaby 14bd28ce00SJiri Slaby /* 15bd28ce00SJiri Slaby * This program is free software; you can redistribute it and/or modify it 16bd28ce00SJiri Slaby * under the terms of the GNU General Public License as published by the Free 17bd28ce00SJiri Slaby * Software Foundation; either version 2 of the License, or (at your option) 18bd28ce00SJiri Slaby * any later version. 19bd28ce00SJiri Slaby */ 20bd28ce00SJiri Slaby 21ad142b9eSFrank Praznik /* 22ad142b9eSFrank Praznik * NOTE: in order for the Sony PS3 BD Remote Control to be found by 23078328daSJiri Kosina * a Bluetooth host, the key combination Start+Enter has to be kept pressed 24078328daSJiri Kosina * for about 7 seconds with the Bluetooth Host Controller in discovering mode. 25078328daSJiri Kosina * 26078328daSJiri Kosina * There will be no PIN request from the device. 27078328daSJiri Kosina */ 28078328daSJiri Kosina 29bd28ce00SJiri Slaby #include <linux/device.h> 30bd28ce00SJiri Slaby #include <linux/hid.h> 31bd28ce00SJiri Slaby #include <linux/module.h> 325a0e3ad6STejun Heo #include <linux/slab.h> 3340e32ee6SJiri Kosina #include <linux/leds.h> 34d902f472SFrank Praznik #include <linux/power_supply.h> 35d902f472SFrank Praznik #include <linux/spinlock.h> 36d2d782fcSFrank Praznik #include <linux/list.h> 378025087aSFrank Praznik #include <linux/idr.h> 38e5606230SFrank Praznik #include <linux/input/mt.h> 39bd28ce00SJiri Slaby 40bd28ce00SJiri Slaby #include "hid-ids.h" 41bd28ce00SJiri Slaby 42f1c458caSSven Eckelmann #define VAIO_RDESC_CONSTANT BIT(0) 43f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_USB BIT(1) 44f1c458caSSven Eckelmann #define SIXAXIS_CONTROLLER_BT BIT(2) 45f1c458caSSven Eckelmann #define BUZZ_CONTROLLER BIT(3) 46f1c458caSSven Eckelmann #define PS3REMOTE BIT(4) 478ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_USB BIT(5) 488ab1676bSFrank Praznik #define DUALSHOCK4_CONTROLLER_BT BIT(6) 49b3bca326SSimon Wood #define MOTION_CONTROLLER_USB BIT(7) 50b3bca326SSimon Wood #define MOTION_CONTROLLER_BT BIT(8) 514545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_USB BIT(9) 524545ee0aSSimon Wood #define NAVIGATION_CONTROLLER_BT BIT(10) 53cc6e0bbbSJiri Kosina 54fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) 55b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) 564545ee0aSSimon Wood #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\ 574545ee0aSSimon Wood NAVIGATION_CONTROLLER_BT) 5868330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ 5968330d83SFrank Praznik DUALSHOCK4_CONTROLLER_BT) 60fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ 614545ee0aSSimon Wood DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\ 624545ee0aSSimon Wood NAVIGATION_CONTROLLER) 6312e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 644545ee0aSSimon Wood MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) 65c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 66c5e0c1c4SFrank Praznik MOTION_CONTROLLER) 6760781cf4SFrank Praznik 6860781cf4SFrank Praznik #define MAX_LEDS 4 690a286ef2SSven Eckelmann 704c3e8298SFrank Praznik /* 714c3e8298SFrank Praznik * The Sixaxis reports both digital and analog values for each button on the 724c3e8298SFrank Praznik * controller except for Start, Select and the PS button. The controller ends 734c3e8298SFrank Praznik * up reporting 27 axes which causes them to spill over into the multi-touch 744c3e8298SFrank Praznik * axis values. Additionally, the controller only has 20 actual, physical axes 754c3e8298SFrank Praznik * so there are several unused axes in between the used ones. 764c3e8298SFrank Praznik */ 77c607fb8dSAntonio Ospite static __u8 sixaxis_rdesc[] = { 78fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 794c3e8298SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */ 80fb705a6dSAntonio Ospite 0xA1, 0x01, /* Collection (Application), */ 81fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 82fb705a6dSAntonio Ospite 0x85, 0x01, /* Report ID (1), */ 83fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 84fb705a6dSAntonio Ospite 0x95, 0x01, /* Report Count (1), */ 85fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 86fb705a6dSAntonio Ospite 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 87fb705a6dSAntonio Ospite 0x81, 0x03, /* Input (Constant, Variable), */ 88fb705a6dSAntonio Ospite 0x75, 0x01, /* Report Size (1), */ 89fb705a6dSAntonio Ospite 0x95, 0x13, /* Report Count (19), */ 90fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 91fb705a6dSAntonio Ospite 0x25, 0x01, /* Logical Maximum (1), */ 92fb705a6dSAntonio Ospite 0x35, 0x00, /* Physical Minimum (0), */ 93fb705a6dSAntonio Ospite 0x45, 0x01, /* Physical Maximum (1), */ 94fb705a6dSAntonio Ospite 0x05, 0x09, /* Usage Page (Button), */ 95fb705a6dSAntonio Ospite 0x19, 0x01, /* Usage Minimum (01h), */ 96fb705a6dSAntonio Ospite 0x29, 0x13, /* Usage Maximum (13h), */ 97fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 98fb705a6dSAntonio Ospite 0x75, 0x01, /* Report Size (1), */ 99fb705a6dSAntonio Ospite 0x95, 0x0D, /* Report Count (13), */ 100fb705a6dSAntonio Ospite 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 101fb705a6dSAntonio Ospite 0x81, 0x03, /* Input (Constant, Variable), */ 102fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 103fb705a6dSAntonio Ospite 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 104fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 105fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 106fb705a6dSAntonio Ospite 0xA1, 0x00, /* Collection (Physical), */ 107fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 108fb705a6dSAntonio Ospite 0x95, 0x04, /* Report Count (4), */ 109fb705a6dSAntonio Ospite 0x35, 0x00, /* Physical Minimum (0), */ 110fb705a6dSAntonio Ospite 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 111fb705a6dSAntonio Ospite 0x09, 0x30, /* Usage (X), */ 112fb705a6dSAntonio Ospite 0x09, 0x31, /* Usage (Y), */ 113fb705a6dSAntonio Ospite 0x09, 0x32, /* Usage (Z), */ 114fb705a6dSAntonio Ospite 0x09, 0x35, /* Usage (Rz), */ 115fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 116fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 117fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 118fb705a6dSAntonio Ospite 0x95, 0x13, /* Report Count (19), */ 119fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 120fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 121fb705a6dSAntonio Ospite 0x95, 0x0C, /* Report Count (12), */ 122fb705a6dSAntonio Ospite 0x81, 0x01, /* Input (Constant), */ 123fb705a6dSAntonio Ospite 0x75, 0x10, /* Report Size (16), */ 124fb705a6dSAntonio Ospite 0x95, 0x04, /* Report Count (4), */ 125fb705a6dSAntonio Ospite 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 126fb705a6dSAntonio Ospite 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 127fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 128fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 129fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 130fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 131fb705a6dSAntonio Ospite 0x85, 0x02, /* Report ID (2), */ 132fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 133fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 134fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 135fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 136fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 137fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 138fb705a6dSAntonio Ospite 0x85, 0xEE, /* Report ID (238), */ 139fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 140fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 141fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 142fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 143fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 144fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 145fb705a6dSAntonio Ospite 0x85, 0xEF, /* Report ID (239), */ 146fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 147fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 148fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 149fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 150fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 151fb705a6dSAntonio Ospite 0xC0 /* End Collection */ 152e57a67daSMauro Carvalho Chehab }; 153e57a67daSMauro Carvalho Chehab 154c5e0c1c4SFrank Praznik /* PS/3 Motion controller */ 155c5e0c1c4SFrank Praznik static __u8 motion_rdesc[] = { 156c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 157c5e0c1c4SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */ 158c5e0c1c4SFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 159c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 160c5e0c1c4SFrank Praznik 0x85, 0x01, /* Report ID (1), */ 161c5e0c1c4SFrank Praznik 0x75, 0x01, /* Report Size (1), */ 1628b2513c3SSimon Wood 0x95, 0x15, /* Report Count (21), */ 163c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 164c5e0c1c4SFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 165c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 166c5e0c1c4SFrank Praznik 0x45, 0x01, /* Physical Maximum (1), */ 167c5e0c1c4SFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 168c5e0c1c4SFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 1698b2513c3SSimon Wood 0x29, 0x15, /* Usage Maximum (15h), */ 1708b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Buttons */ 1718b2513c3SSimon Wood 0x95, 0x0B, /* Report Count (11), */ 172c5e0c1c4SFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 1738b2513c3SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), * Padding */ 174c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 175c5e0c1c4SFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 176c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 177c5e0c1c4SFrank Praznik 0xA1, 0x00, /* Collection (Physical), */ 178c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 1798b2513c3SSimon Wood 0x95, 0x01, /* Report Count (1), */ 180c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 181c5e0c1c4SFrank Praznik 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 182c5e0c1c4SFrank Praznik 0x09, 0x30, /* Usage (X), */ 1838b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Trigger */ 184c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 1858b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 1868b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 1878b2513c3SSimon Wood 0x95, 0x07, /* Report Count (7), * skip 7 bytes */ 1888b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 189c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 190c5e0c1c4SFrank Praznik 0x75, 0x10, /* Report Size (16), */ 1918b2513c3SSimon Wood 0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */ 1928b2513c3SSimon Wood 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */ 1938b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Accels */ 1948b2513c3SSimon Wood 0x09, 0x33, /* Usage (rX), */ 1958b2513c3SSimon Wood 0x09, 0x34, /* Usage (rY), */ 1968b2513c3SSimon Wood 0x09, 0x35, /* Usage (rZ), */ 197c5e0c1c4SFrank Praznik 0x81, 0x02, /* Input (Variable), */ 1988b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 1998b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */ 2008b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2018b2513c3SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 2028b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 2038b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Gyros */ 2048b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2058b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 2068b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */ 2078b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2088b2513c3SSimon Wood 0x75, 0x0C, /* Report Size (12), */ 2098b2513c3SSimon Wood 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */ 2108b2513c3SSimon Wood 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */ 2118b2513c3SSimon Wood 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */ 2128b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2138b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 2148b2513c3SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 2158b2513c3SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 2168b2513c3SSimon Wood 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */ 2178b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 2188b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 2198b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */ 2208b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 2218b2513c3SSimon Wood 0x91, 0x02, /* Output (Variable), */ 2228b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 2238b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */ 2248b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 2258b2513c3SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 226c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 227c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 228c5e0c1c4SFrank Praznik 0x85, 0x02, /* Report ID (2), */ 229c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 230c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 231c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 232c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 233c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 234c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 235c5e0c1c4SFrank Praznik 0x85, 0xEE, /* Report ID (238), */ 236c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 237c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 238c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 239c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 240c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 241c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 242c5e0c1c4SFrank Praznik 0x85, 0xEF, /* Report ID (239), */ 243c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 244c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 245c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 246c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 247c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 248c5e0c1c4SFrank Praznik 0xC0 /* End Collection */ 249c5e0c1c4SFrank Praznik }; 250c5e0c1c4SFrank Praznik 251b2723eb7SSimon Wood /* PS/3 Navigation controller */ 252b2723eb7SSimon Wood static __u8 navigation_rdesc[] = { 253b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 254b2723eb7SSimon Wood 0x09, 0x04, /* Usage (Joystik), */ 255b2723eb7SSimon Wood 0xA1, 0x01, /* Collection (Application), */ 256b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 257b2723eb7SSimon Wood 0x85, 0x01, /* Report ID (1), */ 258b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 259b2723eb7SSimon Wood 0x95, 0x01, /* Report Count (1), */ 260b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 261b2723eb7SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 262b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 263b2723eb7SSimon Wood 0x75, 0x01, /* Report Size (1), */ 264b2723eb7SSimon Wood 0x95, 0x13, /* Report Count (19), */ 265b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 266b2723eb7SSimon Wood 0x25, 0x01, /* Logical Maximum (1), */ 267b2723eb7SSimon Wood 0x35, 0x00, /* Physical Minimum (0), */ 268b2723eb7SSimon Wood 0x45, 0x01, /* Physical Maximum (1), */ 269b2723eb7SSimon Wood 0x05, 0x09, /* Usage Page (Button), */ 270b2723eb7SSimon Wood 0x19, 0x01, /* Usage Minimum (01h), */ 271b2723eb7SSimon Wood 0x29, 0x13, /* Usage Maximum (13h), */ 272b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 273b2723eb7SSimon Wood 0x75, 0x01, /* Report Size (1), */ 274b2723eb7SSimon Wood 0x95, 0x0D, /* Report Count (13), */ 275b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 276b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 277b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 278b2723eb7SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 279b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 280b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 281b2723eb7SSimon Wood 0xA1, 0x00, /* Collection (Physical), */ 282b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 283b2723eb7SSimon Wood 0x95, 0x02, /* Report Count (2), */ 284b2723eb7SSimon Wood 0x35, 0x00, /* Physical Minimum (0), */ 285b2723eb7SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 286b2723eb7SSimon Wood 0x09, 0x30, /* Usage (X), */ 287b2723eb7SSimon Wood 0x09, 0x31, /* Usage (Y), */ 288b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 289b2723eb7SSimon Wood 0xC0, /* End Collection, */ 290b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 291b2723eb7SSimon Wood 0x95, 0x06, /* Report Count (6), */ 292b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 293b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 294b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 295b2723eb7SSimon Wood 0x95, 0x05, /* Report Count (5), */ 296b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 297b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 298b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 299*2259b5bbSSimon Wood 0x95, 0x01, /* Report Count (1), */ 300*2259b5bbSSimon Wood 0x81, 0x02, /* Input (Variable), */ 301*2259b5bbSSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 302*2259b5bbSSimon Wood 0x95, 0x01, /* Report Count (1), */ 303*2259b5bbSSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 304*2259b5bbSSimon Wood 0x81, 0x02, /* Input (Variable), */ 305*2259b5bbSSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 306*2259b5bbSSimon Wood 0x95, 0x1E, /* Report Count (24), */ 307b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 308b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 309b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 310b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 311b2723eb7SSimon Wood 0x91, 0x02, /* Output (Variable), */ 312b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 313b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 314b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 315b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 316b2723eb7SSimon Wood 0xC0, /* End Collection, */ 317b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 318b2723eb7SSimon Wood 0x85, 0x02, /* Report ID (2), */ 319b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 320b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 321b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 322b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 323b2723eb7SSimon Wood 0xC0, /* End Collection, */ 324b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 325b2723eb7SSimon Wood 0x85, 0xEE, /* Report ID (238), */ 326b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 327b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 328b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 329b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 330b2723eb7SSimon Wood 0xC0, /* End Collection, */ 331b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 332b2723eb7SSimon Wood 0x85, 0xEF, /* Report ID (239), */ 333b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 334b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 335b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 336b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 337b2723eb7SSimon Wood 0xC0, /* End Collection, */ 338b2723eb7SSimon Wood 0xC0 /* End Collection */ 339b2723eb7SSimon Wood }; 340c5e0c1c4SFrank Praznik 341ad142b9eSFrank Praznik /* 342ad142b9eSFrank Praznik * The default descriptor doesn't provide mapping for the accelerometers 34358d7027bSFrank Praznik * or orientation sensors. This fixed descriptor maps the accelerometers 34458d7027bSFrank Praznik * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors 34558d7027bSFrank Praznik * to usage values 0x43, 0x44 and 0x45. 34658d7027bSFrank Praznik */ 347ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = { 34858d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 34958d7027bSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 35058d7027bSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 35158d7027bSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 35258d7027bSFrank Praznik 0x09, 0x30, /* Usage (X), */ 35358d7027bSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 35458d7027bSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 35558d7027bSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 35658d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 35758d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 35858d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 35958d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 36058d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 36158d7027bSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 36258d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 36358d7027bSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 36458d7027bSFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 36558d7027bSFrank Praznik 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 36658d7027bSFrank Praznik 0x65, 0x14, /* Unit (Degrees), */ 36758d7027bSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 36858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 36958d7027bSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 37058d7027bSFrank Praznik 0x65, 0x00, /* Unit, */ 37158d7027bSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 37258d7027bSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 37358d7027bSFrank Praznik 0x29, 0x0E, /* Usage Maximum (0Eh), */ 37458d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 37558d7027bSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 37658d7027bSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 37758d7027bSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 37858d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 37958d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 38058d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 38158d7027bSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 38258d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 38358d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 384fb291cbdSFrank Praznik 0x25, 0x3F, /* Logical Maximum (63), */ 38558d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 38658d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 38758d7027bSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 38858d7027bSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 38958d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 39058d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 39158d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 39258d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 39358d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 39458d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 39558d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 39658d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 39758d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 39858d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 39958d7027bSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 40058d7027bSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 40158d7027bSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 40258d7027bSFrank Praznik 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ 40358d7027bSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 40458d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 40558d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 40658d7027bSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 40758d7027bSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 408fb291cbdSFrank Praznik 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ 409fb291cbdSFrank Praznik 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ 41058d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 41158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 41258d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 41358d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 41458d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 415fb291cbdSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 41658d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 41758d7027bSFrank Praznik 0x95, 0x27, /* Report Count (39), */ 41858d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 41958d7027bSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 42058d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 42158d7027bSFrank Praznik 0x95, 0x1F, /* Report Count (31), */ 42258d7027bSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 42358d7027bSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 42458d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 42558d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 42658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42758d7027bSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 42858d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 42958d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 43058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43158d7027bSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 43258d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 43358d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 43458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43558d7027bSFrank Praznik 0x85, 0x10, /* Report ID (16), */ 43658d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 43758d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 43858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43958d7027bSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 44058d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 44158d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 44258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44358d7027bSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 44458d7027bSFrank Praznik 0x06, 0x02, 0xFF, /* Usage Page (FF02h), */ 44558d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 44658d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 44758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44858d7027bSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 44958d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 45058d7027bSFrank Praznik 0x95, 0x16, /* Report Count (22), */ 45158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45258d7027bSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 45358d7027bSFrank Praznik 0x06, 0x05, 0xFF, /* Usage Page (FF05h), */ 45458d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 45558d7027bSFrank Praznik 0x95, 0x10, /* Report Count (16), */ 45658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45758d7027bSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 45858d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 45958d7027bSFrank Praznik 0x95, 0x2C, /* Report Count (44), */ 46058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46158d7027bSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 46258d7027bSFrank Praznik 0x85, 0x80, /* Report ID (128), */ 46358d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 46458d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 46558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46658d7027bSFrank Praznik 0x85, 0x81, /* Report ID (129), */ 46758d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 46858d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 46958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47058d7027bSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 47158d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 47258d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 47358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47458d7027bSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 47558d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 47658d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 47758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47858d7027bSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 47958d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 48058d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 48158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48258d7027bSFrank Praznik 0x85, 0x85, /* Report ID (133), */ 48358d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 48458d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 48558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48658d7027bSFrank Praznik 0x85, 0x86, /* Report ID (134), */ 48758d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 48858d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 48958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49058d7027bSFrank Praznik 0x85, 0x87, /* Report ID (135), */ 49158d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 49258d7027bSFrank Praznik 0x95, 0x23, /* Report Count (35), */ 49358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49458d7027bSFrank Praznik 0x85, 0x88, /* Report ID (136), */ 49558d7027bSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 49658d7027bSFrank Praznik 0x95, 0x22, /* Report Count (34), */ 49758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49858d7027bSFrank Praznik 0x85, 0x89, /* Report ID (137), */ 49958d7027bSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 50058d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 50158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50258d7027bSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 50358d7027bSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 50458d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 50558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50658d7027bSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 50758d7027bSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 50858d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 50958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51058d7027bSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 51158d7027bSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 51258d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 51358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51458d7027bSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 51558d7027bSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 51658d7027bSFrank Praznik 0x95, 0x0C, /* Report Count (12), */ 51758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51858d7027bSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 51958d7027bSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 52058d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 52158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52258d7027bSFrank Praznik 0x85, 0xA1, /* Report ID (161), */ 52358d7027bSFrank Praznik 0x09, 0x41, /* Usage (41h), */ 52458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 52558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52658d7027bSFrank Praznik 0x85, 0xA2, /* Report ID (162), */ 52758d7027bSFrank Praznik 0x09, 0x42, /* Usage (42h), */ 52858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 52958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53058d7027bSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 53158d7027bSFrank Praznik 0x09, 0x43, /* Usage (43h), */ 53258d7027bSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 53358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53458d7027bSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 53558d7027bSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 53658d7027bSFrank Praznik 0x95, 0x0D, /* Report Count (13), */ 53758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53858d7027bSFrank Praznik 0x85, 0xA5, /* Report ID (165), */ 53958d7027bSFrank Praznik 0x09, 0x45, /* Usage (45h), */ 54058d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 54158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54258d7027bSFrank Praznik 0x85, 0xA6, /* Report ID (166), */ 54358d7027bSFrank Praznik 0x09, 0x46, /* Usage (46h), */ 54458d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 54558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54658d7027bSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 54758d7027bSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 54858d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 54958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55058d7027bSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 55158d7027bSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 55258d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 55358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55458d7027bSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 55558d7027bSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 55658d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 55758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55858d7027bSFrank Praznik 0x85, 0xA7, /* Report ID (167), */ 55958d7027bSFrank Praznik 0x09, 0x4A, /* Usage (4Ah), */ 56058d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 56158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56258d7027bSFrank Praznik 0x85, 0xA8, /* Report ID (168), */ 56358d7027bSFrank Praznik 0x09, 0x4B, /* Usage (4Bh), */ 56458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 56558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56658d7027bSFrank Praznik 0x85, 0xA9, /* Report ID (169), */ 56758d7027bSFrank Praznik 0x09, 0x4C, /* Usage (4Ch), */ 56858d7027bSFrank Praznik 0x95, 0x08, /* Report Count (8), */ 56958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57058d7027bSFrank Praznik 0x85, 0xAA, /* Report ID (170), */ 57158d7027bSFrank Praznik 0x09, 0x4E, /* Usage (4Eh), */ 57258d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 57358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57458d7027bSFrank Praznik 0x85, 0xAB, /* Report ID (171), */ 57558d7027bSFrank Praznik 0x09, 0x4F, /* Usage (4Fh), */ 57658d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 57758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57858d7027bSFrank Praznik 0x85, 0xAC, /* Report ID (172), */ 57958d7027bSFrank Praznik 0x09, 0x50, /* Usage (50h), */ 58058d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 58158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58258d7027bSFrank Praznik 0x85, 0xAD, /* Report ID (173), */ 58358d7027bSFrank Praznik 0x09, 0x51, /* Usage (51h), */ 58458d7027bSFrank Praznik 0x95, 0x0B, /* Report Count (11), */ 58558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58658d7027bSFrank Praznik 0x85, 0xAE, /* Report ID (174), */ 58758d7027bSFrank Praznik 0x09, 0x52, /* Usage (52h), */ 58858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 58958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 59058d7027bSFrank Praznik 0x85, 0xAF, /* Report ID (175), */ 59158d7027bSFrank Praznik 0x09, 0x53, /* Usage (53h), */ 59258d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 59358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 59458d7027bSFrank Praznik 0x85, 0xB0, /* Report ID (176), */ 59558d7027bSFrank Praznik 0x09, 0x54, /* Usage (54h), */ 59658d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 59758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 59858d7027bSFrank Praznik 0xC0 /* End Collection */ 599ed19d8cfSFrank Praznik }; 600ed19d8cfSFrank Praznik 601ad142b9eSFrank Praznik /* 602ad142b9eSFrank Praznik * The default behavior of the Dualshock 4 is to send reports using report 603077147a3SFrank Praznik * type 1 when running over Bluetooth. However, when feature report 2 is 604077147a3SFrank Praznik * requested during the controller initialization it starts sending input 605077147a3SFrank Praznik * reports in report 17. Since report 17 is undefined in the default HID 606d829674dSFrank Praznik * descriptor the button and axis definitions must be moved to report 17 or 607077147a3SFrank Praznik * the HID layer won't process the received input. 608d829674dSFrank Praznik */ 609d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = { 610d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 611d829674dSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 612d829674dSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 613d829674dSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 614d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 615d829674dSFrank Praznik 0x95, 0x0A, /* Report Count (9), */ 616d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 617d829674dSFrank Praznik 0x06, 0x04, 0xFF, /* Usage Page (FF04h), */ 618d829674dSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 619d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 620d829674dSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 621d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 622d829674dSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 623d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 624d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 625d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 626d829674dSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 627d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 628d829674dSFrank Praznik 0x95, 0x28, /* Report Count (40), */ 629d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 630d829674dSFrank Praznik 0x85, 0x06, /* Report ID (6), */ 631d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 632d829674dSFrank Praznik 0x95, 0x34, /* Report Count (52), */ 633d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 634d829674dSFrank Praznik 0x85, 0x07, /* Report ID (7), */ 635d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 636d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 637d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 638d829674dSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 639d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 640d829674dSFrank Praznik 0x95, 0x2F, /* Report Count (47), */ 641d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 642d829674dSFrank Praznik 0x06, 0x03, 0xFF, /* Usage Page (FF03h), */ 643d829674dSFrank Praznik 0x85, 0x03, /* Report ID (3), */ 644d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 645d829674dSFrank Praznik 0x95, 0x26, /* Report Count (38), */ 646d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 647d829674dSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 648d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 649d829674dSFrank Praznik 0x95, 0x2E, /* Report Count (46), */ 650d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 651d829674dSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 652d829674dSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 653d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 654d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 655d829674dSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 656d829674dSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 657d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 658d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 659d829674dSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 660d829674dSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 661d829674dSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 662d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 663d829674dSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 664d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 665d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 666d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 667d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 668d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 669d829674dSFrank Praznik 0x09, 0x30, /* Usage (X), */ 670d829674dSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 671d829674dSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 672d829674dSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 673d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 674d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 675d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 676d829674dSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 677d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 678d829674dSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 679d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 680d829674dSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 681d829674dSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 682d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 683d829674dSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 684d829674dSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 685d829674dSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 686d829674dSFrank Praznik 0x29, 0x0E, /* Usage Maximum (0Eh), */ 687d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 688d829674dSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 689d829674dSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 690d829674dSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 691d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 692d829674dSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 693d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 694d829674dSFrank Praznik 0x81, 0x01, /* Input (Constant), */ 695d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 696d829674dSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 697d829674dSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 698d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 699d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 700d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 701d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 702d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 703d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 704d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 705d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 706d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 707d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 708d829674dSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 709d829674dSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 710d829674dSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 711d829674dSFrank Praznik 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ 712d829674dSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 713d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 714d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 715d829674dSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 716d829674dSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 717fb291cbdSFrank Praznik 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ 718fb291cbdSFrank Praznik 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ 719d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 720d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 721d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 722d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 723d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 724d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 725d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 726d829674dSFrank Praznik 0x95, 0x31, /* Report Count (51), */ 727d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 728d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 729d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 730d829674dSFrank Praznik 0x95, 0x4D, /* Report Count (77), */ 731d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 732d829674dSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 733d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 734d829674dSFrank Praznik 0x95, 0x8D, /* Report Count (141), */ 735d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 736d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 737d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 738d829674dSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 739d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 740d829674dSFrank Praznik 0x95, 0xCD, /* Report Count (205), */ 741d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 742d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 743d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 744d829674dSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 745d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 746d829674dSFrank Praznik 0x96, 0x0D, 0x01, /* Report Count (269), */ 747d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 748d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 749d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 750d829674dSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 751d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 752d829674dSFrank Praznik 0x96, 0x4D, 0x01, /* Report Count (333), */ 753d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 754d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 755d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 756d829674dSFrank Praznik 0x85, 0x16, /* Report ID (22), */ 757d829674dSFrank Praznik 0x09, 0x2A, /* Usage (2Ah), */ 758d829674dSFrank Praznik 0x96, 0x8D, 0x01, /* Report Count (397), */ 759d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 760d829674dSFrank Praznik 0x09, 0x2B, /* Usage (2Bh), */ 761d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 762d829674dSFrank Praznik 0x85, 0x17, /* Report ID (23), */ 763d829674dSFrank Praznik 0x09, 0x2C, /* Usage (2Ch), */ 764d829674dSFrank Praznik 0x96, 0xCD, 0x01, /* Report Count (461), */ 765d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 766d829674dSFrank Praznik 0x09, 0x2D, /* Usage (2Dh), */ 767d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 768d829674dSFrank Praznik 0x85, 0x18, /* Report ID (24), */ 769d829674dSFrank Praznik 0x09, 0x2E, /* Usage (2Eh), */ 770d829674dSFrank Praznik 0x96, 0x0D, 0x02, /* Report Count (525), */ 771d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 772d829674dSFrank Praznik 0x09, 0x2F, /* Usage (2Fh), */ 773d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 774d829674dSFrank Praznik 0x85, 0x19, /* Report ID (25), */ 775d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 776d829674dSFrank Praznik 0x96, 0x22, 0x02, /* Report Count (546), */ 777d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 778d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 779d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 780d829674dSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 781d829674dSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 782d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 783d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 784d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 785d829674dSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 786d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 787d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 788d829674dSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 789d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 790d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 791d829674dSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 792d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 793d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 794d829674dSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 795d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 796d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 797d829674dSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 798d829674dSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 799d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 800d829674dSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 801d829674dSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 802d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 803d829674dSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 804d829674dSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 805d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 806d829674dSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 807d829674dSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 808d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 809d829674dSFrank Praznik 0xC0 /* End Collection */ 810d829674dSFrank Praznik }; 811d829674dSFrank Praznik 812078328daSJiri Kosina static __u8 ps3remote_rdesc[] = { 813078328daSJiri Kosina 0x05, 0x01, /* GUsagePage Generic Desktop */ 814078328daSJiri Kosina 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 815078328daSJiri Kosina 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ 816078328daSJiri Kosina 817078328daSJiri Kosina /* Use collection 1 for joypad buttons */ 818078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 819078328daSJiri Kosina 820078328daSJiri Kosina /* Ignore the 1st byte, maybe it is used for a controller 821078328daSJiri Kosina * number but it's not needed for correct operation */ 822078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 823078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 824078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 825078328daSJiri Kosina 826078328daSJiri Kosina /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these 827078328daSJiri Kosina * buttons multiple keypresses are allowed */ 828078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 829078328daSJiri Kosina 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ 830078328daSJiri Kosina 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ 831078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 832078328daSJiri Kosina 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ 833078328daSJiri Kosina 0x75, 0x01, /* GReportSize 0x01 [1] */ 834078328daSJiri Kosina 0x95, 0x18, /* GReportCount 0x18 [24] */ 835078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 836078328daSJiri Kosina 837078328daSJiri Kosina 0xC0, /* MEndCollection */ 838078328daSJiri Kosina 839078328daSJiri Kosina /* Use collection 2 for remote control buttons */ 840078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 841078328daSJiri Kosina 842078328daSJiri Kosina /* 5th byte is used for remote control buttons */ 843078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 844078328daSJiri Kosina 0x18, /* LUsageMinimum [No button pressed] */ 845078328daSJiri Kosina 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ 846078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 847078328daSJiri Kosina 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ 848078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 849078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 850078328daSJiri Kosina 0x80, /* MInput */ 851078328daSJiri Kosina 852078328daSJiri Kosina /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at 853078328daSJiri Kosina * 0xff and 11th is for press indication */ 854078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 855078328daSJiri Kosina 0x95, 0x06, /* GReportCount 0x06 [6] */ 856078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 857078328daSJiri Kosina 858078328daSJiri Kosina /* 12th byte is for battery strength */ 859078328daSJiri Kosina 0x05, 0x06, /* GUsagePage Generic Device Controls */ 860078328daSJiri Kosina 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ 861078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 862078328daSJiri Kosina 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ 863078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 864078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 865078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 866078328daSJiri Kosina 867078328daSJiri Kosina 0xC0, /* MEndCollection */ 868078328daSJiri Kosina 869078328daSJiri Kosina 0xC0 /* MEndCollection [Game Pad] */ 870078328daSJiri Kosina }; 871078328daSJiri Kosina 872078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = { 873078328daSJiri Kosina [0x01] = KEY_SELECT, 874078328daSJiri Kosina [0x02] = BTN_THUMBL, /* L3 */ 875078328daSJiri Kosina [0x03] = BTN_THUMBR, /* R3 */ 876078328daSJiri Kosina [0x04] = BTN_START, 877078328daSJiri Kosina [0x05] = KEY_UP, 878078328daSJiri Kosina [0x06] = KEY_RIGHT, 879078328daSJiri Kosina [0x07] = KEY_DOWN, 880078328daSJiri Kosina [0x08] = KEY_LEFT, 881078328daSJiri Kosina [0x09] = BTN_TL2, /* L2 */ 882078328daSJiri Kosina [0x0a] = BTN_TR2, /* R2 */ 883078328daSJiri Kosina [0x0b] = BTN_TL, /* L1 */ 884078328daSJiri Kosina [0x0c] = BTN_TR, /* R1 */ 885078328daSJiri Kosina [0x0d] = KEY_OPTION, /* options/triangle */ 886078328daSJiri Kosina [0x0e] = KEY_BACK, /* back/circle */ 887078328daSJiri Kosina [0x0f] = BTN_0, /* cross */ 888078328daSJiri Kosina [0x10] = KEY_SCREEN, /* view/square */ 889078328daSJiri Kosina [0x11] = KEY_HOMEPAGE, /* PS button */ 890078328daSJiri Kosina [0x14] = KEY_ENTER, 891078328daSJiri Kosina }; 892078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = { 893078328daSJiri Kosina [0x00] = KEY_1, 894078328daSJiri Kosina [0x01] = KEY_2, 895078328daSJiri Kosina [0x02] = KEY_3, 896078328daSJiri Kosina [0x03] = KEY_4, 897078328daSJiri Kosina [0x04] = KEY_5, 898078328daSJiri Kosina [0x05] = KEY_6, 899078328daSJiri Kosina [0x06] = KEY_7, 900078328daSJiri Kosina [0x07] = KEY_8, 901078328daSJiri Kosina [0x08] = KEY_9, 902078328daSJiri Kosina [0x09] = KEY_0, 903078328daSJiri Kosina [0x0e] = KEY_ESC, /* return */ 904078328daSJiri Kosina [0x0f] = KEY_CLEAR, 905078328daSJiri Kosina [0x16] = KEY_EJECTCD, 906078328daSJiri Kosina [0x1a] = KEY_MENU, /* top menu */ 907078328daSJiri Kosina [0x28] = KEY_TIME, 908078328daSJiri Kosina [0x30] = KEY_PREVIOUS, 909078328daSJiri Kosina [0x31] = KEY_NEXT, 910078328daSJiri Kosina [0x32] = KEY_PLAY, 911078328daSJiri Kosina [0x33] = KEY_REWIND, /* scan back */ 912078328daSJiri Kosina [0x34] = KEY_FORWARD, /* scan forward */ 913078328daSJiri Kosina [0x38] = KEY_STOP, 914078328daSJiri Kosina [0x39] = KEY_PAUSE, 915078328daSJiri Kosina [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ 916078328daSJiri Kosina [0x60] = KEY_FRAMEBACK, /* slow/step back */ 917078328daSJiri Kosina [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ 918078328daSJiri Kosina [0x63] = KEY_SUBTITLE, 919078328daSJiri Kosina [0x64] = KEY_AUDIO, 920078328daSJiri Kosina [0x65] = KEY_ANGLE, 921078328daSJiri Kosina [0x70] = KEY_INFO, /* display */ 922078328daSJiri Kosina [0x80] = KEY_BLUE, 923078328daSJiri Kosina [0x81] = KEY_RED, 924078328daSJiri Kosina [0x82] = KEY_GREEN, 925078328daSJiri Kosina [0x83] = KEY_YELLOW, 926078328daSJiri Kosina }; 927078328daSJiri Kosina 928f04d5140SColin Leitner static const unsigned int buzz_keymap[] = { 929ad142b9eSFrank Praznik /* 930ad142b9eSFrank Praznik * The controller has 4 remote buzzers, each with one LED and 5 931f04d5140SColin Leitner * buttons. 932f04d5140SColin Leitner * 933f04d5140SColin Leitner * We use the mapping chosen by the controller, which is: 934f04d5140SColin Leitner * 935f04d5140SColin Leitner * Key Offset 936f04d5140SColin Leitner * ------------------- 937f04d5140SColin Leitner * Buzz 1 938f04d5140SColin Leitner * Blue 5 939f04d5140SColin Leitner * Orange 4 940f04d5140SColin Leitner * Green 3 941f04d5140SColin Leitner * Yellow 2 942f04d5140SColin Leitner * 943f04d5140SColin Leitner * So, for example, the orange button on the third buzzer is mapped to 944f04d5140SColin Leitner * BTN_TRIGGER_HAPPY14 945f04d5140SColin Leitner */ 946f04d5140SColin Leitner [ 1] = BTN_TRIGGER_HAPPY1, 947f04d5140SColin Leitner [ 2] = BTN_TRIGGER_HAPPY2, 948f04d5140SColin Leitner [ 3] = BTN_TRIGGER_HAPPY3, 949f04d5140SColin Leitner [ 4] = BTN_TRIGGER_HAPPY4, 950f04d5140SColin Leitner [ 5] = BTN_TRIGGER_HAPPY5, 951f04d5140SColin Leitner [ 6] = BTN_TRIGGER_HAPPY6, 952f04d5140SColin Leitner [ 7] = BTN_TRIGGER_HAPPY7, 953f04d5140SColin Leitner [ 8] = BTN_TRIGGER_HAPPY8, 954f04d5140SColin Leitner [ 9] = BTN_TRIGGER_HAPPY9, 955f04d5140SColin Leitner [10] = BTN_TRIGGER_HAPPY10, 956f04d5140SColin Leitner [11] = BTN_TRIGGER_HAPPY11, 957f04d5140SColin Leitner [12] = BTN_TRIGGER_HAPPY12, 958f04d5140SColin Leitner [13] = BTN_TRIGGER_HAPPY13, 959f04d5140SColin Leitner [14] = BTN_TRIGGER_HAPPY14, 960f04d5140SColin Leitner [15] = BTN_TRIGGER_HAPPY15, 961f04d5140SColin Leitner [16] = BTN_TRIGGER_HAPPY16, 962f04d5140SColin Leitner [17] = BTN_TRIGGER_HAPPY17, 963f04d5140SColin Leitner [18] = BTN_TRIGGER_HAPPY18, 964f04d5140SColin Leitner [19] = BTN_TRIGGER_HAPPY19, 965f04d5140SColin Leitner [20] = BTN_TRIGGER_HAPPY20, 966f04d5140SColin Leitner }; 967f04d5140SColin Leitner 968d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = { 969d902f472SFrank Praznik POWER_SUPPLY_PROP_PRESENT, 970d902f472SFrank Praznik POWER_SUPPLY_PROP_CAPACITY, 971d902f472SFrank Praznik POWER_SUPPLY_PROP_SCOPE, 972d902f472SFrank Praznik POWER_SUPPLY_PROP_STATUS, 973d902f472SFrank Praznik }; 974d902f472SFrank Praznik 97555d3b664SFrank Praznik struct sixaxis_led { 97655d3b664SFrank Praznik __u8 time_enabled; /* the total time the led is active (0xff means forever) */ 97755d3b664SFrank Praznik __u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ 97855d3b664SFrank Praznik __u8 enabled; 97955d3b664SFrank Praznik __u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ 98055d3b664SFrank Praznik __u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ 98155d3b664SFrank Praznik } __packed; 98255d3b664SFrank Praznik 98355d3b664SFrank Praznik struct sixaxis_rumble { 98455d3b664SFrank Praznik __u8 padding; 98555d3b664SFrank Praznik __u8 right_duration; /* Right motor duration (0xff means forever) */ 98655d3b664SFrank Praznik __u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ 98755d3b664SFrank Praznik __u8 left_duration; /* Left motor duration (0xff means forever) */ 98855d3b664SFrank Praznik __u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ 98955d3b664SFrank Praznik } __packed; 99055d3b664SFrank Praznik 99155d3b664SFrank Praznik struct sixaxis_output_report { 99255d3b664SFrank Praznik __u8 report_id; 99355d3b664SFrank Praznik struct sixaxis_rumble rumble; 99455d3b664SFrank Praznik __u8 padding[4]; 99555d3b664SFrank Praznik __u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ 99655d3b664SFrank Praznik struct sixaxis_led led[4]; /* LEDx at (4 - x) */ 99755d3b664SFrank Praznik struct sixaxis_led _reserved; /* LED5, not actually soldered */ 99855d3b664SFrank Praznik } __packed; 99955d3b664SFrank Praznik 100055d3b664SFrank Praznik union sixaxis_output_report_01 { 100155d3b664SFrank Praznik struct sixaxis_output_report data; 100255d3b664SFrank Praznik __u8 buf[36]; 100355d3b664SFrank Praznik }; 100455d3b664SFrank Praznik 1005c5e0c1c4SFrank Praznik struct motion_output_report_02 { 1006c5e0c1c4SFrank Praznik u8 type, zero; 1007c5e0c1c4SFrank Praznik u8 r, g, b; 1008c5e0c1c4SFrank Praznik u8 zero2; 1009c5e0c1c4SFrank Praznik u8 rumble; 1010c5e0c1c4SFrank Praznik }; 1011c5e0c1c4SFrank Praznik 10129b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37 10139b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32 10149b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78 10159b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7 101629b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17 1017a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8 101841d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49 10199b2b5c9aSFrank Praznik 10208b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock); 1021d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list); 10228025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator); 1023d2d782fcSFrank Praznik 1024cc6e0bbbSJiri Kosina struct sony_sc { 1025d902f472SFrank Praznik spinlock_t lock; 1026d2d782fcSFrank Praznik struct list_head list_node; 10270a286ef2SSven Eckelmann struct hid_device *hdev; 102860781cf4SFrank Praznik struct led_classdev *leds[MAX_LEDS]; 1029cc6e0bbbSJiri Kosina unsigned long quirks; 10300a286ef2SSven Eckelmann struct work_struct state_worker; 1031297d716fSKrzysztof Kozlowski struct power_supply *battery; 1032297d716fSKrzysztof Kozlowski struct power_supply_desc battery_desc; 10338025087aSFrank Praznik int device_id; 10349b2b5c9aSFrank Praznik __u8 *output_report_dmabuf; 1035f04d5140SColin Leitner 10369f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF 10379f323b68SSven Eckelmann __u8 left; 10389f323b68SSven Eckelmann __u8 right; 10399f323b68SSven Eckelmann #endif 10409f323b68SSven Eckelmann 1041d2d782fcSFrank Praznik __u8 mac_address[6]; 10425f5750d2SFrank Praznik __u8 worker_initialized; 1043d902f472SFrank Praznik __u8 cable_state; 1044d902f472SFrank Praznik __u8 battery_charging; 1045d902f472SFrank Praznik __u8 battery_capacity; 104660781cf4SFrank Praznik __u8 led_state[MAX_LEDS]; 1047b3ed458cSFrank Praznik __u8 led_delay_on[MAX_LEDS]; 1048b3ed458cSFrank Praznik __u8 led_delay_off[MAX_LEDS]; 104960781cf4SFrank Praznik __u8 led_count; 1050cc6e0bbbSJiri Kosina }; 1051cc6e0bbbSJiri Kosina 1052c607fb8dSAntonio Ospite static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, 1053c607fb8dSAntonio Ospite unsigned int *rsize) 1054c607fb8dSAntonio Ospite { 1055c607fb8dSAntonio Ospite *rsize = sizeof(sixaxis_rdesc); 1056c607fb8dSAntonio Ospite return sixaxis_rdesc; 1057c607fb8dSAntonio Ospite } 1058c607fb8dSAntonio Ospite 1059c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, 1060c5e0c1c4SFrank Praznik unsigned int *rsize) 1061c5e0c1c4SFrank Praznik { 1062c5e0c1c4SFrank Praznik *rsize = sizeof(motion_rdesc); 1063c5e0c1c4SFrank Praznik return motion_rdesc; 1064c5e0c1c4SFrank Praznik } 1065c5e0c1c4SFrank Praznik 1066b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc, 1067b2723eb7SSimon Wood unsigned int *rsize) 1068b2723eb7SSimon Wood { 1069b2723eb7SSimon Wood *rsize = sizeof(navigation_rdesc); 1070b2723eb7SSimon Wood return navigation_rdesc; 1071b2723eb7SSimon Wood } 1072b2723eb7SSimon Wood 1073078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, 1074078328daSJiri Kosina unsigned int *rsize) 1075078328daSJiri Kosina { 1076078328daSJiri Kosina *rsize = sizeof(ps3remote_rdesc); 1077078328daSJiri Kosina return ps3remote_rdesc; 1078078328daSJiri Kosina } 1079078328daSJiri Kosina 1080078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, 1081078328daSJiri Kosina struct hid_field *field, struct hid_usage *usage, 1082078328daSJiri Kosina unsigned long **bit, int *max) 1083078328daSJiri Kosina { 1084078328daSJiri Kosina unsigned int key = usage->hid & HID_USAGE; 1085078328daSJiri Kosina 1086078328daSJiri Kosina if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1087078328daSJiri Kosina return -1; 1088078328daSJiri Kosina 1089078328daSJiri Kosina switch (usage->collection_index) { 1090078328daSJiri Kosina case 1: 1091078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) 1092078328daSJiri Kosina return -1; 1093078328daSJiri Kosina 1094078328daSJiri Kosina key = ps3remote_keymap_joypad_buttons[key]; 1095078328daSJiri Kosina if (!key) 1096078328daSJiri Kosina return -1; 1097078328daSJiri Kosina break; 1098078328daSJiri Kosina case 2: 1099078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) 1100078328daSJiri Kosina return -1; 1101078328daSJiri Kosina 1102078328daSJiri Kosina key = ps3remote_keymap_remote_buttons[key]; 1103078328daSJiri Kosina if (!key) 1104078328daSJiri Kosina return -1; 1105078328daSJiri Kosina break; 1106078328daSJiri Kosina default: 1107078328daSJiri Kosina return -1; 1108078328daSJiri Kosina } 1109078328daSJiri Kosina 1110078328daSJiri Kosina hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1111078328daSJiri Kosina return 1; 1112078328daSJiri Kosina } 1113078328daSJiri Kosina 111473e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 111573e4008dSNikolai Kondrashov unsigned int *rsize) 1116cc6e0bbbSJiri Kosina { 1117cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev); 1118cc6e0bbbSJiri Kosina 111999d24902SFernando Luis Vázquez Cao /* 112099d24902SFernando Luis Vázquez Cao * Some Sony RF receivers wrongly declare the mouse pointer as a 112199d24902SFernando Luis Vázquez Cao * a constant non-data variable. 112299d24902SFernando Luis Vázquez Cao */ 112399d24902SFernando Luis Vázquez Cao if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 && 112499d24902SFernando Luis Vázquez Cao /* usage page: generic desktop controls */ 112599d24902SFernando Luis Vázquez Cao /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */ 112699d24902SFernando Luis Vázquez Cao /* usage: mouse */ 112799d24902SFernando Luis Vázquez Cao rdesc[2] == 0x09 && rdesc[3] == 0x02 && 112899d24902SFernando Luis Vázquez Cao /* input (usage page for x,y axes): constant, variable, relative */ 112999d24902SFernando Luis Vázquez Cao rdesc[54] == 0x81 && rdesc[55] == 0x07) { 1130a4649184SFernando Luis Vázquez Cao hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n"); 113199d24902SFernando Luis Vázquez Cao /* input: data, variable, relative */ 1132cc6e0bbbSJiri Kosina rdesc[55] = 0x06; 1133cc6e0bbbSJiri Kosina } 113461ab44beSSimon Wood 1135ed19d8cfSFrank Praznik /* 1136ed19d8cfSFrank Praznik * The default Dualshock 4 USB descriptor doesn't assign 1137ed19d8cfSFrank Praznik * the gyroscope values to corresponding axes so we need a 1138ed19d8cfSFrank Praznik * modified one. 1139ed19d8cfSFrank Praznik */ 1140ed19d8cfSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) { 1141ed19d8cfSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); 1142ed19d8cfSFrank Praznik rdesc = dualshock4_usb_rdesc; 1143ed19d8cfSFrank Praznik *rsize = sizeof(dualshock4_usb_rdesc); 1144d829674dSFrank Praznik } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) { 1145d829674dSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n"); 1146d829674dSFrank Praznik rdesc = dualshock4_bt_rdesc; 1147d829674dSFrank Praznik *rsize = sizeof(dualshock4_bt_rdesc); 1148ed19d8cfSFrank Praznik } 1149ed19d8cfSFrank Praznik 1150c607fb8dSAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER) 1151c607fb8dSAntonio Ospite return sixaxis_fixup(hdev, rdesc, rsize); 1152078328daSJiri Kosina 1153c5e0c1c4SFrank Praznik if (sc->quirks & MOTION_CONTROLLER) 1154c5e0c1c4SFrank Praznik return motion_fixup(hdev, rdesc, rsize); 1155c5e0c1c4SFrank Praznik 11564545ee0aSSimon Wood if (sc->quirks & NAVIGATION_CONTROLLER) 1157b2723eb7SSimon Wood return navigation_fixup(hdev, rdesc, rsize); 11584545ee0aSSimon Wood 1159078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1160078328daSJiri Kosina return ps3remote_fixup(hdev, rdesc, rsize); 1161078328daSJiri Kosina 116273e4008dSNikolai Kondrashov return rdesc; 1163cc6e0bbbSJiri Kosina } 1164cc6e0bbbSJiri Kosina 1165d902f472SFrank Praznik static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) 1166d902f472SFrank Praznik { 1167d902f472SFrank Praznik static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; 1168d902f472SFrank Praznik unsigned long flags; 116912e9a6d7SSimon Wood int offset; 1170d902f472SFrank Praznik __u8 cable_state, battery_capacity, battery_charging; 1171d902f472SFrank Praznik 1172ad142b9eSFrank Praznik /* 1173ad142b9eSFrank Praznik * The sixaxis is charging if the battery value is 0xee 1174d902f472SFrank Praznik * and it is fully charged if the value is 0xef. 1175d902f472SFrank Praznik * It does not report the actual level while charging so it 1176d902f472SFrank Praznik * is set to 100% while charging is in progress. 1177d902f472SFrank Praznik */ 117812e9a6d7SSimon Wood offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30; 117912e9a6d7SSimon Wood 118012e9a6d7SSimon Wood if (rd[offset] >= 0xee) { 1181d902f472SFrank Praznik battery_capacity = 100; 118212e9a6d7SSimon Wood battery_charging = !(rd[offset] & 0x01); 11839fddd74aSFrank Praznik cable_state = 1; 1184d902f472SFrank Praznik } else { 118512e9a6d7SSimon Wood __u8 index = rd[offset] <= 5 ? rd[offset] : 5; 1186ac3c9a94SFrank Praznik battery_capacity = sixaxis_battery_capacity[index]; 1187d902f472SFrank Praznik battery_charging = 0; 11889fddd74aSFrank Praznik cable_state = 0; 1189d902f472SFrank Praznik } 1190d902f472SFrank Praznik 1191d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1192d902f472SFrank Praznik sc->cable_state = cable_state; 1193d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1194d902f472SFrank Praznik sc->battery_charging = battery_charging; 1195d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1196d902f472SFrank Praznik } 1197d902f472SFrank Praznik 1198d902f472SFrank Praznik static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) 1199d902f472SFrank Praznik { 1200e5606230SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 1201e5606230SFrank Praznik struct hid_input, list); 1202e5606230SFrank Praznik struct input_dev *input_dev = hidinput->input; 1203d902f472SFrank Praznik unsigned long flags; 12046c5f860dSFrank Praznik int n, offset; 1205d902f472SFrank Praznik __u8 cable_state, battery_capacity, battery_charging; 1206d902f472SFrank Praznik 1207ad142b9eSFrank Praznik /* 1208ad142b9eSFrank Praznik * Battery and touchpad data starts at byte 30 in the USB report and 12096c5f860dSFrank Praznik * 32 in Bluetooth report. 12106c5f860dSFrank Praznik */ 12116c5f860dSFrank Praznik offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32; 12126c5f860dSFrank Praznik 1213ad142b9eSFrank Praznik /* 1214ad142b9eSFrank Praznik * The lower 4 bits of byte 30 contain the battery level 1215d902f472SFrank Praznik * and the 5th bit contains the USB cable state. 1216d902f472SFrank Praznik */ 12176c5f860dSFrank Praznik cable_state = (rd[offset] >> 4) & 0x01; 12186c5f860dSFrank Praznik battery_capacity = rd[offset] & 0x0F; 1219d902f472SFrank Praznik 1220ad142b9eSFrank Praznik /* 1221ad142b9eSFrank Praznik * When a USB power source is connected the battery level ranges from 12226c5f860dSFrank Praznik * 0 to 10, and when running on battery power it ranges from 0 to 9. 12236c5f860dSFrank Praznik * A battery level above 10 when plugged in means charge completed. 1224d902f472SFrank Praznik */ 12256c5f860dSFrank Praznik if (!cable_state || battery_capacity > 10) 1226d902f472SFrank Praznik battery_charging = 0; 1227d902f472SFrank Praznik else 1228d902f472SFrank Praznik battery_charging = 1; 1229d902f472SFrank Praznik 12306c5f860dSFrank Praznik if (!cable_state) 12316c5f860dSFrank Praznik battery_capacity++; 1232d902f472SFrank Praznik if (battery_capacity > 10) 12336c5f860dSFrank Praznik battery_capacity = 10; 12346c5f860dSFrank Praznik 1235d902f472SFrank Praznik battery_capacity *= 10; 1236d902f472SFrank Praznik 1237d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1238d902f472SFrank Praznik sc->cable_state = cable_state; 1239d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1240d902f472SFrank Praznik sc->battery_charging = battery_charging; 1241d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1242e5606230SFrank Praznik 12436c5f860dSFrank Praznik offset += 5; 12446c5f860dSFrank Praznik 1245ad142b9eSFrank Praznik /* 1246ad142b9eSFrank Praznik * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB 12476c5f860dSFrank Praznik * and 37 on Bluetooth. 1248e5606230SFrank Praznik * The first 7 bits of the first byte is a counter and bit 8 is a touch 1249e5606230SFrank Praznik * indicator that is 0 when pressed and 1 when not pressed. 1250e5606230SFrank Praznik * The next 3 bytes are two 12 bit touch coordinates, X and Y. 1251e5606230SFrank Praznik * The data for the second touch is in the same format and immediatly 1252e5606230SFrank Praznik * follows the data for the first. 1253e5606230SFrank Praznik */ 1254e5606230SFrank Praznik for (n = 0; n < 2; n++) { 1255e5606230SFrank Praznik __u16 x, y; 1256e5606230SFrank Praznik 1257e5606230SFrank Praznik x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); 1258e5606230SFrank Praznik y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); 1259e5606230SFrank Praznik 1260e5606230SFrank Praznik input_mt_slot(input_dev, n); 1261e5606230SFrank Praznik input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1262e5606230SFrank Praznik !(rd[offset] >> 7)); 1263e5606230SFrank Praznik input_report_abs(input_dev, ABS_MT_POSITION_X, x); 1264e5606230SFrank Praznik input_report_abs(input_dev, ABS_MT_POSITION_Y, y); 1265e5606230SFrank Praznik 1266e5606230SFrank Praznik offset += 4; 1267e5606230SFrank Praznik } 1268d902f472SFrank Praznik } 1269d902f472SFrank Praznik 1270c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, 1271c9e4d877SSimon Wood __u8 *rd, int size) 1272c9e4d877SSimon Wood { 1273c9e4d877SSimon Wood struct sony_sc *sc = hid_get_drvdata(hdev); 1274c9e4d877SSimon Wood 1275ad142b9eSFrank Praznik /* 1276ad142b9eSFrank Praznik * Sixaxis HID report has acclerometers/gyro with MSByte first, this 1277c9e4d877SSimon Wood * has to be BYTE_SWAPPED before passing up to joystick interface 1278c9e4d877SSimon Wood */ 1279fee4e2d5SFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { 1280c9e4d877SSimon Wood swap(rd[41], rd[42]); 1281c9e4d877SSimon Wood swap(rd[43], rd[44]); 1282c9e4d877SSimon Wood swap(rd[45], rd[46]); 1283c9e4d877SSimon Wood swap(rd[47], rd[48]); 1284d902f472SFrank Praznik 1285d902f472SFrank Praznik sixaxis_parse_report(sc, rd, size); 128612e9a6d7SSimon Wood } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { 128712e9a6d7SSimon Wood sixaxis_parse_report(sc, rd, size); 12884545ee0aSSimon Wood } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && 12894545ee0aSSimon Wood size == 49) { 12904545ee0aSSimon Wood sixaxis_parse_report(sc, rd, size); 129168330d83SFrank Praznik } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && 129268330d83SFrank Praznik size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) 129368330d83SFrank Praznik && rd[0] == 0x11 && size == 78)) { 1294d902f472SFrank Praznik dualshock4_parse_report(sc, rd, size); 1295c9e4d877SSimon Wood } 1296c9e4d877SSimon Wood 1297c9e4d877SSimon Wood return 0; 1298c9e4d877SSimon Wood } 1299c9e4d877SSimon Wood 1300f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, 1301f04d5140SColin Leitner struct hid_field *field, struct hid_usage *usage, 1302f04d5140SColin Leitner unsigned long **bit, int *max) 1303f04d5140SColin Leitner { 1304f04d5140SColin Leitner struct sony_sc *sc = hid_get_drvdata(hdev); 1305f04d5140SColin Leitner 1306f04d5140SColin Leitner if (sc->quirks & BUZZ_CONTROLLER) { 1307f04d5140SColin Leitner unsigned int key = usage->hid & HID_USAGE; 1308f04d5140SColin Leitner 1309f04d5140SColin Leitner if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1310f04d5140SColin Leitner return -1; 1311f04d5140SColin Leitner 1312f04d5140SColin Leitner switch (usage->collection_index) { 1313f04d5140SColin Leitner case 1: 1314f04d5140SColin Leitner if (key >= ARRAY_SIZE(buzz_keymap)) 1315f04d5140SColin Leitner return -1; 1316f04d5140SColin Leitner 1317f04d5140SColin Leitner key = buzz_keymap[key]; 1318f04d5140SColin Leitner if (!key) 1319f04d5140SColin Leitner return -1; 1320f04d5140SColin Leitner break; 1321f04d5140SColin Leitner default: 1322f04d5140SColin Leitner return -1; 1323f04d5140SColin Leitner } 1324f04d5140SColin Leitner 1325f04d5140SColin Leitner hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1326f04d5140SColin Leitner return 1; 1327f04d5140SColin Leitner } 1328f04d5140SColin Leitner 1329078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1330078328daSJiri Kosina return ps3remote_mapping(hdev, hi, field, usage, bit, max); 1331078328daSJiri Kosina 13326f498018SBenjamin Tissoires /* Let hid-core decide for the others */ 13336f498018SBenjamin Tissoires return 0; 1334f04d5140SColin Leitner } 1335f04d5140SColin Leitner 1336ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count, 1337ce8efc3bSFrank Praznik int w, int h) 1338ce8efc3bSFrank Praznik { 1339ce8efc3bSFrank Praznik struct input_dev *input_dev = hi->input; 1340ce8efc3bSFrank Praznik int ret; 1341ce8efc3bSFrank Praznik 1342ce8efc3bSFrank Praznik ret = input_mt_init_slots(input_dev, touch_count, 0); 1343ce8efc3bSFrank Praznik if (ret < 0) 1344ce8efc3bSFrank Praznik return ret; 1345ce8efc3bSFrank Praznik 1346ce8efc3bSFrank Praznik input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0); 1347ce8efc3bSFrank Praznik input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0); 1348ce8efc3bSFrank Praznik 1349ce8efc3bSFrank Praznik return 0; 1350ce8efc3bSFrank Praznik } 1351ce8efc3bSFrank Praznik 1352ce8efc3bSFrank Praznik static void sony_input_configured(struct hid_device *hdev, 1353ce8efc3bSFrank Praznik struct hid_input *hidinput) 1354ce8efc3bSFrank Praznik { 1355ce8efc3bSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev); 1356ce8efc3bSFrank Praznik 1357ce8efc3bSFrank Praznik /* 1358ce8efc3bSFrank Praznik * The Dualshock 4 touchpad supports 2 touches and has a 1359981c5b4aSFrank Praznik * resolution of 1920x942 (44.86 dots/mm). 1360ce8efc3bSFrank Praznik */ 1361ce8efc3bSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1362981c5b4aSFrank Praznik if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0) 1363ce8efc3bSFrank Praznik hid_err(sc->hdev, 1364ce8efc3bSFrank Praznik "Unable to initialize multi-touch slots\n"); 1365ce8efc3bSFrank Praznik } 1366ce8efc3bSFrank Praznik } 1367ce8efc3bSFrank Praznik 13685710fabfSAntonio Ospite /* 1369bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 1370bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any 1371bd28ce00SJiri Slaby * events. 1372bd28ce00SJiri Slaby */ 1373816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev) 1374bd28ce00SJiri Slaby { 1375a85d67b5SAntonio Ospite const int buf_size = 1376a85d67b5SAntonio Ospite max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); 13772e701a35SAntonio Ospite __u8 *buf; 1378bd28ce00SJiri Slaby int ret; 1379bd28ce00SJiri Slaby 13802e701a35SAntonio Ospite buf = kmalloc(buf_size, GFP_KERNEL); 1381bd28ce00SJiri Slaby if (!buf) 1382bd28ce00SJiri Slaby return -ENOMEM; 1383bd28ce00SJiri Slaby 1384a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE, 1385a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1386a7de9b86SLauri Kasanen if (ret < 0) { 1387a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 1\n"); 1388a7de9b86SLauri Kasanen goto out; 1389a7de9b86SLauri Kasanen } 1390f204828aSBenjamin Tissoires 1391a7de9b86SLauri Kasanen /* 1392a7de9b86SLauri Kasanen * Some compatible controllers like the Speedlink Strike FX and 1393a7de9b86SLauri Kasanen * Gasia need another query plus an USB interrupt to get operational. 1394a7de9b86SLauri Kasanen */ 1395a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE, 1396a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1397a7de9b86SLauri Kasanen if (ret < 0) { 1398a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 2\n"); 1399a7de9b86SLauri Kasanen goto out; 1400a7de9b86SLauri Kasanen } 1401a7de9b86SLauri Kasanen 1402a7de9b86SLauri Kasanen ret = hid_hw_output_report(hdev, buf, 1); 1403bd28ce00SJiri Slaby if (ret < 0) 1404a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 3\n"); 1405bd28ce00SJiri Slaby 1406a7de9b86SLauri Kasanen out: 1407bd28ce00SJiri Slaby kfree(buf); 1408bd28ce00SJiri Slaby 1409bd28ce00SJiri Slaby return ret; 1410bd28ce00SJiri Slaby } 1411bd28ce00SJiri Slaby 1412816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev) 1413f9ce7c28SBastien Nocera { 14149b2b5c9aSFrank Praznik static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 14159b2b5c9aSFrank Praznik __u8 *buf; 14169b2b5c9aSFrank Praznik int ret; 14179b2b5c9aSFrank Praznik 14189b2b5c9aSFrank Praznik buf = kmemdup(report, sizeof(report), GFP_KERNEL); 14199b2b5c9aSFrank Praznik if (!buf) 14209b2b5c9aSFrank Praznik return -ENOMEM; 14219b2b5c9aSFrank Praznik 14229b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), 1423b0dd72aaSBenjamin Tissoires HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 14249b2b5c9aSFrank Praznik 14259b2b5c9aSFrank Praznik kfree(buf); 14269b2b5c9aSFrank Praznik 14279b2b5c9aSFrank Praznik return ret; 1428f9ce7c28SBastien Nocera } 1429f9ce7c28SBastien Nocera 1430ad142b9eSFrank Praznik /* 1431ad142b9eSFrank Praznik * Requesting feature report 0x02 in Bluetooth mode changes the state of the 143268330d83SFrank Praznik * controller so that it sends full input reports of type 0x11. 143368330d83SFrank Praznik */ 143468330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev) 143568330d83SFrank Praznik { 14369b2b5c9aSFrank Praznik __u8 *buf; 14379b2b5c9aSFrank Praznik int ret; 143868330d83SFrank Praznik 14399b2b5c9aSFrank Praznik buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); 14409b2b5c9aSFrank Praznik if (!buf) 14419b2b5c9aSFrank Praznik return -ENOMEM; 14429b2b5c9aSFrank Praznik 14439b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, 144468330d83SFrank Praznik HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 14459b2b5c9aSFrank Praznik 14469b2b5c9aSFrank Praznik kfree(buf); 14479b2b5c9aSFrank Praznik 14489b2b5c9aSFrank Praznik return ret; 1449bd28ce00SJiri Slaby } 1450bd28ce00SJiri Slaby 1451221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc) 14528025087aSFrank Praznik { 14538025087aSFrank Praznik static const __u8 sixaxis_leds[10][4] = { 14548025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x00 }, 14558025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x00 }, 14568025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x00 }, 14578025087aSFrank Praznik { 0x00, 0x00, 0x00, 0x01 }, 14588025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x01 }, 14598025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x01 }, 14608025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x01 }, 14618025087aSFrank Praznik { 0x01, 0x00, 0x01, 0x01 }, 14628025087aSFrank Praznik { 0x00, 0x01, 0x01, 0x01 }, 14638025087aSFrank Praznik { 0x01, 0x01, 0x01, 0x01 } 14648025087aSFrank Praznik }; 14658025087aSFrank Praznik 1466221399b3SFrank Praznik int id = sc->device_id; 1467221399b3SFrank Praznik 1468221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); 14698025087aSFrank Praznik 14708025087aSFrank Praznik if (id < 0) 14718025087aSFrank Praznik return; 14728025087aSFrank Praznik 14738025087aSFrank Praznik id %= 10; 1474221399b3SFrank Praznik memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id])); 14758025087aSFrank Praznik } 14768025087aSFrank Praznik 1477221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc) 14788025087aSFrank Praznik { 14798025087aSFrank Praznik /* The first 4 color/index entries match what the PS4 assigns */ 14808025087aSFrank Praznik static const __u8 color_code[7][3] = { 14818025087aSFrank Praznik /* Blue */ { 0x00, 0x00, 0x01 }, 14828025087aSFrank Praznik /* Red */ { 0x01, 0x00, 0x00 }, 14838025087aSFrank Praznik /* Green */ { 0x00, 0x01, 0x00 }, 14848025087aSFrank Praznik /* Pink */ { 0x02, 0x00, 0x01 }, 14858025087aSFrank Praznik /* Orange */ { 0x02, 0x01, 0x00 }, 14868025087aSFrank Praznik /* Teal */ { 0x00, 0x01, 0x01 }, 14878025087aSFrank Praznik /* White */ { 0x01, 0x01, 0x01 } 14888025087aSFrank Praznik }; 14898025087aSFrank Praznik 1490221399b3SFrank Praznik int id = sc->device_id; 1491221399b3SFrank Praznik 1492221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); 14938025087aSFrank Praznik 14948025087aSFrank Praznik if (id < 0) 14958025087aSFrank Praznik return; 14968025087aSFrank Praznik 14978025087aSFrank Praznik id %= 7; 1498221399b3SFrank Praznik memcpy(sc->led_state, color_code[id], sizeof(color_code[id])); 14998025087aSFrank Praznik } 15008025087aSFrank Praznik 1501221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc) 1502f04d5140SColin Leitner { 1503221399b3SFrank Praznik struct hid_device *hdev = sc->hdev; 1504f04d5140SColin Leitner struct list_head *report_list = 1505f04d5140SColin Leitner &hdev->report_enum[HID_OUTPUT_REPORT].report_list; 1506f04d5140SColin Leitner struct hid_report *report = list_entry(report_list->next, 1507f04d5140SColin Leitner struct hid_report, list); 1508f04d5140SColin Leitner __s32 *value = report->field[0]->value; 1509f04d5140SColin Leitner 1510221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < 4); 1511221399b3SFrank Praznik 1512f04d5140SColin Leitner value[0] = 0x00; 1513221399b3SFrank Praznik value[1] = sc->led_state[0] ? 0xff : 0x00; 1514221399b3SFrank Praznik value[2] = sc->led_state[1] ? 0xff : 0x00; 1515221399b3SFrank Praznik value[3] = sc->led_state[2] ? 0xff : 0x00; 1516221399b3SFrank Praznik value[4] = sc->led_state[3] ? 0xff : 0x00; 1517f04d5140SColin Leitner value[5] = 0x00; 1518f04d5140SColin Leitner value[6] = 0x00; 1519f04d5140SColin Leitner hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 1520f04d5140SColin Leitner } 1521f04d5140SColin Leitner 1522221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc) 15230a286ef2SSven Eckelmann { 1524221399b3SFrank Praznik if (!(sc->quirks & BUZZ_CONTROLLER)) 1525fa57a810SFrank Praznik schedule_work(&sc->state_worker); 1526221399b3SFrank Praznik else 1527221399b3SFrank Praznik buzz_set_leds(sc); 15280a286ef2SSven Eckelmann } 15290a286ef2SSven Eckelmann 1530c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led, 1531f04d5140SColin Leitner enum led_brightness value) 1532f04d5140SColin Leitner { 1533f04d5140SColin Leitner struct device *dev = led->dev->parent; 1534f04d5140SColin Leitner struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1535f04d5140SColin Leitner struct sony_sc *drv_data; 1536f04d5140SColin Leitner 1537f04d5140SColin Leitner int n; 1538b3ed458cSFrank Praznik int force_update; 1539f04d5140SColin Leitner 1540f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 15412251b85fSSven Eckelmann if (!drv_data) { 1542f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1543f04d5140SColin Leitner return; 1544f04d5140SColin Leitner } 1545f04d5140SColin Leitner 1546b3ed458cSFrank Praznik /* 1547b3ed458cSFrank Praznik * The Sixaxis on USB will override any LED settings sent to it 1548b3ed458cSFrank Praznik * and keep flashing all of the LEDs until the PS button is pressed. 1549b3ed458cSFrank Praznik * Updates, even if redundant, must be always be sent to the 1550b3ed458cSFrank Praznik * controller to avoid having to toggle the state of an LED just to 1551b3ed458cSFrank Praznik * stop the flashing later on. 1552b3ed458cSFrank Praznik */ 1553b3ed458cSFrank Praznik force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB); 1554b3ed458cSFrank Praznik 155560781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1556b3ed458cSFrank Praznik if (led == drv_data->leds[n] && (force_update || 1557b3ed458cSFrank Praznik (value != drv_data->led_state[n] || 1558b3ed458cSFrank Praznik drv_data->led_delay_on[n] || 1559b3ed458cSFrank Praznik drv_data->led_delay_off[n]))) { 1560b3ed458cSFrank Praznik 156160781cf4SFrank Praznik drv_data->led_state[n] = value; 1562b3ed458cSFrank Praznik 1563b3ed458cSFrank Praznik /* Setting the brightness stops the blinking */ 1564b3ed458cSFrank Praznik drv_data->led_delay_on[n] = 0; 1565b3ed458cSFrank Praznik drv_data->led_delay_off[n] = 0; 1566b3ed458cSFrank Praznik 1567221399b3SFrank Praznik sony_set_leds(drv_data); 1568f04d5140SColin Leitner break; 1569f04d5140SColin Leitner } 1570f04d5140SColin Leitner } 1571f04d5140SColin Leitner } 1572f04d5140SColin Leitner 1573c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led) 1574f04d5140SColin Leitner { 1575f04d5140SColin Leitner struct device *dev = led->dev->parent; 1576f04d5140SColin Leitner struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1577f04d5140SColin Leitner struct sony_sc *drv_data; 1578f04d5140SColin Leitner 1579f04d5140SColin Leitner int n; 1580f04d5140SColin Leitner 1581f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 15822251b85fSSven Eckelmann if (!drv_data) { 1583f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1584f04d5140SColin Leitner return LED_OFF; 1585f04d5140SColin Leitner } 1586f04d5140SColin Leitner 158760781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 15887db7504aSSimon Wood if (led == drv_data->leds[n]) 15897db7504aSSimon Wood return drv_data->led_state[n]; 1590f04d5140SColin Leitner } 1591f04d5140SColin Leitner 15927db7504aSSimon Wood return LED_OFF; 1593f04d5140SColin Leitner } 1594f04d5140SColin Leitner 1595b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, 1596b3ed458cSFrank Praznik unsigned long *delay_off) 1597b3ed458cSFrank Praznik { 1598b3ed458cSFrank Praznik struct device *dev = led->dev->parent; 1599b3ed458cSFrank Praznik struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1600b3ed458cSFrank Praznik struct sony_sc *drv_data = hid_get_drvdata(hdev); 1601b3ed458cSFrank Praznik int n; 1602b3ed458cSFrank Praznik __u8 new_on, new_off; 1603b3ed458cSFrank Praznik 1604b3ed458cSFrank Praznik if (!drv_data) { 1605b3ed458cSFrank Praznik hid_err(hdev, "No device data\n"); 1606b3ed458cSFrank Praznik return -EINVAL; 1607b3ed458cSFrank Praznik } 1608b3ed458cSFrank Praznik 1609b3ed458cSFrank Praznik /* Max delay is 255 deciseconds or 2550 milliseconds */ 1610b3ed458cSFrank Praznik if (*delay_on > 2550) 1611b3ed458cSFrank Praznik *delay_on = 2550; 1612b3ed458cSFrank Praznik if (*delay_off > 2550) 1613b3ed458cSFrank Praznik *delay_off = 2550; 1614b3ed458cSFrank Praznik 1615b3ed458cSFrank Praznik /* Blink at 1 Hz if both values are zero */ 1616b3ed458cSFrank Praznik if (!*delay_on && !*delay_off) 1617b3ed458cSFrank Praznik *delay_on = *delay_off = 500; 1618b3ed458cSFrank Praznik 1619b3ed458cSFrank Praznik new_on = *delay_on / 10; 1620b3ed458cSFrank Praznik new_off = *delay_off / 10; 1621b3ed458cSFrank Praznik 1622b3ed458cSFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1623b3ed458cSFrank Praznik if (led == drv_data->leds[n]) 1624b3ed458cSFrank Praznik break; 1625b3ed458cSFrank Praznik } 1626b3ed458cSFrank Praznik 1627b3ed458cSFrank Praznik /* This LED is not registered on this device */ 1628b3ed458cSFrank Praznik if (n >= drv_data->led_count) 1629b3ed458cSFrank Praznik return -EINVAL; 1630b3ed458cSFrank Praznik 1631b3ed458cSFrank Praznik /* Don't schedule work if the values didn't change */ 1632b3ed458cSFrank Praznik if (new_on != drv_data->led_delay_on[n] || 1633b3ed458cSFrank Praznik new_off != drv_data->led_delay_off[n]) { 1634b3ed458cSFrank Praznik drv_data->led_delay_on[n] = new_on; 1635b3ed458cSFrank Praznik drv_data->led_delay_off[n] = new_off; 1636b3ed458cSFrank Praznik schedule_work(&drv_data->state_worker); 1637b3ed458cSFrank Praznik } 1638b3ed458cSFrank Praznik 1639b3ed458cSFrank Praznik return 0; 1640b3ed458cSFrank Praznik } 1641b3ed458cSFrank Praznik 1642fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc) 16430a286ef2SSven Eckelmann { 16440a286ef2SSven Eckelmann struct led_classdev *led; 16450a286ef2SSven Eckelmann int n; 16460a286ef2SSven Eckelmann 1647fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 16480a286ef2SSven Eckelmann 1649fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 1650fa57a810SFrank Praznik led = sc->leds[n]; 1651fa57a810SFrank Praznik sc->leds[n] = NULL; 16520a286ef2SSven Eckelmann if (!led) 16530a286ef2SSven Eckelmann continue; 16540a286ef2SSven Eckelmann led_classdev_unregister(led); 16550a286ef2SSven Eckelmann kfree(led); 16560a286ef2SSven Eckelmann } 165760781cf4SFrank Praznik 1658fa57a810SFrank Praznik sc->led_count = 0; 16590a286ef2SSven Eckelmann } 16600a286ef2SSven Eckelmann 1661fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc) 1662f04d5140SColin Leitner { 1663fa57a810SFrank Praznik struct hid_device *hdev = sc->hdev; 166440e32ee6SJiri Kosina int n, ret = 0; 1665b3ed458cSFrank Praznik int use_ds4_names; 166640e32ee6SJiri Kosina struct led_classdev *led; 166740e32ee6SJiri Kosina size_t name_sz; 166840e32ee6SJiri Kosina char *name; 16690a286ef2SSven Eckelmann size_t name_len; 16700a286ef2SSven Eckelmann const char *name_fmt; 1671b3ed458cSFrank Praznik static const char * const ds4_name_str[] = { "red", "green", "blue", 1672b3ed458cSFrank Praznik "global" }; 16735607c89aSFrank Praznik __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; 1674b3ed458cSFrank Praznik __u8 use_hw_blink[MAX_LEDS] = { 0 }; 1675f04d5140SColin Leitner 1676fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 1677f04d5140SColin Leitner 1678fa57a810SFrank Praznik if (sc->quirks & BUZZ_CONTROLLER) { 1679fa57a810SFrank Praznik sc->led_count = 4; 1680b3ed458cSFrank Praznik use_ds4_names = 0; 16810a286ef2SSven Eckelmann name_len = strlen("::buzz#"); 16820a286ef2SSven Eckelmann name_fmt = "%s::buzz%d"; 16839446edb9SKees Cook /* Validate expected report characteristics. */ 16849446edb9SKees Cook if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) 16859446edb9SKees Cook return -ENODEV; 1686fa57a810SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1687221399b3SFrank Praznik dualshock4_set_leds_from_id(sc); 1688221399b3SFrank Praznik sc->led_state[3] = 1; 1689b3ed458cSFrank Praznik sc->led_count = 4; 1690b3ed458cSFrank Praznik memset(max_brightness, 255, 3); 1691b3ed458cSFrank Praznik use_hw_blink[3] = 1; 1692b3ed458cSFrank Praznik use_ds4_names = 1; 169361ebca93SFrank Praznik name_len = 0; 169461ebca93SFrank Praznik name_fmt = "%s:%s"; 1695c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 1696c5e0c1c4SFrank Praznik sc->led_count = 3; 1697c5e0c1c4SFrank Praznik memset(max_brightness, 255, 3); 1698c5e0c1c4SFrank Praznik use_ds4_names = 1; 1699c5e0c1c4SFrank Praznik name_len = 0; 1700c5e0c1c4SFrank Praznik name_fmt = "%s:%s"; 17014545ee0aSSimon Wood } else if (sc->quirks & NAVIGATION_CONTROLLER) { 17024545ee0aSSimon Wood static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; 17034545ee0aSSimon Wood 17044545ee0aSSimon Wood memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds)); 17054545ee0aSSimon Wood sc->led_count = 1; 17064545ee0aSSimon Wood memset(use_hw_blink, 1, 4); 17074545ee0aSSimon Wood use_ds4_names = 0; 17084545ee0aSSimon Wood name_len = strlen("::sony#"); 17094545ee0aSSimon Wood name_fmt = "%s::sony%d"; 171060781cf4SFrank Praznik } else { 1711221399b3SFrank Praznik sixaxis_set_leds_from_id(sc); 1712fa57a810SFrank Praznik sc->led_count = 4; 1713b3ed458cSFrank Praznik memset(use_hw_blink, 1, 4); 1714b3ed458cSFrank Praznik use_ds4_names = 0; 171561ebca93SFrank Praznik name_len = strlen("::sony#"); 171661ebca93SFrank Praznik name_fmt = "%s::sony%d"; 171760781cf4SFrank Praznik } 171860781cf4SFrank Praznik 1719ad142b9eSFrank Praznik /* 1720ad142b9eSFrank Praznik * Clear LEDs as we have no way of reading their initial state. This is 1721f04d5140SColin Leitner * only relevant if the driver is loaded after somebody actively set the 1722ad142b9eSFrank Praznik * LEDs to on 1723ad142b9eSFrank Praznik */ 1724221399b3SFrank Praznik sony_set_leds(sc); 1725f04d5140SColin Leitner 17260a286ef2SSven Eckelmann name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; 1727f04d5140SColin Leitner 1728fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 172961ebca93SFrank Praznik 1730b3ed458cSFrank Praznik if (use_ds4_names) 1731b3ed458cSFrank Praznik name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2; 173261ebca93SFrank Praznik 1733f04d5140SColin Leitner led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); 1734f04d5140SColin Leitner if (!led) { 1735f04d5140SColin Leitner hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); 17368cd5fcdaSJulia Lawall ret = -ENOMEM; 1737f04d5140SColin Leitner goto error_leds; 1738f04d5140SColin Leitner } 1739f04d5140SColin Leitner 1740f04d5140SColin Leitner name = (void *)(&led[1]); 1741b3ed458cSFrank Praznik if (use_ds4_names) 1742b3ed458cSFrank Praznik snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), 1743b3ed458cSFrank Praznik ds4_name_str[n]); 174461ebca93SFrank Praznik else 17450a286ef2SSven Eckelmann snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); 1746f04d5140SColin Leitner led->name = name; 1747221399b3SFrank Praznik led->brightness = sc->led_state[n]; 1748b3ed458cSFrank Praznik led->max_brightness = max_brightness[n]; 1749c5382519SSven Eckelmann led->brightness_get = sony_led_get_brightness; 1750c5382519SSven Eckelmann led->brightness_set = sony_led_set_brightness; 1751f04d5140SColin Leitner 1752b3ed458cSFrank Praznik if (use_hw_blink[n]) 1753b3ed458cSFrank Praznik led->blink_set = sony_led_blink_set; 1754b3ed458cSFrank Praznik 17558025087aSFrank Praznik sc->leds[n] = led; 17568025087aSFrank Praznik 17578cd5fcdaSJulia Lawall ret = led_classdev_register(&hdev->dev, led); 17588cd5fcdaSJulia Lawall if (ret) { 1759f04d5140SColin Leitner hid_err(hdev, "Failed to register LED %d\n", n); 17608025087aSFrank Praznik sc->leds[n] = NULL; 1761f04d5140SColin Leitner kfree(led); 1762f04d5140SColin Leitner goto error_leds; 1763f04d5140SColin Leitner } 1764f04d5140SColin Leitner } 1765f04d5140SColin Leitner 1766f04d5140SColin Leitner return ret; 1767f04d5140SColin Leitner 1768f04d5140SColin Leitner error_leds: 1769fa57a810SFrank Praznik sony_leds_remove(sc); 1770f04d5140SColin Leitner 1771f04d5140SColin Leitner return ret; 1772f04d5140SColin Leitner } 1773f04d5140SColin Leitner 1774cad665a2SFrank Praznik static void sixaxis_state_worker(struct work_struct *work) 1775a08c22c0SSven Eckelmann { 17769b2b5c9aSFrank Praznik static const union sixaxis_output_report_01 default_report = { 177755d3b664SFrank Praznik .buf = { 1778a08c22c0SSven Eckelmann 0x01, 1779a08c22c0SSven Eckelmann 0x00, 0xff, 0x00, 0xff, 0x00, 17800a286ef2SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00, 1781a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1782a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1783a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1784a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1785a08c22c0SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00 178655d3b664SFrank Praznik } 1787a08c22c0SSven Eckelmann }; 17889b2b5c9aSFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 17899b2b5c9aSFrank Praznik struct sixaxis_output_report *report = 17909b2b5c9aSFrank Praznik (struct sixaxis_output_report *)sc->output_report_dmabuf; 17919b2b5c9aSFrank Praznik int n; 17929b2b5c9aSFrank Praznik 17939b2b5c9aSFrank Praznik /* Initialize the report with default values */ 17949b2b5c9aSFrank Praznik memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); 17959f323b68SSven Eckelmann 17960a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 17979b2b5c9aSFrank Praznik report->rumble.right_motor_on = sc->right ? 1 : 0; 17989b2b5c9aSFrank Praznik report->rumble.left_motor_force = sc->left; 17990a286ef2SSven Eckelmann #endif 18000a286ef2SSven Eckelmann 18019b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[0] << 1; 18029b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[1] << 2; 18039b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[2] << 3; 18049b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[3] << 4; 18059f323b68SSven Eckelmann 180688f6576fSSimon Wood /* Set flag for all leds off, required for 3rd party INTEC controller */ 18079b2b5c9aSFrank Praznik if ((report->leds_bitmap & 0x1E) == 0) 18089b2b5c9aSFrank Praznik report->leds_bitmap |= 0x20; 180988f6576fSSimon Wood 1810b3ed458cSFrank Praznik /* 1811b3ed458cSFrank Praznik * The LEDs in the report are indexed in reverse order to their 1812b3ed458cSFrank Praznik * corresponding light on the controller. 1813b3ed458cSFrank Praznik * Index 0 = LED 4, index 1 = LED 3, etc... 1814b3ed458cSFrank Praznik * 1815b3ed458cSFrank Praznik * In the case of both delay values being zero (blinking disabled) the 1816b3ed458cSFrank Praznik * default report values should be used or the controller LED will be 1817b3ed458cSFrank Praznik * always off. 1818b3ed458cSFrank Praznik */ 1819b3ed458cSFrank Praznik for (n = 0; n < 4; n++) { 1820b3ed458cSFrank Praznik if (sc->led_delay_on[n] || sc->led_delay_off[n]) { 18219b2b5c9aSFrank Praznik report->led[3 - n].duty_off = sc->led_delay_off[n]; 18229b2b5c9aSFrank Praznik report->led[3 - n].duty_on = sc->led_delay_on[n]; 1823b3ed458cSFrank Praznik } 1824b3ed458cSFrank Praznik } 1825b3ed458cSFrank Praznik 18269b2b5c9aSFrank Praznik hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, 18279b2b5c9aSFrank Praznik sizeof(struct sixaxis_output_report), 18289b2b5c9aSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 18299f323b68SSven Eckelmann } 18309f323b68SSven Eckelmann 18310bd88dd3SFrank Praznik static void dualshock4_state_worker(struct work_struct *work) 18320bd88dd3SFrank Praznik { 18330bd88dd3SFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 18340da8ea65SFrank Praznik struct hid_device *hdev = sc->hdev; 18359b2b5c9aSFrank Praznik __u8 *buf = sc->output_report_dmabuf; 183648220237SFrank Praznik int offset; 18370da8ea65SFrank Praznik 1838fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 18399b2b5c9aSFrank Praznik memset(buf, 0, DS4_REPORT_0x05_SIZE); 184048220237SFrank Praznik buf[0] = 0x05; 1841b3ed458cSFrank Praznik buf[1] = 0xFF; 184248220237SFrank Praznik offset = 4; 1843fdcf105dSFrank Praznik } else { 18449b2b5c9aSFrank Praznik memset(buf, 0, DS4_REPORT_0x11_SIZE); 1845fdcf105dSFrank Praznik buf[0] = 0x11; 1846fdcf105dSFrank Praznik buf[1] = 0xB0; 1847fdcf105dSFrank Praznik buf[3] = 0x0F; 1848fdcf105dSFrank Praznik offset = 6; 1849fdcf105dSFrank Praznik } 18500bd88dd3SFrank Praznik 18510bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF 185248220237SFrank Praznik buf[offset++] = sc->right; 185348220237SFrank Praznik buf[offset++] = sc->left; 185448220237SFrank Praznik #else 185548220237SFrank Praznik offset += 2; 18560bd88dd3SFrank Praznik #endif 18570bd88dd3SFrank Praznik 1858b3ed458cSFrank Praznik /* LED 3 is the global control */ 1859b3ed458cSFrank Praznik if (sc->led_state[3]) { 186048220237SFrank Praznik buf[offset++] = sc->led_state[0]; 186148220237SFrank Praznik buf[offset++] = sc->led_state[1]; 186248220237SFrank Praznik buf[offset++] = sc->led_state[2]; 1863b3ed458cSFrank Praznik } else { 1864b3ed458cSFrank Praznik offset += 3; 1865b3ed458cSFrank Praznik } 1866b3ed458cSFrank Praznik 1867b3ed458cSFrank Praznik /* If both delay values are zero the DualShock 4 disables blinking. */ 1868b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_on[3]; 1869b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_off[3]; 187060781cf4SFrank Praznik 1871fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 18729b2b5c9aSFrank Praznik hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); 1873fdcf105dSFrank Praznik else 18749b2b5c9aSFrank Praznik hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, 1875fdcf105dSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 18760bd88dd3SFrank Praznik } 18770bd88dd3SFrank Praznik 1878c5e0c1c4SFrank Praznik static void motion_state_worker(struct work_struct *work) 1879c5e0c1c4SFrank Praznik { 1880c5e0c1c4SFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 1881c5e0c1c4SFrank Praznik struct hid_device *hdev = sc->hdev; 1882c5e0c1c4SFrank Praznik struct motion_output_report_02 *report = 1883c5e0c1c4SFrank Praznik (struct motion_output_report_02 *)sc->output_report_dmabuf; 1884c5e0c1c4SFrank Praznik 188541d2d425SSimon Wood memset(report, 0, MOTION_REPORT_0x02_SIZE); 1886c5e0c1c4SFrank Praznik 1887c5e0c1c4SFrank Praznik report->type = 0x02; /* set leds */ 1888c5e0c1c4SFrank Praznik report->r = sc->led_state[0]; 1889c5e0c1c4SFrank Praznik report->g = sc->led_state[1]; 1890c5e0c1c4SFrank Praznik report->b = sc->led_state[2]; 1891c5e0c1c4SFrank Praznik 1892c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF 1893c5e0c1c4SFrank Praznik report->rumble = max(sc->right, sc->left); 1894c5e0c1c4SFrank Praznik #endif 1895c5e0c1c4SFrank Praznik 189641d2d425SSimon Wood hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); 1897c5e0c1c4SFrank Praznik } 1898c5e0c1c4SFrank Praznik 18999b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc) 19009b2b5c9aSFrank Praznik { 19014545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER) || 19024545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER)) 19039b2b5c9aSFrank Praznik sc->output_report_dmabuf = 19049b2b5c9aSFrank Praznik kmalloc(sizeof(union sixaxis_output_report_01), 19059b2b5c9aSFrank Praznik GFP_KERNEL); 19069b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) 19079b2b5c9aSFrank Praznik sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, 19089b2b5c9aSFrank Praznik GFP_KERNEL); 19099b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 19109b2b5c9aSFrank Praznik sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, 19119b2b5c9aSFrank Praznik GFP_KERNEL); 1912c5e0c1c4SFrank Praznik else if (sc->quirks & MOTION_CONTROLLER) 191341d2d425SSimon Wood sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, 1914c5e0c1c4SFrank Praznik GFP_KERNEL); 19159b2b5c9aSFrank Praznik else 19169b2b5c9aSFrank Praznik return 0; 19179b2b5c9aSFrank Praznik 19189b2b5c9aSFrank Praznik if (!sc->output_report_dmabuf) 19199b2b5c9aSFrank Praznik return -ENOMEM; 19209b2b5c9aSFrank Praznik 19219b2b5c9aSFrank Praznik return 0; 19229b2b5c9aSFrank Praznik } 19239b2b5c9aSFrank Praznik 19240a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 19259f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data, 19269f323b68SSven Eckelmann struct ff_effect *effect) 19279f323b68SSven Eckelmann { 1928a08c22c0SSven Eckelmann struct hid_device *hid = input_get_drvdata(dev); 19299f323b68SSven Eckelmann struct sony_sc *sc = hid_get_drvdata(hid); 1930a08c22c0SSven Eckelmann 1931a08c22c0SSven Eckelmann if (effect->type != FF_RUMBLE) 1932a08c22c0SSven Eckelmann return 0; 1933a08c22c0SSven Eckelmann 19349f323b68SSven Eckelmann sc->left = effect->u.rumble.strong_magnitude / 256; 19350bd88dd3SFrank Praznik sc->right = effect->u.rumble.weak_magnitude / 256; 1936a08c22c0SSven Eckelmann 193792b5c411SSven Eckelmann schedule_work(&sc->state_worker); 19389f323b68SSven Eckelmann return 0; 1939a08c22c0SSven Eckelmann } 1940a08c22c0SSven Eckelmann 1941fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 1942a08c22c0SSven Eckelmann { 1943fa57a810SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 1944a08c22c0SSven Eckelmann struct hid_input, list); 1945a08c22c0SSven Eckelmann struct input_dev *input_dev = hidinput->input; 1946a08c22c0SSven Eckelmann 1947a08c22c0SSven Eckelmann input_set_capability(input_dev, EV_FF, FF_RUMBLE); 1948a08c22c0SSven Eckelmann return input_ff_create_memless(input_dev, NULL, sony_play_effect); 1949a08c22c0SSven Eckelmann } 1950a08c22c0SSven Eckelmann 1951a08c22c0SSven Eckelmann #else 1952fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 1953a08c22c0SSven Eckelmann { 1954a08c22c0SSven Eckelmann return 0; 1955a08c22c0SSven Eckelmann } 19569f323b68SSven Eckelmann 1957a08c22c0SSven Eckelmann #endif 1958a08c22c0SSven Eckelmann 1959d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy, 1960d902f472SFrank Praznik enum power_supply_property psp, 1961d902f472SFrank Praznik union power_supply_propval *val) 1962c4e1ddf2SFrank Praznik { 1963297d716fSKrzysztof Kozlowski struct sony_sc *sc = power_supply_get_drvdata(psy); 1964d902f472SFrank Praznik unsigned long flags; 1965d902f472SFrank Praznik int ret = 0; 1966d902f472SFrank Praznik u8 battery_charging, battery_capacity, cable_state; 1967c4e1ddf2SFrank Praznik 1968d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1969d902f472SFrank Praznik battery_charging = sc->battery_charging; 1970d902f472SFrank Praznik battery_capacity = sc->battery_capacity; 1971d902f472SFrank Praznik cable_state = sc->cable_state; 1972d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1973c4e1ddf2SFrank Praznik 1974d902f472SFrank Praznik switch (psp) { 1975d902f472SFrank Praznik case POWER_SUPPLY_PROP_PRESENT: 1976d902f472SFrank Praznik val->intval = 1; 1977d902f472SFrank Praznik break; 1978d902f472SFrank Praznik case POWER_SUPPLY_PROP_SCOPE: 1979d902f472SFrank Praznik val->intval = POWER_SUPPLY_SCOPE_DEVICE; 1980d902f472SFrank Praznik break; 1981d902f472SFrank Praznik case POWER_SUPPLY_PROP_CAPACITY: 1982d902f472SFrank Praznik val->intval = battery_capacity; 1983d902f472SFrank Praznik break; 1984d902f472SFrank Praznik case POWER_SUPPLY_PROP_STATUS: 1985d902f472SFrank Praznik if (battery_charging) 1986d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_CHARGING; 1987d902f472SFrank Praznik else 1988d902f472SFrank Praznik if (battery_capacity == 100 && cable_state) 1989d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_FULL; 1990d902f472SFrank Praznik else 1991d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 1992d902f472SFrank Praznik break; 1993d902f472SFrank Praznik default: 1994d902f472SFrank Praznik ret = -EINVAL; 1995d902f472SFrank Praznik break; 1996c4e1ddf2SFrank Praznik } 1997d902f472SFrank Praznik return ret; 1998d902f472SFrank Praznik } 1999d902f472SFrank Praznik 2000d902f472SFrank Praznik static int sony_battery_probe(struct sony_sc *sc) 2001d902f472SFrank Praznik { 2002297d716fSKrzysztof Kozlowski struct power_supply_config psy_cfg = { .drv_data = sc, }; 2003d902f472SFrank Praznik struct hid_device *hdev = sc->hdev; 2004d902f472SFrank Praznik int ret; 2005d902f472SFrank Praznik 2006ad142b9eSFrank Praznik /* 2007ad142b9eSFrank Praznik * Set the default battery level to 100% to avoid low battery warnings 2008d9a293a9SFrank Praznik * if the battery is polled before the first device report is received. 2009d9a293a9SFrank Praznik */ 2010d9a293a9SFrank Praznik sc->battery_capacity = 100; 2011d9a293a9SFrank Praznik 2012297d716fSKrzysztof Kozlowski sc->battery_desc.properties = sony_battery_props; 2013297d716fSKrzysztof Kozlowski sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props); 2014297d716fSKrzysztof Kozlowski sc->battery_desc.get_property = sony_battery_get_property; 2015297d716fSKrzysztof Kozlowski sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 2016297d716fSKrzysztof Kozlowski sc->battery_desc.use_for_apm = 0; 2017297d716fSKrzysztof Kozlowski sc->battery_desc.name = kasprintf(GFP_KERNEL, 2018297d716fSKrzysztof Kozlowski "sony_controller_battery_%pMR", 2019314531f1SFrank Praznik sc->mac_address); 2020297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 2021d902f472SFrank Praznik return -ENOMEM; 2022d902f472SFrank Praznik 2023297d716fSKrzysztof Kozlowski sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc, 2024297d716fSKrzysztof Kozlowski &psy_cfg); 2025297d716fSKrzysztof Kozlowski if (IS_ERR(sc->battery)) { 2026297d716fSKrzysztof Kozlowski ret = PTR_ERR(sc->battery); 2027d902f472SFrank Praznik hid_err(hdev, "Unable to register battery device\n"); 2028d902f472SFrank Praznik goto err_free; 2029d902f472SFrank Praznik } 2030d902f472SFrank Praznik 2031297d716fSKrzysztof Kozlowski power_supply_powers(sc->battery, &hdev->dev); 2032d902f472SFrank Praznik return 0; 2033d902f472SFrank Praznik 2034d902f472SFrank Praznik err_free: 2035297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 2036297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 2037d902f472SFrank Praznik return ret; 2038d902f472SFrank Praznik } 2039d902f472SFrank Praznik 2040d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc) 2041d902f472SFrank Praznik { 2042297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 2043d902f472SFrank Praznik return; 2044d902f472SFrank Praznik 2045297d716fSKrzysztof Kozlowski power_supply_unregister(sc->battery); 2046297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 2047297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 2048d902f472SFrank Praznik } 2049d902f472SFrank Praznik 2050d2d782fcSFrank Praznik /* 2051d2d782fcSFrank Praznik * If a controller is plugged in via USB while already connected via Bluetooth 2052d2d782fcSFrank Praznik * it will show up as two devices. A global list of connected controllers and 2053d2d782fcSFrank Praznik * their MAC addresses is maintained to ensure that a device is only connected 2054d2d782fcSFrank Praznik * once. 2055d2d782fcSFrank Praznik */ 2056d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc) 2057d2d782fcSFrank Praznik { 2058d2d782fcSFrank Praznik struct sony_sc *entry; 2059d2d782fcSFrank Praznik unsigned long flags; 2060d2d782fcSFrank Praznik int ret; 2061d2d782fcSFrank Praznik 2062d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 2063d2d782fcSFrank Praznik 2064d2d782fcSFrank Praznik list_for_each_entry(entry, &sony_device_list, list_node) { 2065d2d782fcSFrank Praznik ret = memcmp(sc->mac_address, entry->mac_address, 2066d2d782fcSFrank Praznik sizeof(sc->mac_address)); 2067d2d782fcSFrank Praznik if (!ret) { 2068d2d782fcSFrank Praznik ret = -EEXIST; 2069d2d782fcSFrank Praznik hid_info(sc->hdev, "controller with MAC address %pMR already connected\n", 2070d2d782fcSFrank Praznik sc->mac_address); 2071d2d782fcSFrank Praznik goto unlock; 2072d2d782fcSFrank Praznik } 2073c4e1ddf2SFrank Praznik } 2074c4e1ddf2SFrank Praznik 2075d2d782fcSFrank Praznik ret = 0; 2076d2d782fcSFrank Praznik list_add(&(sc->list_node), &sony_device_list); 2077c4e1ddf2SFrank Praznik 2078d2d782fcSFrank Praznik unlock: 2079d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 2080d2d782fcSFrank Praznik return ret; 2081d2d782fcSFrank Praznik } 2082d2d782fcSFrank Praznik 2083d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc) 2084d2d782fcSFrank Praznik { 2085d2d782fcSFrank Praznik unsigned long flags; 2086d2d782fcSFrank Praznik 2087d2d782fcSFrank Praznik if (sc->list_node.next) { 2088d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 2089d2d782fcSFrank Praznik list_del(&(sc->list_node)); 2090d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 2091d2d782fcSFrank Praznik } 2092d2d782fcSFrank Praznik } 2093d2d782fcSFrank Praznik 2094d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc) 2095d2d782fcSFrank Praznik { 2096d2d782fcSFrank Praznik int ret; 2097d2d782fcSFrank Praznik 2098d2d782fcSFrank Praznik /* HIDP stores the device MAC address as a string in the uniq field. */ 2099d2d782fcSFrank Praznik ret = strlen(sc->hdev->uniq); 2100d2d782fcSFrank Praznik if (ret != 17) 2101c4e1ddf2SFrank Praznik return -EINVAL; 2102d2d782fcSFrank Praznik 2103d2d782fcSFrank Praznik ret = sscanf(sc->hdev->uniq, 2104d2d782fcSFrank Praznik "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 2105d2d782fcSFrank Praznik &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3], 2106d2d782fcSFrank Praznik &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]); 2107d2d782fcSFrank Praznik 2108d2d782fcSFrank Praznik if (ret != 6) 2109d2d782fcSFrank Praznik return -EINVAL; 2110d2d782fcSFrank Praznik 2111d2d782fcSFrank Praznik return 0; 2112c4e1ddf2SFrank Praznik } 2113c4e1ddf2SFrank Praznik 2114d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc) 2115d2d782fcSFrank Praznik { 21169b2b5c9aSFrank Praznik __u8 *buf = NULL; 2117d2d782fcSFrank Praznik int n, ret; 2118d2d782fcSFrank Praznik 2119d2d782fcSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || 212012e9a6d7SSimon Wood (sc->quirks & MOTION_CONTROLLER_BT) || 21214545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT) || 2122d2d782fcSFrank Praznik (sc->quirks & SIXAXIS_CONTROLLER_BT)) { 2123d2d782fcSFrank Praznik /* 2124d2d782fcSFrank Praznik * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC 2125d2d782fcSFrank Praznik * address from the uniq string where HIDP stores it. 2126d2d782fcSFrank Praznik * As uniq cannot be guaranteed to be a MAC address in all cases 2127d2d782fcSFrank Praznik * a failure of this function should not prevent the connection. 2128d2d782fcSFrank Praznik */ 2129d2d782fcSFrank Praznik if (sony_get_bt_devaddr(sc) < 0) { 2130d2d782fcSFrank Praznik hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); 2131d2d782fcSFrank Praznik return 0; 2132d2d782fcSFrank Praznik } 2133d2d782fcSFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 21349b2b5c9aSFrank Praznik buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); 21359b2b5c9aSFrank Praznik if (!buf) 21369b2b5c9aSFrank Praznik return -ENOMEM; 2137d2d782fcSFrank Praznik 2138d2d782fcSFrank Praznik /* 2139d2d782fcSFrank Praznik * The MAC address of a DS4 controller connected via USB can be 2140d2d782fcSFrank Praznik * retrieved with feature report 0x81. The address begins at 2141d2d782fcSFrank Praznik * offset 1. 2142d2d782fcSFrank Praznik */ 21439b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0x81, buf, 21449b2b5c9aSFrank Praznik DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, 21459b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2146d2d782fcSFrank Praznik 21479b2b5c9aSFrank Praznik if (ret != DS4_REPORT_0x81_SIZE) { 2148d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); 21499b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 21509b2b5c9aSFrank Praznik goto out_free; 2151d2d782fcSFrank Praznik } 2152d2d782fcSFrank Praznik 2153d2d782fcSFrank Praznik memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); 21544545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 21554545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 21569b2b5c9aSFrank Praznik buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); 21579b2b5c9aSFrank Praznik if (!buf) 21589b2b5c9aSFrank Praznik return -ENOMEM; 2159d2d782fcSFrank Praznik 2160d2d782fcSFrank Praznik /* 2161d2d782fcSFrank Praznik * The MAC address of a Sixaxis controller connected via USB can 2162d2d782fcSFrank Praznik * be retrieved with feature report 0xf2. The address begins at 2163d2d782fcSFrank Praznik * offset 4. 2164d2d782fcSFrank Praznik */ 21659b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, 21669b2b5c9aSFrank Praznik SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, 21679b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2168d2d782fcSFrank Praznik 21699b2b5c9aSFrank Praznik if (ret != SIXAXIS_REPORT_0xF2_SIZE) { 2170d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); 21719b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 21729b2b5c9aSFrank Praznik goto out_free; 2173d2d782fcSFrank Praznik } 2174d2d782fcSFrank Praznik 2175d2d782fcSFrank Praznik /* 2176d2d782fcSFrank Praznik * The Sixaxis device MAC in the report is big-endian and must 2177d2d782fcSFrank Praznik * be byte-swapped. 2178d2d782fcSFrank Praznik */ 2179d2d782fcSFrank Praznik for (n = 0; n < 6; n++) 2180d2d782fcSFrank Praznik sc->mac_address[5-n] = buf[4+n]; 2181d2d782fcSFrank Praznik } else { 2182d2d782fcSFrank Praznik return 0; 2183d2d782fcSFrank Praznik } 2184d2d782fcSFrank Praznik 21859b2b5c9aSFrank Praznik ret = sony_check_add_dev_list(sc); 21869b2b5c9aSFrank Praznik 21879b2b5c9aSFrank Praznik out_free: 21889b2b5c9aSFrank Praznik 21899b2b5c9aSFrank Praznik kfree(buf); 21909b2b5c9aSFrank Praznik 21919b2b5c9aSFrank Praznik return ret; 2192d2d782fcSFrank Praznik } 2193d2d782fcSFrank Praznik 21948025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc) 21958025087aSFrank Praznik { 21968025087aSFrank Praznik int ret; 21978025087aSFrank Praznik 21988025087aSFrank Praznik /* 21998025087aSFrank Praznik * Only DualShock 4 or Sixaxis controllers get an id. 22008025087aSFrank Praznik * All others are set to -1. 22018025087aSFrank Praznik */ 22028025087aSFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) || 22038025087aSFrank Praznik (sc->quirks & DUALSHOCK4_CONTROLLER)) { 22048025087aSFrank Praznik ret = ida_simple_get(&sony_device_id_allocator, 0, 0, 22058025087aSFrank Praznik GFP_KERNEL); 22068025087aSFrank Praznik if (ret < 0) { 22078025087aSFrank Praznik sc->device_id = -1; 22088025087aSFrank Praznik return ret; 22098025087aSFrank Praznik } 22108025087aSFrank Praznik sc->device_id = ret; 22118025087aSFrank Praznik } else { 22128025087aSFrank Praznik sc->device_id = -1; 22138025087aSFrank Praznik } 22148025087aSFrank Praznik 22158025087aSFrank Praznik return 0; 22168025087aSFrank Praznik } 22178025087aSFrank Praznik 22188025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc) 22198025087aSFrank Praznik { 22208025087aSFrank Praznik if (sc->device_id >= 0) { 22218025087aSFrank Praznik ida_simple_remove(&sony_device_id_allocator, sc->device_id); 22228025087aSFrank Praznik sc->device_id = -1; 22238025087aSFrank Praznik } 22248025087aSFrank Praznik } 22258025087aSFrank Praznik 222646262047SFrank Praznik static inline void sony_init_work(struct sony_sc *sc, 222746262047SFrank Praznik void (*worker)(struct work_struct *)) 222846262047SFrank Praznik { 222946262047SFrank Praznik if (!sc->worker_initialized) 223046262047SFrank Praznik INIT_WORK(&sc->state_worker, worker); 223146262047SFrank Praznik 223246262047SFrank Praznik sc->worker_initialized = 1; 223346262047SFrank Praznik } 223446262047SFrank Praznik 223546262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc) 223646262047SFrank Praznik { 223746262047SFrank Praznik if (sc->worker_initialized) 223846262047SFrank Praznik cancel_work_sync(&sc->state_worker); 223946262047SFrank Praznik } 2240d2d782fcSFrank Praznik 2241bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 2242bd28ce00SJiri Slaby { 2243bd28ce00SJiri Slaby int ret; 2244cc6e0bbbSJiri Kosina unsigned long quirks = id->driver_data; 2245cc6e0bbbSJiri Kosina struct sony_sc *sc; 2246f04d5140SColin Leitner unsigned int connect_mask = HID_CONNECT_DEFAULT; 2247cc6e0bbbSJiri Kosina 2248abf832bfSBenjamin Tissoires sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); 2249cc6e0bbbSJiri Kosina if (sc == NULL) { 22504291ee30SJoe Perches hid_err(hdev, "can't alloc sony descriptor\n"); 2251cc6e0bbbSJiri Kosina return -ENOMEM; 2252cc6e0bbbSJiri Kosina } 2253cc6e0bbbSJiri Kosina 2254b94993f6SFrank Praznik spin_lock_init(&sc->lock); 2255b94993f6SFrank Praznik 2256cc6e0bbbSJiri Kosina sc->quirks = quirks; 2257cc6e0bbbSJiri Kosina hid_set_drvdata(hdev, sc); 22580a286ef2SSven Eckelmann sc->hdev = hdev; 2259bd28ce00SJiri Slaby 2260bd28ce00SJiri Slaby ret = hid_parse(hdev); 2261bd28ce00SJiri Slaby if (ret) { 22624291ee30SJoe Perches hid_err(hdev, "parse failed\n"); 2263abf832bfSBenjamin Tissoires return ret; 2264bd28ce00SJiri Slaby } 2265bd28ce00SJiri Slaby 2266f04d5140SColin Leitner if (sc->quirks & VAIO_RDESC_CONSTANT) 2267f04d5140SColin Leitner connect_mask |= HID_CONNECT_HIDDEV_FORCE; 226850764650SAntonio Ospite else if (sc->quirks & SIXAXIS_CONTROLLER) 2269f04d5140SColin Leitner connect_mask |= HID_CONNECT_HIDDEV_FORCE; 2270f04d5140SColin Leitner 2271f04d5140SColin Leitner ret = hid_hw_start(hdev, connect_mask); 2272bd28ce00SJiri Slaby if (ret) { 22734291ee30SJoe Perches hid_err(hdev, "hw start failed\n"); 2274abf832bfSBenjamin Tissoires return ret; 2275bd28ce00SJiri Slaby } 2276bd28ce00SJiri Slaby 22778025087aSFrank Praznik ret = sony_set_device_id(sc); 22788025087aSFrank Praznik if (ret < 0) { 22798025087aSFrank Praznik hid_err(hdev, "failed to allocate the device id\n"); 22808025087aSFrank Praznik goto err_stop; 22818025087aSFrank Praznik } 22828025087aSFrank Praznik 2283131a8a9aSFrank Praznik ret = sony_allocate_output_report(sc); 2284131a8a9aSFrank Praznik if (ret < 0) { 2285131a8a9aSFrank Praznik hid_err(hdev, "failed to allocate the output report buffer\n"); 2286131a8a9aSFrank Praznik goto err_stop; 2287131a8a9aSFrank Praznik } 2288131a8a9aSFrank Praznik 22894545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 22904545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 2291e534a935SBenjamin Tissoires /* 2292e534a935SBenjamin Tissoires * The Sony Sixaxis does not handle HID Output Reports on the 2293e534a935SBenjamin Tissoires * Interrupt EP like it could, so we need to force HID Output 2294e534a935SBenjamin Tissoires * Reports to use HID_REQ_SET_REPORT on the Control EP. 2295e534a935SBenjamin Tissoires * 2296e534a935SBenjamin Tissoires * There is also another issue about HID Output Reports via USB, 2297e534a935SBenjamin Tissoires * the Sixaxis does not want the report_id as part of the data 2298e534a935SBenjamin Tissoires * packet, so we have to discard buf[0] when sending the actual 2299e534a935SBenjamin Tissoires * control message, even for numbered reports, humpf! 2300e534a935SBenjamin Tissoires */ 2301e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2302e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; 2303816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev); 230446262047SFrank Praznik sony_init_work(sc, sixaxis_state_worker); 23054545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || 23064545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT)) { 23072078b9bbSFrank Praznik /* 23082078b9bbSFrank Praznik * The Sixaxis wants output reports sent on the ctrl endpoint 23092078b9bbSFrank Praznik * when connected via Bluetooth. 23102078b9bbSFrank Praznik */ 23112078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2312816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev); 231346262047SFrank Praznik sony_init_work(sc, sixaxis_state_worker); 2314fee4e2d5SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 231568330d83SFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { 23162078b9bbSFrank Praznik /* 23172078b9bbSFrank Praznik * The DualShock 4 wants output reports sent on the ctrl 23182078b9bbSFrank Praznik * endpoint when connected via Bluetooth. 23192078b9bbSFrank Praznik */ 23202078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 232168330d83SFrank Praznik ret = dualshock4_set_operational_bt(hdev); 232268330d83SFrank Praznik if (ret < 0) { 232368330d83SFrank Praznik hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); 232468330d83SFrank Praznik goto err_stop; 232568330d83SFrank Praznik } 232668330d83SFrank Praznik } 2327c4e1ddf2SFrank Praznik 232846262047SFrank Praznik sony_init_work(sc, dualshock4_state_worker); 2329c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 2330c5e0c1c4SFrank Praznik sony_init_work(sc, motion_state_worker); 23310bd88dd3SFrank Praznik } else { 23320bd88dd3SFrank Praznik ret = 0; 23330bd88dd3SFrank Praznik } 2334f9ce7c28SBastien Nocera 23354dfdc464SJiri Kosina if (ret < 0) 2336bd28ce00SJiri Slaby goto err_stop; 2337bd28ce00SJiri Slaby 2338d2d782fcSFrank Praznik ret = sony_check_add(sc); 2339d2d782fcSFrank Praznik if (ret < 0) 2340d2d782fcSFrank Praznik goto err_stop; 2341d2d782fcSFrank Praznik 23420a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) { 2343fa57a810SFrank Praznik ret = sony_leds_init(sc); 23440a286ef2SSven Eckelmann if (ret < 0) 23450a286ef2SSven Eckelmann goto err_stop; 23460a286ef2SSven Eckelmann } 23470a286ef2SSven Eckelmann 2348d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 2349d902f472SFrank Praznik ret = sony_battery_probe(sc); 2350a08c22c0SSven Eckelmann if (ret < 0) 2351a08c22c0SSven Eckelmann goto err_stop; 2352a08c22c0SSven Eckelmann 2353d902f472SFrank Praznik /* Open the device to receive reports with battery info */ 2354d902f472SFrank Praznik ret = hid_hw_open(hdev); 2355d902f472SFrank Praznik if (ret < 0) { 2356d902f472SFrank Praznik hid_err(hdev, "hw open failed\n"); 2357d902f472SFrank Praznik goto err_stop; 2358d902f472SFrank Praznik } 2359d902f472SFrank Praznik } 2360d902f472SFrank Praznik 2361c8de9dbbSFrank Praznik if (sc->quirks & SONY_FF_SUPPORT) { 2362fa57a810SFrank Praznik ret = sony_init_ff(sc); 2363d902f472SFrank Praznik if (ret < 0) 2364d902f472SFrank Praznik goto err_close; 23655f5750d2SFrank Praznik } 2366bd28ce00SJiri Slaby 2367f425458eSH Hartley Sweeten return 0; 2368d902f472SFrank Praznik err_close: 2369d902f472SFrank Praznik hid_hw_close(hdev); 2370bd28ce00SJiri Slaby err_stop: 23710a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2372fa57a810SFrank Praznik sony_leds_remove(sc); 2373d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) 2374d902f472SFrank Praznik sony_battery_remove(sc); 237546262047SFrank Praznik sony_cancel_work_sync(sc); 23769b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 2377d2d782fcSFrank Praznik sony_remove_dev_list(sc); 23788025087aSFrank Praznik sony_release_device_id(sc); 2379bd28ce00SJiri Slaby hid_hw_stop(hdev); 2380bd28ce00SJiri Slaby return ret; 2381bd28ce00SJiri Slaby } 2382bd28ce00SJiri Slaby 2383bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev) 2384bd28ce00SJiri Slaby { 2385bd28ce00SJiri Slaby struct sony_sc *sc = hid_get_drvdata(hdev); 2386bd28ce00SJiri Slaby 23870a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2388fa57a810SFrank Praznik sony_leds_remove(sc); 2389bd28ce00SJiri Slaby 2390d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 2391d902f472SFrank Praznik hid_hw_close(hdev); 2392d902f472SFrank Praznik sony_battery_remove(sc); 2393d902f472SFrank Praznik } 2394d902f472SFrank Praznik 239546262047SFrank Praznik sony_cancel_work_sync(sc); 23969f323b68SSven Eckelmann 23979b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 23989b2b5c9aSFrank Praznik 2399d2d782fcSFrank Praznik sony_remove_dev_list(sc); 2400bd28ce00SJiri Slaby 24018025087aSFrank Praznik sony_release_device_id(sc); 24028025087aSFrank Praznik 2403bd28ce00SJiri Slaby hid_hw_stop(hdev); 2404bd28ce00SJiri Slaby } 2405bd28ce00SJiri Slaby 2406bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = { 2407bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2408bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_USB }, 2409bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 24104545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_USB }, 24116eabaaa0SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 24124545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_BT }, 2413c5e0c1c4SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2414b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_USB }, 2415a4afa854SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2416b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_BT }, 2417bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2418bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_BT }, 2419bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 2420bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2421bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), 2422bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2423bd28ce00SJiri Slaby /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as 2424bd28ce00SJiri Slaby * Logitech joystick from the device descriptor. */ 2425bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), 2426bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2427bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), 2428bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2429bd28ce00SJiri Slaby /* PS3 BD Remote Control */ 2430bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), 2431bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 2432bd28ce00SJiri Slaby /* Logitech Harmony Adapter for PS3 */ 2433bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), 2434bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 243568a49e51SFrank Praznik /* SMK-Link PS3 BD Remote Control */ 243668a49e51SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), 243768a49e51SFrank Praznik .driver_data = PS3REMOTE }, 24380bd88dd3SFrank Praznik /* Sony Dualshock 4 controllers for PS4 */ 24390bd88dd3SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 24408ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_USB }, 24410bd88dd3SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 24428ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_BT }, 2443bd28ce00SJiri Slaby { } 2444bd28ce00SJiri Slaby }; 2445bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices); 2446bd28ce00SJiri Slaby 2447bd28ce00SJiri Slaby static struct hid_driver sony_driver = { 2448bd28ce00SJiri Slaby .name = "sony", 2449bd28ce00SJiri Slaby .id_table = sony_devices, 2450bd28ce00SJiri Slaby .input_mapping = sony_mapping, 2451ce8efc3bSFrank Praznik .input_configured = sony_input_configured, 2452bd28ce00SJiri Slaby .probe = sony_probe, 2453bd28ce00SJiri Slaby .remove = sony_remove, 2454bd28ce00SJiri Slaby .report_fixup = sony_report_fixup, 2455bd28ce00SJiri Slaby .raw_event = sony_raw_event 2456bd28ce00SJiri Slaby }; 24578025087aSFrank Praznik 24588025087aSFrank Praznik static int __init sony_init(void) 24598025087aSFrank Praznik { 24608025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 24618025087aSFrank Praznik 24628025087aSFrank Praznik return hid_register_driver(&sony_driver); 24638025087aSFrank Praznik } 24648025087aSFrank Praznik 24658025087aSFrank Praznik static void __exit sony_exit(void) 24668025087aSFrank Praznik { 24678025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 24688025087aSFrank Praznik 24698025087aSFrank Praznik hid_unregister_driver(&sony_driver); 24706c40065fSAntonio Ospite ida_destroy(&sony_device_id_allocator); 24718025087aSFrank Praznik } 24728025087aSFrank Praznik module_init(sony_init); 24738025087aSFrank Praznik module_exit(sony_exit); 2474bd28ce00SJiri Slaby 2475bd28ce00SJiri Slaby MODULE_LICENSE("GPL"); 2476