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) 51cc6e0bbbSJiri Kosina 52fee4e2d5SFrank Praznik #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) 53b3bca326SSimon Wood #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) 5468330d83SFrank Praznik #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ 5568330d83SFrank Praznik DUALSHOCK4_CONTROLLER_BT) 56fee4e2d5SFrank Praznik #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ 57c5e0c1c4SFrank Praznik DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER) 5812e9a6d7SSimon Wood #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 5912e9a6d7SSimon Wood MOTION_CONTROLLER_BT) 60c5e0c1c4SFrank Praznik #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 61c5e0c1c4SFrank Praznik MOTION_CONTROLLER) 6260781cf4SFrank Praznik 6360781cf4SFrank Praznik #define MAX_LEDS 4 640a286ef2SSven Eckelmann 654c3e8298SFrank Praznik /* 664c3e8298SFrank Praznik * The Sixaxis reports both digital and analog values for each button on the 674c3e8298SFrank Praznik * controller except for Start, Select and the PS button. The controller ends 684c3e8298SFrank Praznik * up reporting 27 axes which causes them to spill over into the multi-touch 694c3e8298SFrank Praznik * axis values. Additionally, the controller only has 20 actual, physical axes 704c3e8298SFrank Praznik * so there are several unused axes in between the used ones. 714c3e8298SFrank Praznik */ 72c607fb8dSAntonio Ospite static __u8 sixaxis_rdesc[] = { 73fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 744c3e8298SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */ 75fb705a6dSAntonio Ospite 0xA1, 0x01, /* Collection (Application), */ 76fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 77fb705a6dSAntonio Ospite 0x85, 0x01, /* Report ID (1), */ 78fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 79fb705a6dSAntonio Ospite 0x95, 0x01, /* Report Count (1), */ 80fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 81fb705a6dSAntonio Ospite 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 82fb705a6dSAntonio Ospite 0x81, 0x03, /* Input (Constant, Variable), */ 83fb705a6dSAntonio Ospite 0x75, 0x01, /* Report Size (1), */ 84fb705a6dSAntonio Ospite 0x95, 0x13, /* Report Count (19), */ 85fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 86fb705a6dSAntonio Ospite 0x25, 0x01, /* Logical Maximum (1), */ 87fb705a6dSAntonio Ospite 0x35, 0x00, /* Physical Minimum (0), */ 88fb705a6dSAntonio Ospite 0x45, 0x01, /* Physical Maximum (1), */ 89fb705a6dSAntonio Ospite 0x05, 0x09, /* Usage Page (Button), */ 90fb705a6dSAntonio Ospite 0x19, 0x01, /* Usage Minimum (01h), */ 91fb705a6dSAntonio Ospite 0x29, 0x13, /* Usage Maximum (13h), */ 92fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 93fb705a6dSAntonio Ospite 0x75, 0x01, /* Report Size (1), */ 94fb705a6dSAntonio Ospite 0x95, 0x0D, /* Report Count (13), */ 95fb705a6dSAntonio Ospite 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 96fb705a6dSAntonio Ospite 0x81, 0x03, /* Input (Constant, Variable), */ 97fb705a6dSAntonio Ospite 0x15, 0x00, /* Logical Minimum (0), */ 98fb705a6dSAntonio Ospite 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 99fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 100fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 101fb705a6dSAntonio Ospite 0xA1, 0x00, /* Collection (Physical), */ 102fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 103fb705a6dSAntonio Ospite 0x95, 0x04, /* Report Count (4), */ 104fb705a6dSAntonio Ospite 0x35, 0x00, /* Physical Minimum (0), */ 105fb705a6dSAntonio Ospite 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 106fb705a6dSAntonio Ospite 0x09, 0x30, /* Usage (X), */ 107fb705a6dSAntonio Ospite 0x09, 0x31, /* Usage (Y), */ 108fb705a6dSAntonio Ospite 0x09, 0x32, /* Usage (Z), */ 109fb705a6dSAntonio Ospite 0x09, 0x35, /* Usage (Rz), */ 110fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 111fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 112fb705a6dSAntonio Ospite 0x05, 0x01, /* Usage Page (Desktop), */ 113fb705a6dSAntonio Ospite 0x95, 0x13, /* Report Count (19), */ 114fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 115fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 116fb705a6dSAntonio Ospite 0x95, 0x0C, /* Report Count (12), */ 117fb705a6dSAntonio Ospite 0x81, 0x01, /* Input (Constant), */ 118fb705a6dSAntonio Ospite 0x75, 0x10, /* Report Size (16), */ 119fb705a6dSAntonio Ospite 0x95, 0x04, /* Report Count (4), */ 120fb705a6dSAntonio Ospite 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 121fb705a6dSAntonio Ospite 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 122fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 123fb705a6dSAntonio Ospite 0x81, 0x02, /* Input (Variable), */ 124fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 125fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 126fb705a6dSAntonio Ospite 0x85, 0x02, /* Report ID (2), */ 127fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 128fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 129fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 130fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 131fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 132fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 133fb705a6dSAntonio Ospite 0x85, 0xEE, /* Report ID (238), */ 134fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 135fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 136fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 137fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 138fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 139fb705a6dSAntonio Ospite 0xA1, 0x02, /* Collection (Logical), */ 140fb705a6dSAntonio Ospite 0x85, 0xEF, /* Report ID (239), */ 141fb705a6dSAntonio Ospite 0x75, 0x08, /* Report Size (8), */ 142fb705a6dSAntonio Ospite 0x95, 0x30, /* Report Count (48), */ 143fb705a6dSAntonio Ospite 0x09, 0x01, /* Usage (Pointer), */ 144fb705a6dSAntonio Ospite 0xB1, 0x02, /* Feature (Variable), */ 145fb705a6dSAntonio Ospite 0xC0, /* End Collection, */ 146fb705a6dSAntonio Ospite 0xC0 /* End Collection */ 147e57a67daSMauro Carvalho Chehab }; 148e57a67daSMauro Carvalho Chehab 149c5e0c1c4SFrank Praznik /* PS/3 Motion controller */ 150c5e0c1c4SFrank Praznik static __u8 motion_rdesc[] = { 151c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 152c5e0c1c4SFrank Praznik 0x09, 0x04, /* Usage (Joystick), */ 153c5e0c1c4SFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 154c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 155c5e0c1c4SFrank Praznik 0x85, 0x01, /* Report ID (1), */ 156c5e0c1c4SFrank Praznik 0x75, 0x01, /* Report Size (1), */ 157*8b2513c3SSimon Wood 0x95, 0x15, /* Report Count (21), */ 158c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 159c5e0c1c4SFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 160c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 161c5e0c1c4SFrank Praznik 0x45, 0x01, /* Physical Maximum (1), */ 162c5e0c1c4SFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 163c5e0c1c4SFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 164*8b2513c3SSimon Wood 0x29, 0x15, /* Usage Maximum (15h), */ 165*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Buttons */ 166*8b2513c3SSimon Wood 0x95, 0x0B, /* Report Count (11), */ 167c5e0c1c4SFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 168*8b2513c3SSimon Wood 0x81, 0x03, /* Input (Constant, Variable), * Padding */ 169c5e0c1c4SFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 170c5e0c1c4SFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 171c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 172c5e0c1c4SFrank Praznik 0xA1, 0x00, /* Collection (Physical), */ 173c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 174*8b2513c3SSimon Wood 0x95, 0x01, /* Report Count (1), */ 175c5e0c1c4SFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 176c5e0c1c4SFrank Praznik 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 177c5e0c1c4SFrank Praznik 0x09, 0x30, /* Usage (X), */ 178*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), * Trigger */ 179c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 180*8b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 181*8b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 182*8b2513c3SSimon Wood 0x95, 0x07, /* Report Count (7), * skip 7 bytes */ 183*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 184c5e0c1c4SFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 185c5e0c1c4SFrank Praznik 0x75, 0x10, /* Report Size (16), */ 186*8b2513c3SSimon Wood 0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */ 187*8b2513c3SSimon Wood 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */ 188*8b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Accels */ 189*8b2513c3SSimon Wood 0x09, 0x33, /* Usage (rX), */ 190*8b2513c3SSimon Wood 0x09, 0x34, /* Usage (rY), */ 191*8b2513c3SSimon Wood 0x09, 0x35, /* Usage (rZ), */ 192c5e0c1c4SFrank Praznik 0x81, 0x02, /* Input (Variable), */ 193*8b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 194*8b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */ 195*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 196*8b2513c3SSimon Wood 0x05, 0x01, /* Usage Page (Desktop), */ 197*8b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 198*8b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * 3x Gyros */ 199*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 200*8b2513c3SSimon Wood 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 201*8b2513c3SSimon Wood 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */ 202*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 203*8b2513c3SSimon Wood 0x75, 0x0C, /* Report Size (12), */ 204*8b2513c3SSimon Wood 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */ 205*8b2513c3SSimon Wood 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */ 206*8b2513c3SSimon Wood 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */ 207*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 208*8b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 209*8b2513c3SSimon Wood 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 210*8b2513c3SSimon Wood 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 211*8b2513c3SSimon Wood 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */ 212*8b2513c3SSimon Wood 0x81, 0x02, /* Input (Variable), */ 213*8b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 214*8b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */ 215*8b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 216*8b2513c3SSimon Wood 0x91, 0x02, /* Output (Variable), */ 217*8b2513c3SSimon Wood 0x75, 0x08, /* Report Size (8), */ 218*8b2513c3SSimon Wood 0x95, 0x30, /* Report Count (48), */ 219*8b2513c3SSimon Wood 0x09, 0x01, /* Usage (Pointer), */ 220*8b2513c3SSimon Wood 0xB1, 0x02, /* Feature (Variable), */ 221c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 222c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 223c5e0c1c4SFrank Praznik 0x85, 0x02, /* Report ID (2), */ 224c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 225c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 226c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 227c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 228c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 229c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 230c5e0c1c4SFrank Praznik 0x85, 0xEE, /* Report ID (238), */ 231c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 232c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 233c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 234c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 235c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 236c5e0c1c4SFrank Praznik 0xA1, 0x02, /* Collection (Logical), */ 237c5e0c1c4SFrank Praznik 0x85, 0xEF, /* Report ID (239), */ 238c5e0c1c4SFrank Praznik 0x75, 0x08, /* Report Size (8), */ 239c5e0c1c4SFrank Praznik 0x95, 0x30, /* Report Count (48), */ 240c5e0c1c4SFrank Praznik 0x09, 0x01, /* Usage (Pointer), */ 241c5e0c1c4SFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 242c5e0c1c4SFrank Praznik 0xC0, /* End Collection, */ 243c5e0c1c4SFrank Praznik 0xC0 /* End Collection */ 244c5e0c1c4SFrank Praznik }; 245c5e0c1c4SFrank Praznik 246c5e0c1c4SFrank Praznik 247ad142b9eSFrank Praznik /* 248ad142b9eSFrank Praznik * The default descriptor doesn't provide mapping for the accelerometers 24958d7027bSFrank Praznik * or orientation sensors. This fixed descriptor maps the accelerometers 25058d7027bSFrank Praznik * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors 25158d7027bSFrank Praznik * to usage values 0x43, 0x44 and 0x45. 25258d7027bSFrank Praznik */ 253ed19d8cfSFrank Praznik static u8 dualshock4_usb_rdesc[] = { 25458d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 25558d7027bSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 25658d7027bSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 25758d7027bSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 25858d7027bSFrank Praznik 0x09, 0x30, /* Usage (X), */ 25958d7027bSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 26058d7027bSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 26158d7027bSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 26258d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 26358d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 26458d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 26558d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 26658d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 26758d7027bSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 26858d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 26958d7027bSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 27058d7027bSFrank Praznik 0x35, 0x00, /* Physical Minimum (0), */ 27158d7027bSFrank Praznik 0x46, 0x3B, 0x01, /* Physical Maximum (315), */ 27258d7027bSFrank Praznik 0x65, 0x14, /* Unit (Degrees), */ 27358d7027bSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 27458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 27558d7027bSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 27658d7027bSFrank Praznik 0x65, 0x00, /* Unit, */ 27758d7027bSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 27858d7027bSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 27958d7027bSFrank Praznik 0x29, 0x0E, /* Usage Maximum (0Eh), */ 28058d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 28158d7027bSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 28258d7027bSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 28358d7027bSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 28458d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 28558d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 28658d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 28758d7027bSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 28858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 28958d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 290fb291cbdSFrank Praznik 0x25, 0x3F, /* Logical Maximum (63), */ 29158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 29258d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 29358d7027bSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 29458d7027bSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 29558d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 29658d7027bSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 29758d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 29858d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 29958d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 30058d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 30158d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 30258d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 30358d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 30458d7027bSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 30558d7027bSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 30658d7027bSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 30758d7027bSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 30858d7027bSFrank Praznik 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ 30958d7027bSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 31058d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 31158d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 31258d7027bSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 31358d7027bSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 314fb291cbdSFrank Praznik 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ 315fb291cbdSFrank Praznik 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ 31658d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 31758d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 31858d7027bSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 31958d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 32058d7027bSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 321fb291cbdSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 32258d7027bSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 32358d7027bSFrank Praznik 0x95, 0x27, /* Report Count (39), */ 32458d7027bSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 32558d7027bSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 32658d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 32758d7027bSFrank Praznik 0x95, 0x1F, /* Report Count (31), */ 32858d7027bSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 32958d7027bSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 33058d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 33158d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 33258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 33358d7027bSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 33458d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 33558d7027bSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 33658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 33758d7027bSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 33858d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 33958d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 34058d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 34158d7027bSFrank Praznik 0x85, 0x10, /* Report ID (16), */ 34258d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 34358d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 34458d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 34558d7027bSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 34658d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 34758d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 34858d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 34958d7027bSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 35058d7027bSFrank Praznik 0x06, 0x02, 0xFF, /* Usage Page (FF02h), */ 35158d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 35258d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 35358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 35458d7027bSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 35558d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 35658d7027bSFrank Praznik 0x95, 0x16, /* Report Count (22), */ 35758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 35858d7027bSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 35958d7027bSFrank Praznik 0x06, 0x05, 0xFF, /* Usage Page (FF05h), */ 36058d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 36158d7027bSFrank Praznik 0x95, 0x10, /* Report Count (16), */ 36258d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 36358d7027bSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 36458d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 36558d7027bSFrank Praznik 0x95, 0x2C, /* Report Count (44), */ 36658d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 36758d7027bSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 36858d7027bSFrank Praznik 0x85, 0x80, /* Report ID (128), */ 36958d7027bSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 37058d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 37158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 37258d7027bSFrank Praznik 0x85, 0x81, /* Report ID (129), */ 37358d7027bSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 37458d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 37558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 37658d7027bSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 37758d7027bSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 37858d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 37958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 38058d7027bSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 38158d7027bSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 38258d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 38358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 38458d7027bSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 38558d7027bSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 38658d7027bSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 38758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 38858d7027bSFrank Praznik 0x85, 0x85, /* Report ID (133), */ 38958d7027bSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 39058d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 39158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 39258d7027bSFrank Praznik 0x85, 0x86, /* Report ID (134), */ 39358d7027bSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 39458d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 39558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 39658d7027bSFrank Praznik 0x85, 0x87, /* Report ID (135), */ 39758d7027bSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 39858d7027bSFrank Praznik 0x95, 0x23, /* Report Count (35), */ 39958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 40058d7027bSFrank Praznik 0x85, 0x88, /* Report ID (136), */ 40158d7027bSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 40258d7027bSFrank Praznik 0x95, 0x22, /* Report Count (34), */ 40358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 40458d7027bSFrank Praznik 0x85, 0x89, /* Report ID (137), */ 40558d7027bSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 40658d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 40758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 40858d7027bSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 40958d7027bSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 41058d7027bSFrank Praznik 0x95, 0x05, /* Report Count (5), */ 41158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 41258d7027bSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 41358d7027bSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 41458d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 41558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 41658d7027bSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 41758d7027bSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 41858d7027bSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 41958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42058d7027bSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 42158d7027bSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 42258d7027bSFrank Praznik 0x95, 0x0C, /* Report Count (12), */ 42358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42458d7027bSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 42558d7027bSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 42658d7027bSFrank Praznik 0x95, 0x06, /* Report Count (6), */ 42758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 42858d7027bSFrank Praznik 0x85, 0xA1, /* Report ID (161), */ 42958d7027bSFrank Praznik 0x09, 0x41, /* Usage (41h), */ 43058d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 43158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43258d7027bSFrank Praznik 0x85, 0xA2, /* Report ID (162), */ 43358d7027bSFrank Praznik 0x09, 0x42, /* Usage (42h), */ 43458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 43558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 43658d7027bSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 43758d7027bSFrank Praznik 0x09, 0x43, /* Usage (43h), */ 43858d7027bSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 43958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44058d7027bSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 44158d7027bSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 44258d7027bSFrank Praznik 0x95, 0x0D, /* Report Count (13), */ 44358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44458d7027bSFrank Praznik 0x85, 0xA5, /* Report ID (165), */ 44558d7027bSFrank Praznik 0x09, 0x45, /* Usage (45h), */ 44658d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 44758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 44858d7027bSFrank Praznik 0x85, 0xA6, /* Report ID (166), */ 44958d7027bSFrank Praznik 0x09, 0x46, /* Usage (46h), */ 45058d7027bSFrank Praznik 0x95, 0x15, /* Report Count (21), */ 45158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45258d7027bSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 45358d7027bSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 45458d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 45558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 45658d7027bSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 45758d7027bSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 45858d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 45958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46058d7027bSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 46158d7027bSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 46258d7027bSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 46358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46458d7027bSFrank Praznik 0x85, 0xA7, /* Report ID (167), */ 46558d7027bSFrank Praznik 0x09, 0x4A, /* Usage (4Ah), */ 46658d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 46758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 46858d7027bSFrank Praznik 0x85, 0xA8, /* Report ID (168), */ 46958d7027bSFrank Praznik 0x09, 0x4B, /* Usage (4Bh), */ 47058d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 47158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47258d7027bSFrank Praznik 0x85, 0xA9, /* Report ID (169), */ 47358d7027bSFrank Praznik 0x09, 0x4C, /* Usage (4Ch), */ 47458d7027bSFrank Praznik 0x95, 0x08, /* Report Count (8), */ 47558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 47658d7027bSFrank Praznik 0x85, 0xAA, /* Report ID (170), */ 47758d7027bSFrank Praznik 0x09, 0x4E, /* Usage (4Eh), */ 47858d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 47958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48058d7027bSFrank Praznik 0x85, 0xAB, /* Report ID (171), */ 48158d7027bSFrank Praznik 0x09, 0x4F, /* Usage (4Fh), */ 48258d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 48358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48458d7027bSFrank Praznik 0x85, 0xAC, /* Report ID (172), */ 48558d7027bSFrank Praznik 0x09, 0x50, /* Usage (50h), */ 48658d7027bSFrank Praznik 0x95, 0x39, /* Report Count (57), */ 48758d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 48858d7027bSFrank Praznik 0x85, 0xAD, /* Report ID (173), */ 48958d7027bSFrank Praznik 0x09, 0x51, /* Usage (51h), */ 49058d7027bSFrank Praznik 0x95, 0x0B, /* Report Count (11), */ 49158d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49258d7027bSFrank Praznik 0x85, 0xAE, /* Report ID (174), */ 49358d7027bSFrank Praznik 0x09, 0x52, /* Usage (52h), */ 49458d7027bSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 49558d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 49658d7027bSFrank Praznik 0x85, 0xAF, /* Report ID (175), */ 49758d7027bSFrank Praznik 0x09, 0x53, /* Usage (53h), */ 49858d7027bSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 49958d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50058d7027bSFrank Praznik 0x85, 0xB0, /* Report ID (176), */ 50158d7027bSFrank Praznik 0x09, 0x54, /* Usage (54h), */ 50258d7027bSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 50358d7027bSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 50458d7027bSFrank Praznik 0xC0 /* End Collection */ 505ed19d8cfSFrank Praznik }; 506ed19d8cfSFrank Praznik 507ad142b9eSFrank Praznik /* 508ad142b9eSFrank Praznik * The default behavior of the Dualshock 4 is to send reports using report 509077147a3SFrank Praznik * type 1 when running over Bluetooth. However, when feature report 2 is 510077147a3SFrank Praznik * requested during the controller initialization it starts sending input 511077147a3SFrank Praznik * reports in report 17. Since report 17 is undefined in the default HID 512d829674dSFrank Praznik * descriptor the button and axis definitions must be moved to report 17 or 513077147a3SFrank Praznik * the HID layer won't process the received input. 514d829674dSFrank Praznik */ 515d829674dSFrank Praznik static u8 dualshock4_bt_rdesc[] = { 516d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 517d829674dSFrank Praznik 0x09, 0x05, /* Usage (Gamepad), */ 518d829674dSFrank Praznik 0xA1, 0x01, /* Collection (Application), */ 519d829674dSFrank Praznik 0x85, 0x01, /* Report ID (1), */ 520d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 521d829674dSFrank Praznik 0x95, 0x0A, /* Report Count (9), */ 522d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 523d829674dSFrank Praznik 0x06, 0x04, 0xFF, /* Usage Page (FF04h), */ 524d829674dSFrank Praznik 0x85, 0x02, /* Report ID (2), */ 525d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 526d829674dSFrank Praznik 0x95, 0x24, /* Report Count (36), */ 527d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 528d829674dSFrank Praznik 0x85, 0xA3, /* Report ID (163), */ 529d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 530d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 531d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 532d829674dSFrank Praznik 0x85, 0x05, /* Report ID (5), */ 533d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 534d829674dSFrank Praznik 0x95, 0x28, /* Report Count (40), */ 535d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 536d829674dSFrank Praznik 0x85, 0x06, /* Report ID (6), */ 537d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 538d829674dSFrank Praznik 0x95, 0x34, /* Report Count (52), */ 539d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 540d829674dSFrank Praznik 0x85, 0x07, /* Report ID (7), */ 541d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 542d829674dSFrank Praznik 0x95, 0x30, /* Report Count (48), */ 543d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 544d829674dSFrank Praznik 0x85, 0x08, /* Report ID (8), */ 545d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 546d829674dSFrank Praznik 0x95, 0x2F, /* Report Count (47), */ 547d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 548d829674dSFrank Praznik 0x06, 0x03, 0xFF, /* Usage Page (FF03h), */ 549d829674dSFrank Praznik 0x85, 0x03, /* Report ID (3), */ 550d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 551d829674dSFrank Praznik 0x95, 0x26, /* Report Count (38), */ 552d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 553d829674dSFrank Praznik 0x85, 0x04, /* Report ID (4), */ 554d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 555d829674dSFrank Praznik 0x95, 0x2E, /* Report Count (46), */ 556d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 557d829674dSFrank Praznik 0x85, 0xF0, /* Report ID (240), */ 558d829674dSFrank Praznik 0x09, 0x47, /* Usage (47h), */ 559d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 560d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 561d829674dSFrank Praznik 0x85, 0xF1, /* Report ID (241), */ 562d829674dSFrank Praznik 0x09, 0x48, /* Usage (48h), */ 563d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 564d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 565d829674dSFrank Praznik 0x85, 0xF2, /* Report ID (242), */ 566d829674dSFrank Praznik 0x09, 0x49, /* Usage (49h), */ 567d829674dSFrank Praznik 0x95, 0x0F, /* Report Count (15), */ 568d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 569d829674dSFrank Praznik 0x85, 0x11, /* Report ID (17), */ 570d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 571d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 572d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 573d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 574d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 575d829674dSFrank Praznik 0x09, 0x30, /* Usage (X), */ 576d829674dSFrank Praznik 0x09, 0x31, /* Usage (Y), */ 577d829674dSFrank Praznik 0x09, 0x32, /* Usage (Z), */ 578d829674dSFrank Praznik 0x09, 0x35, /* Usage (Rz), */ 579d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 580d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 581d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 582d829674dSFrank Praznik 0x95, 0x04, /* Report Count (4), */ 583d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 584d829674dSFrank Praznik 0x09, 0x39, /* Usage (Hat Switch), */ 585d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 586d829674dSFrank Praznik 0x25, 0x07, /* Logical Maximum (7), */ 587d829674dSFrank Praznik 0x75, 0x04, /* Report Size (4), */ 588d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 589d829674dSFrank Praznik 0x81, 0x42, /* Input (Variable, Null State), */ 590d829674dSFrank Praznik 0x05, 0x09, /* Usage Page (Button), */ 591d829674dSFrank Praznik 0x19, 0x01, /* Usage Minimum (01h), */ 592d829674dSFrank Praznik 0x29, 0x0E, /* Usage Maximum (0Eh), */ 593d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 594d829674dSFrank Praznik 0x25, 0x01, /* Logical Maximum (1), */ 595d829674dSFrank Praznik 0x75, 0x01, /* Report Size (1), */ 596d829674dSFrank Praznik 0x95, 0x0E, /* Report Count (14), */ 597d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 598d829674dSFrank Praznik 0x75, 0x06, /* Report Size (6), */ 599d829674dSFrank Praznik 0x95, 0x01, /* Report Count (1), */ 600d829674dSFrank Praznik 0x81, 0x01, /* Input (Constant), */ 601d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 602d829674dSFrank Praznik 0x09, 0x33, /* Usage (Rx), */ 603d829674dSFrank Praznik 0x09, 0x34, /* Usage (Ry), */ 604d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 605d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 606d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 607d829674dSFrank Praznik 0x95, 0x02, /* Report Count (2), */ 608d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 609d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 610d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 611d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 612d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 613d829674dSFrank Praznik 0x05, 0x01, /* Usage Page (Desktop), */ 614d829674dSFrank Praznik 0x19, 0x40, /* Usage Minimum (40h), */ 615d829674dSFrank Praznik 0x29, 0x42, /* Usage Maximum (42h), */ 616d829674dSFrank Praznik 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 617d829674dSFrank Praznik 0x26, 0x00, 0x7F, /* Logical Maximum (32767), */ 618d829674dSFrank Praznik 0x75, 0x10, /* Report Size (16), */ 619d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 620d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 621d829674dSFrank Praznik 0x19, 0x43, /* Usage Minimum (43h), */ 622d829674dSFrank Praznik 0x29, 0x45, /* Usage Maximum (45h), */ 623fb291cbdSFrank Praznik 0x16, 0x00, 0xE0, /* Logical Minimum (-8192), */ 624fb291cbdSFrank Praznik 0x26, 0xFF, 0x1F, /* Logical Maximum (8191), */ 625d829674dSFrank Praznik 0x95, 0x03, /* Report Count (3), */ 626d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 627d829674dSFrank Praznik 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 628d829674dSFrank Praznik 0x09, 0x20, /* Usage (20h), */ 629d829674dSFrank Praznik 0x15, 0x00, /* Logical Minimum (0), */ 630d829674dSFrank Praznik 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 631d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 632d829674dSFrank Praznik 0x95, 0x31, /* Report Count (51), */ 633d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 634d829674dSFrank Praznik 0x09, 0x21, /* Usage (21h), */ 635d829674dSFrank Praznik 0x75, 0x08, /* Report Size (8), */ 636d829674dSFrank Praznik 0x95, 0x4D, /* Report Count (77), */ 637d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 638d829674dSFrank Praznik 0x85, 0x12, /* Report ID (18), */ 639d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 640d829674dSFrank Praznik 0x95, 0x8D, /* Report Count (141), */ 641d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 642d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 643d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 644d829674dSFrank Praznik 0x85, 0x13, /* Report ID (19), */ 645d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 646d829674dSFrank Praznik 0x95, 0xCD, /* Report Count (205), */ 647d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 648d829674dSFrank Praznik 0x09, 0x25, /* Usage (25h), */ 649d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 650d829674dSFrank Praznik 0x85, 0x14, /* Report ID (20), */ 651d829674dSFrank Praznik 0x09, 0x26, /* Usage (26h), */ 652d829674dSFrank Praznik 0x96, 0x0D, 0x01, /* Report Count (269), */ 653d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 654d829674dSFrank Praznik 0x09, 0x27, /* Usage (27h), */ 655d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 656d829674dSFrank Praznik 0x85, 0x15, /* Report ID (21), */ 657d829674dSFrank Praznik 0x09, 0x28, /* Usage (28h), */ 658d829674dSFrank Praznik 0x96, 0x4D, 0x01, /* Report Count (333), */ 659d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 660d829674dSFrank Praznik 0x09, 0x29, /* Usage (29h), */ 661d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 662d829674dSFrank Praznik 0x85, 0x16, /* Report ID (22), */ 663d829674dSFrank Praznik 0x09, 0x2A, /* Usage (2Ah), */ 664d829674dSFrank Praznik 0x96, 0x8D, 0x01, /* Report Count (397), */ 665d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 666d829674dSFrank Praznik 0x09, 0x2B, /* Usage (2Bh), */ 667d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 668d829674dSFrank Praznik 0x85, 0x17, /* Report ID (23), */ 669d829674dSFrank Praznik 0x09, 0x2C, /* Usage (2Ch), */ 670d829674dSFrank Praznik 0x96, 0xCD, 0x01, /* Report Count (461), */ 671d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 672d829674dSFrank Praznik 0x09, 0x2D, /* Usage (2Dh), */ 673d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 674d829674dSFrank Praznik 0x85, 0x18, /* Report ID (24), */ 675d829674dSFrank Praznik 0x09, 0x2E, /* Usage (2Eh), */ 676d829674dSFrank Praznik 0x96, 0x0D, 0x02, /* Report Count (525), */ 677d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 678d829674dSFrank Praznik 0x09, 0x2F, /* Usage (2Fh), */ 679d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 680d829674dSFrank Praznik 0x85, 0x19, /* Report ID (25), */ 681d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 682d829674dSFrank Praznik 0x96, 0x22, 0x02, /* Report Count (546), */ 683d829674dSFrank Praznik 0x81, 0x02, /* Input (Variable), */ 684d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 685d829674dSFrank Praznik 0x91, 0x02, /* Output (Variable), */ 686d829674dSFrank Praznik 0x06, 0x80, 0xFF, /* Usage Page (FF80h), */ 687d829674dSFrank Praznik 0x85, 0x82, /* Report ID (130), */ 688d829674dSFrank Praznik 0x09, 0x22, /* Usage (22h), */ 689d829674dSFrank Praznik 0x95, 0x3F, /* Report Count (63), */ 690d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 691d829674dSFrank Praznik 0x85, 0x83, /* Report ID (131), */ 692d829674dSFrank Praznik 0x09, 0x23, /* Usage (23h), */ 693d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 694d829674dSFrank Praznik 0x85, 0x84, /* Report ID (132), */ 695d829674dSFrank Praznik 0x09, 0x24, /* Usage (24h), */ 696d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 697d829674dSFrank Praznik 0x85, 0x90, /* Report ID (144), */ 698d829674dSFrank Praznik 0x09, 0x30, /* Usage (30h), */ 699d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 700d829674dSFrank Praznik 0x85, 0x91, /* Report ID (145), */ 701d829674dSFrank Praznik 0x09, 0x31, /* Usage (31h), */ 702d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 703d829674dSFrank Praznik 0x85, 0x92, /* Report ID (146), */ 704d829674dSFrank Praznik 0x09, 0x32, /* Usage (32h), */ 705d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 706d829674dSFrank Praznik 0x85, 0x93, /* Report ID (147), */ 707d829674dSFrank Praznik 0x09, 0x33, /* Usage (33h), */ 708d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 709d829674dSFrank Praznik 0x85, 0xA0, /* Report ID (160), */ 710d829674dSFrank Praznik 0x09, 0x40, /* Usage (40h), */ 711d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 712d829674dSFrank Praznik 0x85, 0xA4, /* Report ID (164), */ 713d829674dSFrank Praznik 0x09, 0x44, /* Usage (44h), */ 714d829674dSFrank Praznik 0xB1, 0x02, /* Feature (Variable), */ 715d829674dSFrank Praznik 0xC0 /* End Collection */ 716d829674dSFrank Praznik }; 717d829674dSFrank Praznik 718078328daSJiri Kosina static __u8 ps3remote_rdesc[] = { 719078328daSJiri Kosina 0x05, 0x01, /* GUsagePage Generic Desktop */ 720078328daSJiri Kosina 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 721078328daSJiri Kosina 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ 722078328daSJiri Kosina 723078328daSJiri Kosina /* Use collection 1 for joypad buttons */ 724078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 725078328daSJiri Kosina 726078328daSJiri Kosina /* Ignore the 1st byte, maybe it is used for a controller 727078328daSJiri Kosina * number but it's not needed for correct operation */ 728078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 729078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 730078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 731078328daSJiri Kosina 732078328daSJiri Kosina /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these 733078328daSJiri Kosina * buttons multiple keypresses are allowed */ 734078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 735078328daSJiri Kosina 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ 736078328daSJiri Kosina 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ 737078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 738078328daSJiri Kosina 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ 739078328daSJiri Kosina 0x75, 0x01, /* GReportSize 0x01 [1] */ 740078328daSJiri Kosina 0x95, 0x18, /* GReportCount 0x18 [24] */ 741078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 742078328daSJiri Kosina 743078328daSJiri Kosina 0xC0, /* MEndCollection */ 744078328daSJiri Kosina 745078328daSJiri Kosina /* Use collection 2 for remote control buttons */ 746078328daSJiri Kosina 0xA1, 0x02, /* MCollection Logical (interrelated data) */ 747078328daSJiri Kosina 748078328daSJiri Kosina /* 5th byte is used for remote control buttons */ 749078328daSJiri Kosina 0x05, 0x09, /* GUsagePage Button */ 750078328daSJiri Kosina 0x18, /* LUsageMinimum [No button pressed] */ 751078328daSJiri Kosina 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ 752078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 753078328daSJiri Kosina 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ 754078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 755078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 756078328daSJiri Kosina 0x80, /* MInput */ 757078328daSJiri Kosina 758078328daSJiri Kosina /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at 759078328daSJiri Kosina * 0xff and 11th is for press indication */ 760078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 761078328daSJiri Kosina 0x95, 0x06, /* GReportCount 0x06 [6] */ 762078328daSJiri Kosina 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ 763078328daSJiri Kosina 764078328daSJiri Kosina /* 12th byte is for battery strength */ 765078328daSJiri Kosina 0x05, 0x06, /* GUsagePage Generic Device Controls */ 766078328daSJiri Kosina 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ 767078328daSJiri Kosina 0x14, /* GLogicalMinimum [0] */ 768078328daSJiri Kosina 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ 769078328daSJiri Kosina 0x75, 0x08, /* GReportSize 0x08 [8] */ 770078328daSJiri Kosina 0x95, 0x01, /* GReportCount 0x01 [1] */ 771078328daSJiri Kosina 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 772078328daSJiri Kosina 773078328daSJiri Kosina 0xC0, /* MEndCollection */ 774078328daSJiri Kosina 775078328daSJiri Kosina 0xC0 /* MEndCollection [Game Pad] */ 776078328daSJiri Kosina }; 777078328daSJiri Kosina 778078328daSJiri Kosina static const unsigned int ps3remote_keymap_joypad_buttons[] = { 779078328daSJiri Kosina [0x01] = KEY_SELECT, 780078328daSJiri Kosina [0x02] = BTN_THUMBL, /* L3 */ 781078328daSJiri Kosina [0x03] = BTN_THUMBR, /* R3 */ 782078328daSJiri Kosina [0x04] = BTN_START, 783078328daSJiri Kosina [0x05] = KEY_UP, 784078328daSJiri Kosina [0x06] = KEY_RIGHT, 785078328daSJiri Kosina [0x07] = KEY_DOWN, 786078328daSJiri Kosina [0x08] = KEY_LEFT, 787078328daSJiri Kosina [0x09] = BTN_TL2, /* L2 */ 788078328daSJiri Kosina [0x0a] = BTN_TR2, /* R2 */ 789078328daSJiri Kosina [0x0b] = BTN_TL, /* L1 */ 790078328daSJiri Kosina [0x0c] = BTN_TR, /* R1 */ 791078328daSJiri Kosina [0x0d] = KEY_OPTION, /* options/triangle */ 792078328daSJiri Kosina [0x0e] = KEY_BACK, /* back/circle */ 793078328daSJiri Kosina [0x0f] = BTN_0, /* cross */ 794078328daSJiri Kosina [0x10] = KEY_SCREEN, /* view/square */ 795078328daSJiri Kosina [0x11] = KEY_HOMEPAGE, /* PS button */ 796078328daSJiri Kosina [0x14] = KEY_ENTER, 797078328daSJiri Kosina }; 798078328daSJiri Kosina static const unsigned int ps3remote_keymap_remote_buttons[] = { 799078328daSJiri Kosina [0x00] = KEY_1, 800078328daSJiri Kosina [0x01] = KEY_2, 801078328daSJiri Kosina [0x02] = KEY_3, 802078328daSJiri Kosina [0x03] = KEY_4, 803078328daSJiri Kosina [0x04] = KEY_5, 804078328daSJiri Kosina [0x05] = KEY_6, 805078328daSJiri Kosina [0x06] = KEY_7, 806078328daSJiri Kosina [0x07] = KEY_8, 807078328daSJiri Kosina [0x08] = KEY_9, 808078328daSJiri Kosina [0x09] = KEY_0, 809078328daSJiri Kosina [0x0e] = KEY_ESC, /* return */ 810078328daSJiri Kosina [0x0f] = KEY_CLEAR, 811078328daSJiri Kosina [0x16] = KEY_EJECTCD, 812078328daSJiri Kosina [0x1a] = KEY_MENU, /* top menu */ 813078328daSJiri Kosina [0x28] = KEY_TIME, 814078328daSJiri Kosina [0x30] = KEY_PREVIOUS, 815078328daSJiri Kosina [0x31] = KEY_NEXT, 816078328daSJiri Kosina [0x32] = KEY_PLAY, 817078328daSJiri Kosina [0x33] = KEY_REWIND, /* scan back */ 818078328daSJiri Kosina [0x34] = KEY_FORWARD, /* scan forward */ 819078328daSJiri Kosina [0x38] = KEY_STOP, 820078328daSJiri Kosina [0x39] = KEY_PAUSE, 821078328daSJiri Kosina [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ 822078328daSJiri Kosina [0x60] = KEY_FRAMEBACK, /* slow/step back */ 823078328daSJiri Kosina [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ 824078328daSJiri Kosina [0x63] = KEY_SUBTITLE, 825078328daSJiri Kosina [0x64] = KEY_AUDIO, 826078328daSJiri Kosina [0x65] = KEY_ANGLE, 827078328daSJiri Kosina [0x70] = KEY_INFO, /* display */ 828078328daSJiri Kosina [0x80] = KEY_BLUE, 829078328daSJiri Kosina [0x81] = KEY_RED, 830078328daSJiri Kosina [0x82] = KEY_GREEN, 831078328daSJiri Kosina [0x83] = KEY_YELLOW, 832078328daSJiri Kosina }; 833078328daSJiri Kosina 834f04d5140SColin Leitner static const unsigned int buzz_keymap[] = { 835ad142b9eSFrank Praznik /* 836ad142b9eSFrank Praznik * The controller has 4 remote buzzers, each with one LED and 5 837f04d5140SColin Leitner * buttons. 838f04d5140SColin Leitner * 839f04d5140SColin Leitner * We use the mapping chosen by the controller, which is: 840f04d5140SColin Leitner * 841f04d5140SColin Leitner * Key Offset 842f04d5140SColin Leitner * ------------------- 843f04d5140SColin Leitner * Buzz 1 844f04d5140SColin Leitner * Blue 5 845f04d5140SColin Leitner * Orange 4 846f04d5140SColin Leitner * Green 3 847f04d5140SColin Leitner * Yellow 2 848f04d5140SColin Leitner * 849f04d5140SColin Leitner * So, for example, the orange button on the third buzzer is mapped to 850f04d5140SColin Leitner * BTN_TRIGGER_HAPPY14 851f04d5140SColin Leitner */ 852f04d5140SColin Leitner [ 1] = BTN_TRIGGER_HAPPY1, 853f04d5140SColin Leitner [ 2] = BTN_TRIGGER_HAPPY2, 854f04d5140SColin Leitner [ 3] = BTN_TRIGGER_HAPPY3, 855f04d5140SColin Leitner [ 4] = BTN_TRIGGER_HAPPY4, 856f04d5140SColin Leitner [ 5] = BTN_TRIGGER_HAPPY5, 857f04d5140SColin Leitner [ 6] = BTN_TRIGGER_HAPPY6, 858f04d5140SColin Leitner [ 7] = BTN_TRIGGER_HAPPY7, 859f04d5140SColin Leitner [ 8] = BTN_TRIGGER_HAPPY8, 860f04d5140SColin Leitner [ 9] = BTN_TRIGGER_HAPPY9, 861f04d5140SColin Leitner [10] = BTN_TRIGGER_HAPPY10, 862f04d5140SColin Leitner [11] = BTN_TRIGGER_HAPPY11, 863f04d5140SColin Leitner [12] = BTN_TRIGGER_HAPPY12, 864f04d5140SColin Leitner [13] = BTN_TRIGGER_HAPPY13, 865f04d5140SColin Leitner [14] = BTN_TRIGGER_HAPPY14, 866f04d5140SColin Leitner [15] = BTN_TRIGGER_HAPPY15, 867f04d5140SColin Leitner [16] = BTN_TRIGGER_HAPPY16, 868f04d5140SColin Leitner [17] = BTN_TRIGGER_HAPPY17, 869f04d5140SColin Leitner [18] = BTN_TRIGGER_HAPPY18, 870f04d5140SColin Leitner [19] = BTN_TRIGGER_HAPPY19, 871f04d5140SColin Leitner [20] = BTN_TRIGGER_HAPPY20, 872f04d5140SColin Leitner }; 873f04d5140SColin Leitner 874d902f472SFrank Praznik static enum power_supply_property sony_battery_props[] = { 875d902f472SFrank Praznik POWER_SUPPLY_PROP_PRESENT, 876d902f472SFrank Praznik POWER_SUPPLY_PROP_CAPACITY, 877d902f472SFrank Praznik POWER_SUPPLY_PROP_SCOPE, 878d902f472SFrank Praznik POWER_SUPPLY_PROP_STATUS, 879d902f472SFrank Praznik }; 880d902f472SFrank Praznik 88155d3b664SFrank Praznik struct sixaxis_led { 88255d3b664SFrank Praznik __u8 time_enabled; /* the total time the led is active (0xff means forever) */ 88355d3b664SFrank Praznik __u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ 88455d3b664SFrank Praznik __u8 enabled; 88555d3b664SFrank Praznik __u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ 88655d3b664SFrank Praznik __u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ 88755d3b664SFrank Praznik } __packed; 88855d3b664SFrank Praznik 88955d3b664SFrank Praznik struct sixaxis_rumble { 89055d3b664SFrank Praznik __u8 padding; 89155d3b664SFrank Praznik __u8 right_duration; /* Right motor duration (0xff means forever) */ 89255d3b664SFrank Praznik __u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ 89355d3b664SFrank Praznik __u8 left_duration; /* Left motor duration (0xff means forever) */ 89455d3b664SFrank Praznik __u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ 89555d3b664SFrank Praznik } __packed; 89655d3b664SFrank Praznik 89755d3b664SFrank Praznik struct sixaxis_output_report { 89855d3b664SFrank Praznik __u8 report_id; 89955d3b664SFrank Praznik struct sixaxis_rumble rumble; 90055d3b664SFrank Praznik __u8 padding[4]; 90155d3b664SFrank Praznik __u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ 90255d3b664SFrank Praznik struct sixaxis_led led[4]; /* LEDx at (4 - x) */ 90355d3b664SFrank Praznik struct sixaxis_led _reserved; /* LED5, not actually soldered */ 90455d3b664SFrank Praznik } __packed; 90555d3b664SFrank Praznik 90655d3b664SFrank Praznik union sixaxis_output_report_01 { 90755d3b664SFrank Praznik struct sixaxis_output_report data; 90855d3b664SFrank Praznik __u8 buf[36]; 90955d3b664SFrank Praznik }; 91055d3b664SFrank Praznik 911c5e0c1c4SFrank Praznik struct motion_output_report_02 { 912c5e0c1c4SFrank Praznik u8 type, zero; 913c5e0c1c4SFrank Praznik u8 r, g, b; 914c5e0c1c4SFrank Praznik u8 zero2; 915c5e0c1c4SFrank Praznik u8 rumble; 916c5e0c1c4SFrank Praznik }; 917c5e0c1c4SFrank Praznik 9189b2b5c9aSFrank Praznik #define DS4_REPORT_0x02_SIZE 37 9199b2b5c9aSFrank Praznik #define DS4_REPORT_0x05_SIZE 32 9209b2b5c9aSFrank Praznik #define DS4_REPORT_0x11_SIZE 78 9219b2b5c9aSFrank Praznik #define DS4_REPORT_0x81_SIZE 7 92229b691a8SAntonio Ospite #define SIXAXIS_REPORT_0xF2_SIZE 17 923a85d67b5SAntonio Ospite #define SIXAXIS_REPORT_0xF5_SIZE 8 92441d2d425SSimon Wood #define MOTION_REPORT_0x02_SIZE 49 9259b2b5c9aSFrank Praznik 9268b402c92SJiri Kosina static DEFINE_SPINLOCK(sony_dev_list_lock); 927d2d782fcSFrank Praznik static LIST_HEAD(sony_device_list); 9288025087aSFrank Praznik static DEFINE_IDA(sony_device_id_allocator); 929d2d782fcSFrank Praznik 930cc6e0bbbSJiri Kosina struct sony_sc { 931d902f472SFrank Praznik spinlock_t lock; 932d2d782fcSFrank Praznik struct list_head list_node; 9330a286ef2SSven Eckelmann struct hid_device *hdev; 93460781cf4SFrank Praznik struct led_classdev *leds[MAX_LEDS]; 935cc6e0bbbSJiri Kosina unsigned long quirks; 9360a286ef2SSven Eckelmann struct work_struct state_worker; 937297d716fSKrzysztof Kozlowski struct power_supply *battery; 938297d716fSKrzysztof Kozlowski struct power_supply_desc battery_desc; 9398025087aSFrank Praznik int device_id; 9409b2b5c9aSFrank Praznik __u8 *output_report_dmabuf; 941f04d5140SColin Leitner 9429f323b68SSven Eckelmann #ifdef CONFIG_SONY_FF 9439f323b68SSven Eckelmann __u8 left; 9449f323b68SSven Eckelmann __u8 right; 9459f323b68SSven Eckelmann #endif 9469f323b68SSven Eckelmann 947d2d782fcSFrank Praznik __u8 mac_address[6]; 9485f5750d2SFrank Praznik __u8 worker_initialized; 949d902f472SFrank Praznik __u8 cable_state; 950d902f472SFrank Praznik __u8 battery_charging; 951d902f472SFrank Praznik __u8 battery_capacity; 95260781cf4SFrank Praznik __u8 led_state[MAX_LEDS]; 953b3ed458cSFrank Praznik __u8 led_delay_on[MAX_LEDS]; 954b3ed458cSFrank Praznik __u8 led_delay_off[MAX_LEDS]; 95560781cf4SFrank Praznik __u8 led_count; 956cc6e0bbbSJiri Kosina }; 957cc6e0bbbSJiri Kosina 958c607fb8dSAntonio Ospite static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, 959c607fb8dSAntonio Ospite unsigned int *rsize) 960c607fb8dSAntonio Ospite { 961c607fb8dSAntonio Ospite *rsize = sizeof(sixaxis_rdesc); 962c607fb8dSAntonio Ospite return sixaxis_rdesc; 963c607fb8dSAntonio Ospite } 964c607fb8dSAntonio Ospite 965c5e0c1c4SFrank Praznik static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, 966c5e0c1c4SFrank Praznik unsigned int *rsize) 967c5e0c1c4SFrank Praznik { 968c5e0c1c4SFrank Praznik *rsize = sizeof(motion_rdesc); 969c5e0c1c4SFrank Praznik return motion_rdesc; 970c5e0c1c4SFrank Praznik } 971c5e0c1c4SFrank Praznik 972078328daSJiri Kosina static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, 973078328daSJiri Kosina unsigned int *rsize) 974078328daSJiri Kosina { 975078328daSJiri Kosina *rsize = sizeof(ps3remote_rdesc); 976078328daSJiri Kosina return ps3remote_rdesc; 977078328daSJiri Kosina } 978078328daSJiri Kosina 979078328daSJiri Kosina static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, 980078328daSJiri Kosina struct hid_field *field, struct hid_usage *usage, 981078328daSJiri Kosina unsigned long **bit, int *max) 982078328daSJiri Kosina { 983078328daSJiri Kosina unsigned int key = usage->hid & HID_USAGE; 984078328daSJiri Kosina 985078328daSJiri Kosina if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 986078328daSJiri Kosina return -1; 987078328daSJiri Kosina 988078328daSJiri Kosina switch (usage->collection_index) { 989078328daSJiri Kosina case 1: 990078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) 991078328daSJiri Kosina return -1; 992078328daSJiri Kosina 993078328daSJiri Kosina key = ps3remote_keymap_joypad_buttons[key]; 994078328daSJiri Kosina if (!key) 995078328daSJiri Kosina return -1; 996078328daSJiri Kosina break; 997078328daSJiri Kosina case 2: 998078328daSJiri Kosina if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) 999078328daSJiri Kosina return -1; 1000078328daSJiri Kosina 1001078328daSJiri Kosina key = ps3remote_keymap_remote_buttons[key]; 1002078328daSJiri Kosina if (!key) 1003078328daSJiri Kosina return -1; 1004078328daSJiri Kosina break; 1005078328daSJiri Kosina default: 1006078328daSJiri Kosina return -1; 1007078328daSJiri Kosina } 1008078328daSJiri Kosina 1009078328daSJiri Kosina hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1010078328daSJiri Kosina return 1; 1011078328daSJiri Kosina } 1012078328daSJiri Kosina 101373e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 101473e4008dSNikolai Kondrashov unsigned int *rsize) 1015cc6e0bbbSJiri Kosina { 1016cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev); 1017cc6e0bbbSJiri Kosina 101899d24902SFernando Luis Vázquez Cao /* 101999d24902SFernando Luis Vázquez Cao * Some Sony RF receivers wrongly declare the mouse pointer as a 102099d24902SFernando Luis Vázquez Cao * a constant non-data variable. 102199d24902SFernando Luis Vázquez Cao */ 102299d24902SFernando Luis Vázquez Cao if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 && 102399d24902SFernando Luis Vázquez Cao /* usage page: generic desktop controls */ 102499d24902SFernando Luis Vázquez Cao /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */ 102599d24902SFernando Luis Vázquez Cao /* usage: mouse */ 102699d24902SFernando Luis Vázquez Cao rdesc[2] == 0x09 && rdesc[3] == 0x02 && 102799d24902SFernando Luis Vázquez Cao /* input (usage page for x,y axes): constant, variable, relative */ 102899d24902SFernando Luis Vázquez Cao rdesc[54] == 0x81 && rdesc[55] == 0x07) { 1029a4649184SFernando Luis Vázquez Cao hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n"); 103099d24902SFernando Luis Vázquez Cao /* input: data, variable, relative */ 1031cc6e0bbbSJiri Kosina rdesc[55] = 0x06; 1032cc6e0bbbSJiri Kosina } 103361ab44beSSimon Wood 1034ed19d8cfSFrank Praznik /* 1035ed19d8cfSFrank Praznik * The default Dualshock 4 USB descriptor doesn't assign 1036ed19d8cfSFrank Praznik * the gyroscope values to corresponding axes so we need a 1037ed19d8cfSFrank Praznik * modified one. 1038ed19d8cfSFrank Praznik */ 1039ed19d8cfSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) { 1040ed19d8cfSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n"); 1041ed19d8cfSFrank Praznik rdesc = dualshock4_usb_rdesc; 1042ed19d8cfSFrank Praznik *rsize = sizeof(dualshock4_usb_rdesc); 1043d829674dSFrank Praznik } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) { 1044d829674dSFrank Praznik hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n"); 1045d829674dSFrank Praznik rdesc = dualshock4_bt_rdesc; 1046d829674dSFrank Praznik *rsize = sizeof(dualshock4_bt_rdesc); 1047ed19d8cfSFrank Praznik } 1048ed19d8cfSFrank Praznik 1049c607fb8dSAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER) 1050c607fb8dSAntonio Ospite return sixaxis_fixup(hdev, rdesc, rsize); 1051078328daSJiri Kosina 1052c5e0c1c4SFrank Praznik if (sc->quirks & MOTION_CONTROLLER) 1053c5e0c1c4SFrank Praznik return motion_fixup(hdev, rdesc, rsize); 1054c5e0c1c4SFrank Praznik 1055078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1056078328daSJiri Kosina return ps3remote_fixup(hdev, rdesc, rsize); 1057078328daSJiri Kosina 105873e4008dSNikolai Kondrashov return rdesc; 1059cc6e0bbbSJiri Kosina } 1060cc6e0bbbSJiri Kosina 1061d902f472SFrank Praznik static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) 1062d902f472SFrank Praznik { 1063d902f472SFrank Praznik static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; 1064d902f472SFrank Praznik unsigned long flags; 106512e9a6d7SSimon Wood int offset; 1066d902f472SFrank Praznik __u8 cable_state, battery_capacity, battery_charging; 1067d902f472SFrank Praznik 1068ad142b9eSFrank Praznik /* 1069ad142b9eSFrank Praznik * The sixaxis is charging if the battery value is 0xee 1070d902f472SFrank Praznik * and it is fully charged if the value is 0xef. 1071d902f472SFrank Praznik * It does not report the actual level while charging so it 1072d902f472SFrank Praznik * is set to 100% while charging is in progress. 1073d902f472SFrank Praznik */ 107412e9a6d7SSimon Wood offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30; 107512e9a6d7SSimon Wood 107612e9a6d7SSimon Wood if (rd[offset] >= 0xee) { 1077d902f472SFrank Praznik battery_capacity = 100; 107812e9a6d7SSimon Wood battery_charging = !(rd[offset] & 0x01); 10799fddd74aSFrank Praznik cable_state = 1; 1080d902f472SFrank Praznik } else { 108112e9a6d7SSimon Wood __u8 index = rd[offset] <= 5 ? rd[offset] : 5; 1082ac3c9a94SFrank Praznik battery_capacity = sixaxis_battery_capacity[index]; 1083d902f472SFrank Praznik battery_charging = 0; 10849fddd74aSFrank Praznik cable_state = 0; 1085d902f472SFrank Praznik } 1086d902f472SFrank Praznik 1087d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1088d902f472SFrank Praznik sc->cable_state = cable_state; 1089d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1090d902f472SFrank Praznik sc->battery_charging = battery_charging; 1091d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1092d902f472SFrank Praznik } 1093d902f472SFrank Praznik 1094d902f472SFrank Praznik static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) 1095d902f472SFrank Praznik { 1096e5606230SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 1097e5606230SFrank Praznik struct hid_input, list); 1098e5606230SFrank Praznik struct input_dev *input_dev = hidinput->input; 1099d902f472SFrank Praznik unsigned long flags; 11006c5f860dSFrank Praznik int n, offset; 1101d902f472SFrank Praznik __u8 cable_state, battery_capacity, battery_charging; 1102d902f472SFrank Praznik 1103ad142b9eSFrank Praznik /* 1104ad142b9eSFrank Praznik * Battery and touchpad data starts at byte 30 in the USB report and 11056c5f860dSFrank Praznik * 32 in Bluetooth report. 11066c5f860dSFrank Praznik */ 11076c5f860dSFrank Praznik offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32; 11086c5f860dSFrank Praznik 1109ad142b9eSFrank Praznik /* 1110ad142b9eSFrank Praznik * The lower 4 bits of byte 30 contain the battery level 1111d902f472SFrank Praznik * and the 5th bit contains the USB cable state. 1112d902f472SFrank Praznik */ 11136c5f860dSFrank Praznik cable_state = (rd[offset] >> 4) & 0x01; 11146c5f860dSFrank Praznik battery_capacity = rd[offset] & 0x0F; 1115d902f472SFrank Praznik 1116ad142b9eSFrank Praznik /* 1117ad142b9eSFrank Praznik * When a USB power source is connected the battery level ranges from 11186c5f860dSFrank Praznik * 0 to 10, and when running on battery power it ranges from 0 to 9. 11196c5f860dSFrank Praznik * A battery level above 10 when plugged in means charge completed. 1120d902f472SFrank Praznik */ 11216c5f860dSFrank Praznik if (!cable_state || battery_capacity > 10) 1122d902f472SFrank Praznik battery_charging = 0; 1123d902f472SFrank Praznik else 1124d902f472SFrank Praznik battery_charging = 1; 1125d902f472SFrank Praznik 11266c5f860dSFrank Praznik if (!cable_state) 11276c5f860dSFrank Praznik battery_capacity++; 1128d902f472SFrank Praznik if (battery_capacity > 10) 11296c5f860dSFrank Praznik battery_capacity = 10; 11306c5f860dSFrank Praznik 1131d902f472SFrank Praznik battery_capacity *= 10; 1132d902f472SFrank Praznik 1133d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1134d902f472SFrank Praznik sc->cable_state = cable_state; 1135d902f472SFrank Praznik sc->battery_capacity = battery_capacity; 1136d902f472SFrank Praznik sc->battery_charging = battery_charging; 1137d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1138e5606230SFrank Praznik 11396c5f860dSFrank Praznik offset += 5; 11406c5f860dSFrank Praznik 1141ad142b9eSFrank Praznik /* 1142ad142b9eSFrank Praznik * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB 11436c5f860dSFrank Praznik * and 37 on Bluetooth. 1144e5606230SFrank Praznik * The first 7 bits of the first byte is a counter and bit 8 is a touch 1145e5606230SFrank Praznik * indicator that is 0 when pressed and 1 when not pressed. 1146e5606230SFrank Praznik * The next 3 bytes are two 12 bit touch coordinates, X and Y. 1147e5606230SFrank Praznik * The data for the second touch is in the same format and immediatly 1148e5606230SFrank Praznik * follows the data for the first. 1149e5606230SFrank Praznik */ 1150e5606230SFrank Praznik for (n = 0; n < 2; n++) { 1151e5606230SFrank Praznik __u16 x, y; 1152e5606230SFrank Praznik 1153e5606230SFrank Praznik x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); 1154e5606230SFrank Praznik y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); 1155e5606230SFrank Praznik 1156e5606230SFrank Praznik input_mt_slot(input_dev, n); 1157e5606230SFrank Praznik input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1158e5606230SFrank Praznik !(rd[offset] >> 7)); 1159e5606230SFrank Praznik input_report_abs(input_dev, ABS_MT_POSITION_X, x); 1160e5606230SFrank Praznik input_report_abs(input_dev, ABS_MT_POSITION_Y, y); 1161e5606230SFrank Praznik 1162e5606230SFrank Praznik offset += 4; 1163e5606230SFrank Praznik } 1164d902f472SFrank Praznik } 1165d902f472SFrank Praznik 1166c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, 1167c9e4d877SSimon Wood __u8 *rd, int size) 1168c9e4d877SSimon Wood { 1169c9e4d877SSimon Wood struct sony_sc *sc = hid_get_drvdata(hdev); 1170c9e4d877SSimon Wood 1171ad142b9eSFrank Praznik /* 1172ad142b9eSFrank Praznik * Sixaxis HID report has acclerometers/gyro with MSByte first, this 1173c9e4d877SSimon Wood * has to be BYTE_SWAPPED before passing up to joystick interface 1174c9e4d877SSimon Wood */ 1175fee4e2d5SFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { 1176c9e4d877SSimon Wood swap(rd[41], rd[42]); 1177c9e4d877SSimon Wood swap(rd[43], rd[44]); 1178c9e4d877SSimon Wood swap(rd[45], rd[46]); 1179c9e4d877SSimon Wood swap(rd[47], rd[48]); 1180d902f472SFrank Praznik 1181d902f472SFrank Praznik sixaxis_parse_report(sc, rd, size); 118212e9a6d7SSimon Wood } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { 118312e9a6d7SSimon Wood sixaxis_parse_report(sc, rd, size); 118468330d83SFrank Praznik } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && 118568330d83SFrank Praznik size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) 118668330d83SFrank Praznik && rd[0] == 0x11 && size == 78)) { 1187d902f472SFrank Praznik dualshock4_parse_report(sc, rd, size); 1188c9e4d877SSimon Wood } 1189c9e4d877SSimon Wood 1190c9e4d877SSimon Wood return 0; 1191c9e4d877SSimon Wood } 1192c9e4d877SSimon Wood 1193f04d5140SColin Leitner static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, 1194f04d5140SColin Leitner struct hid_field *field, struct hid_usage *usage, 1195f04d5140SColin Leitner unsigned long **bit, int *max) 1196f04d5140SColin Leitner { 1197f04d5140SColin Leitner struct sony_sc *sc = hid_get_drvdata(hdev); 1198f04d5140SColin Leitner 1199f04d5140SColin Leitner if (sc->quirks & BUZZ_CONTROLLER) { 1200f04d5140SColin Leitner unsigned int key = usage->hid & HID_USAGE; 1201f04d5140SColin Leitner 1202f04d5140SColin Leitner if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) 1203f04d5140SColin Leitner return -1; 1204f04d5140SColin Leitner 1205f04d5140SColin Leitner switch (usage->collection_index) { 1206f04d5140SColin Leitner case 1: 1207f04d5140SColin Leitner if (key >= ARRAY_SIZE(buzz_keymap)) 1208f04d5140SColin Leitner return -1; 1209f04d5140SColin Leitner 1210f04d5140SColin Leitner key = buzz_keymap[key]; 1211f04d5140SColin Leitner if (!key) 1212f04d5140SColin Leitner return -1; 1213f04d5140SColin Leitner break; 1214f04d5140SColin Leitner default: 1215f04d5140SColin Leitner return -1; 1216f04d5140SColin Leitner } 1217f04d5140SColin Leitner 1218f04d5140SColin Leitner hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); 1219f04d5140SColin Leitner return 1; 1220f04d5140SColin Leitner } 1221f04d5140SColin Leitner 1222078328daSJiri Kosina if (sc->quirks & PS3REMOTE) 1223078328daSJiri Kosina return ps3remote_mapping(hdev, hi, field, usage, bit, max); 1224078328daSJiri Kosina 12256f498018SBenjamin Tissoires /* Let hid-core decide for the others */ 12266f498018SBenjamin Tissoires return 0; 1227f04d5140SColin Leitner } 1228f04d5140SColin Leitner 1229ce8efc3bSFrank Praznik static int sony_register_touchpad(struct hid_input *hi, int touch_count, 1230ce8efc3bSFrank Praznik int w, int h) 1231ce8efc3bSFrank Praznik { 1232ce8efc3bSFrank Praznik struct input_dev *input_dev = hi->input; 1233ce8efc3bSFrank Praznik int ret; 1234ce8efc3bSFrank Praznik 1235ce8efc3bSFrank Praznik ret = input_mt_init_slots(input_dev, touch_count, 0); 1236ce8efc3bSFrank Praznik if (ret < 0) 1237ce8efc3bSFrank Praznik return ret; 1238ce8efc3bSFrank Praznik 1239ce8efc3bSFrank Praznik input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0); 1240ce8efc3bSFrank Praznik input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0); 1241ce8efc3bSFrank Praznik 1242ce8efc3bSFrank Praznik return 0; 1243ce8efc3bSFrank Praznik } 1244ce8efc3bSFrank Praznik 1245ce8efc3bSFrank Praznik static void sony_input_configured(struct hid_device *hdev, 1246ce8efc3bSFrank Praznik struct hid_input *hidinput) 1247ce8efc3bSFrank Praznik { 1248ce8efc3bSFrank Praznik struct sony_sc *sc = hid_get_drvdata(hdev); 1249ce8efc3bSFrank Praznik 1250ce8efc3bSFrank Praznik /* 1251ce8efc3bSFrank Praznik * The Dualshock 4 touchpad supports 2 touches and has a 1252981c5b4aSFrank Praznik * resolution of 1920x942 (44.86 dots/mm). 1253ce8efc3bSFrank Praznik */ 1254ce8efc3bSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1255981c5b4aSFrank Praznik if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0) 1256ce8efc3bSFrank Praznik hid_err(sc->hdev, 1257ce8efc3bSFrank Praznik "Unable to initialize multi-touch slots\n"); 1258ce8efc3bSFrank Praznik } 1259ce8efc3bSFrank Praznik } 1260ce8efc3bSFrank Praznik 12615710fabfSAntonio Ospite /* 1262bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 1263bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any 1264bd28ce00SJiri Slaby * events. 1265bd28ce00SJiri Slaby */ 1266816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev) 1267bd28ce00SJiri Slaby { 1268a85d67b5SAntonio Ospite const int buf_size = 1269a85d67b5SAntonio Ospite max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); 12702e701a35SAntonio Ospite __u8 *buf; 1271bd28ce00SJiri Slaby int ret; 1272bd28ce00SJiri Slaby 12732e701a35SAntonio Ospite buf = kmalloc(buf_size, GFP_KERNEL); 1274bd28ce00SJiri Slaby if (!buf) 1275bd28ce00SJiri Slaby return -ENOMEM; 1276bd28ce00SJiri Slaby 1277a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE, 1278a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1279a7de9b86SLauri Kasanen if (ret < 0) { 1280a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 1\n"); 1281a7de9b86SLauri Kasanen goto out; 1282a7de9b86SLauri Kasanen } 1283f204828aSBenjamin Tissoires 1284a7de9b86SLauri Kasanen /* 1285a7de9b86SLauri Kasanen * Some compatible controllers like the Speedlink Strike FX and 1286a7de9b86SLauri Kasanen * Gasia need another query plus an USB interrupt to get operational. 1287a7de9b86SLauri Kasanen */ 1288a85d67b5SAntonio Ospite ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE, 1289a85d67b5SAntonio Ospite HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 1290a7de9b86SLauri Kasanen if (ret < 0) { 1291a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 2\n"); 1292a7de9b86SLauri Kasanen goto out; 1293a7de9b86SLauri Kasanen } 1294a7de9b86SLauri Kasanen 1295a7de9b86SLauri Kasanen ret = hid_hw_output_report(hdev, buf, 1); 1296bd28ce00SJiri Slaby if (ret < 0) 1297a7de9b86SLauri Kasanen hid_err(hdev, "can't set operational mode: step 3\n"); 1298bd28ce00SJiri Slaby 1299a7de9b86SLauri Kasanen out: 1300bd28ce00SJiri Slaby kfree(buf); 1301bd28ce00SJiri Slaby 1302bd28ce00SJiri Slaby return ret; 1303bd28ce00SJiri Slaby } 1304bd28ce00SJiri Slaby 1305816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev) 1306f9ce7c28SBastien Nocera { 13079b2b5c9aSFrank Praznik static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 13089b2b5c9aSFrank Praznik __u8 *buf; 13099b2b5c9aSFrank Praznik int ret; 13109b2b5c9aSFrank Praznik 13119b2b5c9aSFrank Praznik buf = kmemdup(report, sizeof(report), GFP_KERNEL); 13129b2b5c9aSFrank Praznik if (!buf) 13139b2b5c9aSFrank Praznik return -ENOMEM; 13149b2b5c9aSFrank Praznik 13159b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), 1316b0dd72aaSBenjamin Tissoires HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 13179b2b5c9aSFrank Praznik 13189b2b5c9aSFrank Praznik kfree(buf); 13199b2b5c9aSFrank Praznik 13209b2b5c9aSFrank Praznik return ret; 1321f9ce7c28SBastien Nocera } 1322f9ce7c28SBastien Nocera 1323ad142b9eSFrank Praznik /* 1324ad142b9eSFrank Praznik * Requesting feature report 0x02 in Bluetooth mode changes the state of the 132568330d83SFrank Praznik * controller so that it sends full input reports of type 0x11. 132668330d83SFrank Praznik */ 132768330d83SFrank Praznik static int dualshock4_set_operational_bt(struct hid_device *hdev) 132868330d83SFrank Praznik { 13299b2b5c9aSFrank Praznik __u8 *buf; 13309b2b5c9aSFrank Praznik int ret; 133168330d83SFrank Praznik 13329b2b5c9aSFrank Praznik buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); 13339b2b5c9aSFrank Praznik if (!buf) 13349b2b5c9aSFrank Praznik return -ENOMEM; 13359b2b5c9aSFrank Praznik 13369b2b5c9aSFrank Praznik ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, 133768330d83SFrank Praznik HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 13389b2b5c9aSFrank Praznik 13399b2b5c9aSFrank Praznik kfree(buf); 13409b2b5c9aSFrank Praznik 13419b2b5c9aSFrank Praznik return ret; 1342bd28ce00SJiri Slaby } 1343bd28ce00SJiri Slaby 1344221399b3SFrank Praznik static void sixaxis_set_leds_from_id(struct sony_sc *sc) 13458025087aSFrank Praznik { 13468025087aSFrank Praznik static const __u8 sixaxis_leds[10][4] = { 13478025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x00 }, 13488025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x00 }, 13498025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x00 }, 13508025087aSFrank Praznik { 0x00, 0x00, 0x00, 0x01 }, 13518025087aSFrank Praznik { 0x01, 0x00, 0x00, 0x01 }, 13528025087aSFrank Praznik { 0x00, 0x01, 0x00, 0x01 }, 13538025087aSFrank Praznik { 0x00, 0x00, 0x01, 0x01 }, 13548025087aSFrank Praznik { 0x01, 0x00, 0x01, 0x01 }, 13558025087aSFrank Praznik { 0x00, 0x01, 0x01, 0x01 }, 13568025087aSFrank Praznik { 0x01, 0x01, 0x01, 0x01 } 13578025087aSFrank Praznik }; 13588025087aSFrank Praznik 1359221399b3SFrank Praznik int id = sc->device_id; 1360221399b3SFrank Praznik 1361221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); 13628025087aSFrank Praznik 13638025087aSFrank Praznik if (id < 0) 13648025087aSFrank Praznik return; 13658025087aSFrank Praznik 13668025087aSFrank Praznik id %= 10; 1367221399b3SFrank Praznik memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id])); 13688025087aSFrank Praznik } 13698025087aSFrank Praznik 1370221399b3SFrank Praznik static void dualshock4_set_leds_from_id(struct sony_sc *sc) 13718025087aSFrank Praznik { 13728025087aSFrank Praznik /* The first 4 color/index entries match what the PS4 assigns */ 13738025087aSFrank Praznik static const __u8 color_code[7][3] = { 13748025087aSFrank Praznik /* Blue */ { 0x00, 0x00, 0x01 }, 13758025087aSFrank Praznik /* Red */ { 0x01, 0x00, 0x00 }, 13768025087aSFrank Praznik /* Green */ { 0x00, 0x01, 0x00 }, 13778025087aSFrank Praznik /* Pink */ { 0x02, 0x00, 0x01 }, 13788025087aSFrank Praznik /* Orange */ { 0x02, 0x01, 0x00 }, 13798025087aSFrank Praznik /* Teal */ { 0x00, 0x01, 0x01 }, 13808025087aSFrank Praznik /* White */ { 0x01, 0x01, 0x01 } 13818025087aSFrank Praznik }; 13828025087aSFrank Praznik 1383221399b3SFrank Praznik int id = sc->device_id; 1384221399b3SFrank Praznik 1385221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); 13868025087aSFrank Praznik 13878025087aSFrank Praznik if (id < 0) 13888025087aSFrank Praznik return; 13898025087aSFrank Praznik 13908025087aSFrank Praznik id %= 7; 1391221399b3SFrank Praznik memcpy(sc->led_state, color_code[id], sizeof(color_code[id])); 13928025087aSFrank Praznik } 13938025087aSFrank Praznik 1394221399b3SFrank Praznik static void buzz_set_leds(struct sony_sc *sc) 1395f04d5140SColin Leitner { 1396221399b3SFrank Praznik struct hid_device *hdev = sc->hdev; 1397f04d5140SColin Leitner struct list_head *report_list = 1398f04d5140SColin Leitner &hdev->report_enum[HID_OUTPUT_REPORT].report_list; 1399f04d5140SColin Leitner struct hid_report *report = list_entry(report_list->next, 1400f04d5140SColin Leitner struct hid_report, list); 1401f04d5140SColin Leitner __s32 *value = report->field[0]->value; 1402f04d5140SColin Leitner 1403221399b3SFrank Praznik BUILD_BUG_ON(MAX_LEDS < 4); 1404221399b3SFrank Praznik 1405f04d5140SColin Leitner value[0] = 0x00; 1406221399b3SFrank Praznik value[1] = sc->led_state[0] ? 0xff : 0x00; 1407221399b3SFrank Praznik value[2] = sc->led_state[1] ? 0xff : 0x00; 1408221399b3SFrank Praznik value[3] = sc->led_state[2] ? 0xff : 0x00; 1409221399b3SFrank Praznik value[4] = sc->led_state[3] ? 0xff : 0x00; 1410f04d5140SColin Leitner value[5] = 0x00; 1411f04d5140SColin Leitner value[6] = 0x00; 1412f04d5140SColin Leitner hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 1413f04d5140SColin Leitner } 1414f04d5140SColin Leitner 1415221399b3SFrank Praznik static void sony_set_leds(struct sony_sc *sc) 14160a286ef2SSven Eckelmann { 1417221399b3SFrank Praznik if (!(sc->quirks & BUZZ_CONTROLLER)) 1418fa57a810SFrank Praznik schedule_work(&sc->state_worker); 1419221399b3SFrank Praznik else 1420221399b3SFrank Praznik buzz_set_leds(sc); 14210a286ef2SSven Eckelmann } 14220a286ef2SSven Eckelmann 1423c5382519SSven Eckelmann static void sony_led_set_brightness(struct led_classdev *led, 1424f04d5140SColin Leitner enum led_brightness value) 1425f04d5140SColin Leitner { 1426f04d5140SColin Leitner struct device *dev = led->dev->parent; 1427f04d5140SColin Leitner struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1428f04d5140SColin Leitner struct sony_sc *drv_data; 1429f04d5140SColin Leitner 1430f04d5140SColin Leitner int n; 1431b3ed458cSFrank Praznik int force_update; 1432f04d5140SColin Leitner 1433f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 14342251b85fSSven Eckelmann if (!drv_data) { 1435f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1436f04d5140SColin Leitner return; 1437f04d5140SColin Leitner } 1438f04d5140SColin Leitner 1439b3ed458cSFrank Praznik /* 1440b3ed458cSFrank Praznik * The Sixaxis on USB will override any LED settings sent to it 1441b3ed458cSFrank Praznik * and keep flashing all of the LEDs until the PS button is pressed. 1442b3ed458cSFrank Praznik * Updates, even if redundant, must be always be sent to the 1443b3ed458cSFrank Praznik * controller to avoid having to toggle the state of an LED just to 1444b3ed458cSFrank Praznik * stop the flashing later on. 1445b3ed458cSFrank Praznik */ 1446b3ed458cSFrank Praznik force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB); 1447b3ed458cSFrank Praznik 144860781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1449b3ed458cSFrank Praznik if (led == drv_data->leds[n] && (force_update || 1450b3ed458cSFrank Praznik (value != drv_data->led_state[n] || 1451b3ed458cSFrank Praznik drv_data->led_delay_on[n] || 1452b3ed458cSFrank Praznik drv_data->led_delay_off[n]))) { 1453b3ed458cSFrank Praznik 145460781cf4SFrank Praznik drv_data->led_state[n] = value; 1455b3ed458cSFrank Praznik 1456b3ed458cSFrank Praznik /* Setting the brightness stops the blinking */ 1457b3ed458cSFrank Praznik drv_data->led_delay_on[n] = 0; 1458b3ed458cSFrank Praznik drv_data->led_delay_off[n] = 0; 1459b3ed458cSFrank Praznik 1460221399b3SFrank Praznik sony_set_leds(drv_data); 1461f04d5140SColin Leitner break; 1462f04d5140SColin Leitner } 1463f04d5140SColin Leitner } 1464f04d5140SColin Leitner } 1465f04d5140SColin Leitner 1466c5382519SSven Eckelmann static enum led_brightness sony_led_get_brightness(struct led_classdev *led) 1467f04d5140SColin Leitner { 1468f04d5140SColin Leitner struct device *dev = led->dev->parent; 1469f04d5140SColin Leitner struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1470f04d5140SColin Leitner struct sony_sc *drv_data; 1471f04d5140SColin Leitner 1472f04d5140SColin Leitner int n; 1473f04d5140SColin Leitner 1474f04d5140SColin Leitner drv_data = hid_get_drvdata(hdev); 14752251b85fSSven Eckelmann if (!drv_data) { 1476f04d5140SColin Leitner hid_err(hdev, "No device data\n"); 1477f04d5140SColin Leitner return LED_OFF; 1478f04d5140SColin Leitner } 1479f04d5140SColin Leitner 148060781cf4SFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 14817db7504aSSimon Wood if (led == drv_data->leds[n]) 14827db7504aSSimon Wood return drv_data->led_state[n]; 1483f04d5140SColin Leitner } 1484f04d5140SColin Leitner 14857db7504aSSimon Wood return LED_OFF; 1486f04d5140SColin Leitner } 1487f04d5140SColin Leitner 1488b3ed458cSFrank Praznik static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, 1489b3ed458cSFrank Praznik unsigned long *delay_off) 1490b3ed458cSFrank Praznik { 1491b3ed458cSFrank Praznik struct device *dev = led->dev->parent; 1492b3ed458cSFrank Praznik struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1493b3ed458cSFrank Praznik struct sony_sc *drv_data = hid_get_drvdata(hdev); 1494b3ed458cSFrank Praznik int n; 1495b3ed458cSFrank Praznik __u8 new_on, new_off; 1496b3ed458cSFrank Praznik 1497b3ed458cSFrank Praznik if (!drv_data) { 1498b3ed458cSFrank Praznik hid_err(hdev, "No device data\n"); 1499b3ed458cSFrank Praznik return -EINVAL; 1500b3ed458cSFrank Praznik } 1501b3ed458cSFrank Praznik 1502b3ed458cSFrank Praznik /* Max delay is 255 deciseconds or 2550 milliseconds */ 1503b3ed458cSFrank Praznik if (*delay_on > 2550) 1504b3ed458cSFrank Praznik *delay_on = 2550; 1505b3ed458cSFrank Praznik if (*delay_off > 2550) 1506b3ed458cSFrank Praznik *delay_off = 2550; 1507b3ed458cSFrank Praznik 1508b3ed458cSFrank Praznik /* Blink at 1 Hz if both values are zero */ 1509b3ed458cSFrank Praznik if (!*delay_on && !*delay_off) 1510b3ed458cSFrank Praznik *delay_on = *delay_off = 500; 1511b3ed458cSFrank Praznik 1512b3ed458cSFrank Praznik new_on = *delay_on / 10; 1513b3ed458cSFrank Praznik new_off = *delay_off / 10; 1514b3ed458cSFrank Praznik 1515b3ed458cSFrank Praznik for (n = 0; n < drv_data->led_count; n++) { 1516b3ed458cSFrank Praznik if (led == drv_data->leds[n]) 1517b3ed458cSFrank Praznik break; 1518b3ed458cSFrank Praznik } 1519b3ed458cSFrank Praznik 1520b3ed458cSFrank Praznik /* This LED is not registered on this device */ 1521b3ed458cSFrank Praznik if (n >= drv_data->led_count) 1522b3ed458cSFrank Praznik return -EINVAL; 1523b3ed458cSFrank Praznik 1524b3ed458cSFrank Praznik /* Don't schedule work if the values didn't change */ 1525b3ed458cSFrank Praznik if (new_on != drv_data->led_delay_on[n] || 1526b3ed458cSFrank Praznik new_off != drv_data->led_delay_off[n]) { 1527b3ed458cSFrank Praznik drv_data->led_delay_on[n] = new_on; 1528b3ed458cSFrank Praznik drv_data->led_delay_off[n] = new_off; 1529b3ed458cSFrank Praznik schedule_work(&drv_data->state_worker); 1530b3ed458cSFrank Praznik } 1531b3ed458cSFrank Praznik 1532b3ed458cSFrank Praznik return 0; 1533b3ed458cSFrank Praznik } 1534b3ed458cSFrank Praznik 1535fa57a810SFrank Praznik static void sony_leds_remove(struct sony_sc *sc) 15360a286ef2SSven Eckelmann { 15370a286ef2SSven Eckelmann struct led_classdev *led; 15380a286ef2SSven Eckelmann int n; 15390a286ef2SSven Eckelmann 1540fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 15410a286ef2SSven Eckelmann 1542fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 1543fa57a810SFrank Praznik led = sc->leds[n]; 1544fa57a810SFrank Praznik sc->leds[n] = NULL; 15450a286ef2SSven Eckelmann if (!led) 15460a286ef2SSven Eckelmann continue; 15470a286ef2SSven Eckelmann led_classdev_unregister(led); 15480a286ef2SSven Eckelmann kfree(led); 15490a286ef2SSven Eckelmann } 155060781cf4SFrank Praznik 1551fa57a810SFrank Praznik sc->led_count = 0; 15520a286ef2SSven Eckelmann } 15530a286ef2SSven Eckelmann 1554fa57a810SFrank Praznik static int sony_leds_init(struct sony_sc *sc) 1555f04d5140SColin Leitner { 1556fa57a810SFrank Praznik struct hid_device *hdev = sc->hdev; 155740e32ee6SJiri Kosina int n, ret = 0; 1558b3ed458cSFrank Praznik int use_ds4_names; 155940e32ee6SJiri Kosina struct led_classdev *led; 156040e32ee6SJiri Kosina size_t name_sz; 156140e32ee6SJiri Kosina char *name; 15620a286ef2SSven Eckelmann size_t name_len; 15630a286ef2SSven Eckelmann const char *name_fmt; 1564b3ed458cSFrank Praznik static const char * const ds4_name_str[] = { "red", "green", "blue", 1565b3ed458cSFrank Praznik "global" }; 15665607c89aSFrank Praznik __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; 1567b3ed458cSFrank Praznik __u8 use_hw_blink[MAX_LEDS] = { 0 }; 1568f04d5140SColin Leitner 1569fa57a810SFrank Praznik BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); 1570f04d5140SColin Leitner 1571fa57a810SFrank Praznik if (sc->quirks & BUZZ_CONTROLLER) { 1572fa57a810SFrank Praznik sc->led_count = 4; 1573b3ed458cSFrank Praznik use_ds4_names = 0; 15740a286ef2SSven Eckelmann name_len = strlen("::buzz#"); 15750a286ef2SSven Eckelmann name_fmt = "%s::buzz%d"; 15769446edb9SKees Cook /* Validate expected report characteristics. */ 15779446edb9SKees Cook if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) 15789446edb9SKees Cook return -ENODEV; 1579fa57a810SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 1580221399b3SFrank Praznik dualshock4_set_leds_from_id(sc); 1581221399b3SFrank Praznik sc->led_state[3] = 1; 1582b3ed458cSFrank Praznik sc->led_count = 4; 1583b3ed458cSFrank Praznik memset(max_brightness, 255, 3); 1584b3ed458cSFrank Praznik use_hw_blink[3] = 1; 1585b3ed458cSFrank Praznik use_ds4_names = 1; 158661ebca93SFrank Praznik name_len = 0; 158761ebca93SFrank Praznik name_fmt = "%s:%s"; 1588c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 1589c5e0c1c4SFrank Praznik sc->led_count = 3; 1590c5e0c1c4SFrank Praznik memset(max_brightness, 255, 3); 1591c5e0c1c4SFrank Praznik use_ds4_names = 1; 1592c5e0c1c4SFrank Praznik name_len = 0; 1593c5e0c1c4SFrank Praznik name_fmt = "%s:%s"; 159460781cf4SFrank Praznik } else { 1595221399b3SFrank Praznik sixaxis_set_leds_from_id(sc); 1596fa57a810SFrank Praznik sc->led_count = 4; 1597b3ed458cSFrank Praznik memset(use_hw_blink, 1, 4); 1598b3ed458cSFrank Praznik use_ds4_names = 0; 159961ebca93SFrank Praznik name_len = strlen("::sony#"); 160061ebca93SFrank Praznik name_fmt = "%s::sony%d"; 160160781cf4SFrank Praznik } 160260781cf4SFrank Praznik 1603ad142b9eSFrank Praznik /* 1604ad142b9eSFrank Praznik * Clear LEDs as we have no way of reading their initial state. This is 1605f04d5140SColin Leitner * only relevant if the driver is loaded after somebody actively set the 1606ad142b9eSFrank Praznik * LEDs to on 1607ad142b9eSFrank Praznik */ 1608221399b3SFrank Praznik sony_set_leds(sc); 1609f04d5140SColin Leitner 16100a286ef2SSven Eckelmann name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; 1611f04d5140SColin Leitner 1612fa57a810SFrank Praznik for (n = 0; n < sc->led_count; n++) { 161361ebca93SFrank Praznik 1614b3ed458cSFrank Praznik if (use_ds4_names) 1615b3ed458cSFrank Praznik name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2; 161661ebca93SFrank Praznik 1617f04d5140SColin Leitner led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); 1618f04d5140SColin Leitner if (!led) { 1619f04d5140SColin Leitner hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); 16208cd5fcdaSJulia Lawall ret = -ENOMEM; 1621f04d5140SColin Leitner goto error_leds; 1622f04d5140SColin Leitner } 1623f04d5140SColin Leitner 1624f04d5140SColin Leitner name = (void *)(&led[1]); 1625b3ed458cSFrank Praznik if (use_ds4_names) 1626b3ed458cSFrank Praznik snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), 1627b3ed458cSFrank Praznik ds4_name_str[n]); 162861ebca93SFrank Praznik else 16290a286ef2SSven Eckelmann snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); 1630f04d5140SColin Leitner led->name = name; 1631221399b3SFrank Praznik led->brightness = sc->led_state[n]; 1632b3ed458cSFrank Praznik led->max_brightness = max_brightness[n]; 1633c5382519SSven Eckelmann led->brightness_get = sony_led_get_brightness; 1634c5382519SSven Eckelmann led->brightness_set = sony_led_set_brightness; 1635f04d5140SColin Leitner 1636b3ed458cSFrank Praznik if (use_hw_blink[n]) 1637b3ed458cSFrank Praznik led->blink_set = sony_led_blink_set; 1638b3ed458cSFrank Praznik 16398025087aSFrank Praznik sc->leds[n] = led; 16408025087aSFrank Praznik 16418cd5fcdaSJulia Lawall ret = led_classdev_register(&hdev->dev, led); 16428cd5fcdaSJulia Lawall if (ret) { 1643f04d5140SColin Leitner hid_err(hdev, "Failed to register LED %d\n", n); 16448025087aSFrank Praznik sc->leds[n] = NULL; 1645f04d5140SColin Leitner kfree(led); 1646f04d5140SColin Leitner goto error_leds; 1647f04d5140SColin Leitner } 1648f04d5140SColin Leitner } 1649f04d5140SColin Leitner 1650f04d5140SColin Leitner return ret; 1651f04d5140SColin Leitner 1652f04d5140SColin Leitner error_leds: 1653fa57a810SFrank Praznik sony_leds_remove(sc); 1654f04d5140SColin Leitner 1655f04d5140SColin Leitner return ret; 1656f04d5140SColin Leitner } 1657f04d5140SColin Leitner 1658cad665a2SFrank Praznik static void sixaxis_state_worker(struct work_struct *work) 1659a08c22c0SSven Eckelmann { 16609b2b5c9aSFrank Praznik static const union sixaxis_output_report_01 default_report = { 166155d3b664SFrank Praznik .buf = { 1662a08c22c0SSven Eckelmann 0x01, 1663a08c22c0SSven Eckelmann 0x00, 0xff, 0x00, 0xff, 0x00, 16640a286ef2SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00, 1665a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1666a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1667a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1668a08c22c0SSven Eckelmann 0xff, 0x27, 0x10, 0x00, 0x32, 1669a08c22c0SSven Eckelmann 0x00, 0x00, 0x00, 0x00, 0x00 167055d3b664SFrank Praznik } 1671a08c22c0SSven Eckelmann }; 16729b2b5c9aSFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 16739b2b5c9aSFrank Praznik struct sixaxis_output_report *report = 16749b2b5c9aSFrank Praznik (struct sixaxis_output_report *)sc->output_report_dmabuf; 16759b2b5c9aSFrank Praznik int n; 16769b2b5c9aSFrank Praznik 16779b2b5c9aSFrank Praznik /* Initialize the report with default values */ 16789b2b5c9aSFrank Praznik memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); 16799f323b68SSven Eckelmann 16800a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 16819b2b5c9aSFrank Praznik report->rumble.right_motor_on = sc->right ? 1 : 0; 16829b2b5c9aSFrank Praznik report->rumble.left_motor_force = sc->left; 16830a286ef2SSven Eckelmann #endif 16840a286ef2SSven Eckelmann 16859b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[0] << 1; 16869b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[1] << 2; 16879b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[2] << 3; 16889b2b5c9aSFrank Praznik report->leds_bitmap |= sc->led_state[3] << 4; 16899f323b68SSven Eckelmann 169088f6576fSSimon Wood /* Set flag for all leds off, required for 3rd party INTEC controller */ 16919b2b5c9aSFrank Praznik if ((report->leds_bitmap & 0x1E) == 0) 16929b2b5c9aSFrank Praznik report->leds_bitmap |= 0x20; 169388f6576fSSimon Wood 1694b3ed458cSFrank Praznik /* 1695b3ed458cSFrank Praznik * The LEDs in the report are indexed in reverse order to their 1696b3ed458cSFrank Praznik * corresponding light on the controller. 1697b3ed458cSFrank Praznik * Index 0 = LED 4, index 1 = LED 3, etc... 1698b3ed458cSFrank Praznik * 1699b3ed458cSFrank Praznik * In the case of both delay values being zero (blinking disabled) the 1700b3ed458cSFrank Praznik * default report values should be used or the controller LED will be 1701b3ed458cSFrank Praznik * always off. 1702b3ed458cSFrank Praznik */ 1703b3ed458cSFrank Praznik for (n = 0; n < 4; n++) { 1704b3ed458cSFrank Praznik if (sc->led_delay_on[n] || sc->led_delay_off[n]) { 17059b2b5c9aSFrank Praznik report->led[3 - n].duty_off = sc->led_delay_off[n]; 17069b2b5c9aSFrank Praznik report->led[3 - n].duty_on = sc->led_delay_on[n]; 1707b3ed458cSFrank Praznik } 1708b3ed458cSFrank Praznik } 1709b3ed458cSFrank Praznik 17109b2b5c9aSFrank Praznik hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, 17119b2b5c9aSFrank Praznik sizeof(struct sixaxis_output_report), 17129b2b5c9aSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 17139f323b68SSven Eckelmann } 17149f323b68SSven Eckelmann 17150bd88dd3SFrank Praznik static void dualshock4_state_worker(struct work_struct *work) 17160bd88dd3SFrank Praznik { 17170bd88dd3SFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 17180da8ea65SFrank Praznik struct hid_device *hdev = sc->hdev; 17199b2b5c9aSFrank Praznik __u8 *buf = sc->output_report_dmabuf; 172048220237SFrank Praznik int offset; 17210da8ea65SFrank Praznik 1722fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 17239b2b5c9aSFrank Praznik memset(buf, 0, DS4_REPORT_0x05_SIZE); 172448220237SFrank Praznik buf[0] = 0x05; 1725b3ed458cSFrank Praznik buf[1] = 0xFF; 172648220237SFrank Praznik offset = 4; 1727fdcf105dSFrank Praznik } else { 17289b2b5c9aSFrank Praznik memset(buf, 0, DS4_REPORT_0x11_SIZE); 1729fdcf105dSFrank Praznik buf[0] = 0x11; 1730fdcf105dSFrank Praznik buf[1] = 0xB0; 1731fdcf105dSFrank Praznik buf[3] = 0x0F; 1732fdcf105dSFrank Praznik offset = 6; 1733fdcf105dSFrank Praznik } 17340bd88dd3SFrank Praznik 17350bd88dd3SFrank Praznik #ifdef CONFIG_SONY_FF 173648220237SFrank Praznik buf[offset++] = sc->right; 173748220237SFrank Praznik buf[offset++] = sc->left; 173848220237SFrank Praznik #else 173948220237SFrank Praznik offset += 2; 17400bd88dd3SFrank Praznik #endif 17410bd88dd3SFrank Praznik 1742b3ed458cSFrank Praznik /* LED 3 is the global control */ 1743b3ed458cSFrank Praznik if (sc->led_state[3]) { 174448220237SFrank Praznik buf[offset++] = sc->led_state[0]; 174548220237SFrank Praznik buf[offset++] = sc->led_state[1]; 174648220237SFrank Praznik buf[offset++] = sc->led_state[2]; 1747b3ed458cSFrank Praznik } else { 1748b3ed458cSFrank Praznik offset += 3; 1749b3ed458cSFrank Praznik } 1750b3ed458cSFrank Praznik 1751b3ed458cSFrank Praznik /* If both delay values are zero the DualShock 4 disables blinking. */ 1752b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_on[3]; 1753b3ed458cSFrank Praznik buf[offset++] = sc->led_delay_off[3]; 175460781cf4SFrank Praznik 1755fdcf105dSFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 17569b2b5c9aSFrank Praznik hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); 1757fdcf105dSFrank Praznik else 17589b2b5c9aSFrank Praznik hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, 1759fdcf105dSFrank Praznik HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 17600bd88dd3SFrank Praznik } 17610bd88dd3SFrank Praznik 1762c5e0c1c4SFrank Praznik static void motion_state_worker(struct work_struct *work) 1763c5e0c1c4SFrank Praznik { 1764c5e0c1c4SFrank Praznik struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 1765c5e0c1c4SFrank Praznik struct hid_device *hdev = sc->hdev; 1766c5e0c1c4SFrank Praznik struct motion_output_report_02 *report = 1767c5e0c1c4SFrank Praznik (struct motion_output_report_02 *)sc->output_report_dmabuf; 1768c5e0c1c4SFrank Praznik 176941d2d425SSimon Wood memset(report, 0, MOTION_REPORT_0x02_SIZE); 1770c5e0c1c4SFrank Praznik 1771c5e0c1c4SFrank Praznik report->type = 0x02; /* set leds */ 1772c5e0c1c4SFrank Praznik report->r = sc->led_state[0]; 1773c5e0c1c4SFrank Praznik report->g = sc->led_state[1]; 1774c5e0c1c4SFrank Praznik report->b = sc->led_state[2]; 1775c5e0c1c4SFrank Praznik 1776c5e0c1c4SFrank Praznik #ifdef CONFIG_SONY_FF 1777c5e0c1c4SFrank Praznik report->rumble = max(sc->right, sc->left); 1778c5e0c1c4SFrank Praznik #endif 1779c5e0c1c4SFrank Praznik 178041d2d425SSimon Wood hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); 1781c5e0c1c4SFrank Praznik } 1782c5e0c1c4SFrank Praznik 17839b2b5c9aSFrank Praznik static int sony_allocate_output_report(struct sony_sc *sc) 17849b2b5c9aSFrank Praznik { 17859b2b5c9aSFrank Praznik if (sc->quirks & SIXAXIS_CONTROLLER) 17869b2b5c9aSFrank Praznik sc->output_report_dmabuf = 17879b2b5c9aSFrank Praznik kmalloc(sizeof(union sixaxis_output_report_01), 17889b2b5c9aSFrank Praznik GFP_KERNEL); 17899b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) 17909b2b5c9aSFrank Praznik sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, 17919b2b5c9aSFrank Praznik GFP_KERNEL); 17929b2b5c9aSFrank Praznik else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) 17939b2b5c9aSFrank Praznik sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, 17949b2b5c9aSFrank Praznik GFP_KERNEL); 1795c5e0c1c4SFrank Praznik else if (sc->quirks & MOTION_CONTROLLER) 179641d2d425SSimon Wood sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, 1797c5e0c1c4SFrank Praznik GFP_KERNEL); 17989b2b5c9aSFrank Praznik else 17999b2b5c9aSFrank Praznik return 0; 18009b2b5c9aSFrank Praznik 18019b2b5c9aSFrank Praznik if (!sc->output_report_dmabuf) 18029b2b5c9aSFrank Praznik return -ENOMEM; 18039b2b5c9aSFrank Praznik 18049b2b5c9aSFrank Praznik return 0; 18059b2b5c9aSFrank Praznik } 18069b2b5c9aSFrank Praznik 18070a286ef2SSven Eckelmann #ifdef CONFIG_SONY_FF 18089f323b68SSven Eckelmann static int sony_play_effect(struct input_dev *dev, void *data, 18099f323b68SSven Eckelmann struct ff_effect *effect) 18109f323b68SSven Eckelmann { 1811a08c22c0SSven Eckelmann struct hid_device *hid = input_get_drvdata(dev); 18129f323b68SSven Eckelmann struct sony_sc *sc = hid_get_drvdata(hid); 1813a08c22c0SSven Eckelmann 1814a08c22c0SSven Eckelmann if (effect->type != FF_RUMBLE) 1815a08c22c0SSven Eckelmann return 0; 1816a08c22c0SSven Eckelmann 18179f323b68SSven Eckelmann sc->left = effect->u.rumble.strong_magnitude / 256; 18180bd88dd3SFrank Praznik sc->right = effect->u.rumble.weak_magnitude / 256; 1819a08c22c0SSven Eckelmann 182092b5c411SSven Eckelmann schedule_work(&sc->state_worker); 18219f323b68SSven Eckelmann return 0; 1822a08c22c0SSven Eckelmann } 1823a08c22c0SSven Eckelmann 1824fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 1825a08c22c0SSven Eckelmann { 1826fa57a810SFrank Praznik struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, 1827a08c22c0SSven Eckelmann struct hid_input, list); 1828a08c22c0SSven Eckelmann struct input_dev *input_dev = hidinput->input; 1829a08c22c0SSven Eckelmann 1830a08c22c0SSven Eckelmann input_set_capability(input_dev, EV_FF, FF_RUMBLE); 1831a08c22c0SSven Eckelmann return input_ff_create_memless(input_dev, NULL, sony_play_effect); 1832a08c22c0SSven Eckelmann } 1833a08c22c0SSven Eckelmann 1834a08c22c0SSven Eckelmann #else 1835fa57a810SFrank Praznik static int sony_init_ff(struct sony_sc *sc) 1836a08c22c0SSven Eckelmann { 1837a08c22c0SSven Eckelmann return 0; 1838a08c22c0SSven Eckelmann } 18399f323b68SSven Eckelmann 1840a08c22c0SSven Eckelmann #endif 1841a08c22c0SSven Eckelmann 1842d902f472SFrank Praznik static int sony_battery_get_property(struct power_supply *psy, 1843d902f472SFrank Praznik enum power_supply_property psp, 1844d902f472SFrank Praznik union power_supply_propval *val) 1845c4e1ddf2SFrank Praznik { 1846297d716fSKrzysztof Kozlowski struct sony_sc *sc = power_supply_get_drvdata(psy); 1847d902f472SFrank Praznik unsigned long flags; 1848d902f472SFrank Praznik int ret = 0; 1849d902f472SFrank Praznik u8 battery_charging, battery_capacity, cable_state; 1850c4e1ddf2SFrank Praznik 1851d902f472SFrank Praznik spin_lock_irqsave(&sc->lock, flags); 1852d902f472SFrank Praznik battery_charging = sc->battery_charging; 1853d902f472SFrank Praznik battery_capacity = sc->battery_capacity; 1854d902f472SFrank Praznik cable_state = sc->cable_state; 1855d902f472SFrank Praznik spin_unlock_irqrestore(&sc->lock, flags); 1856c4e1ddf2SFrank Praznik 1857d902f472SFrank Praznik switch (psp) { 1858d902f472SFrank Praznik case POWER_SUPPLY_PROP_PRESENT: 1859d902f472SFrank Praznik val->intval = 1; 1860d902f472SFrank Praznik break; 1861d902f472SFrank Praznik case POWER_SUPPLY_PROP_SCOPE: 1862d902f472SFrank Praznik val->intval = POWER_SUPPLY_SCOPE_DEVICE; 1863d902f472SFrank Praznik break; 1864d902f472SFrank Praznik case POWER_SUPPLY_PROP_CAPACITY: 1865d902f472SFrank Praznik val->intval = battery_capacity; 1866d902f472SFrank Praznik break; 1867d902f472SFrank Praznik case POWER_SUPPLY_PROP_STATUS: 1868d902f472SFrank Praznik if (battery_charging) 1869d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_CHARGING; 1870d902f472SFrank Praznik else 1871d902f472SFrank Praznik if (battery_capacity == 100 && cable_state) 1872d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_FULL; 1873d902f472SFrank Praznik else 1874d902f472SFrank Praznik val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 1875d902f472SFrank Praznik break; 1876d902f472SFrank Praznik default: 1877d902f472SFrank Praznik ret = -EINVAL; 1878d902f472SFrank Praznik break; 1879c4e1ddf2SFrank Praznik } 1880d902f472SFrank Praznik return ret; 1881d902f472SFrank Praznik } 1882d902f472SFrank Praznik 1883d902f472SFrank Praznik static int sony_battery_probe(struct sony_sc *sc) 1884d902f472SFrank Praznik { 1885297d716fSKrzysztof Kozlowski struct power_supply_config psy_cfg = { .drv_data = sc, }; 1886d902f472SFrank Praznik struct hid_device *hdev = sc->hdev; 1887d902f472SFrank Praznik int ret; 1888d902f472SFrank Praznik 1889ad142b9eSFrank Praznik /* 1890ad142b9eSFrank Praznik * Set the default battery level to 100% to avoid low battery warnings 1891d9a293a9SFrank Praznik * if the battery is polled before the first device report is received. 1892d9a293a9SFrank Praznik */ 1893d9a293a9SFrank Praznik sc->battery_capacity = 100; 1894d9a293a9SFrank Praznik 1895297d716fSKrzysztof Kozlowski sc->battery_desc.properties = sony_battery_props; 1896297d716fSKrzysztof Kozlowski sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props); 1897297d716fSKrzysztof Kozlowski sc->battery_desc.get_property = sony_battery_get_property; 1898297d716fSKrzysztof Kozlowski sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 1899297d716fSKrzysztof Kozlowski sc->battery_desc.use_for_apm = 0; 1900297d716fSKrzysztof Kozlowski sc->battery_desc.name = kasprintf(GFP_KERNEL, 1901297d716fSKrzysztof Kozlowski "sony_controller_battery_%pMR", 1902314531f1SFrank Praznik sc->mac_address); 1903297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 1904d902f472SFrank Praznik return -ENOMEM; 1905d902f472SFrank Praznik 1906297d716fSKrzysztof Kozlowski sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc, 1907297d716fSKrzysztof Kozlowski &psy_cfg); 1908297d716fSKrzysztof Kozlowski if (IS_ERR(sc->battery)) { 1909297d716fSKrzysztof Kozlowski ret = PTR_ERR(sc->battery); 1910d902f472SFrank Praznik hid_err(hdev, "Unable to register battery device\n"); 1911d902f472SFrank Praznik goto err_free; 1912d902f472SFrank Praznik } 1913d902f472SFrank Praznik 1914297d716fSKrzysztof Kozlowski power_supply_powers(sc->battery, &hdev->dev); 1915d902f472SFrank Praznik return 0; 1916d902f472SFrank Praznik 1917d902f472SFrank Praznik err_free: 1918297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 1919297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 1920d902f472SFrank Praznik return ret; 1921d902f472SFrank Praznik } 1922d902f472SFrank Praznik 1923d902f472SFrank Praznik static void sony_battery_remove(struct sony_sc *sc) 1924d902f472SFrank Praznik { 1925297d716fSKrzysztof Kozlowski if (!sc->battery_desc.name) 1926d902f472SFrank Praznik return; 1927d902f472SFrank Praznik 1928297d716fSKrzysztof Kozlowski power_supply_unregister(sc->battery); 1929297d716fSKrzysztof Kozlowski kfree(sc->battery_desc.name); 1930297d716fSKrzysztof Kozlowski sc->battery_desc.name = NULL; 1931d902f472SFrank Praznik } 1932d902f472SFrank Praznik 1933d2d782fcSFrank Praznik /* 1934d2d782fcSFrank Praznik * If a controller is plugged in via USB while already connected via Bluetooth 1935d2d782fcSFrank Praznik * it will show up as two devices. A global list of connected controllers and 1936d2d782fcSFrank Praznik * their MAC addresses is maintained to ensure that a device is only connected 1937d2d782fcSFrank Praznik * once. 1938d2d782fcSFrank Praznik */ 1939d2d782fcSFrank Praznik static int sony_check_add_dev_list(struct sony_sc *sc) 1940d2d782fcSFrank Praznik { 1941d2d782fcSFrank Praznik struct sony_sc *entry; 1942d2d782fcSFrank Praznik unsigned long flags; 1943d2d782fcSFrank Praznik int ret; 1944d2d782fcSFrank Praznik 1945d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 1946d2d782fcSFrank Praznik 1947d2d782fcSFrank Praznik list_for_each_entry(entry, &sony_device_list, list_node) { 1948d2d782fcSFrank Praznik ret = memcmp(sc->mac_address, entry->mac_address, 1949d2d782fcSFrank Praznik sizeof(sc->mac_address)); 1950d2d782fcSFrank Praznik if (!ret) { 1951d2d782fcSFrank Praznik ret = -EEXIST; 1952d2d782fcSFrank Praznik hid_info(sc->hdev, "controller with MAC address %pMR already connected\n", 1953d2d782fcSFrank Praznik sc->mac_address); 1954d2d782fcSFrank Praznik goto unlock; 1955d2d782fcSFrank Praznik } 1956c4e1ddf2SFrank Praznik } 1957c4e1ddf2SFrank Praznik 1958d2d782fcSFrank Praznik ret = 0; 1959d2d782fcSFrank Praznik list_add(&(sc->list_node), &sony_device_list); 1960c4e1ddf2SFrank Praznik 1961d2d782fcSFrank Praznik unlock: 1962d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 1963d2d782fcSFrank Praznik return ret; 1964d2d782fcSFrank Praznik } 1965d2d782fcSFrank Praznik 1966d2d782fcSFrank Praznik static void sony_remove_dev_list(struct sony_sc *sc) 1967d2d782fcSFrank Praznik { 1968d2d782fcSFrank Praznik unsigned long flags; 1969d2d782fcSFrank Praznik 1970d2d782fcSFrank Praznik if (sc->list_node.next) { 1971d2d782fcSFrank Praznik spin_lock_irqsave(&sony_dev_list_lock, flags); 1972d2d782fcSFrank Praznik list_del(&(sc->list_node)); 1973d2d782fcSFrank Praznik spin_unlock_irqrestore(&sony_dev_list_lock, flags); 1974d2d782fcSFrank Praznik } 1975d2d782fcSFrank Praznik } 1976d2d782fcSFrank Praznik 1977d2d782fcSFrank Praznik static int sony_get_bt_devaddr(struct sony_sc *sc) 1978d2d782fcSFrank Praznik { 1979d2d782fcSFrank Praznik int ret; 1980d2d782fcSFrank Praznik 1981d2d782fcSFrank Praznik /* HIDP stores the device MAC address as a string in the uniq field. */ 1982d2d782fcSFrank Praznik ret = strlen(sc->hdev->uniq); 1983d2d782fcSFrank Praznik if (ret != 17) 1984c4e1ddf2SFrank Praznik return -EINVAL; 1985d2d782fcSFrank Praznik 1986d2d782fcSFrank Praznik ret = sscanf(sc->hdev->uniq, 1987d2d782fcSFrank Praznik "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 1988d2d782fcSFrank Praznik &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3], 1989d2d782fcSFrank Praznik &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]); 1990d2d782fcSFrank Praznik 1991d2d782fcSFrank Praznik if (ret != 6) 1992d2d782fcSFrank Praznik return -EINVAL; 1993d2d782fcSFrank Praznik 1994d2d782fcSFrank Praznik return 0; 1995c4e1ddf2SFrank Praznik } 1996c4e1ddf2SFrank Praznik 1997d2d782fcSFrank Praznik static int sony_check_add(struct sony_sc *sc) 1998d2d782fcSFrank Praznik { 19999b2b5c9aSFrank Praznik __u8 *buf = NULL; 2000d2d782fcSFrank Praznik int n, ret; 2001d2d782fcSFrank Praznik 2002d2d782fcSFrank Praznik if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || 200312e9a6d7SSimon Wood (sc->quirks & MOTION_CONTROLLER_BT) || 2004d2d782fcSFrank Praznik (sc->quirks & SIXAXIS_CONTROLLER_BT)) { 2005d2d782fcSFrank Praznik /* 2006d2d782fcSFrank Praznik * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC 2007d2d782fcSFrank Praznik * address from the uniq string where HIDP stores it. 2008d2d782fcSFrank Praznik * As uniq cannot be guaranteed to be a MAC address in all cases 2009d2d782fcSFrank Praznik * a failure of this function should not prevent the connection. 2010d2d782fcSFrank Praznik */ 2011d2d782fcSFrank Praznik if (sony_get_bt_devaddr(sc) < 0) { 2012d2d782fcSFrank Praznik hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); 2013d2d782fcSFrank Praznik return 0; 2014d2d782fcSFrank Praznik } 2015d2d782fcSFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 20169b2b5c9aSFrank Praznik buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); 20179b2b5c9aSFrank Praznik if (!buf) 20189b2b5c9aSFrank Praznik return -ENOMEM; 2019d2d782fcSFrank Praznik 2020d2d782fcSFrank Praznik /* 2021d2d782fcSFrank Praznik * The MAC address of a DS4 controller connected via USB can be 2022d2d782fcSFrank Praznik * retrieved with feature report 0x81. The address begins at 2023d2d782fcSFrank Praznik * offset 1. 2024d2d782fcSFrank Praznik */ 20259b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0x81, buf, 20269b2b5c9aSFrank Praznik DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, 20279b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2028d2d782fcSFrank Praznik 20299b2b5c9aSFrank Praznik if (ret != DS4_REPORT_0x81_SIZE) { 2030d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); 20319b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 20329b2b5c9aSFrank Praznik goto out_free; 2033d2d782fcSFrank Praznik } 2034d2d782fcSFrank Praznik 2035d2d782fcSFrank Praznik memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); 2036d2d782fcSFrank Praznik } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { 20379b2b5c9aSFrank Praznik buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); 20389b2b5c9aSFrank Praznik if (!buf) 20399b2b5c9aSFrank Praznik return -ENOMEM; 2040d2d782fcSFrank Praznik 2041d2d782fcSFrank Praznik /* 2042d2d782fcSFrank Praznik * The MAC address of a Sixaxis controller connected via USB can 2043d2d782fcSFrank Praznik * be retrieved with feature report 0xf2. The address begins at 2044d2d782fcSFrank Praznik * offset 4. 2045d2d782fcSFrank Praznik */ 20469b2b5c9aSFrank Praznik ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, 20479b2b5c9aSFrank Praznik SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, 20489b2b5c9aSFrank Praznik HID_REQ_GET_REPORT); 2049d2d782fcSFrank Praznik 20509b2b5c9aSFrank Praznik if (ret != SIXAXIS_REPORT_0xF2_SIZE) { 2051d2d782fcSFrank Praznik hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); 20529b2b5c9aSFrank Praznik ret = ret < 0 ? ret : -EINVAL; 20539b2b5c9aSFrank Praznik goto out_free; 2054d2d782fcSFrank Praznik } 2055d2d782fcSFrank Praznik 2056d2d782fcSFrank Praznik /* 2057d2d782fcSFrank Praznik * The Sixaxis device MAC in the report is big-endian and must 2058d2d782fcSFrank Praznik * be byte-swapped. 2059d2d782fcSFrank Praznik */ 2060d2d782fcSFrank Praznik for (n = 0; n < 6; n++) 2061d2d782fcSFrank Praznik sc->mac_address[5-n] = buf[4+n]; 2062d2d782fcSFrank Praznik } else { 2063d2d782fcSFrank Praznik return 0; 2064d2d782fcSFrank Praznik } 2065d2d782fcSFrank Praznik 20669b2b5c9aSFrank Praznik ret = sony_check_add_dev_list(sc); 20679b2b5c9aSFrank Praznik 20689b2b5c9aSFrank Praznik out_free: 20699b2b5c9aSFrank Praznik 20709b2b5c9aSFrank Praznik kfree(buf); 20719b2b5c9aSFrank Praznik 20729b2b5c9aSFrank Praznik return ret; 2073d2d782fcSFrank Praznik } 2074d2d782fcSFrank Praznik 20758025087aSFrank Praznik static int sony_set_device_id(struct sony_sc *sc) 20768025087aSFrank Praznik { 20778025087aSFrank Praznik int ret; 20788025087aSFrank Praznik 20798025087aSFrank Praznik /* 20808025087aSFrank Praznik * Only DualShock 4 or Sixaxis controllers get an id. 20818025087aSFrank Praznik * All others are set to -1. 20828025087aSFrank Praznik */ 20838025087aSFrank Praznik if ((sc->quirks & SIXAXIS_CONTROLLER) || 20848025087aSFrank Praznik (sc->quirks & DUALSHOCK4_CONTROLLER)) { 20858025087aSFrank Praznik ret = ida_simple_get(&sony_device_id_allocator, 0, 0, 20868025087aSFrank Praznik GFP_KERNEL); 20878025087aSFrank Praznik if (ret < 0) { 20888025087aSFrank Praznik sc->device_id = -1; 20898025087aSFrank Praznik return ret; 20908025087aSFrank Praznik } 20918025087aSFrank Praznik sc->device_id = ret; 20928025087aSFrank Praznik } else { 20938025087aSFrank Praznik sc->device_id = -1; 20948025087aSFrank Praznik } 20958025087aSFrank Praznik 20968025087aSFrank Praznik return 0; 20978025087aSFrank Praznik } 20988025087aSFrank Praznik 20998025087aSFrank Praznik static void sony_release_device_id(struct sony_sc *sc) 21008025087aSFrank Praznik { 21018025087aSFrank Praznik if (sc->device_id >= 0) { 21028025087aSFrank Praznik ida_simple_remove(&sony_device_id_allocator, sc->device_id); 21038025087aSFrank Praznik sc->device_id = -1; 21048025087aSFrank Praznik } 21058025087aSFrank Praznik } 21068025087aSFrank Praznik 210746262047SFrank Praznik static inline void sony_init_work(struct sony_sc *sc, 210846262047SFrank Praznik void (*worker)(struct work_struct *)) 210946262047SFrank Praznik { 211046262047SFrank Praznik if (!sc->worker_initialized) 211146262047SFrank Praznik INIT_WORK(&sc->state_worker, worker); 211246262047SFrank Praznik 211346262047SFrank Praznik sc->worker_initialized = 1; 211446262047SFrank Praznik } 211546262047SFrank Praznik 211646262047SFrank Praznik static inline void sony_cancel_work_sync(struct sony_sc *sc) 211746262047SFrank Praznik { 211846262047SFrank Praznik if (sc->worker_initialized) 211946262047SFrank Praznik cancel_work_sync(&sc->state_worker); 212046262047SFrank Praznik } 2121d2d782fcSFrank Praznik 2122bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 2123bd28ce00SJiri Slaby { 2124bd28ce00SJiri Slaby int ret; 2125cc6e0bbbSJiri Kosina unsigned long quirks = id->driver_data; 2126cc6e0bbbSJiri Kosina struct sony_sc *sc; 2127f04d5140SColin Leitner unsigned int connect_mask = HID_CONNECT_DEFAULT; 2128cc6e0bbbSJiri Kosina 2129abf832bfSBenjamin Tissoires sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); 2130cc6e0bbbSJiri Kosina if (sc == NULL) { 21314291ee30SJoe Perches hid_err(hdev, "can't alloc sony descriptor\n"); 2132cc6e0bbbSJiri Kosina return -ENOMEM; 2133cc6e0bbbSJiri Kosina } 2134cc6e0bbbSJiri Kosina 2135b94993f6SFrank Praznik spin_lock_init(&sc->lock); 2136b94993f6SFrank Praznik 2137cc6e0bbbSJiri Kosina sc->quirks = quirks; 2138cc6e0bbbSJiri Kosina hid_set_drvdata(hdev, sc); 21390a286ef2SSven Eckelmann sc->hdev = hdev; 2140bd28ce00SJiri Slaby 2141bd28ce00SJiri Slaby ret = hid_parse(hdev); 2142bd28ce00SJiri Slaby if (ret) { 21434291ee30SJoe Perches hid_err(hdev, "parse failed\n"); 2144abf832bfSBenjamin Tissoires return ret; 2145bd28ce00SJiri Slaby } 2146bd28ce00SJiri Slaby 2147f04d5140SColin Leitner if (sc->quirks & VAIO_RDESC_CONSTANT) 2148f04d5140SColin Leitner connect_mask |= HID_CONNECT_HIDDEV_FORCE; 214950764650SAntonio Ospite else if (sc->quirks & SIXAXIS_CONTROLLER) 2150f04d5140SColin Leitner connect_mask |= HID_CONNECT_HIDDEV_FORCE; 2151f04d5140SColin Leitner 2152f04d5140SColin Leitner ret = hid_hw_start(hdev, connect_mask); 2153bd28ce00SJiri Slaby if (ret) { 21544291ee30SJoe Perches hid_err(hdev, "hw start failed\n"); 2155abf832bfSBenjamin Tissoires return ret; 2156bd28ce00SJiri Slaby } 2157bd28ce00SJiri Slaby 21588025087aSFrank Praznik ret = sony_set_device_id(sc); 21598025087aSFrank Praznik if (ret < 0) { 21608025087aSFrank Praznik hid_err(hdev, "failed to allocate the device id\n"); 21618025087aSFrank Praznik goto err_stop; 21628025087aSFrank Praznik } 21638025087aSFrank Praznik 2164131a8a9aSFrank Praznik ret = sony_allocate_output_report(sc); 2165131a8a9aSFrank Praznik if (ret < 0) { 2166131a8a9aSFrank Praznik hid_err(hdev, "failed to allocate the output report buffer\n"); 2167131a8a9aSFrank Praznik goto err_stop; 2168131a8a9aSFrank Praznik } 2169131a8a9aSFrank Praznik 2170569b10a5SAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER_USB) { 2171e534a935SBenjamin Tissoires /* 2172e534a935SBenjamin Tissoires * The Sony Sixaxis does not handle HID Output Reports on the 2173e534a935SBenjamin Tissoires * Interrupt EP like it could, so we need to force HID Output 2174e534a935SBenjamin Tissoires * Reports to use HID_REQ_SET_REPORT on the Control EP. 2175e534a935SBenjamin Tissoires * 2176e534a935SBenjamin Tissoires * There is also another issue about HID Output Reports via USB, 2177e534a935SBenjamin Tissoires * the Sixaxis does not want the report_id as part of the data 2178e534a935SBenjamin Tissoires * packet, so we have to discard buf[0] when sending the actual 2179e534a935SBenjamin Tissoires * control message, even for numbered reports, humpf! 2180e534a935SBenjamin Tissoires */ 2181e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2182e534a935SBenjamin Tissoires hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; 2183816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev); 218446262047SFrank Praznik sony_init_work(sc, sixaxis_state_worker); 2185fee4e2d5SFrank Praznik } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { 21862078b9bbSFrank Praznik /* 21872078b9bbSFrank Praznik * The Sixaxis wants output reports sent on the ctrl endpoint 21882078b9bbSFrank Praznik * when connected via Bluetooth. 21892078b9bbSFrank Praznik */ 21902078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2191816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev); 219246262047SFrank Praznik sony_init_work(sc, sixaxis_state_worker); 2193fee4e2d5SFrank Praznik } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { 219468330d83SFrank Praznik if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { 21952078b9bbSFrank Praznik /* 21962078b9bbSFrank Praznik * The DualShock 4 wants output reports sent on the ctrl 21972078b9bbSFrank Praznik * endpoint when connected via Bluetooth. 21982078b9bbSFrank Praznik */ 21992078b9bbSFrank Praznik hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 220068330d83SFrank Praznik ret = dualshock4_set_operational_bt(hdev); 220168330d83SFrank Praznik if (ret < 0) { 220268330d83SFrank Praznik hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); 220368330d83SFrank Praznik goto err_stop; 220468330d83SFrank Praznik } 220568330d83SFrank Praznik } 2206c4e1ddf2SFrank Praznik 220746262047SFrank Praznik sony_init_work(sc, dualshock4_state_worker); 2208c5e0c1c4SFrank Praznik } else if (sc->quirks & MOTION_CONTROLLER) { 2209c5e0c1c4SFrank Praznik sony_init_work(sc, motion_state_worker); 22100bd88dd3SFrank Praznik } else { 22110bd88dd3SFrank Praznik ret = 0; 22120bd88dd3SFrank Praznik } 2213f9ce7c28SBastien Nocera 22144dfdc464SJiri Kosina if (ret < 0) 2215bd28ce00SJiri Slaby goto err_stop; 2216bd28ce00SJiri Slaby 2217d2d782fcSFrank Praznik ret = sony_check_add(sc); 2218d2d782fcSFrank Praznik if (ret < 0) 2219d2d782fcSFrank Praznik goto err_stop; 2220d2d782fcSFrank Praznik 22210a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) { 2222fa57a810SFrank Praznik ret = sony_leds_init(sc); 22230a286ef2SSven Eckelmann if (ret < 0) 22240a286ef2SSven Eckelmann goto err_stop; 22250a286ef2SSven Eckelmann } 22260a286ef2SSven Eckelmann 2227d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 2228d902f472SFrank Praznik ret = sony_battery_probe(sc); 2229a08c22c0SSven Eckelmann if (ret < 0) 2230a08c22c0SSven Eckelmann goto err_stop; 2231a08c22c0SSven Eckelmann 2232d902f472SFrank Praznik /* Open the device to receive reports with battery info */ 2233d902f472SFrank Praznik ret = hid_hw_open(hdev); 2234d902f472SFrank Praznik if (ret < 0) { 2235d902f472SFrank Praznik hid_err(hdev, "hw open failed\n"); 2236d902f472SFrank Praznik goto err_stop; 2237d902f472SFrank Praznik } 2238d902f472SFrank Praznik } 2239d902f472SFrank Praznik 2240c8de9dbbSFrank Praznik if (sc->quirks & SONY_FF_SUPPORT) { 2241fa57a810SFrank Praznik ret = sony_init_ff(sc); 2242d902f472SFrank Praznik if (ret < 0) 2243d902f472SFrank Praznik goto err_close; 22445f5750d2SFrank Praznik } 2245bd28ce00SJiri Slaby 2246f425458eSH Hartley Sweeten return 0; 2247d902f472SFrank Praznik err_close: 2248d902f472SFrank Praznik hid_hw_close(hdev); 2249bd28ce00SJiri Slaby err_stop: 22500a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2251fa57a810SFrank Praznik sony_leds_remove(sc); 2252d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) 2253d902f472SFrank Praznik sony_battery_remove(sc); 225446262047SFrank Praznik sony_cancel_work_sync(sc); 22559b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 2256d2d782fcSFrank Praznik sony_remove_dev_list(sc); 22578025087aSFrank Praznik sony_release_device_id(sc); 2258bd28ce00SJiri Slaby hid_hw_stop(hdev); 2259bd28ce00SJiri Slaby return ret; 2260bd28ce00SJiri Slaby } 2261bd28ce00SJiri Slaby 2262bd28ce00SJiri Slaby static void sony_remove(struct hid_device *hdev) 2263bd28ce00SJiri Slaby { 2264bd28ce00SJiri Slaby struct sony_sc *sc = hid_get_drvdata(hdev); 2265bd28ce00SJiri Slaby 22660a286ef2SSven Eckelmann if (sc->quirks & SONY_LED_SUPPORT) 2267fa57a810SFrank Praznik sony_leds_remove(sc); 2268bd28ce00SJiri Slaby 2269d902f472SFrank Praznik if (sc->quirks & SONY_BATTERY_SUPPORT) { 2270d902f472SFrank Praznik hid_hw_close(hdev); 2271d902f472SFrank Praznik sony_battery_remove(sc); 2272d902f472SFrank Praznik } 2273d902f472SFrank Praznik 227446262047SFrank Praznik sony_cancel_work_sync(sc); 22759f323b68SSven Eckelmann 22769b2b5c9aSFrank Praznik kfree(sc->output_report_dmabuf); 22779b2b5c9aSFrank Praznik 2278d2d782fcSFrank Praznik sony_remove_dev_list(sc); 2279bd28ce00SJiri Slaby 22808025087aSFrank Praznik sony_release_device_id(sc); 22818025087aSFrank Praznik 2282bd28ce00SJiri Slaby hid_hw_stop(hdev); 2283bd28ce00SJiri Slaby } 2284bd28ce00SJiri Slaby 2285bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = { 2286bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2287bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_USB }, 2288bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 2289bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_USB }, 2290c5e0c1c4SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2291b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_USB }, 2292a4afa854SSimon Wood { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), 2293b3bca326SSimon Wood .driver_data = MOTION_CONTROLLER_BT }, 2294bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2295bd28ce00SJiri Slaby .driver_data = SIXAXIS_CONTROLLER_BT }, 2296bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 2297bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2298bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), 2299bd28ce00SJiri Slaby .driver_data = VAIO_RDESC_CONSTANT }, 2300bd28ce00SJiri Slaby /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as 2301bd28ce00SJiri Slaby * Logitech joystick from the device descriptor. */ 2302bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), 2303bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2304bd28ce00SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), 2305bd28ce00SJiri Slaby .driver_data = BUZZ_CONTROLLER }, 2306bd28ce00SJiri Slaby /* PS3 BD Remote Control */ 2307bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), 2308bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 2309bd28ce00SJiri Slaby /* Logitech Harmony Adapter for PS3 */ 2310bd28ce00SJiri Slaby { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), 2311bd28ce00SJiri Slaby .driver_data = PS3REMOTE }, 231268a49e51SFrank Praznik /* SMK-Link PS3 BD Remote Control */ 231368a49e51SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), 231468a49e51SFrank Praznik .driver_data = PS3REMOTE }, 23150bd88dd3SFrank Praznik /* Sony Dualshock 4 controllers for PS4 */ 23160bd88dd3SFrank Praznik { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 23178ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_USB }, 23180bd88dd3SFrank Praznik { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), 23198ab1676bSFrank Praznik .driver_data = DUALSHOCK4_CONTROLLER_BT }, 2320bd28ce00SJiri Slaby { } 2321bd28ce00SJiri Slaby }; 2322bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices); 2323bd28ce00SJiri Slaby 2324bd28ce00SJiri Slaby static struct hid_driver sony_driver = { 2325bd28ce00SJiri Slaby .name = "sony", 2326bd28ce00SJiri Slaby .id_table = sony_devices, 2327bd28ce00SJiri Slaby .input_mapping = sony_mapping, 2328ce8efc3bSFrank Praznik .input_configured = sony_input_configured, 2329bd28ce00SJiri Slaby .probe = sony_probe, 2330bd28ce00SJiri Slaby .remove = sony_remove, 2331bd28ce00SJiri Slaby .report_fixup = sony_report_fixup, 2332bd28ce00SJiri Slaby .raw_event = sony_raw_event 2333bd28ce00SJiri Slaby }; 23348025087aSFrank Praznik 23358025087aSFrank Praznik static int __init sony_init(void) 23368025087aSFrank Praznik { 23378025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 23388025087aSFrank Praznik 23398025087aSFrank Praznik return hid_register_driver(&sony_driver); 23408025087aSFrank Praznik } 23418025087aSFrank Praznik 23428025087aSFrank Praznik static void __exit sony_exit(void) 23438025087aSFrank Praznik { 23448025087aSFrank Praznik dbg_hid("Sony:%s\n", __func__); 23458025087aSFrank Praznik 23468025087aSFrank Praznik hid_unregister_driver(&sony_driver); 23476c40065fSAntonio Ospite ida_destroy(&sony_device_id_allocator); 23488025087aSFrank Praznik } 23498025087aSFrank Praznik module_init(sony_init); 23508025087aSFrank Praznik module_exit(sony_exit); 2351bd28ce00SJiri Slaby 2352bd28ce00SJiri Slaby MODULE_LICENSE("GPL"); 2353