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 251*b2723eb7SSimon Wood /* PS/3 Navigation controller */ 252*b2723eb7SSimon Wood static __u8 navigation_rdesc[] = { 253*b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 254*b2723eb7SSimon Wood 0x09, 0x04, /* Usage (Joystik), */ 255*b2723eb7SSimon Wood 0xA1, 0x01, /* Collection (Application), */ 256*b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 257*b2723eb7SSimon Wood 0x85, 0x01, /* Report ID (1), */ 258*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 259*b2723eb7SSimon Wood 0x95, 0x01, /* Report Count (1), */ 260*b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 261*b2723eb7SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 262*b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 263*b2723eb7SSimon Wood 0x75, 0x01, /* Report Size (1), */ 264*b2723eb7SSimon Wood 0x95, 0x13, /* Report Count (19), */ 265*b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 266*b2723eb7SSimon Wood 0x25, 0x01, /* Logical Maximum (1), */ 267*b2723eb7SSimon Wood 0x35, 0x00, /* Physical Minimum (0), */ 268*b2723eb7SSimon Wood 0x45, 0x01, /* Physical Maximum (1), */ 269*b2723eb7SSimon Wood 0x05, 0x09, /* Usage Page (Button), */ 270*b2723eb7SSimon Wood 0x19, 0x01, /* Usage Minimum (01h), */ 271*b2723eb7SSimon Wood 0x29, 0x13, /* Usage Maximum (13h), */ 272*b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 273*b2723eb7SSimon Wood 0x75, 0x01, /* Report Size (1), */ 274*b2723eb7SSimon Wood 0x95, 0x0D, /* Report Count (13), */ 275*b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 276*b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 277*b2723eb7SSimon Wood 0x15, 0x00, /* Logical Minimum (0), */ 278*b2723eb7SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 279*b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 280*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 281*b2723eb7SSimon Wood 0xA1, 0x00, /* Collection (Physical), */ 282*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 283*b2723eb7SSimon Wood 0x95, 0x02, /* Report Count (2), */ 284*b2723eb7SSimon Wood 0x35, 0x00, /* Physical Minimum (0), */ 285*b2723eb7SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 286*b2723eb7SSimon Wood 0x09, 0x30, /* Usage (X), */ 287*b2723eb7SSimon Wood 0x09, 0x31, /* Usage (Y), */ 288*b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 289*b2723eb7SSimon Wood 0xC0, /* End Collection, */ 290*b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 291*b2723eb7SSimon Wood 0x95, 0x06, /* Report Count (6), */ 292*b2723eb7SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), */ 293*b2723eb7SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 294*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 295*b2723eb7SSimon Wood 0x95, 0x05, /* Report Count (5), */ 296*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 297*b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 298*b2723eb7SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 299*b2723eb7SSimon Wood 0x95, 0x20, /* Report Count (26), */ 300*b2723eb7SSimon Wood 0x81, 0x02, /* Input (Variable), */ 301*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 302*b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 303*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 304*b2723eb7SSimon Wood 0x91, 0x02, /* Output (Variable), */ 305*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 306*b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 307*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 308*b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 309*b2723eb7SSimon Wood 0xC0, /* End Collection, */ 310*b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 311*b2723eb7SSimon Wood 0x85, 0x02, /* Report ID (2), */ 312*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 313*b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 314*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 315*b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 316*b2723eb7SSimon Wood 0xC0, /* End Collection, */ 317*b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 318*b2723eb7SSimon Wood 0x85, 0xEE, /* Report ID (238), */ 319*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 320*b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 321*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 322*b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 323*b2723eb7SSimon Wood 0xC0, /* End Collection, */ 324*b2723eb7SSimon Wood 0xA1, 0x02, /* Collection (Logical), */ 325*b2723eb7SSimon Wood 0x85, 0xEF, /* Report ID (239), */ 326*b2723eb7SSimon Wood 0x75, 0x08, /* Report Size (8), */ 327*b2723eb7SSimon Wood 0x95, 0x30, /* Report Count (48), */ 328*b2723eb7SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 329*b2723eb7SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 330*b2723eb7SSimon Wood 0xC0, /* End Collection, */ 331*b2723eb7SSimon Wood 0xC0 /* End Collection */ 332*b2723eb7SSimon Wood }; 333c5e0c1c4SFrank Praznik 334ad142b9eSFrank Praznik /* 335ad142b9eSFrank Praznik * The default descriptor doesn't provide mapping for the accelerometers 33658d7027bSFrank Praznik * or orientation sensors. This fixed descriptor maps the accelerometers 33758d7027bSFrank Praznik * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors 33858d7027bSFrank Praznik * to usage values 0x43, 0x44 and 0x45. 33958d7027bSFrank Praznik */ 340ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = { 34158d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 34258d7027bSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 34358d7027bSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 34458d7027bSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 34558d7027bSFrank Praznik 0x09, 0x30, /* Usage (X), */ 34658d7027bSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 34758d7027bSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 34858d7027bSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 34958d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 35058d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 35158d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 35258d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 35358d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 35458d7027bSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 35558d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 35658d7027bSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 35758d7027bSFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 35858d7027bSFrank Praznik 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 35958d7027bSFrank Praznik 0x65, 0x14, /* Unit (Degrees), */ 36058d7027bSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 36158d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 36258d7027bSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 36358d7027bSFrank Praznik 0x65, 0x00, /* Unit, */ 36458d7027bSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 36558d7027bSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 36658d7027bSFrank Praznik 0x29, 0x0E, /* Usage Maximum (0Eh), */ 36758d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 36858d7027bSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 36958d7027bSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 37058d7027bSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 37158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 37258d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 37358d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 37458d7027bSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 37558d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 37658d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 377fb291cbdSFrank Praznik 0x25, 0x3F, /* Logical Maximum (63), */ 37858d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 37958d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 38058d7027bSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 38158d7027bSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 38258d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 38358d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 38458d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 38558d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 38658d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 38758d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 38858d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 38958d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 39058d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 39158d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 39258d7027bSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 39358d7027bSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 39458d7027bSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 39558d7027bSFrank Praznik 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ 39658d7027bSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 39758d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 39858d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 39958d7027bSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 40058d7027bSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 401fb291cbdSFrank Praznik 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ 402fb291cbdSFrank Praznik 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ 40358d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 40458d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 40558d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 40658d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 40758d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 408fb291cbdSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 40958d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 41058d7027bSFrank Praznik 0x95, 0x27, /* Report Count (39), */ 41158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 41258d7027bSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 41358d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 41458d7027bSFrank Praznik 0x95, 0x1F, /* Report Count (31), */ 41558d7027bSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 41658d7027bSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 41758d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 41858d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 41958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42058d7027bSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 42158d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 42258d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 42358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42458d7027bSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 42558d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 42658d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 42758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42858d7027bSFrank Praznik 0x85, 0x10, /* Report ID (16), */ 42958d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 43058d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 43158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43258d7027bSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 43358d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 43458d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 43558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43658d7027bSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 43758d7027bSFrank Praznik 0x06, 0x02, 0xFF, /* Usage Page (FF02h), */ 43858d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 43958d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 44058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44158d7027bSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 44258d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 44358d7027bSFrank Praznik 0x95, 0x16, /* Report Count (22), */ 44458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44558d7027bSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 44658d7027bSFrank Praznik 0x06, 0x05, 0xFF, /* Usage Page (FF05h), */ 44758d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 44858d7027bSFrank Praznik 0x95, 0x10, /* Report Count (16), */ 44958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45058d7027bSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 45158d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 45258d7027bSFrank Praznik 0x95, 0x2C, /* Report Count (44), */ 45358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45458d7027bSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 45558d7027bSFrank Praznik 0x85, 0x80, /* Report ID (128), */ 45658d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 45758d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 45858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45958d7027bSFrank Praznik 0x85, 0x81, /* Report ID (129), */ 46058d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 46158d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 46258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46358d7027bSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 46458d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 46558d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 46658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46758d7027bSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 46858d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 46958d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 47058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47158d7027bSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 47258d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 47358d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 47458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47558d7027bSFrank Praznik 0x85, 0x85, /* Report ID (133), */ 47658d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 47758d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 47858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47958d7027bSFrank Praznik 0x85, 0x86, /* Report ID (134), */ 48058d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 48158d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 48258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48358d7027bSFrank Praznik 0x85, 0x87, /* Report ID (135), */ 48458d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 48558d7027bSFrank Praznik 0x95, 0x23, /* Report Count (35), */ 48658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48758d7027bSFrank Praznik 0x85, 0x88, /* Report ID (136), */ 48858d7027bSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 48958d7027bSFrank Praznik 0x95, 0x22, /* Report Count (34), */ 49058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49158d7027bSFrank Praznik 0x85, 0x89, /* Report ID (137), */ 49258d7027bSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 49358d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 49458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49558d7027bSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 49658d7027bSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 49758d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 49858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49958d7027bSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 50058d7027bSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 50158d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 50258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50358d7027bSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 50458d7027bSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 50558d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 50658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50758d7027bSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 50858d7027bSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 50958d7027bSFrank Praznik 0x95, 0x0C, /* Report Count (12), */ 51058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51158d7027bSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 51258d7027bSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 51358d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 51458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51558d7027bSFrank Praznik 0x85, 0xA1, /* Report ID (161), */ 51658d7027bSFrank Praznik 0x09, 0x41, /* Usage (41h), */ 51758d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 51858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 51958d7027bSFrank Praznik 0x85, 0xA2, /* Report ID (162), */ 52058d7027bSFrank Praznik 0x09, 0x42, /* Usage (42h), */ 52158d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 52258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52358d7027bSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 52458d7027bSFrank Praznik 0x09, 0x43, /* Usage (43h), */ 52558d7027bSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 52658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 52758d7027bSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 52858d7027bSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 52958d7027bSFrank Praznik 0x95, 0x0D, /* Report Count (13), */ 53058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53158d7027bSFrank Praznik 0x85, 0xA5, /* Report ID (165), */ 53258d7027bSFrank Praznik 0x09, 0x45, /* Usage (45h), */ 53358d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 53458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53558d7027bSFrank Praznik 0x85, 0xA6, /* Report ID (166), */ 53658d7027bSFrank Praznik 0x09, 0x46, /* Usage (46h), */ 53758d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 53858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 53958d7027bSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 54058d7027bSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 54158d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 54258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54358d7027bSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 54458d7027bSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 54558d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 54658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 54758d7027bSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 54858d7027bSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 54958d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 55058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55158d7027bSFrank Praznik 0x85, 0xA7, /* Report ID (167), */ 55258d7027bSFrank Praznik 0x09, 0x4A, /* Usage (4Ah), */ 55358d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 55458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55558d7027bSFrank Praznik 0x85, 0xA8, /* Report ID (168), */ 55658d7027bSFrank Praznik 0x09, 0x4B, /* Usage (4Bh), */ 55758d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 55858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 55958d7027bSFrank Praznik 0x85, 0xA9, /* Report ID (169), */ 56058d7027bSFrank Praznik 0x09, 0x4C, /* Usage (4Ch), */ 56158d7027bSFrank Praznik 0x95, 0x08, /* Report Count (8), */ 56258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56358d7027bSFrank Praznik 0x85, 0xAA, /* Report ID (170), */ 56458d7027bSFrank Praznik 0x09, 0x4E, /* Usage (4Eh), */ 56558d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 56658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 56758d7027bSFrank Praznik 0x85, 0xAB, /* Report ID (171), */ 56858d7027bSFrank Praznik 0x09, 0x4F, /* Usage (4Fh), */ 56958d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 57058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57158d7027bSFrank Praznik 0x85, 0xAC, /* Report ID (172), */ 57258d7027bSFrank Praznik 0x09, 0x50, /* Usage (50h), */ 57358d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 57458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57558d7027bSFrank Praznik 0x85, 0xAD, /* Report ID (173), */ 57658d7027bSFrank Praznik 0x09, 0x51, /* Usage (51h), */ 57758d7027bSFrank Praznik 0x95, 0x0B, /* Report Count (11), */ 57858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 57958d7027bSFrank Praznik 0x85, 0xAE, /* Report ID (174), */ 58058d7027bSFrank Praznik 0x09, 0x52, /* Usage (52h), */ 58158d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 58258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58358d7027bSFrank Praznik 0x85, 0xAF, /* Report ID (175), */ 58458d7027bSFrank Praznik 0x09, 0x53, /* Usage (53h), */ 58558d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 58658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 58758d7027bSFrank Praznik 0x85, 0xB0, /* Report ID (176), */ 58858d7027bSFrank Praznik 0x09, 0x54, /* Usage (54h), */ 58958d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 59058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 59158d7027bSFrank Praznik 0xC0 /* End Collection */ 592ed19d8cfSFrank Praznik }; 593ed19d8cfSFrank Praznik 594ad142b9eSFrank Praznik /* 595ad142b9eSFrank Praznik * The default behavior of the Dualshock 4 is to send reports using report 596077147a3SFrank Praznik * type 1 when running over Bluetooth. However, when feature report 2 is 597077147a3SFrank Praznik * requested during the controller initialization it starts sending input 598077147a3SFrank Praznik * reports in report 17. Since report 17 is undefined in the default HID 599d829674dSFrank Praznik * descriptor the button and axis definitions must be moved to report 17 or 600077147a3SFrank Praznik * the HID layer won't process the received input. 601d829674dSFrank Praznik */ 602d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = { 603d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 604d829674dSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 605d829674dSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 606d829674dSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 607d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 608d829674dSFrank Praznik 0x95, 0x0A, /* Report Count (9), */ 609d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 610d829674dSFrank Praznik 0x06, 0x04, 0xFF, /* Usage Page (FF04h), */ 611d829674dSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 612d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 613d829674dSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 614d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 615d829674dSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 616d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 617d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 618d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 619d829674dSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 620d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 621d829674dSFrank Praznik 0x95, 0x28, /* Report Count (40), */ 622d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 623d829674dSFrank Praznik 0x85, 0x06, /* Report ID (6), */ 624d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 625d829674dSFrank Praznik 0x95, 0x34, /* Report Count (52), */ 626d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 627d829674dSFrank Praznik 0x85, 0x07, /* Report ID (7), */ 628d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 629d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 630d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 631d829674dSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 632d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 633d829674dSFrank Praznik 0x95, 0x2F, /* Report Count (47), */ 634d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 635d829674dSFrank Praznik 0x06, 0x03, 0xFF, /* Usage Page (FF03h), */ 636d829674dSFrank Praznik 0x85, 0x03, /* Report ID (3), */ 637d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 638d829674dSFrank Praznik 0x95, 0x26, /* Report Count (38), */ 639d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 640d829674dSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 641d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 642d829674dSFrank Praznik 0x95, 0x2E, /* Report Count (46), */ 643d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 644d829674dSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 645d829674dSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 646d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 647d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 648d829674dSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 649d829674dSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 650d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 651d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 652d829674dSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 653d829674dSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 654d829674dSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 655d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 656d829674dSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 657d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 658d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 659d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 660d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 661d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 662d829674dSFrank Praznik 0x09, 0x30, /* Usage (X), */ 663d829674dSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 664d829674dSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 665d829674dSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 666d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 667d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 668d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 669d829674dSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 670d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 671d829674dSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 672d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 673d829674dSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 674d829674dSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 675d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 676d829674dSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 677d829674dSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 678d829674dSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 679d829674dSFrank Praznik 0x29, 0x0E, /* Usage Maximum (0Eh), */ 680d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 681d829674dSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 682d829674dSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 683d829674dSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 684d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 685d829674dSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 686d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 687d829674dSFrank Praznik 0x81, 0x01, /* Input (Constant), */ 688d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 689d829674dSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 690d829674dSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 691d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 692d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 693d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 694d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 695d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 696d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 697d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 698d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 699d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 700d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 701d829674dSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 702d829674dSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 703d829674dSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 704d829674dSFrank Praznik 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ 705d829674dSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 706d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 707d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 708d829674dSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 709d829674dSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 710fb291cbdSFrank Praznik 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ 711fb291cbdSFrank Praznik 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ 712d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 713d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 714d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 715d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 716d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 717d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 718d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 719d829674dSFrank Praznik 0x95, 0x31, /* Report Count (51), */ 720d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 721d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 722d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 723d829674dSFrank Praznik 0x95, 0x4D, /* Report Count (77), */ 724d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 725d829674dSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 726d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 727d829674dSFrank Praznik 0x95, 0x8D, /* Report Count (141), */ 728d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 729d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 730d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 731d829674dSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 732d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 733d829674dSFrank Praznik 0x95, 0xCD, /* Report Count (205), */ 734d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 735d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 736d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 737d829674dSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 738d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 739d829674dSFrank Praznik 0x96, 0x0D, 0x01, /* Report Count (269), */ 740d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 741d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 742d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 743d829674dSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 744d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 745d829674dSFrank Praznik 0x96, 0x4D, 0x01, /* Report Count (333), */ 746d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 747d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 748d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 749d829674dSFrank Praznik 0x85, 0x16, /* Report ID (22), */ 750d829674dSFrank Praznik 0x09, 0x2A, /* Usage (2Ah), */ 751d829674dSFrank Praznik 0x96, 0x8D, 0x01, /* Report Count (397), */ 752d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 753d829674dSFrank Praznik 0x09, 0x2B, /* Usage (2Bh), */ 754d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 755d829674dSFrank Praznik 0x85, 0x17, /* Report ID (23), */ 756d829674dSFrank Praznik 0x09, 0x2C, /* Usage (2Ch), */ 757d829674dSFrank Praznik 0x96, 0xCD, 0x01, /* Report Count (461), */ 758d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 759d829674dSFrank Praznik 0x09, 0x2D, /* Usage (2Dh), */ 760d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 761d829674dSFrank Praznik 0x85, 0x18, /* Report ID (24), */ 762d829674dSFrank Praznik 0x09, 0x2E, /* Usage (2Eh), */ 763d829674dSFrank Praznik 0x96, 0x0D, 0x02, /* Report Count (525), */ 764d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 765d829674dSFrank Praznik 0x09, 0x2F, /* Usage (2Fh), */ 766d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 767d829674dSFrank Praznik 0x85, 0x19, /* Report ID (25), */ 768d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 769d829674dSFrank Praznik 0x96, 0x22, 0x02, /* Report Count (546), */ 770d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 771d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 772d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 773d829674dSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 774d829674dSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 775d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 776d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 777d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 778d829674dSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 779d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 780d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 781d829674dSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 782d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 783d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 784d829674dSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 785d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 786d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 787d829674dSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 788d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 789d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 790d829674dSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 791d829674dSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 792d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 793d829674dSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 794d829674dSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 795d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 796d829674dSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 797d829674dSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 798d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 799d829674dSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 800d829674dSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 801d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 802d829674dSFrank Praznik 0xC0 /* End Collection */ 803d829674dSFrank Praznik }; 804d829674dSFrank Praznik 805078328daSJiri Kosina static __u8 ps3remote_rdesc[] = { 806078328daSJiri Kosina 0x05, 0x01, /* GUsagePage Generic Desktop */ 807078328daSJiri Kosina 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 808078328daSJiri Kosina 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ 809078328daSJiri Kosina 810078328daSJiri Kosina /* Use collection 1 for joypad buttons */ 811078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 812078328daSJiri Kosina 813078328daSJiri Kosina /* Ignore the 1st byte, maybe it is used for a controller 814078328daSJiri Kosina * number but it's not needed for correct operation */ 815078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 816078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 817078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 818078328daSJiri Kosina 819078328daSJiri Kosina /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these 820078328daSJiri Kosina * buttons multiple keypresses are allowed */ 821078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 822078328daSJiri Kosina 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ 823078328daSJiri Kosina 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ 824078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 825078328daSJiri Kosina 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ 826078328daSJiri Kosina 0x75, 0x01, /* GReportSize 0x01 [1] */ 827078328daSJiri Kosina 0x95, 0x18, /* GReportCount 0x18 [24] */ 828078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 829078328daSJiri Kosina 830078328daSJiri Kosina 0xC0, /* MEndCollection */ 831078328daSJiri Kosina 832078328daSJiri Kosina /* Use collection 2 for remote control buttons */ 833078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 834078328daSJiri Kosina 835078328daSJiri Kosina /* 5th byte is used for remote control buttons */ 836078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 837078328daSJiri Kosina 0x18, /* LUsageMinimum [No button pressed] */ 838078328daSJiri Kosina 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ 839078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 840078328daSJiri Kosina 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ 841078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 842078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 843078328daSJiri Kosina 0x80, /* MInput */ 844078328daSJiri Kosina 845078328daSJiri Kosina /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at 846078328daSJiri Kosina * 0xff and 11th is for press indication */ 847078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 848078328daSJiri Kosina 0x95, 0x06, /* GReportCount 0x06 [6] */ 849078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 850078328daSJiri Kosina 851078328daSJiri Kosina /* 12th byte is for battery strength */ 852078328daSJiri Kosina 0x05, 0x06, /* GUsagePage Generic Device Controls */ 853078328daSJiri Kosina 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ 854078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 855078328daSJiri Kosina 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ 856078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 857078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 858078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 859078328daSJiri Kosina 860078328daSJiri Kosina 0xC0, /* MEndCollection */ 861078328daSJiri Kosina 862078328daSJiri Kosina 0xC0 /* MEndCollection [Game Pad] */ 863078328daSJiri Kosina }; 864078328daSJiri Kosina 865078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = { 866078328daSJiri Kosina [0x01] = KEY_SELECT, 867078328daSJiri Kosina [0x02] = BTN_THUMBL, /* L3 */ 868078328daSJiri Kosina [0x03] = BTN_THUMBR, /* R3 */ 869078328daSJiri Kosina [0x04] = BTN_START, 870078328daSJiri Kosina [0x05] = KEY_UP, 871078328daSJiri Kosina [0x06] = KEY_RIGHT, 872078328daSJiri Kosina [0x07] = KEY_DOWN, 873078328daSJiri Kosina [0x08] = KEY_LEFT, 874078328daSJiri Kosina [0x09] = BTN_TL2, /* L2 */ 875078328daSJiri Kosina [0x0a] = BTN_TR2, /* R2 */ 876078328daSJiri Kosina [0x0b] = BTN_TL, /* L1 */ 877078328daSJiri Kosina [0x0c] = BTN_TR, /* R1 */ 878078328daSJiri Kosina [0x0d] = KEY_OPTION, /* options/triangle */ 879078328daSJiri Kosina [0x0e] = KEY_BACK, /* back/circle */ 880078328daSJiri Kosina [0x0f] = BTN_0, /* cross */ 881078328daSJiri Kosina [0x10] = KEY_SCREEN, /* view/square */ 882078328daSJiri Kosina [0x11] = KEY_HOMEPAGE, /* PS button */ 883078328daSJiri Kosina [0x14] = KEY_ENTER, 884078328daSJiri Kosina }; 885078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = { 886078328daSJiri Kosina [0x00] = KEY_1, 887078328daSJiri Kosina [0x01] = KEY_2, 888078328daSJiri Kosina [0x02] = KEY_3, 889078328daSJiri Kosina [0x03] = KEY_4, 890078328daSJiri Kosina [0x04] = KEY_5, 891078328daSJiri Kosina [0x05] = KEY_6, 892078328daSJiri Kosina [0x06] = KEY_7, 893078328daSJiri Kosina [0x07] = KEY_8, 894078328daSJiri Kosina [0x08] = KEY_9, 895078328daSJiri Kosina [0x09] = KEY_0, 896078328daSJiri Kosina [0x0e] = KEY_ESC, /* return */ 897078328daSJiri Kosina [0x0f] = KEY_CLEAR, 898078328daSJiri Kosina [0x16] = KEY_EJECTCD, 899078328daSJiri Kosina [0x1a] = KEY_MENU, /* top menu */ 900078328daSJiri Kosina [0x28] = KEY_TIME, 901078328daSJiri Kosina [0x30] = KEY_PREVIOUS, 902078328daSJiri Kosina [0x31] = KEY_NEXT, 903078328daSJiri Kosina [0x32] = KEY_PLAY, 904078328daSJiri Kosina [0x33] = KEY_REWIND, /* scan back */ 905078328daSJiri Kosina [0x34] = KEY_FORWARD, /* scan forward */ 906078328daSJiri Kosina [0x38] = KEY_STOP, 907078328daSJiri Kosina [0x39] = KEY_PAUSE, 908078328daSJiri Kosina [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ 909078328daSJiri Kosina [0x60] = KEY_FRAMEBACK, /* slow/step back */ 910078328daSJiri Kosina [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ 911078328daSJiri Kosina [0x63] = KEY_SUBTITLE, 912078328daSJiri Kosina [0x64] = KEY_AUDIO, 913078328daSJiri Kosina [0x65] = KEY_ANGLE, 914078328daSJiri Kosina [0x70] = KEY_INFO, /* display */ 915078328daSJiri Kosina [0x80] = KEY_BLUE, 916078328daSJiri Kosina [0x81] = KEY_RED, 917078328daSJiri Kosina [0x82] = KEY_GREEN, 918078328daSJiri Kosina [0x83] = KEY_YELLOW, 919078328daSJiri Kosina }; 920078328daSJiri Kosina 921f04d5140SColin Leitner static const unsigned int buzz_keymap[] = { 922ad142b9eSFrank Praznik /* 923ad142b9eSFrank Praznik * The controller has 4 remote buzzers, each with one LED and 5 924f04d5140SColin Leitner * buttons. 925f04d5140SColin Leitner * 926f04d5140SColin Leitner * We use the mapping chosen by the controller, which is: 927f04d5140SColin Leitner * 928f04d5140SColin Leitner * Key Offset 929f04d5140SColin Leitner * ------------------- 930f04d5140SColin Leitner * Buzz 1 931f04d5140SColin Leitner * Blue 5 932f04d5140SColin Leitner * Orange 4 933f04d5140SColin Leitner * Green 3 934f04d5140SColin Leitner * Yellow 2 935f04d5140SColin Leitner * 936f04d5140SColin Leitner * So, for example, the orange button on the third buzzer is mapped to 937f04d5140SColin Leitner * BTN_TRIGGER_HAPPY14 938f04d5140SColin Leitner */ 939f04d5140SColin Leitner [ 1] = BTN_TRIGGER_HAPPY1, 940f04d5140SColin Leitner [ 2] = BTN_TRIGGER_HAPPY2, 941f04d5140SColin Leitner [ 3] = BTN_TRIGGER_HAPPY3, 942f04d5140SColin Leitner [ 4] = BTN_TRIGGER_HAPPY4, 943f04d5140SColin Leitner [ 5] = BTN_TRIGGER_HAPPY5, 944f04d5140SColin Leitner [ 6] = BTN_TRIGGER_HAPPY6, 945f04d5140SColin Leitner [ 7] = BTN_TRIGGER_HAPPY7, 946f04d5140SColin Leitner [ 8] = BTN_TRIGGER_HAPPY8, 947f04d5140SColin Leitner [ 9] = BTN_TRIGGER_HAPPY9, 948f04d5140SColin Leitner [10] = BTN_TRIGGER_HAPPY10, 949f04d5140SColin Leitner [11] = BTN_TRIGGER_HAPPY11, 950f04d5140SColin Leitner [12] = BTN_TRIGGER_HAPPY12, 951f04d5140SColin Leitner [13] = BTN_TRIGGER_HAPPY13, 952f04d5140SColin Leitner [14] = BTN_TRIGGER_HAPPY14, 953f04d5140SColin Leitner [15] = BTN_TRIGGER_HAPPY15, 954f04d5140SColin Leitner [16] = BTN_TRIGGER_HAPPY16, 955f04d5140SColin Leitner [17] = BTN_TRIGGER_HAPPY17, 956f04d5140SColin Leitner [18] = BTN_TRIGGER_HAPPY18, 957f04d5140SColin Leitner [19] = BTN_TRIGGER_HAPPY19, 958f04d5140SColin Leitner [20] = BTN_TRIGGER_HAPPY20, 959f04d5140SColin Leitner }; 960f04d5140SColin Leitner 961d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = { 962d902f472SFrank Praznik POWER_SUPPLY_PROP_PRESENT, 963d902f472SFrank Praznik POWER_SUPPLY_PROP_CAPACITY, 964d902f472SFrank Praznik POWER_SUPPLY_PROP_SCOPE, 965d902f472SFrank Praznik POWER_SUPPLY_PROP_STATUS, 966d902f472SFrank Praznik }; 967d902f472SFrank Praznik 96855d3b664SFrank Praznik struct sixaxis_led { 96955d3b664SFrank Praznik __u8 time_enabled; /* the total time the led is active (0xff means forever) */ 97055d3b664SFrank Praznik __u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ 97155d3b664SFrank Praznik __u8 enabled; 97255d3b664SFrank Praznik __u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ 97355d3b664SFrank Praznik __u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ 97455d3b664SFrank Praznik } __packed; 97555d3b664SFrank Praznik 97655d3b664SFrank Praznik struct sixaxis_rumble { 97755d3b664SFrank Praznik __u8 padding; 97855d3b664SFrank Praznik __u8 right_duration; /* Right motor duration (0xff means forever) */ 97955d3b664SFrank Praznik __u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ 98055d3b664SFrank Praznik __u8 left_duration; /* Left motor duration (0xff means forever) */ 98155d3b664SFrank Praznik __u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ 98255d3b664SFrank Praznik } __packed; 98355d3b664SFrank Praznik 98455d3b664SFrank Praznik struct sixaxis_output_report { 98555d3b664SFrank Praznik __u8 report_id; 98655d3b664SFrank Praznik struct sixaxis_rumble rumble; 98755d3b664SFrank Praznik __u8 padding[4]; 98855d3b664SFrank Praznik __u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ 98955d3b664SFrank Praznik struct sixaxis_led led[4]; /* LEDx at (4 - x) */ 99055d3b664SFrank Praznik struct sixaxis_led _reserved; /* LED5, not actually soldered */ 99155d3b664SFrank Praznik } __packed; 99255d3b664SFrank Praznik 99355d3b664SFrank Praznik union sixaxis_output_report_01 { 99455d3b664SFrank Praznik struct sixaxis_output_report data; 99555d3b664SFrank Praznik __u8 buf[36]; 99655d3b664SFrank Praznik }; 99755d3b664SFrank Praznik 998c5e0c1c4SFrank Praznik struct motion_output_report_02 { 999c5e0c1c4SFrank Praznik u8 type, zero; 1000c5e0c1c4SFrank Praznik u8 r, g, b; 1001c5e0c1c4SFrank Praznik u8 zero2; 1002c5e0c1c4SFrank Praznik u8 rumble; 1003c5e0c1c4SFrank Praznik }; 1004c5e0c1c4SFrank Praznik 10059b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37 10069b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32 10079b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78 10089b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7 100929b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17 1010a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8 101141d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49 10129b2b5c9aSFrank Praznik 10138b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock); 1014d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list); 10158025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator); 1016d2d782fcSFrank Praznik 1017cc6e0bbbSJiri Kosina struct sony_sc { 1018d902f472SFrank Praznik spinlock_t lock; 1019d2d782fcSFrank Praznik struct list_head list_node; 10200a286ef2SSven Eckelmann struct hid_device *hdev; 102160781cf4SFrank Praznik struct led_classdev *leds[MAX_LEDS]; 1022cc6e0bbbSJiri Kosina unsigned long quirks; 10230a286ef2SSven Eckelmann struct work_struct state_worker; 1024297d716fSKrzysztof Kozlowski struct power_supply *battery; 1025297d716fSKrzysztof Kozlowski struct power_supply_desc battery_desc; 10268025087aSFrank Praznik int device_id; 10279b2b5c9aSFrank Praznik __u8 *output_report_dmabuf; 1028f04d5140SColin Leitner 10299f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF 10309f323b68SSven Eckelmann __u8 left; 10319f323b68SSven Eckelmann __u8 right; 10329f323b68SSven Eckelmann #endif 10339f323b68SSven Eckelmann 1034d2d782fcSFrank Praznik __u8 mac_address[6]; 10355f5750d2SFrank Praznik __u8 worker_initialized; 1036d902f472SFrank Praznik __u8 cable_state; 1037d902f472SFrank Praznik __u8 battery_charging; 1038d902f472SFrank Praznik __u8 battery_capacity; 103960781cf4SFrank Praznik __u8 led_state[MAX_LEDS]; 1040b3ed458cSFrank Praznik __u8 led_delay_on[MAX_LEDS]; 1041b3ed458cSFrank Praznik __u8 led_delay_off[MAX_LEDS]; 104260781cf4SFrank Praznik __u8 led_count; 1043cc6e0bbbSJiri Kosina }; 1044cc6e0bbbSJiri Kosina 1045c607fb8dSAntonio Ospite static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, 1046c607fb8dSAntonio Ospite unsigned int *rsize) 1047c607fb8dSAntonio Ospite { 1048c607fb8dSAntonio Ospite *rsize = sizeof(sixaxis_rdesc); 1049c607fb8dSAntonio Ospite return sixaxis_rdesc; 1050c607fb8dSAntonio Ospite } 1051c607fb8dSAntonio Ospite 1052c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, 1053c5e0c1c4SFrank Praznik unsigned int *rsize) 1054c5e0c1c4SFrank Praznik { 1055c5e0c1c4SFrank Praznik *rsize = sizeof(motion_rdesc); 1056c5e0c1c4SFrank Praznik return motion_rdesc; 1057c5e0c1c4SFrank Praznik } 1058c5e0c1c4SFrank Praznik 1059*b2723eb7SSimon Wood static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc, 1060*b2723eb7SSimon Wood unsigned int *rsize) 1061*b2723eb7SSimon Wood { 1062*b2723eb7SSimon Wood *rsize = sizeof(navigation_rdesc); 1063*b2723eb7SSimon Wood return navigation_rdesc; 1064*b2723eb7SSimon Wood } 1065*b2723eb7SSimon Wood 1066078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, 1067078328daSJiri Kosina unsigned int *rsize) 1068078328daSJiri Kosina { 1069078328daSJiri Kosina *rsize = sizeof(ps3remote_rdesc); 1070078328daSJiri Kosina return ps3remote_rdesc; 1071078328daSJiri Kosina } 1072078328daSJiri Kosina 1073078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, 1074078328daSJiri Kosina struct hid_field *field, struct hid_usage *usage, 1075078328daSJiri Kosina unsigned long **bit, int *max) 1076078328daSJiri Kosina { 1077078328daSJiri Kosina unsigned int key = usage->hid & HID_USAGE; 1078078328daSJiri Kosina 1079078328daSJiri Kosina if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1080078328daSJiri Kosina return -1; 1081078328daSJiri Kosina 1082078328daSJiri Kosina switch (usage->collection_index) { 1083078328daSJiri Kosina case 1: 1084078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) 1085078328daSJiri Kosina return -1; 1086078328daSJiri Kosina 1087078328daSJiri Kosina key = ps3remote_keymap_joypad_buttons[key]; 1088078328daSJiri Kosina if (!key) 1089078328daSJiri Kosina return -1; 1090078328daSJiri Kosina break; 1091078328daSJiri Kosina case 2: 1092078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) 1093078328daSJiri Kosina return -1; 1094078328daSJiri Kosina 1095078328daSJiri Kosina key = ps3remote_keymap_remote_buttons[key]; 1096078328daSJiri Kosina if (!key) 1097078328daSJiri Kosina return -1; 1098078328daSJiri Kosina break; 1099078328daSJiri Kosina default: 1100078328daSJiri Kosina return -1; 1101078328daSJiri Kosina } 1102078328daSJiri Kosina 1103078328daSJiri Kosina hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1104078328daSJiri Kosina return 1; 1105078328daSJiri Kosina } 1106078328daSJiri Kosina 110773e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 110873e4008dSNikolai Kondrashov unsigned int *rsize) 1109cc6e0bbbSJiri Kosina { 1110cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev); 1111cc6e0bbbSJiri Kosina 111299d24902SFernando Luis Vázquez Cao /* 111399d24902SFernando Luis Vázquez Cao * Some Sony RF receivers wrongly declare the mouse pointer as a 111499d24902SFernando Luis Vázquez Cao * a constant non-data variable. 111599d24902SFernando Luis Vázquez Cao */ 111699d24902SFernando Luis Vázquez Cao if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 && 111799d24902SFernando Luis Vázquez Cao /* usage page: generic desktop controls */ 111899d24902SFernando Luis Vázquez Cao /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */ 111999d24902SFernando Luis Vázquez Cao /* usage: mouse */ 112099d24902SFernando Luis Vázquez Cao rdesc[2] == 0x09 && rdesc[3] == 0x02 && 112199d24902SFernando Luis Vázquez Cao /* input (usage page for x,y axes): constant, variable, relative */ 112299d24902SFernando Luis Vázquez Cao rdesc[54] == 0x81 && rdesc[55] == 0x07) { 1123a4649184SFernando Luis Vázquez Cao hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n"); 112499d24902SFernando Luis Vázquez Cao /* input: data, variable, relative */ 1125cc6e0bbbSJiri Kosina rdesc[55] = 0x06; 1126cc6e0bbbSJiri Kosina } 112761ab44beSSimon Wood 1128ed19d8cfSFrank Praznik /* 1129ed19d8cfSFrank Praznik * The default Dualshock 4 USB descriptor doesn't assign 1130ed19d8cfSFrank Praznik * the gyroscope values to corresponding axes so we need a 1131ed19d8cfSFrank Praznik * modified one. 1132ed19d8cfSFrank Praznik */ 1133ed19d8cfSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) { 1134ed19d8cfSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); 1135ed19d8cfSFrank Praznik rdesc = dualshock4_usb_rdesc; 1136ed19d8cfSFrank Praznik *rsize = sizeof(dualshock4_usb_rdesc); 1137d829674dSFrank Praznik } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) { 1138d829674dSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n"); 1139d829674dSFrank Praznik rdesc = dualshock4_bt_rdesc; 1140d829674dSFrank Praznik *rsize = sizeof(dualshock4_bt_rdesc); 1141ed19d8cfSFrank Praznik } 1142ed19d8cfSFrank Praznik 1143c607fb8dSAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER) 1144c607fb8dSAntonio Ospite return sixaxis_fixup(hdev, rdesc, rsize); 1145078328daSJiri Kosina 1146c5e0c1c4SFrank Praznik if (sc->quirks & MOTION_CONTROLLER) 1147c5e0c1c4SFrank Praznik return motion_fixup(hdev, rdesc, rsize); 1148c5e0c1c4SFrank Praznik 11494545ee0aSSimon Wood if (sc->quirks & NAVIGATION_CONTROLLER) 1150*b2723eb7SSimon Wood return navigation_fixup(hdev, rdesc, rsize); 11514545ee0aSSimon Wood 1152078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1153078328daSJiri Kosina return ps3remote_fixup(hdev, rdesc, rsize); 1154078328daSJiri Kosina 115573e4008dSNikolai Kondrashov return rdesc; 1156cc6e0bbbSJiri Kosina } 1157cc6e0bbbSJiri Kosina 1158d902f472SFrank Praznik static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) 1159d902f472SFrank Praznik { 1160d902f472SFrank Praznik static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; 1161d902f472SFrank Praznik unsigned long flags; 116212e9a6d7SSimon Wood int offset; 1163d902f472SFrank Praznik __u8 cable_state, battery_capacity, battery_charging; 1164d902f472SFrank Praznik 1165ad142b9eSFrank Praznik /* 1166ad142b9eSFrank Praznik * The sixaxis is charging if the battery value is 0xee 1167d902f472SFrank Praznik * and it is fully charged if the value is 0xef. 1168d902f472SFrank Praznik * It does not report the actual level while charging so it 1169d902f472SFrank Praznik * is set to 100% while charging is in progress. 1170d902f472SFrank Praznik */ 117112e9a6d7SSimon Wood offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30; 117212e9a6d7SSimon Wood 117312e9a6d7SSimon Wood if (rd[offset] >= 0xee) { 1174d902f472SFrank Praznik battery_capacity = 100; 117512e9a6d7SSimon Wood battery_charging = !(rd[offset] & 0x01); 11769fddd74aSFrank Praznik cable_state = 1; 1177d902f472SFrank Praznik } else { 117812e9a6d7SSimon Wood __u8 index = rd[offset] <= 5 ? rd[offset] : 5; 1179ac3c9a94SFrank Praznik battery_capacity = sixaxis_battery_capacity[index]; 1180d902f472SFrank Praznik battery_charging = 0; 11819fddd74aSFrank Praznik cable_state = 0; 1182d902f472SFrank Praznik } 1183d902f472SFrank Praznik 1184d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1185d902f472SFrank Praznik sc->cable_state = cable_state; 1186d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1187d902f472SFrank Praznik sc->battery_charging = battery_charging; 1188d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1189d902f472SFrank Praznik } 1190d902f472SFrank Praznik 1191d902f472SFrank Praznik static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) 1192d902f472SFrank Praznik { 1193e5606230SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 1194e5606230SFrank Praznik struct hid_input, list); 1195e5606230SFrank Praznik struct input_dev *input_dev = hidinput->input; 1196d902f472SFrank Praznik unsigned long flags; 11976c5f860dSFrank Praznik int n, offset; 1198d902f472SFrank Praznik __u8 cable_state, battery_capacity, battery_charging; 1199d902f472SFrank Praznik 1200ad142b9eSFrank Praznik /* 1201ad142b9eSFrank Praznik * Battery and touchpad data starts at byte 30 in the USB report and 12026c5f860dSFrank Praznik * 32 in Bluetooth report. 12036c5f860dSFrank Praznik */ 12046c5f860dSFrank Praznik offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32; 12056c5f860dSFrank Praznik 1206ad142b9eSFrank Praznik /* 1207ad142b9eSFrank Praznik * The lower 4 bits of byte 30 contain the battery level 1208d902f472SFrank Praznik * and the 5th bit contains the USB cable state. 1209d902f472SFrank Praznik */ 12106c5f860dSFrank Praznik cable_state = (rd[offset] >> 4) & 0x01; 12116c5f860dSFrank Praznik battery_capacity = rd[offset] & 0x0F; 1212d902f472SFrank Praznik 1213ad142b9eSFrank Praznik /* 1214ad142b9eSFrank Praznik * When a USB power source is connected the battery level ranges from 12156c5f860dSFrank Praznik * 0 to 10, and when running on battery power it ranges from 0 to 9. 12166c5f860dSFrank Praznik * A battery level above 10 when plugged in means charge completed. 1217d902f472SFrank Praznik */ 12186c5f860dSFrank Praznik if (!cable_state || battery_capacity > 10) 1219d902f472SFrank Praznik battery_charging = 0; 1220d902f472SFrank Praznik else 1221d902f472SFrank Praznik battery_charging = 1; 1222d902f472SFrank Praznik 12236c5f860dSFrank Praznik if (!cable_state) 12246c5f860dSFrank Praznik battery_capacity++; 1225d902f472SFrank Praznik if (battery_capacity > 10) 12266c5f860dSFrank Praznik battery_capacity = 10; 12276c5f860dSFrank Praznik 1228d902f472SFrank Praznik battery_capacity *= 10; 1229d902f472SFrank Praznik 1230d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1231d902f472SFrank Praznik sc->cable_state = cable_state; 1232d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1233d902f472SFrank Praznik sc->battery_charging = battery_charging; 1234d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1235e5606230SFrank Praznik 12366c5f860dSFrank Praznik offset += 5; 12376c5f860dSFrank Praznik 1238ad142b9eSFrank Praznik /* 1239ad142b9eSFrank Praznik * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB 12406c5f860dSFrank Praznik * and 37 on Bluetooth. 1241e5606230SFrank Praznik * The first 7 bits of the first byte is a counter and bit 8 is a touch 1242e5606230SFrank Praznik * indicator that is 0 when pressed and 1 when not pressed. 1243e5606230SFrank Praznik * The next 3 bytes are two 12 bit touch coordinates, X and Y. 1244e5606230SFrank Praznik * The data for the second touch is in the same format and immediatly 1245e5606230SFrank Praznik * follows the data for the first. 1246e5606230SFrank Praznik */ 1247e5606230SFrank Praznik for (n = 0; n < 2; n++) { 1248e5606230SFrank Praznik __u16 x, y; 1249e5606230SFrank Praznik 1250e5606230SFrank Praznik x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); 1251e5606230SFrank Praznik y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); 1252e5606230SFrank Praznik 1253e5606230SFrank Praznik input_mt_slot(input_dev, n); 1254e5606230SFrank Praznik input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1255e5606230SFrank Praznik !(rd[offset] >> 7)); 1256e5606230SFrank Praznik input_report_abs(input_dev, ABS_MT_POSITION_X, x); 1257e5606230SFrank Praznik input_report_abs(input_dev, ABS_MT_POSITION_Y, y); 1258e5606230SFrank Praznik 1259e5606230SFrank Praznik offset += 4; 1260e5606230SFrank Praznik } 1261d902f472SFrank Praznik } 1262d902f472SFrank Praznik 1263c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, 1264c9e4d877SSimon Wood __u8 *rd, int size) 1265c9e4d877SSimon Wood { 1266c9e4d877SSimon Wood struct sony_sc *sc = hid_get_drvdata(hdev); 1267c9e4d877SSimon Wood 1268ad142b9eSFrank Praznik /* 1269ad142b9eSFrank Praznik * Sixaxis HID report has acclerometers/gyro with MSByte first, this 1270c9e4d877SSimon Wood * has to be BYTE_SWAPPED before passing up to joystick interface 1271c9e4d877SSimon Wood */ 1272fee4e2d5SFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { 1273c9e4d877SSimon Wood swap(rd[41], rd[42]); 1274c9e4d877SSimon Wood swap(rd[43], rd[44]); 1275c9e4d877SSimon Wood swap(rd[45], rd[46]); 1276c9e4d877SSimon Wood swap(rd[47], rd[48]); 1277d902f472SFrank Praznik 1278d902f472SFrank Praznik sixaxis_parse_report(sc, rd, size); 127912e9a6d7SSimon Wood } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { 128012e9a6d7SSimon Wood sixaxis_parse_report(sc, rd, size); 12814545ee0aSSimon Wood } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && 12824545ee0aSSimon Wood size == 49) { 12834545ee0aSSimon Wood sixaxis_parse_report(sc, rd, size); 128468330d83SFrank Praznik } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && 128568330d83SFrank Praznik size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) 128668330d83SFrank Praznik && rd[0] == 0x11 && size == 78)) { 1287d902f472SFrank Praznik dualshock4_parse_report(sc, rd, size); 1288c9e4d877SSimon Wood } 1289c9e4d877SSimon Wood 1290c9e4d877SSimon Wood return 0; 1291c9e4d877SSimon Wood } 1292c9e4d877SSimon Wood 1293f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, 1294f04d5140SColin Leitner struct hid_field *field, struct hid_usage *usage, 1295f04d5140SColin Leitner unsigned long **bit, int *max) 1296f04d5140SColin Leitner { 1297f04d5140SColin Leitner struct sony_sc *sc = hid_get_drvdata(hdev); 1298f04d5140SColin Leitner 1299f04d5140SColin Leitner if (sc->quirks & BUZZ_CONTROLLER) { 1300f04d5140SColin Leitner unsigned int key = usage->hid & HID_USAGE; 1301f04d5140SColin Leitner 1302f04d5140SColin Leitner if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1303f04d5140SColin Leitner return -1; 1304f04d5140SColin Leitner 1305f04d5140SColin Leitner switch (usage->collection_index) { 1306f04d5140SColin Leitner case 1: 1307f04d5140SColin Leitner if (key >= ARRAY_SIZE(buzz_keymap)) 1308f04d5140SColin Leitner return -1; 1309f04d5140SColin Leitner 1310f04d5140SColin Leitner key = buzz_keymap[key]; 1311f04d5140SColin Leitner if (!key) 1312f04d5140SColin Leitner return -1; 1313f04d5140SColin Leitner break; 1314f04d5140SColin Leitner default: 1315f04d5140SColin Leitner return -1; 1316f04d5140SColin Leitner } 1317f04d5140SColin Leitner 1318f04d5140SColin Leitner hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1319f04d5140SColin Leitner return 1; 1320f04d5140SColin Leitner } 1321f04d5140SColin Leitner 1322078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1323078328daSJiri Kosina return ps3remote_mapping(hdev, hi, field, usage, bit, max); 1324078328daSJiri Kosina 13256f498018SBenjamin Tissoires /* Let hid-core decide for the others */ 13266f498018SBenjamin Tissoires return 0; 1327f04d5140SColin Leitner } 1328f04d5140SColin Leitner 1329ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count, 1330ce8efc3bSFrank Praznik int w, int h) 1331ce8efc3bSFrank Praznik { 1332ce8efc3bSFrank Praznik struct input_dev *input_dev = hi->input; 1333ce8efc3bSFrank Praznik int ret; 1334ce8efc3bSFrank Praznik 1335ce8efc3bSFrank Praznik ret = input_mt_init_slots(input_dev, touch_count, 0); 1336ce8efc3bSFrank Praznik if (ret < 0) 1337ce8efc3bSFrank Praznik return ret; 1338ce8efc3bSFrank Praznik 1339ce8efc3bSFrank Praznik input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0); 1340ce8efc3bSFrank Praznik input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0); 1341ce8efc3bSFrank Praznik 1342ce8efc3bSFrank Praznik return 0; 1343ce8efc3bSFrank Praznik } 1344ce8efc3bSFrank Praznik 1345ce8efc3bSFrank Praznik static void sony_input_configured(struct hid_device *hdev, 1346ce8efc3bSFrank Praznik struct hid_input *hidinput) 1347ce8efc3bSFrank Praznik { 1348ce8efc3bSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev); 1349ce8efc3bSFrank Praznik 1350ce8efc3bSFrank Praznik /* 1351ce8efc3bSFrank Praznik * The Dualshock 4 touchpad supports 2 touches and has a 1352981c5b4aSFrank Praznik * resolution of 1920x942 (44.86 dots/mm). 1353ce8efc3bSFrank Praznik */ 1354ce8efc3bSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1355981c5b4aSFrank Praznik if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0) 1356ce8efc3bSFrank Praznik hid_err(sc->hdev, 1357ce8efc3bSFrank Praznik "Unable to initialize multi-touch slots\n"); 1358ce8efc3bSFrank Praznik } 1359ce8efc3bSFrank Praznik } 1360ce8efc3bSFrank Praznik 13615710fabfSAntonio Ospite /* 1362bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 1363bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any 1364bd28ce00SJiri Slaby * events. 1365bd28ce00SJiri Slaby */ 1366816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev) 1367bd28ce00SJiri Slaby { 1368a85d67b5SAntonio Ospite const int buf_size = 1369a85d67b5SAntonio Ospite max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); 13702e701a35SAntonio Ospite __u8 *buf; 1371bd28ce00SJiri Slaby int ret; 1372bd28ce00SJiri Slaby 13732e701a35SAntonio Ospite buf = kmalloc(buf_size, GFP_KERNEL); 1374bd28ce00SJiri Slaby if (!buf) 1375bd28ce00SJiri Slaby return -ENOMEM; 1376bd28ce00SJiri Slaby 1377a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE, 1378a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1379a7de9b86SLauri Kasanen if (ret < 0) { 1380a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 1\n"); 1381a7de9b86SLauri Kasanen goto out; 1382a7de9b86SLauri Kasanen } 1383f204828aSBenjamin Tissoires 1384a7de9b86SLauri Kasanen /* 1385a7de9b86SLauri Kasanen * Some compatible controllers like the Speedlink Strike FX and 1386a7de9b86SLauri Kasanen * Gasia need another query plus an USB interrupt to get operational. 1387a7de9b86SLauri Kasanen */ 1388a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE, 1389a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1390a7de9b86SLauri Kasanen if (ret < 0) { 1391a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 2\n"); 1392a7de9b86SLauri Kasanen goto out; 1393a7de9b86SLauri Kasanen } 1394a7de9b86SLauri Kasanen 1395a7de9b86SLauri Kasanen ret = hid_hw_output_report(hdev, buf, 1); 1396bd28ce00SJiri Slaby if (ret < 0) 1397a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 3\n"); 1398bd28ce00SJiri Slaby 1399a7de9b86SLauri Kasanen out: 1400bd28ce00SJiri Slaby kfree(buf); 1401bd28ce00SJiri Slaby 1402bd28ce00SJiri Slaby return ret; 1403bd28ce00SJiri Slaby } 1404bd28ce00SJiri Slaby 1405816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev) 1406f9ce7c28SBastien Nocera { 14079b2b5c9aSFrank Praznik static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 14089b2b5c9aSFrank Praznik __u8 *buf; 14099b2b5c9aSFrank Praznik int ret; 14109b2b5c9aSFrank Praznik 14119b2b5c9aSFrank Praznik buf = kmemdup(report, sizeof(report), GFP_KERNEL); 14129b2b5c9aSFrank Praznik if (!buf) 14139b2b5c9aSFrank Praznik return -ENOMEM; 14149b2b5c9aSFrank Praznik 14159b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), 1416b0dd72aaSBenjamin Tissoires HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 14179b2b5c9aSFrank Praznik 14189b2b5c9aSFrank Praznik kfree(buf); 14199b2b5c9aSFrank Praznik 14209b2b5c9aSFrank Praznik return ret; 1421f9ce7c28SBastien Nocera } 1422f9ce7c28SBastien Nocera 1423ad142b9eSFrank Praznik /* 1424ad142b9eSFrank Praznik * Requesting feature report 0x02 in Bluetooth mode changes the state of the 142568330d83SFrank Praznik * controller so that it sends full input reports of type 0x11. 142668330d83SFrank Praznik */ 142768330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev) 142868330d83SFrank Praznik { 14299b2b5c9aSFrank Praznik __u8 *buf; 14309b2b5c9aSFrank Praznik int ret; 143168330d83SFrank Praznik 14329b2b5c9aSFrank Praznik buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); 14339b2b5c9aSFrank Praznik if (!buf) 14349b2b5c9aSFrank Praznik return -ENOMEM; 14359b2b5c9aSFrank Praznik 14369b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, 143768330d83SFrank Praznik HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 14389b2b5c9aSFrank Praznik 14399b2b5c9aSFrank Praznik kfree(buf); 14409b2b5c9aSFrank Praznik 14419b2b5c9aSFrank Praznik return ret; 1442bd28ce00SJiri Slaby } 1443bd28ce00SJiri Slaby 1444221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc) 14458025087aSFrank Praznik { 14468025087aSFrank Praznik static const __u8 sixaxis_leds[10][4] = { 14478025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x00 }, 14488025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x00 }, 14498025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x00 }, 14508025087aSFrank Praznik { 0x00, 0x00, 0x00, 0x01 }, 14518025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x01 }, 14528025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x01 }, 14538025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x01 }, 14548025087aSFrank Praznik { 0x01, 0x00, 0x01, 0x01 }, 14558025087aSFrank Praznik { 0x00, 0x01, 0x01, 0x01 }, 14568025087aSFrank Praznik { 0x01, 0x01, 0x01, 0x01 } 14578025087aSFrank Praznik }; 14588025087aSFrank Praznik 1459221399b3SFrank Praznik int id = sc->device_id; 1460221399b3SFrank Praznik 1461221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); 14628025087aSFrank Praznik 14638025087aSFrank Praznik if (id < 0) 14648025087aSFrank Praznik return; 14658025087aSFrank Praznik 14668025087aSFrank Praznik id %= 10; 1467221399b3SFrank Praznik memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id])); 14688025087aSFrank Praznik } 14698025087aSFrank Praznik 1470221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc) 14718025087aSFrank Praznik { 14728025087aSFrank Praznik /* The first 4 color/index entries match what the PS4 assigns */ 14738025087aSFrank Praznik static const __u8 color_code[7][3] = { 14748025087aSFrank Praznik /* Blue */ { 0x00, 0x00, 0x01 }, 14758025087aSFrank Praznik /* Red */ { 0x01, 0x00, 0x00 }, 14768025087aSFrank Praznik /* Green */ { 0x00, 0x01, 0x00 }, 14778025087aSFrank Praznik /* Pink */ { 0x02, 0x00, 0x01 }, 14788025087aSFrank Praznik /* Orange */ { 0x02, 0x01, 0x00 }, 14798025087aSFrank Praznik /* Teal */ { 0x00, 0x01, 0x01 }, 14808025087aSFrank Praznik /* White */ { 0x01, 0x01, 0x01 } 14818025087aSFrank Praznik }; 14828025087aSFrank Praznik 1483221399b3SFrank Praznik int id = sc->device_id; 1484221399b3SFrank Praznik 1485221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); 14868025087aSFrank Praznik 14878025087aSFrank Praznik if (id < 0) 14888025087aSFrank Praznik return; 14898025087aSFrank Praznik 14908025087aSFrank Praznik id %= 7; 1491221399b3SFrank Praznik memcpy(sc->led_state, color_code[id], sizeof(color_code[id])); 14928025087aSFrank Praznik } 14938025087aSFrank Praznik 1494221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc) 1495f04d5140SColin Leitner { 1496221399b3SFrank Praznik struct hid_device *hdev = sc->hdev; 1497f04d5140SColin Leitner struct list_head *report_list = 1498f04d5140SColin Leitner &hdev->report_enum[HID_OUTPUT_REPORT].report_list; 1499f04d5140SColin Leitner struct hid_report *report = list_entry(report_list->next, 1500f04d5140SColin Leitner struct hid_report, list); 1501f04d5140SColin Leitner __s32 *value = report->field[0]->value; 1502f04d5140SColin Leitner 1503221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < 4); 1504221399b3SFrank Praznik 1505f04d5140SColin Leitner value[0] = 0x00; 1506221399b3SFrank Praznik value[1] = sc->led_state[0] ? 0xff : 0x00; 1507221399b3SFrank Praznik value[2] = sc->led_state[1] ? 0xff : 0x00; 1508221399b3SFrank Praznik value[3] = sc->led_state[2] ? 0xff : 0x00; 1509221399b3SFrank Praznik value[4] = sc->led_state[3] ? 0xff : 0x00; 1510f04d5140SColin Leitner value[5] = 0x00; 1511f04d5140SColin Leitner value[6] = 0x00; 1512f04d5140SColin Leitner hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 1513f04d5140SColin Leitner } 1514f04d5140SColin Leitner 1515221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc) 15160a286ef2SSven Eckelmann { 1517221399b3SFrank Praznik if (!(sc->quirks & BUZZ_CONTROLLER)) 1518fa57a810SFrank Praznik schedule_work(&sc->state_worker); 1519221399b3SFrank Praznik else 1520221399b3SFrank Praznik buzz_set_leds(sc); 15210a286ef2SSven Eckelmann } 15220a286ef2SSven Eckelmann 1523c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led, 1524f04d5140SColin Leitner enum led_brightness value) 1525f04d5140SColin Leitner { 1526f04d5140SColin Leitner struct device *dev = led->dev->parent; 1527f04d5140SColin Leitner struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1528f04d5140SColin Leitner struct sony_sc *drv_data; 1529f04d5140SColin Leitner 1530f04d5140SColin Leitner int n; 1531b3ed458cSFrank Praznik int force_update; 1532f04d5140SColin Leitner 1533f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 15342251b85fSSven Eckelmann if (!drv_data) { 1535f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1536f04d5140SColin Leitner return; 1537f04d5140SColin Leitner } 1538f04d5140SColin Leitner 1539b3ed458cSFrank Praznik /* 1540b3ed458cSFrank Praznik * The Sixaxis on USB will override any LED settings sent to it 1541b3ed458cSFrank Praznik * and keep flashing all of the LEDs until the PS button is pressed. 1542b3ed458cSFrank Praznik * Updates, even if redundant, must be always be sent to the 1543b3ed458cSFrank Praznik * controller to avoid having to toggle the state of an LED just to 1544b3ed458cSFrank Praznik * stop the flashing later on. 1545b3ed458cSFrank Praznik */ 1546b3ed458cSFrank Praznik force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB); 1547b3ed458cSFrank Praznik 154860781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1549b3ed458cSFrank Praznik if (led == drv_data->leds[n] && (force_update || 1550b3ed458cSFrank Praznik (value != drv_data->led_state[n] || 1551b3ed458cSFrank Praznik drv_data->led_delay_on[n] || 1552b3ed458cSFrank Praznik drv_data->led_delay_off[n]))) { 1553b3ed458cSFrank Praznik 155460781cf4SFrank Praznik drv_data->led_state[n] = value; 1555b3ed458cSFrank Praznik 1556b3ed458cSFrank Praznik /* Setting the brightness stops the blinking */ 1557b3ed458cSFrank Praznik drv_data->led_delay_on[n] = 0; 1558b3ed458cSFrank Praznik drv_data->led_delay_off[n] = 0; 1559b3ed458cSFrank Praznik 1560221399b3SFrank Praznik sony_set_leds(drv_data); 1561f04d5140SColin Leitner break; 1562f04d5140SColin Leitner } 1563f04d5140SColin Leitner } 1564f04d5140SColin Leitner } 1565f04d5140SColin Leitner 1566c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led) 1567f04d5140SColin Leitner { 1568f04d5140SColin Leitner struct device *dev = led->dev->parent; 1569f04d5140SColin Leitner struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1570f04d5140SColin Leitner struct sony_sc *drv_data; 1571f04d5140SColin Leitner 1572f04d5140SColin Leitner int n; 1573f04d5140SColin Leitner 1574f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 15752251b85fSSven Eckelmann if (!drv_data) { 1576f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1577f04d5140SColin Leitner return LED_OFF; 1578f04d5140SColin Leitner } 1579f04d5140SColin Leitner 158060781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 15817db7504aSSimon Wood if (led == drv_data->leds[n]) 15827db7504aSSimon Wood return drv_data->led_state[n]; 1583f04d5140SColin Leitner } 1584f04d5140SColin Leitner 15857db7504aSSimon Wood return LED_OFF; 1586f04d5140SColin Leitner } 1587f04d5140SColin Leitner 1588b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, 1589b3ed458cSFrank Praznik unsigned long *delay_off) 1590b3ed458cSFrank Praznik { 1591b3ed458cSFrank Praznik struct device *dev = led->dev->parent; 1592b3ed458cSFrank Praznik struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1593b3ed458cSFrank Praznik struct sony_sc *drv_data = hid_get_drvdata(hdev); 1594b3ed458cSFrank Praznik int n; 1595b3ed458cSFrank Praznik __u8 new_on, new_off; 1596b3ed458cSFrank Praznik 1597b3ed458cSFrank Praznik if (!drv_data) { 1598b3ed458cSFrank Praznik hid_err(hdev, "No device data\n"); 1599b3ed458cSFrank Praznik return -EINVAL; 1600b3ed458cSFrank Praznik } 1601b3ed458cSFrank Praznik 1602b3ed458cSFrank Praznik /* Max delay is 255 deciseconds or 2550 milliseconds */ 1603b3ed458cSFrank Praznik if (*delay_on > 2550) 1604b3ed458cSFrank Praznik *delay_on = 2550; 1605b3ed458cSFrank Praznik if (*delay_off > 2550) 1606b3ed458cSFrank Praznik *delay_off = 2550; 1607b3ed458cSFrank Praznik 1608b3ed458cSFrank Praznik /* Blink at 1 Hz if both values are zero */ 1609b3ed458cSFrank Praznik if (!*delay_on && !*delay_off) 1610b3ed458cSFrank Praznik *delay_on = *delay_off = 500; 1611b3ed458cSFrank Praznik 1612b3ed458cSFrank Praznik new_on = *delay_on / 10; 1613b3ed458cSFrank Praznik new_off = *delay_off / 10; 1614b3ed458cSFrank Praznik 1615b3ed458cSFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1616b3ed458cSFrank Praznik if (led == drv_data->leds[n]) 1617b3ed458cSFrank Praznik break; 1618b3ed458cSFrank Praznik } 1619b3ed458cSFrank Praznik 1620b3ed458cSFrank Praznik /* This LED is not registered on this device */ 1621b3ed458cSFrank Praznik if (n >= drv_data->led_count) 1622b3ed458cSFrank Praznik return -EINVAL; 1623b3ed458cSFrank Praznik 1624b3ed458cSFrank Praznik /* Don't schedule work if the values didn't change */ 1625b3ed458cSFrank Praznik if (new_on != drv_data->led_delay_on[n] || 1626b3ed458cSFrank Praznik new_off != drv_data->led_delay_off[n]) { 1627b3ed458cSFrank Praznik drv_data->led_delay_on[n] = new_on; 1628b3ed458cSFrank Praznik drv_data->led_delay_off[n] = new_off; 1629b3ed458cSFrank Praznik schedule_work(&drv_data->state_worker); 1630b3ed458cSFrank Praznik } 1631b3ed458cSFrank Praznik 1632b3ed458cSFrank Praznik return 0; 1633b3ed458cSFrank Praznik } 1634b3ed458cSFrank Praznik 1635fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc) 16360a286ef2SSven Eckelmann { 16370a286ef2SSven Eckelmann struct led_classdev *led; 16380a286ef2SSven Eckelmann int n; 16390a286ef2SSven Eckelmann 1640fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 16410a286ef2SSven Eckelmann 1642fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 1643fa57a810SFrank Praznik led = sc->leds[n]; 1644fa57a810SFrank Praznik sc->leds[n] = NULL; 16450a286ef2SSven Eckelmann if (!led) 16460a286ef2SSven Eckelmann continue; 16470a286ef2SSven Eckelmann led_classdev_unregister(led); 16480a286ef2SSven Eckelmann kfree(led); 16490a286ef2SSven Eckelmann } 165060781cf4SFrank Praznik 1651fa57a810SFrank Praznik sc->led_count = 0; 16520a286ef2SSven Eckelmann } 16530a286ef2SSven Eckelmann 1654fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc) 1655f04d5140SColin Leitner { 1656fa57a810SFrank Praznik struct hid_device *hdev = sc->hdev; 165740e32ee6SJiri Kosina int n, ret = 0; 1658b3ed458cSFrank Praznik int use_ds4_names; 165940e32ee6SJiri Kosina struct led_classdev *led; 166040e32ee6SJiri Kosina size_t name_sz; 166140e32ee6SJiri Kosina char *name; 16620a286ef2SSven Eckelmann size_t name_len; 16630a286ef2SSven Eckelmann const char *name_fmt; 1664b3ed458cSFrank Praznik static const char * const ds4_name_str[] = { "red", "green", "blue", 1665b3ed458cSFrank Praznik "global" }; 16665607c89aSFrank Praznik __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; 1667b3ed458cSFrank Praznik __u8 use_hw_blink[MAX_LEDS] = { 0 }; 1668f04d5140SColin Leitner 1669fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 1670f04d5140SColin Leitner 1671fa57a810SFrank Praznik if (sc->quirks & BUZZ_CONTROLLER) { 1672fa57a810SFrank Praznik sc->led_count = 4; 1673b3ed458cSFrank Praznik use_ds4_names = 0; 16740a286ef2SSven Eckelmann name_len = strlen("::buzz#"); 16750a286ef2SSven Eckelmann name_fmt = "%s::buzz%d"; 16769446edb9SKees Cook /* Validate expected report characteristics. */ 16779446edb9SKees Cook if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) 16789446edb9SKees Cook return -ENODEV; 1679fa57a810SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1680221399b3SFrank Praznik dualshock4_set_leds_from_id(sc); 1681221399b3SFrank Praznik sc->led_state[3] = 1; 1682b3ed458cSFrank Praznik sc->led_count = 4; 1683b3ed458cSFrank Praznik memset(max_brightness, 255, 3); 1684b3ed458cSFrank Praznik use_hw_blink[3] = 1; 1685b3ed458cSFrank Praznik use_ds4_names = 1; 168661ebca93SFrank Praznik name_len = 0; 168761ebca93SFrank Praznik name_fmt = "%s:%s"; 1688c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 1689c5e0c1c4SFrank Praznik sc->led_count = 3; 1690c5e0c1c4SFrank Praznik memset(max_brightness, 255, 3); 1691c5e0c1c4SFrank Praznik use_ds4_names = 1; 1692c5e0c1c4SFrank Praznik name_len = 0; 1693c5e0c1c4SFrank Praznik name_fmt = "%s:%s"; 16944545ee0aSSimon Wood } else if (sc->quirks & NAVIGATION_CONTROLLER) { 16954545ee0aSSimon Wood static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; 16964545ee0aSSimon Wood 16974545ee0aSSimon Wood memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds)); 16984545ee0aSSimon Wood sc->led_count = 1; 16994545ee0aSSimon Wood memset(use_hw_blink, 1, 4); 17004545ee0aSSimon Wood use_ds4_names = 0; 17014545ee0aSSimon Wood name_len = strlen("::sony#"); 17024545ee0aSSimon Wood name_fmt = "%s::sony%d"; 170360781cf4SFrank Praznik } else { 1704221399b3SFrank Praznik sixaxis_set_leds_from_id(sc); 1705fa57a810SFrank Praznik sc->led_count = 4; 1706b3ed458cSFrank Praznik memset(use_hw_blink, 1, 4); 1707b3ed458cSFrank Praznik use_ds4_names = 0; 170861ebca93SFrank Praznik name_len = strlen("::sony#"); 170961ebca93SFrank Praznik name_fmt = "%s::sony%d"; 171060781cf4SFrank Praznik } 171160781cf4SFrank Praznik 1712ad142b9eSFrank Praznik /* 1713ad142b9eSFrank Praznik * Clear LEDs as we have no way of reading their initial state. This is 1714f04d5140SColin Leitner * only relevant if the driver is loaded after somebody actively set the 1715ad142b9eSFrank Praznik * LEDs to on 1716ad142b9eSFrank Praznik */ 1717221399b3SFrank Praznik sony_set_leds(sc); 1718f04d5140SColin Leitner 17190a286ef2SSven Eckelmann name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; 1720f04d5140SColin Leitner 1721fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 172261ebca93SFrank Praznik 1723b3ed458cSFrank Praznik if (use_ds4_names) 1724b3ed458cSFrank Praznik name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2; 172561ebca93SFrank Praznik 1726f04d5140SColin Leitner led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); 1727f04d5140SColin Leitner if (!led) { 1728f04d5140SColin Leitner hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); 17298cd5fcdaSJulia Lawall ret = -ENOMEM; 1730f04d5140SColin Leitner goto error_leds; 1731f04d5140SColin Leitner } 1732f04d5140SColin Leitner 1733f04d5140SColin Leitner name = (void *)(&led[1]); 1734b3ed458cSFrank Praznik if (use_ds4_names) 1735b3ed458cSFrank Praznik snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), 1736b3ed458cSFrank Praznik ds4_name_str[n]); 173761ebca93SFrank Praznik else 17380a286ef2SSven Eckelmann snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); 1739f04d5140SColin Leitner led->name = name; 1740221399b3SFrank Praznik led->brightness = sc->led_state[n]; 1741b3ed458cSFrank Praznik led->max_brightness = max_brightness[n]; 1742c5382519SSven Eckelmann led->brightness_get = sony_led_get_brightness; 1743c5382519SSven Eckelmann led->brightness_set = sony_led_set_brightness; 1744f04d5140SColin Leitner 1745b3ed458cSFrank Praznik if (use_hw_blink[n]) 1746b3ed458cSFrank Praznik led->blink_set = sony_led_blink_set; 1747b3ed458cSFrank Praznik 17488025087aSFrank Praznik sc->leds[n] = led; 17498025087aSFrank Praznik 17508cd5fcdaSJulia Lawall ret = led_classdev_register(&hdev->dev, led); 17518cd5fcdaSJulia Lawall if (ret) { 1752f04d5140SColin Leitner hid_err(hdev, "Failed to register LED %d\n", n); 17538025087aSFrank Praznik sc->leds[n] = NULL; 1754f04d5140SColin Leitner kfree(led); 1755f04d5140SColin Leitner goto error_leds; 1756f04d5140SColin Leitner } 1757f04d5140SColin Leitner } 1758f04d5140SColin Leitner 1759f04d5140SColin Leitner return ret; 1760f04d5140SColin Leitner 1761f04d5140SColin Leitner error_leds: 1762fa57a810SFrank Praznik sony_leds_remove(sc); 1763f04d5140SColin Leitner 1764f04d5140SColin Leitner return ret; 1765f04d5140SColin Leitner } 1766f04d5140SColin Leitner 1767cad665a2SFrank Praznik static void sixaxis_state_worker(struct work_struct *work) 1768a08c22c0SSven Eckelmann { 17699b2b5c9aSFrank Praznik static const union sixaxis_output_report_01 default_report = { 177055d3b664SFrank Praznik .buf = { 1771a08c22c0SSven Eckelmann 0x01, 1772a08c22c0SSven Eckelmann 0x00, 0xff, 0x00, 0xff, 0x00, 17730a286ef2SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00, 1774a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1775a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1776a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1777a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1778a08c22c0SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00 177955d3b664SFrank Praznik } 1780a08c22c0SSven Eckelmann }; 17819b2b5c9aSFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 17829b2b5c9aSFrank Praznik struct sixaxis_output_report *report = 17839b2b5c9aSFrank Praznik (struct sixaxis_output_report *)sc->output_report_dmabuf; 17849b2b5c9aSFrank Praznik int n; 17859b2b5c9aSFrank Praznik 17869b2b5c9aSFrank Praznik /* Initialize the report with default values */ 17879b2b5c9aSFrank Praznik memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); 17889f323b68SSven Eckelmann 17890a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 17909b2b5c9aSFrank Praznik report->rumble.right_motor_on = sc->right ? 1 : 0; 17919b2b5c9aSFrank Praznik report->rumble.left_motor_force = sc->left; 17920a286ef2SSven Eckelmann #endif 17930a286ef2SSven Eckelmann 17949b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[0] << 1; 17959b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[1] << 2; 17969b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[2] << 3; 17979b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[3] << 4; 17989f323b68SSven Eckelmann 179988f6576fSSimon Wood /* Set flag for all leds off, required for 3rd party INTEC controller */ 18009b2b5c9aSFrank Praznik if ((report->leds_bitmap & 0x1E) == 0) 18019b2b5c9aSFrank Praznik report->leds_bitmap |= 0x20; 180288f6576fSSimon Wood 1803b3ed458cSFrank Praznik /* 1804b3ed458cSFrank Praznik * The LEDs in the report are indexed in reverse order to their 1805b3ed458cSFrank Praznik * corresponding light on the controller. 1806b3ed458cSFrank Praznik * Index 0 = LED 4, index 1 = LED 3, etc... 1807b3ed458cSFrank Praznik * 1808b3ed458cSFrank Praznik * In the case of both delay values being zero (blinking disabled) the 1809b3ed458cSFrank Praznik * default report values should be used or the controller LED will be 1810b3ed458cSFrank Praznik * always off. 1811b3ed458cSFrank Praznik */ 1812b3ed458cSFrank Praznik for (n = 0; n < 4; n++) { 1813b3ed458cSFrank Praznik if (sc->led_delay_on[n] || sc->led_delay_off[n]) { 18149b2b5c9aSFrank Praznik report->led[3 - n].duty_off = sc->led_delay_off[n]; 18159b2b5c9aSFrank Praznik report->led[3 - n].duty_on = sc->led_delay_on[n]; 1816b3ed458cSFrank Praznik } 1817b3ed458cSFrank Praznik } 1818b3ed458cSFrank Praznik 18199b2b5c9aSFrank Praznik hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, 18209b2b5c9aSFrank Praznik sizeof(struct sixaxis_output_report), 18219b2b5c9aSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 18229f323b68SSven Eckelmann } 18239f323b68SSven Eckelmann 18240bd88dd3SFrank Praznik static void dualshock4_state_worker(struct work_struct *work) 18250bd88dd3SFrank Praznik { 18260bd88dd3SFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 18270da8ea65SFrank Praznik struct hid_device *hdev = sc->hdev; 18289b2b5c9aSFrank Praznik __u8 *buf = sc->output_report_dmabuf; 182948220237SFrank Praznik int offset; 18300da8ea65SFrank Praznik 1831fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 18329b2b5c9aSFrank Praznik memset(buf, 0, DS4_REPORT_0x05_SIZE); 183348220237SFrank Praznik buf[0] = 0x05; 1834b3ed458cSFrank Praznik buf[1] = 0xFF; 183548220237SFrank Praznik offset = 4; 1836fdcf105dSFrank Praznik } else { 18379b2b5c9aSFrank Praznik memset(buf, 0, DS4_REPORT_0x11_SIZE); 1838fdcf105dSFrank Praznik buf[0] = 0x11; 1839fdcf105dSFrank Praznik buf[1] = 0xB0; 1840fdcf105dSFrank Praznik buf[3] = 0x0F; 1841fdcf105dSFrank Praznik offset = 6; 1842fdcf105dSFrank Praznik } 18430bd88dd3SFrank Praznik 18440bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF 184548220237SFrank Praznik buf[offset++] = sc->right; 184648220237SFrank Praznik buf[offset++] = sc->left; 184748220237SFrank Praznik #else 184848220237SFrank Praznik offset += 2; 18490bd88dd3SFrank Praznik #endif 18500bd88dd3SFrank Praznik 1851b3ed458cSFrank Praznik /* LED 3 is the global control */ 1852b3ed458cSFrank Praznik if (sc->led_state[3]) { 185348220237SFrank Praznik buf[offset++] = sc->led_state[0]; 185448220237SFrank Praznik buf[offset++] = sc->led_state[1]; 185548220237SFrank Praznik buf[offset++] = sc->led_state[2]; 1856b3ed458cSFrank Praznik } else { 1857b3ed458cSFrank Praznik offset += 3; 1858b3ed458cSFrank Praznik } 1859b3ed458cSFrank Praznik 1860b3ed458cSFrank Praznik /* If both delay values are zero the DualShock 4 disables blinking. */ 1861b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_on[3]; 1862b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_off[3]; 186360781cf4SFrank Praznik 1864fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 18659b2b5c9aSFrank Praznik hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); 1866fdcf105dSFrank Praznik else 18679b2b5c9aSFrank Praznik hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, 1868fdcf105dSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 18690bd88dd3SFrank Praznik } 18700bd88dd3SFrank Praznik 1871c5e0c1c4SFrank Praznik static void motion_state_worker(struct work_struct *work) 1872c5e0c1c4SFrank Praznik { 1873c5e0c1c4SFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 1874c5e0c1c4SFrank Praznik struct hid_device *hdev = sc->hdev; 1875c5e0c1c4SFrank Praznik struct motion_output_report_02 *report = 1876c5e0c1c4SFrank Praznik (struct motion_output_report_02 *)sc->output_report_dmabuf; 1877c5e0c1c4SFrank Praznik 187841d2d425SSimon Wood memset(report, 0, MOTION_REPORT_0x02_SIZE); 1879c5e0c1c4SFrank Praznik 1880c5e0c1c4SFrank Praznik report->type = 0x02; /* set leds */ 1881c5e0c1c4SFrank Praznik report->r = sc->led_state[0]; 1882c5e0c1c4SFrank Praznik report->g = sc->led_state[1]; 1883c5e0c1c4SFrank Praznik report->b = sc->led_state[2]; 1884c5e0c1c4SFrank Praznik 1885c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF 1886c5e0c1c4SFrank Praznik report->rumble = max(sc->right, sc->left); 1887c5e0c1c4SFrank Praznik #endif 1888c5e0c1c4SFrank Praznik 188941d2d425SSimon Wood hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); 1890c5e0c1c4SFrank Praznik } 1891c5e0c1c4SFrank Praznik 18929b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc) 18939b2b5c9aSFrank Praznik { 18944545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER) || 18954545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER)) 18969b2b5c9aSFrank Praznik sc->output_report_dmabuf = 18979b2b5c9aSFrank Praznik kmalloc(sizeof(union sixaxis_output_report_01), 18989b2b5c9aSFrank Praznik GFP_KERNEL); 18999b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) 19009b2b5c9aSFrank Praznik sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, 19019b2b5c9aSFrank Praznik GFP_KERNEL); 19029b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 19039b2b5c9aSFrank Praznik sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, 19049b2b5c9aSFrank Praznik GFP_KERNEL); 1905c5e0c1c4SFrank Praznik else if (sc->quirks & MOTION_CONTROLLER) 190641d2d425SSimon Wood sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, 1907c5e0c1c4SFrank Praznik GFP_KERNEL); 19089b2b5c9aSFrank Praznik else 19099b2b5c9aSFrank Praznik return 0; 19109b2b5c9aSFrank Praznik 19119b2b5c9aSFrank Praznik if (!sc->output_report_dmabuf) 19129b2b5c9aSFrank Praznik return -ENOMEM; 19139b2b5c9aSFrank Praznik 19149b2b5c9aSFrank Praznik return 0; 19159b2b5c9aSFrank Praznik } 19169b2b5c9aSFrank Praznik 19170a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 19189f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data, 19199f323b68SSven Eckelmann struct ff_effect *effect) 19209f323b68SSven Eckelmann { 1921a08c22c0SSven Eckelmann struct hid_device *hid = input_get_drvdata(dev); 19229f323b68SSven Eckelmann struct sony_sc *sc = hid_get_drvdata(hid); 1923a08c22c0SSven Eckelmann 1924a08c22c0SSven Eckelmann if (effect->type != FF_RUMBLE) 1925a08c22c0SSven Eckelmann return 0; 1926a08c22c0SSven Eckelmann 19279f323b68SSven Eckelmann sc->left = effect->u.rumble.strong_magnitude / 256; 19280bd88dd3SFrank Praznik sc->right = effect->u.rumble.weak_magnitude / 256; 1929a08c22c0SSven Eckelmann 193092b5c411SSven Eckelmann schedule_work(&sc->state_worker); 19319f323b68SSven Eckelmann return 0; 1932a08c22c0SSven Eckelmann } 1933a08c22c0SSven Eckelmann 1934fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 1935a08c22c0SSven Eckelmann { 1936fa57a810SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 1937a08c22c0SSven Eckelmann struct hid_input, list); 1938a08c22c0SSven Eckelmann struct input_dev *input_dev = hidinput->input; 1939a08c22c0SSven Eckelmann 1940a08c22c0SSven Eckelmann input_set_capability(input_dev, EV_FF, FF_RUMBLE); 1941a08c22c0SSven Eckelmann return input_ff_create_memless(input_dev, NULL, sony_play_effect); 1942a08c22c0SSven Eckelmann } 1943a08c22c0SSven Eckelmann 1944a08c22c0SSven Eckelmann #else 1945fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 1946a08c22c0SSven Eckelmann { 1947a08c22c0SSven Eckelmann return 0; 1948a08c22c0SSven Eckelmann } 19499f323b68SSven Eckelmann 1950a08c22c0SSven Eckelmann #endif 1951a08c22c0SSven Eckelmann 1952d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy, 1953d902f472SFrank Praznik enum power_supply_property psp, 1954d902f472SFrank Praznik union power_supply_propval *val) 1955c4e1ddf2SFrank Praznik { 1956297d716fSKrzysztof Kozlowski struct sony_sc *sc = power_supply_get_drvdata(psy); 1957d902f472SFrank Praznik unsigned long flags; 1958d902f472SFrank Praznik int ret = 0; 1959d902f472SFrank Praznik u8 battery_charging, battery_capacity, cable_state; 1960c4e1ddf2SFrank Praznik 1961d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1962d902f472SFrank Praznik battery_charging = sc->battery_charging; 1963d902f472SFrank Praznik battery_capacity = sc->battery_capacity; 1964d902f472SFrank Praznik cable_state = sc->cable_state; 1965d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1966c4e1ddf2SFrank Praznik 1967d902f472SFrank Praznik switch (psp) { 1968d902f472SFrank Praznik case POWER_SUPPLY_PROP_PRESENT: 1969d902f472SFrank Praznik val->intval = 1; 1970d902f472SFrank Praznik break; 1971d902f472SFrank Praznik case POWER_SUPPLY_PROP_SCOPE: 1972d902f472SFrank Praznik val->intval = POWER_SUPPLY_SCOPE_DEVICE; 1973d902f472SFrank Praznik break; 1974d902f472SFrank Praznik case POWER_SUPPLY_PROP_CAPACITY: 1975d902f472SFrank Praznik val->intval = battery_capacity; 1976d902f472SFrank Praznik break; 1977d902f472SFrank Praznik case POWER_SUPPLY_PROP_STATUS: 1978d902f472SFrank Praznik if (battery_charging) 1979d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_CHARGING; 1980d902f472SFrank Praznik else 1981d902f472SFrank Praznik if (battery_capacity == 100 && cable_state) 1982d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_FULL; 1983d902f472SFrank Praznik else 1984d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 1985d902f472SFrank Praznik break; 1986d902f472SFrank Praznik default: 1987d902f472SFrank Praznik ret = -EINVAL; 1988d902f472SFrank Praznik break; 1989c4e1ddf2SFrank Praznik } 1990d902f472SFrank Praznik return ret; 1991d902f472SFrank Praznik } 1992d902f472SFrank Praznik 1993d902f472SFrank Praznik static int sony_battery_probe(struct sony_sc *sc) 1994d902f472SFrank Praznik { 1995297d716fSKrzysztof Kozlowski struct power_supply_config psy_cfg = { .drv_data = sc, }; 1996d902f472SFrank Praznik struct hid_device *hdev = sc->hdev; 1997d902f472SFrank Praznik int ret; 1998d902f472SFrank Praznik 1999ad142b9eSFrank Praznik /* 2000ad142b9eSFrank Praznik * Set the default battery level to 100% to avoid low battery warnings 2001d9a293a9SFrank Praznik * if the battery is polled before the first device report is received. 2002d9a293a9SFrank Praznik */ 2003d9a293a9SFrank Praznik sc->battery_capacity = 100; 2004d9a293a9SFrank Praznik 2005297d716fSKrzysztof Kozlowski sc->battery_desc.properties = sony_battery_props; 2006297d716fSKrzysztof Kozlowski sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props); 2007297d716fSKrzysztof Kozlowski sc->battery_desc.get_property = sony_battery_get_property; 2008297d716fSKrzysztof Kozlowski sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 2009297d716fSKrzysztof Kozlowski sc->battery_desc.use_for_apm = 0; 2010297d716fSKrzysztof Kozlowski sc->battery_desc.name = kasprintf(GFP_KERNEL, 2011297d716fSKrzysztof Kozlowski "sony_controller_battery_%pMR", 2012314531f1SFrank Praznik sc->mac_address); 2013297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 2014d902f472SFrank Praznik return -ENOMEM; 2015d902f472SFrank Praznik 2016297d716fSKrzysztof Kozlowski sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc, 2017297d716fSKrzysztof Kozlowski &psy_cfg); 2018297d716fSKrzysztof Kozlowski if (IS_ERR(sc->battery)) { 2019297d716fSKrzysztof Kozlowski ret = PTR_ERR(sc->battery); 2020d902f472SFrank Praznik hid_err(hdev, "Unable to register battery device\n"); 2021d902f472SFrank Praznik goto err_free; 2022d902f472SFrank Praznik } 2023d902f472SFrank Praznik 2024297d716fSKrzysztof Kozlowski power_supply_powers(sc->battery, &hdev->dev); 2025d902f472SFrank Praznik return 0; 2026d902f472SFrank Praznik 2027d902f472SFrank Praznik err_free: 2028297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 2029297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 2030d902f472SFrank Praznik return ret; 2031d902f472SFrank Praznik } 2032d902f472SFrank Praznik 2033d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc) 2034d902f472SFrank Praznik { 2035297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 2036d902f472SFrank Praznik return; 2037d902f472SFrank Praznik 2038297d716fSKrzysztof Kozlowski power_supply_unregister(sc->battery); 2039297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 2040297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 2041d902f472SFrank Praznik } 2042d902f472SFrank Praznik 2043d2d782fcSFrank Praznik /* 2044d2d782fcSFrank Praznik * If a controller is plugged in via USB while already connected via Bluetooth 2045d2d782fcSFrank Praznik * it will show up as two devices. A global list of connected controllers and 2046d2d782fcSFrank Praznik * their MAC addresses is maintained to ensure that a device is only connected 2047d2d782fcSFrank Praznik * once. 2048d2d782fcSFrank Praznik */ 2049d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc) 2050d2d782fcSFrank Praznik { 2051d2d782fcSFrank Praznik struct sony_sc *entry; 2052d2d782fcSFrank Praznik unsigned long flags; 2053d2d782fcSFrank Praznik int ret; 2054d2d782fcSFrank Praznik 2055d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 2056d2d782fcSFrank Praznik 2057d2d782fcSFrank Praznik list_for_each_entry(entry, &sony_device_list, list_node) { 2058d2d782fcSFrank Praznik ret = memcmp(sc->mac_address, entry->mac_address, 2059d2d782fcSFrank Praznik sizeof(sc->mac_address)); 2060d2d782fcSFrank Praznik if (!ret) { 2061d2d782fcSFrank Praznik ret = -EEXIST; 2062d2d782fcSFrank Praznik hid_info(sc->hdev, "controller with MAC address %pMR already connected\n", 2063d2d782fcSFrank Praznik sc->mac_address); 2064d2d782fcSFrank Praznik goto unlock; 2065d2d782fcSFrank Praznik } 2066c4e1ddf2SFrank Praznik } 2067c4e1ddf2SFrank Praznik 2068d2d782fcSFrank Praznik ret = 0; 2069d2d782fcSFrank Praznik list_add(&(sc->list_node), &sony_device_list); 2070c4e1ddf2SFrank Praznik 2071d2d782fcSFrank Praznik unlock: 2072d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 2073d2d782fcSFrank Praznik return ret; 2074d2d782fcSFrank Praznik } 2075d2d782fcSFrank Praznik 2076d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc) 2077d2d782fcSFrank Praznik { 2078d2d782fcSFrank Praznik unsigned long flags; 2079d2d782fcSFrank Praznik 2080d2d782fcSFrank Praznik if (sc->list_node.next) { 2081d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 2082d2d782fcSFrank Praznik list_del(&(sc->list_node)); 2083d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 2084d2d782fcSFrank Praznik } 2085d2d782fcSFrank Praznik } 2086d2d782fcSFrank Praznik 2087d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc) 2088d2d782fcSFrank Praznik { 2089d2d782fcSFrank Praznik int ret; 2090d2d782fcSFrank Praznik 2091d2d782fcSFrank Praznik /* HIDP stores the device MAC address as a string in the uniq field. */ 2092d2d782fcSFrank Praznik ret = strlen(sc->hdev->uniq); 2093d2d782fcSFrank Praznik if (ret != 17) 2094c4e1ddf2SFrank Praznik return -EINVAL; 2095d2d782fcSFrank Praznik 2096d2d782fcSFrank Praznik ret = sscanf(sc->hdev->uniq, 2097d2d782fcSFrank Praznik "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 2098d2d782fcSFrank Praznik &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3], 2099d2d782fcSFrank Praznik &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]); 2100d2d782fcSFrank Praznik 2101d2d782fcSFrank Praznik if (ret != 6) 2102d2d782fcSFrank Praznik return -EINVAL; 2103d2d782fcSFrank Praznik 2104d2d782fcSFrank Praznik return 0; 2105c4e1ddf2SFrank Praznik } 2106c4e1ddf2SFrank Praznik 2107d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc) 2108d2d782fcSFrank Praznik { 21099b2b5c9aSFrank Praznik __u8 *buf = NULL; 2110d2d782fcSFrank Praznik int n, ret; 2111d2d782fcSFrank Praznik 2112d2d782fcSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || 211312e9a6d7SSimon Wood (sc->quirks & MOTION_CONTROLLER_BT) || 21144545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT) || 2115d2d782fcSFrank Praznik (sc->quirks & SIXAXIS_CONTROLLER_BT)) { 2116d2d782fcSFrank Praznik /* 2117d2d782fcSFrank Praznik * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC 2118d2d782fcSFrank Praznik * address from the uniq string where HIDP stores it. 2119d2d782fcSFrank Praznik * As uniq cannot be guaranteed to be a MAC address in all cases 2120d2d782fcSFrank Praznik * a failure of this function should not prevent the connection. 2121d2d782fcSFrank Praznik */ 2122d2d782fcSFrank Praznik if (sony_get_bt_devaddr(sc) < 0) { 2123d2d782fcSFrank Praznik hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); 2124d2d782fcSFrank Praznik return 0; 2125d2d782fcSFrank Praznik } 2126d2d782fcSFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 21279b2b5c9aSFrank Praznik buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); 21289b2b5c9aSFrank Praznik if (!buf) 21299b2b5c9aSFrank Praznik return -ENOMEM; 2130d2d782fcSFrank Praznik 2131d2d782fcSFrank Praznik /* 2132d2d782fcSFrank Praznik * The MAC address of a DS4 controller connected via USB can be 2133d2d782fcSFrank Praznik * retrieved with feature report 0x81. The address begins at 2134d2d782fcSFrank Praznik * offset 1. 2135d2d782fcSFrank Praznik */ 21369b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0x81, buf, 21379b2b5c9aSFrank Praznik DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, 21389b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2139d2d782fcSFrank Praznik 21409b2b5c9aSFrank Praznik if (ret != DS4_REPORT_0x81_SIZE) { 2141d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); 21429b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 21439b2b5c9aSFrank Praznik goto out_free; 2144d2d782fcSFrank Praznik } 2145d2d782fcSFrank Praznik 2146d2d782fcSFrank Praznik memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); 21474545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 21484545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 21499b2b5c9aSFrank Praznik buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); 21509b2b5c9aSFrank Praznik if (!buf) 21519b2b5c9aSFrank Praznik return -ENOMEM; 2152d2d782fcSFrank Praznik 2153d2d782fcSFrank Praznik /* 2154d2d782fcSFrank Praznik * The MAC address of a Sixaxis controller connected via USB can 2155d2d782fcSFrank Praznik * be retrieved with feature report 0xf2. The address begins at 2156d2d782fcSFrank Praznik * offset 4. 2157d2d782fcSFrank Praznik */ 21589b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, 21599b2b5c9aSFrank Praznik SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, 21609b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2161d2d782fcSFrank Praznik 21629b2b5c9aSFrank Praznik if (ret != SIXAXIS_REPORT_0xF2_SIZE) { 2163d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); 21649b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 21659b2b5c9aSFrank Praznik goto out_free; 2166d2d782fcSFrank Praznik } 2167d2d782fcSFrank Praznik 2168d2d782fcSFrank Praznik /* 2169d2d782fcSFrank Praznik * The Sixaxis device MAC in the report is big-endian and must 2170d2d782fcSFrank Praznik * be byte-swapped. 2171d2d782fcSFrank Praznik */ 2172d2d782fcSFrank Praznik for (n = 0; n < 6; n++) 2173d2d782fcSFrank Praznik sc->mac_address[5-n] = buf[4+n]; 2174d2d782fcSFrank Praznik } else { 2175d2d782fcSFrank Praznik return 0; 2176d2d782fcSFrank Praznik } 2177d2d782fcSFrank Praznik 21789b2b5c9aSFrank Praznik ret = sony_check_add_dev_list(sc); 21799b2b5c9aSFrank Praznik 21809b2b5c9aSFrank Praznik out_free: 21819b2b5c9aSFrank Praznik 21829b2b5c9aSFrank Praznik kfree(buf); 21839b2b5c9aSFrank Praznik 21849b2b5c9aSFrank Praznik return ret; 2185d2d782fcSFrank Praznik } 2186d2d782fcSFrank Praznik 21878025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc) 21888025087aSFrank Praznik { 21898025087aSFrank Praznik int ret; 21908025087aSFrank Praznik 21918025087aSFrank Praznik /* 21928025087aSFrank Praznik * Only DualShock 4 or Sixaxis controllers get an id. 21938025087aSFrank Praznik * All others are set to -1. 21948025087aSFrank Praznik */ 21958025087aSFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) || 21968025087aSFrank Praznik (sc->quirks & DUALSHOCK4_CONTROLLER)) { 21978025087aSFrank Praznik ret = ida_simple_get(&sony_device_id_allocator, 0, 0, 21988025087aSFrank Praznik GFP_KERNEL); 21998025087aSFrank Praznik if (ret < 0) { 22008025087aSFrank Praznik sc->device_id = -1; 22018025087aSFrank Praznik return ret; 22028025087aSFrank Praznik } 22038025087aSFrank Praznik sc->device_id = ret; 22048025087aSFrank Praznik } else { 22058025087aSFrank Praznik sc->device_id = -1; 22068025087aSFrank Praznik } 22078025087aSFrank Praznik 22088025087aSFrank Praznik return 0; 22098025087aSFrank Praznik } 22108025087aSFrank Praznik 22118025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc) 22128025087aSFrank Praznik { 22138025087aSFrank Praznik if (sc->device_id >= 0) { 22148025087aSFrank Praznik ida_simple_remove(&sony_device_id_allocator, sc->device_id); 22158025087aSFrank Praznik sc->device_id = -1; 22168025087aSFrank Praznik } 22178025087aSFrank Praznik } 22188025087aSFrank Praznik 221946262047SFrank Praznik static inline void sony_init_work(struct sony_sc *sc, 222046262047SFrank Praznik void (*worker)(struct work_struct *)) 222146262047SFrank Praznik { 222246262047SFrank Praznik if (!sc->worker_initialized) 222346262047SFrank Praznik INIT_WORK(&sc->state_worker, worker); 222446262047SFrank Praznik 222546262047SFrank Praznik sc->worker_initialized = 1; 222646262047SFrank Praznik } 222746262047SFrank Praznik 222846262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc) 222946262047SFrank Praznik { 223046262047SFrank Praznik if (sc->worker_initialized) 223146262047SFrank Praznik cancel_work_sync(&sc->state_worker); 223246262047SFrank Praznik } 2233d2d782fcSFrank Praznik 2234bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 2235bd28ce00SJiri Slaby { 2236bd28ce00SJiri Slaby int ret; 2237cc6e0bbbSJiri Kosina unsigned long quirks = id->driver_data; 2238cc6e0bbbSJiri Kosina struct sony_sc *sc; 2239f04d5140SColin Leitner unsigned int connect_mask = HID_CONNECT_DEFAULT; 2240cc6e0bbbSJiri Kosina 2241abf832bfSBenjamin Tissoires sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); 2242cc6e0bbbSJiri Kosina if (sc == NULL) { 22434291ee30SJoe Perches hid_err(hdev, "can't alloc sony descriptor\n"); 2244cc6e0bbbSJiri Kosina return -ENOMEM; 2245cc6e0bbbSJiri Kosina } 2246cc6e0bbbSJiri Kosina 2247b94993f6SFrank Praznik spin_lock_init(&sc->lock); 2248b94993f6SFrank Praznik 2249cc6e0bbbSJiri Kosina sc->quirks = quirks; 2250cc6e0bbbSJiri Kosina hid_set_drvdata(hdev, sc); 22510a286ef2SSven Eckelmann sc->hdev = hdev; 2252bd28ce00SJiri Slaby 2253bd28ce00SJiri Slaby ret = hid_parse(hdev); 2254bd28ce00SJiri Slaby if (ret) { 22554291ee30SJoe Perches hid_err(hdev, "parse failed\n"); 2256abf832bfSBenjamin Tissoires return ret; 2257bd28ce00SJiri Slaby } 2258bd28ce00SJiri Slaby 2259f04d5140SColin Leitner if (sc->quirks & VAIO_RDESC_CONSTANT) 2260f04d5140SColin Leitner connect_mask |= HID_CONNECT_HIDDEV_FORCE; 226150764650SAntonio Ospite else if (sc->quirks & SIXAXIS_CONTROLLER) 2262f04d5140SColin Leitner connect_mask |= HID_CONNECT_HIDDEV_FORCE; 2263f04d5140SColin Leitner 2264f04d5140SColin Leitner ret = hid_hw_start(hdev, connect_mask); 2265bd28ce00SJiri Slaby if (ret) { 22664291ee30SJoe Perches hid_err(hdev, "hw start failed\n"); 2267abf832bfSBenjamin Tissoires return ret; 2268bd28ce00SJiri Slaby } 2269bd28ce00SJiri Slaby 22708025087aSFrank Praznik ret = sony_set_device_id(sc); 22718025087aSFrank Praznik if (ret < 0) { 22728025087aSFrank Praznik hid_err(hdev, "failed to allocate the device id\n"); 22738025087aSFrank Praznik goto err_stop; 22748025087aSFrank Praznik } 22758025087aSFrank Praznik 2276131a8a9aSFrank Praznik ret = sony_allocate_output_report(sc); 2277131a8a9aSFrank Praznik if (ret < 0) { 2278131a8a9aSFrank Praznik hid_err(hdev, "failed to allocate the output report buffer\n"); 2279131a8a9aSFrank Praznik goto err_stop; 2280131a8a9aSFrank Praznik } 2281131a8a9aSFrank Praznik 22824545ee0aSSimon Wood if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 22834545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 2284e534a935SBenjamin Tissoires /* 2285e534a935SBenjamin Tissoires * The Sony Sixaxis does not handle HID Output Reports on the 2286e534a935SBenjamin Tissoires * Interrupt EP like it could, so we need to force HID Output 2287e534a935SBenjamin Tissoires * Reports to use HID_REQ_SET_REPORT on the Control EP. 2288e534a935SBenjamin Tissoires * 2289e534a935SBenjamin Tissoires * There is also another issue about HID Output Reports via USB, 2290e534a935SBenjamin Tissoires * the Sixaxis does not want the report_id as part of the data 2291e534a935SBenjamin Tissoires * packet, so we have to discard buf[0] when sending the actual 2292e534a935SBenjamin Tissoires * control message, even for numbered reports, humpf! 2293e534a935SBenjamin Tissoires */ 2294e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2295e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; 2296816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev); 229746262047SFrank Praznik sony_init_work(sc, sixaxis_state_worker); 22984545ee0aSSimon Wood } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || 22994545ee0aSSimon Wood (sc->quirks & NAVIGATION_CONTROLLER_BT)) { 23002078b9bbSFrank Praznik /* 23012078b9bbSFrank Praznik * The Sixaxis wants output reports sent on the ctrl endpoint 23022078b9bbSFrank Praznik * when connected via Bluetooth. 23032078b9bbSFrank Praznik */ 23042078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2305816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev); 230646262047SFrank Praznik sony_init_work(sc, sixaxis_state_worker); 2307fee4e2d5SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 230868330d83SFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { 23092078b9bbSFrank Praznik /* 23102078b9bbSFrank Praznik * The DualShock 4 wants output reports sent on the ctrl 23112078b9bbSFrank Praznik * endpoint when connected via Bluetooth. 23122078b9bbSFrank Praznik */ 23132078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 231468330d83SFrank Praznik ret = dualshock4_set_operational_bt(hdev); 231568330d83SFrank Praznik if (ret < 0) { 231668330d83SFrank Praznik hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); 231768330d83SFrank Praznik goto err_stop; 231868330d83SFrank Praznik } 231968330d83SFrank Praznik } 2320c4e1ddf2SFrank Praznik 232146262047SFrank Praznik sony_init_work(sc, dualshock4_state_worker); 2322c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 2323c5e0c1c4SFrank Praznik sony_init_work(sc, motion_state_worker); 23240bd88dd3SFrank Praznik } else { 23250bd88dd3SFrank Praznik ret = 0; 23260bd88dd3SFrank Praznik } 2327f9ce7c28SBastien Nocera 23284dfdc464SJiri Kosina if (ret < 0) 2329bd28ce00SJiri Slaby goto err_stop; 2330bd28ce00SJiri Slaby 2331d2d782fcSFrank Praznik ret = sony_check_add(sc); 2332d2d782fcSFrank Praznik if (ret < 0) 2333d2d782fcSFrank Praznik goto err_stop; 2334d2d782fcSFrank Praznik 23350a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) { 2336fa57a810SFrank Praznik ret = sony_leds_init(sc); 23370a286ef2SSven Eckelmann if (ret < 0) 23380a286ef2SSven Eckelmann goto err_stop; 23390a286ef2SSven Eckelmann } 23400a286ef2SSven Eckelmann 2341d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 2342d902f472SFrank Praznik ret = sony_battery_probe(sc); 2343a08c22c0SSven Eckelmann if (ret < 0) 2344a08c22c0SSven Eckelmann goto err_stop; 2345a08c22c0SSven Eckelmann 2346d902f472SFrank Praznik /* Open the device to receive reports with battery info */ 2347d902f472SFrank Praznik ret = hid_hw_open(hdev); 2348d902f472SFrank Praznik if (ret < 0) { 2349d902f472SFrank Praznik hid_err(hdev, "hw open failed\n"); 2350d902f472SFrank Praznik goto err_stop; 2351d902f472SFrank Praznik } 2352d902f472SFrank Praznik } 2353d902f472SFrank Praznik 2354c8de9dbbSFrank Praznik if (sc->quirks & SONY_FF_SUPPORT) { 2355fa57a810SFrank Praznik ret = sony_init_ff(sc); 2356d902f472SFrank Praznik if (ret < 0) 2357d902f472SFrank Praznik goto err_close; 23585f5750d2SFrank Praznik } 2359bd28ce00SJiri Slaby 2360f425458eSH Hartley Sweeten return 0; 2361d902f472SFrank Praznik err_close: 2362d902f472SFrank Praznik hid_hw_close(hdev); 2363bd28ce00SJiri Slaby err_stop: 23640a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2365fa57a810SFrank Praznik sony_leds_remove(sc); 2366d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) 2367d902f472SFrank Praznik sony_battery_remove(sc); 236846262047SFrank Praznik sony_cancel_work_sync(sc); 23699b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 2370d2d782fcSFrank Praznik sony_remove_dev_list(sc); 23718025087aSFrank Praznik sony_release_device_id(sc); 2372bd28ce00SJiri Slaby hid_hw_stop(hdev); 2373bd28ce00SJiri Slaby return ret; 2374bd28ce00SJiri Slaby } 2375bd28ce00SJiri Slaby 2376bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev) 2377bd28ce00SJiri Slaby { 2378bd28ce00SJiri Slaby struct sony_sc *sc = hid_get_drvdata(hdev); 2379bd28ce00SJiri Slaby 23800a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2381fa57a810SFrank Praznik sony_leds_remove(sc); 2382bd28ce00SJiri Slaby 2383d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 2384d902f472SFrank Praznik hid_hw_close(hdev); 2385d902f472SFrank Praznik sony_battery_remove(sc); 2386d902f472SFrank Praznik } 2387d902f472SFrank Praznik 238846262047SFrank Praznik sony_cancel_work_sync(sc); 23899f323b68SSven Eckelmann 23909b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 23919b2b5c9aSFrank Praznik 2392d2d782fcSFrank Praznik sony_remove_dev_list(sc); 2393bd28ce00SJiri Slaby 23948025087aSFrank Praznik sony_release_device_id(sc); 23958025087aSFrank Praznik 2396bd28ce00SJiri Slaby hid_hw_stop(hdev); 2397bd28ce00SJiri Slaby } 2398bd28ce00SJiri Slaby 2399bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = { 2400bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2401bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_USB }, 2402bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 24034545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_USB }, 24046eabaaa0SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 24054545ee0aSSimon Wood .driver_data = NAVIGATION_CONTROLLER_BT }, 2406c5e0c1c4SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2407b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_USB }, 2408a4afa854SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2409b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_BT }, 2410bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2411bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_BT }, 2412bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 2413bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2414bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), 2415bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2416bd28ce00SJiri Slaby /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as 2417bd28ce00SJiri Slaby * Logitech joystick from the device descriptor. */ 2418bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), 2419bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2420bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), 2421bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2422bd28ce00SJiri Slaby /* PS3 BD Remote Control */ 2423bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), 2424bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 2425bd28ce00SJiri Slaby /* Logitech Harmony Adapter for PS3 */ 2426bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), 2427bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 242868a49e51SFrank Praznik /* SMK-Link PS3 BD Remote Control */ 242968a49e51SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), 243068a49e51SFrank Praznik .driver_data = PS3REMOTE }, 24310bd88dd3SFrank Praznik /* Sony Dualshock 4 controllers for PS4 */ 24320bd88dd3SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 24338ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_USB }, 24340bd88dd3SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 24358ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_BT }, 2436bd28ce00SJiri Slaby { } 2437bd28ce00SJiri Slaby }; 2438bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices); 2439bd28ce00SJiri Slaby 2440bd28ce00SJiri Slaby static struct hid_driver sony_driver = { 2441bd28ce00SJiri Slaby .name = "sony", 2442bd28ce00SJiri Slaby .id_table = sony_devices, 2443bd28ce00SJiri Slaby .input_mapping = sony_mapping, 2444ce8efc3bSFrank Praznik .input_configured = sony_input_configured, 2445bd28ce00SJiri Slaby .probe = sony_probe, 2446bd28ce00SJiri Slaby .remove = sony_remove, 2447bd28ce00SJiri Slaby .report_fixup = sony_report_fixup, 2448bd28ce00SJiri Slaby .raw_event = sony_raw_event 2449bd28ce00SJiri Slaby }; 24508025087aSFrank Praznik 24518025087aSFrank Praznik static int __init sony_init(void) 24528025087aSFrank Praznik { 24538025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 24548025087aSFrank Praznik 24558025087aSFrank Praznik return hid_register_driver(&sony_driver); 24568025087aSFrank Praznik } 24578025087aSFrank Praznik 24588025087aSFrank Praznik static void __exit sony_exit(void) 24598025087aSFrank Praznik { 24608025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 24618025087aSFrank Praznik 24628025087aSFrank Praznik hid_unregister_driver(&sony_driver); 24636c40065fSAntonio Ospite ida_destroy(&sony_device_id_allocator); 24648025087aSFrank Praznik } 24658025087aSFrank Praznik module_init(sony_init); 24668025087aSFrank Praznik module_exit(sony_exit); 2467bd28ce00SJiri Slaby 2468bd28ce00SJiri Slaby MODULE_LICENSE("GPL"); 2469