1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 /* 32 * Sony PS4 DualShock 4 driver 33 * https://eleccelerator.com/wiki/index.php?title=DualShock_4 34 * https://gist.github.com/johndrinkwater/7708901 35 * https://www.psdevwiki.com/ps4/DS4-USB 36 */ 37 38 #include "opt_hid.h" 39 40 #include <sys/param.h> 41 #include <sys/bus.h> 42 #include <sys/kernel.h> 43 #include <sys/lock.h> 44 #include <sys/malloc.h> 45 #include <sys/module.h> 46 #include <sys/sx.h> 47 #include <sys/sysctl.h> 48 49 #include <dev/evdev/input.h> 50 #include <dev/evdev/evdev.h> 51 52 #define HID_DEBUG_VAR ps4dshock_debug 53 #include <dev/hid/hid.h> 54 #include <dev/hid/hidbus.h> 55 #include <dev/hid/hidquirk.h> 56 #include <dev/hid/hidmap.h> 57 #include "usbdevs.h" 58 59 #ifdef HID_DEBUG 60 static int ps4dshock_debug = 1; 61 62 static SYSCTL_NODE(_hw_hid, OID_AUTO, ps4dshock, CTLFLAG_RW, 0, 63 "Sony PS4 DualShock Gamepad"); 64 SYSCTL_INT(_hw_hid_ps4dshock, OID_AUTO, debug, CTLFLAG_RWTUN, 65 &ps4dshock_debug, 0, "Debug level"); 66 #endif 67 68 static const uint8_t ps4dshock_rdesc[] = { 69 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 70 0x09, 0x05, /* Usage (Game Pad) */ 71 0xA1, 0x01, /* Collection (Application) */ 72 0x85, 0x01, /* Report ID (1) */ 73 0x09, 0x30, /* Usage (X) */ 74 0x09, 0x31, /* Usage (Y) */ 75 0x09, 0x33, /* Usage (Rx) */ 76 0x09, 0x34, /* Usage (Ry) */ 77 0x15, 0x00, /* Logical Minimum (0) */ 78 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 79 0x75, 0x08, /* Report Size (8) */ 80 0x95, 0x04, /* Report Count (4) */ 81 0x81, 0x02, /* Input (Data,Var,Abs) */ 82 0x09, 0x39, /* Usage (Hat switch) */ 83 0x15, 0x00, /* Logical Minimum (0) */ 84 0x25, 0x07, /* Logical Maximum (7) */ 85 0x35, 0x00, /* Physical Minimum (0) */ 86 0x46, 0x3B, 0x01, /* Physical Maximum (315) */ 87 0x65, 0x14, /* Unit (System: English Rotation, Length: Centimeter) */ 88 0x75, 0x04, /* Report Size (4) */ 89 0x95, 0x01, /* Report Count (1) */ 90 0x81, 0x42, /* Input (Data,Var,Abs,Null State) */ 91 0x65, 0x00, /* Unit (None) */ 92 0x45, 0x00, /* Physical Maximum (0) */ 93 0x05, 0x09, /* Usage Page (Button) */ 94 0x19, 0x01, /* Usage Minimum (0x01) */ 95 0x29, 0x0E, /* Usage Maximum (0x0E) */ 96 0x15, 0x00, /* Logical Minimum (0) */ 97 0x25, 0x01, /* Logical Maximum (1) */ 98 0x75, 0x01, /* Report Size (1) */ 99 0x95, 0x0E, /* Report Count (14) */ 100 0x81, 0x02, /* Input (Data,Var,Abs) */ 101 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ 102 0x09, 0x20, /* Usage (0x20) */ 103 0x75, 0x06, /* Report Size (6) */ 104 0x95, 0x01, /* Report Count (1) */ 105 0x15, 0x00, /* Logical Minimum (0) */ 106 0x25, 0x3F, /* Logical Maximum (63) */ 107 0x81, 0x02, /* Input (Data,Var,Abs) */ 108 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 109 0x09, 0x32, /* Usage (Z) */ 110 0x09, 0x35, /* Usage (Rz) */ 111 0x15, 0x00, /* Logical Minimum (0) */ 112 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 113 0x75, 0x08, /* Report Size (8) */ 114 0x95, 0x02, /* Report Count (2) */ 115 0x81, 0x02, /* Input (Data,Var,Abs) */ 116 0xC0, /* End Collection */ 117 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 118 0x09, 0x08, /* Usage (Multi-axis Controller) */ 119 0xA1, 0x01, /* Collection (Application) */ 120 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ 121 0x09, 0x21, /* Usage (0x21) */ 122 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65534) */ 123 0x75, 0x10, /* Report Size (16) */ 124 0x95, 0x01, /* Report Count (1) */ 125 0x81, 0x02, /* Input (Data,Var,Abs) */ 126 0x05, 0x06, /* Usage Page (Generic Dev Ctrls) */ 127 0x09, 0x20, /* Usage (Battery Strength) */ 128 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 129 0x75, 0x08, /* Report Size (8) */ 130 0x95, 0x01, /* Report Count (1) */ 131 0x81, 0x02, /* Input (Data,Var,Abs) */ 132 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 133 0x19, 0x33, /* Usage Minimum (RX) */ 134 0x29, 0x35, /* Usage Maximum (RZ) */ 135 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ 136 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ 137 0x75, 0x10, /* Report Size (16) */ 138 0x95, 0x03, /* Report Count (3) */ 139 0x81, 0x02, /* Input (Data,Var,Abs) */ 140 0x19, 0x30, /* Usage Minimum (X) */ 141 0x29, 0x32, /* Usage Maximum (Z) */ 142 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ 143 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ 144 0x95, 0x03, /* Report Count (3) */ 145 0x81, 0x02, /* Input (Data,Var,Abs) */ 146 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ 147 0x09, 0x21, /* Usage (0x21) */ 148 0x15, 0x00, /* Logical Minimum (0) */ 149 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 150 0x75, 0x08, /* Report Size (8) */ 151 0x95, 0x05, /* Report Count (5) */ 152 0x81, 0x03, /* Input (Const) */ 153 0xC0, /* End Collection */ 154 0x05, 0x0C, /* Usage Page (Consumer) */ 155 0x09, 0x05, /* Usage (Headphone) */ 156 0xA1, 0x01, /* Collection (Application) */ 157 0x75, 0x05, /* Report Size (5) */ 158 0x95, 0x01, /* Report Count (1) */ 159 0x81, 0x03, /* Input (Const) */ 160 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ 161 0x09, 0x20, /* Usage (0x20) */ 162 0x09, 0x21, /* Usage (0x21) */ 163 0x15, 0x00, /* Logical Minimum (0) */ 164 0x25, 0x01, /* Logical Maximum (1) */ 165 0x75, 0x01, /* Report Size (1) */ 166 0x95, 0x02, /* Report Count (2) */ 167 0x81, 0x02, /* Input (Data,Var,Abs) */ 168 0x75, 0x01, /* Report Size (1) */ 169 0x95, 0x01, /* Report Count (1) */ 170 0x81, 0x03, /* Input (Const) */ 171 0x75, 0x08, /* Report Size (8) */ 172 0x95, 0x02, /* Report Count (2) */ 173 0x81, 0x03, /* Input (Const) */ 174 0xC0, /* End Collection */ 175 0x05, 0x0D, /* Usage Page (Digitizer) */ 176 0x09, 0x05, /* Usage (Touch Pad) */ 177 0xA1, 0x01, /* Collection (Application) */ 178 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ 179 0x09, 0x21, /* Usage (0x21) */ 180 0x15, 0x00, /* Logical Minimum (0) */ 181 0x25, 0x03, /* Logical Maximum (3) */ 182 0x75, 0x04, /* Report Size (4) */ 183 0x95, 0x01, /* Report Count (1) */ 184 0x81, 0x02, /* Input (Data,Var,Abs) */ 185 0x75, 0x04, /* Report Size (4) */ 186 0x95, 0x01, /* Report Count (1) */ 187 0x81, 0x03, /* Input (Data,Var,Abs) */ 188 0x05, 0x0D, /* Usage Page (Digitizer) */ 189 0x09, 0x56, /* Usage (0x56) */ 190 0x55, 0x0C, /* Unit Exponent (-4) */ 191 0x66, 0x01, 0x10, /* Unit (System: SI Linear, Time: Seconds) */ 192 0x46, 0xCC, 0x06, /* Physical Maximum (1740) */ 193 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 194 0x75, 0x08, /* Report Size (8) */ 195 0x95, 0x01, /* Report Count (1) */ 196 0x81, 0x02, /* Input (Data,Var,Abs) */ 197 0x65, 0x00, /* Unit (None) */ 198 0x45, 0x00, /* Physical Maximum (0) */ 199 0x05, 0x0D, /* Usage Page (Digitizer) */ 200 0x09, 0x22, /* Usage (Finger) */ 201 0xA1, 0x02, /* Collection (Logical) */ 202 0x09, 0x51, /* Usage (0x51) */ 203 0x25, 0x7F, /* Logical Maximum (127) */ 204 0x75, 0x07, /* Report Size (7) */ 205 0x95, 0x01, /* Report Count (1) */ 206 0x81, 0x02, /* Input (Data,Var,Abs) */ 207 0x09, 0x42, /* Usage (Tip Switch) */ 208 0x25, 0x01, /* Logical Maximum (1) */ 209 0x75, 0x01, /* Report Size (1) */ 210 0x95, 0x01, /* Report Count (1) */ 211 0x81, 0x02, /* Input (Data,Var,Abs) */ 212 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 213 0x09, 0x30, /* Usage (X) */ 214 0x55, 0x0E, /* Unit Exponent (-2) */ 215 0x65, 0x11, /* Unit (System: SI Linear, Length: Centimeter) */ 216 0x35, 0x00, /* Physical Minimum (0) */ 217 0x46, 0x80, 0x02, /* Physical Maximum (640) */ 218 0x26, 0x80, 0x07, /* Logical Maximum (1920) */ 219 0x75, 0x0C, /* Report Size (12) */ 220 0x81, 0x02, /* Input (Data,Var,Abs) */ 221 0x09, 0x31, /* Usage (Y) */ 222 0x46, 0xC0, 0x00, /* Physical Maximum (192) */ 223 0x26, 0xAE, 0x03, /* Logical Maximum (942) */ 224 0x81, 0x02, /* Input (Data,Var,Abs) */ 225 0x65, 0x00, /* Unit (None) */ 226 0x45, 0x00, /* Physical Maximum (0) */ 227 0xC0, /* End Collection */ 228 0x05, 0x0D, /* Usage Page (Digitizer) */ 229 0x09, 0x22, /* Usage (Finger) */ 230 0xA1, 0x02, /* Collection (Logical) */ 231 0x09, 0x51, /* Usage (0x51) */ 232 0x25, 0x7F, /* Logical Maximum (127) */ 233 0x75, 0x07, /* Report Size (7) */ 234 0x95, 0x01, /* Report Count (1) */ 235 0x81, 0x02, /* Input (Data,Var,Abs) */ 236 0x09, 0x42, /* Usage (Tip Switch) */ 237 0x25, 0x01, /* Logical Maximum (1) */ 238 0x75, 0x01, /* Report Size (1) */ 239 0x95, 0x01, /* Report Count (1) */ 240 0x81, 0x02, /* Input (Data,Var,Abs) */ 241 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 242 0x09, 0x30, /* Usage (X) */ 243 0x55, 0x0E, /* Unit Exponent (-2) */ 244 0x65, 0x11, /* Unit (System: SI Linear, Length: Centimeter) */ 245 0x35, 0x00, /* Physical Minimum (0) */ 246 0x46, 0x80, 0x02, /* Physical Maximum (640) */ 247 0x26, 0x80, 0x07, /* Logical Maximum (1920) */ 248 0x75, 0x0C, /* Report Size (12) */ 249 0x81, 0x02, /* Input (Data,Var,Abs) */ 250 0x09, 0x31, /* Usage (Y) */ 251 0x46, 0xC0, 0x00, /* Physical Maximum (192) */ 252 0x26, 0xAE, 0x03, /* Logical Maximum (942) */ 253 0x81, 0x02, /* Input (Data,Var,Abs) */ 254 0x65, 0x00, /* Unit (None) */ 255 0x45, 0x00, /* Physical Maximum (0) */ 256 0xC0, /* End Collection */ 257 0x05, 0x0D, /* Usage Page (Digitizer) */ 258 0x09, 0x56, /* Usage (0x56) */ 259 0x55, 0x0C, /* Unit Exponent (-4) */ 260 0x66, 0x01, 0x10, /* Unit (System: SI Linear, Time: Seconds) */ 261 0x46, 0xCC, 0x06, /* Physical Maximum (1740) */ 262 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 263 0x75, 0x08, /* Report Size (8) */ 264 0x95, 0x01, /* Report Count (1) */ 265 0x81, 0x02, /* Input (Data,Var,Abs) */ 266 0x65, 0x00, /* Unit (None) */ 267 0x45, 0x00, /* Physical Maximum (0) */ 268 0x05, 0x0D, /* Usage Page (Digitizer) */ 269 0x09, 0x22, /* Usage (Finger) */ 270 0xA1, 0x02, /* Collection (Logical) */ 271 0x09, 0x51, /* Usage (0x51) */ 272 0x25, 0x7F, /* Logical Maximum (127) */ 273 0x75, 0x07, /* Report Size (7) */ 274 0x95, 0x01, /* Report Count (1) */ 275 0x81, 0x02, /* Input (Data,Var,Abs) */ 276 0x09, 0x42, /* Usage (Tip Switch) */ 277 0x25, 0x01, /* Logical Maximum (1) */ 278 0x75, 0x01, /* Report Size (1) */ 279 0x95, 0x01, /* Report Count (1) */ 280 0x81, 0x02, /* Input (Data,Var,Abs) */ 281 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 282 0x09, 0x30, /* Usage (X) */ 283 0x55, 0x0E, /* Unit Exponent (-2) */ 284 0x65, 0x11, /* Unit (System: SI Linear, Length: Centimeter) */ 285 0x35, 0x00, /* Physical Minimum (0) */ 286 0x46, 0x80, 0x02, /* Physical Maximum (640) */ 287 0x26, 0x80, 0x07, /* Logical Maximum (1920) */ 288 0x75, 0x0C, /* Report Size (12) */ 289 0x81, 0x02, /* Input (Data,Var,Abs) */ 290 0x09, 0x31, /* Usage (Y) */ 291 0x46, 0xC0, 0x00, /* Physical Maximum (192) */ 292 0x26, 0xAE, 0x03, /* Logical Maximum (942) */ 293 0x81, 0x02, /* Input (Data,Var,Abs) */ 294 0x65, 0x00, /* Unit (None) */ 295 0x45, 0x00, /* Physical Maximum (0) */ 296 0xC0, /* End Collection */ 297 0x05, 0x0D, /* Usage Page (Digitizer) */ 298 0x09, 0x22, /* Usage (Finger) */ 299 0xA1, 0x02, /* Collection (Logical) */ 300 0x09, 0x51, /* Usage (0x51) */ 301 0x25, 0x7F, /* Logical Maximum (127) */ 302 0x75, 0x07, /* Report Size (7) */ 303 0x95, 0x01, /* Report Count (1) */ 304 0x81, 0x02, /* Input (Data,Var,Abs) */ 305 0x09, 0x42, /* Usage (Tip Switch) */ 306 0x25, 0x01, /* Logical Maximum (1) */ 307 0x75, 0x01, /* Report Size (1) */ 308 0x95, 0x01, /* Report Count (1) */ 309 0x81, 0x02, /* Input (Data,Var,Abs) */ 310 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 311 0x09, 0x30, /* Usage (X) */ 312 0x55, 0x0E, /* Unit Exponent (-2) */ 313 0x65, 0x11, /* Unit (System: SI Linear, Length: Centimeter) */ 314 0x35, 0x00, /* Physical Minimum (0) */ 315 0x46, 0x80, 0x02, /* Physical Maximum (640) */ 316 0x26, 0x80, 0x07, /* Logical Maximum (1920) */ 317 0x75, 0x0C, /* Report Size (12) */ 318 0x81, 0x02, /* Input (Data,Var,Abs) */ 319 0x09, 0x31, /* Usage (Y) */ 320 0x46, 0xC0, 0x00, /* Physical Maximum (192) */ 321 0x26, 0xAE, 0x03, /* Logical Maximum (942) */ 322 0x81, 0x02, /* Input (Data,Var,Abs) */ 323 0x65, 0x00, /* Unit (None) */ 324 0x45, 0x00, /* Physical Maximum (0) */ 325 0xC0, /* End Collection */ 326 0x05, 0x0D, /* Usage Page (Digitizer) */ 327 0x09, 0x56, /* Usage (0x56) */ 328 0x55, 0x0C, /* Unit Exponent (-4) */ 329 0x66, 0x01, 0x10, /* Unit (System: SI Linear, Time: Seconds) */ 330 0x46, 0xCC, 0x06, /* Physical Maximum (1740) */ 331 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 332 0x75, 0x08, /* Report Size (8) */ 333 0x95, 0x01, /* Report Count (1) */ 334 0x81, 0x02, /* Input (Data,Var,Abs) */ 335 0x65, 0x00, /* Unit (None) */ 336 0x45, 0x00, /* Physical Maximum (0) */ 337 0x05, 0x0D, /* Usage Page (Digitizer) */ 338 0x09, 0x22, /* Usage (Finger) */ 339 0xA1, 0x02, /* Collection (Logical) */ 340 0x09, 0x51, /* Usage (0x51) */ 341 0x25, 0x7F, /* Logical Maximum (127) */ 342 0x75, 0x07, /* Report Size (7) */ 343 0x95, 0x01, /* Report Count (1) */ 344 0x81, 0x02, /* Input (Data,Var,Abs) */ 345 0x09, 0x42, /* Usage (Tip Switch) */ 346 0x25, 0x01, /* Logical Maximum (1) */ 347 0x75, 0x01, /* Report Size (1) */ 348 0x95, 0x01, /* Report Count (1) */ 349 0x81, 0x02, /* Input (Data,Var,Abs) */ 350 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 351 0x09, 0x30, /* Usage (X) */ 352 0x55, 0x0E, /* Unit Exponent (-2) */ 353 0x65, 0x11, /* Unit (System: SI Linear, Length: Centimeter) */ 354 0x35, 0x00, /* Physical Minimum (0) */ 355 0x46, 0x80, 0x02, /* Physical Maximum (640) */ 356 0x26, 0x80, 0x07, /* Logical Maximum (1920) */ 357 0x75, 0x0C, /* Report Size (12) */ 358 0x81, 0x02, /* Input (Data,Var,Abs) */ 359 0x09, 0x31, /* Usage (Y) */ 360 0x46, 0xC0, 0x00, /* Physical Maximum (192) */ 361 0x26, 0xAE, 0x03, /* Logical Maximum (942) */ 362 0x81, 0x02, /* Input (Data,Var,Abs) */ 363 0x65, 0x00, /* Unit (None) */ 364 0x45, 0x00, /* Physical Maximum (0) */ 365 0xC0, /* End Collection */ 366 0x05, 0x0D, /* Usage Page (Digitizer) */ 367 0x09, 0x22, /* Usage (Finger) */ 368 0xA1, 0x02, /* Collection (Logical) */ 369 0x09, 0x51, /* Usage (0x51) */ 370 0x25, 0x7F, /* Logical Maximum (127) */ 371 0x75, 0x07, /* Report Size (7) */ 372 0x95, 0x01, /* Report Count (1) */ 373 0x81, 0x02, /* Input (Data,Var,Abs) */ 374 0x09, 0x42, /* Usage (Tip Switch) */ 375 0x25, 0x01, /* Logical Maximum (1) */ 376 0x75, 0x01, /* Report Size (1) */ 377 0x95, 0x01, /* Report Count (1) */ 378 0x81, 0x02, /* Input (Data,Var,Abs) */ 379 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 380 0x09, 0x30, /* Usage (X) */ 381 0x55, 0x0E, /* Unit Exponent (-2) */ 382 0x65, 0x11, /* Unit (System: SI Linear, Length: Centimeter) */ 383 0x35, 0x00, /* Physical Minimum (0) */ 384 0x46, 0x80, 0x02, /* Physical Maximum (640) */ 385 0x26, 0x80, 0x07, /* Logical Maximum (1920) */ 386 0x75, 0x0C, /* Report Size (12) */ 387 0x81, 0x02, /* Input (Data,Var,Abs) */ 388 0x09, 0x31, /* Usage (Y) */ 389 0x46, 0xC0, 0x00, /* Physical Maximum (192) */ 390 0x26, 0xAE, 0x03, /* Logical Maximum (942) */ 391 0x81, 0x02, /* Input (Data,Var,Abs) */ 392 0x65, 0x00, /* Unit (None) */ 393 0x45, 0x00, /* Physical Maximum (0) */ 394 0xC0, /* End Collection */ 395 0x75, 0x08, /* Report Size (8) */ 396 0x95, 0x03, /* Report Count (3) */ 397 0x81, 0x03, /* Input (Const) */ 398 /* Output and feature reports */ 399 0x85, 0x05, /* Report ID (5) */ 400 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ 401 0x09, 0x22, /* Usage (0x22) */ 402 0x15, 0x00, /* Logical Minimum (0) */ 403 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ 404 0x95, 0x1F, /* Report Count (31) */ 405 0x91, 0x02, /* Output (Data,Var,Abs) */ 406 0x85, 0x04, /* Report ID (4) */ 407 0x09, 0x23, /* Usage (0x23) */ 408 0x95, 0x24, /* Report Count (36) */ 409 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 410 0x85, 0x02, /* Report ID (2) */ 411 0x09, 0x24, /* Usage (0x24) */ 412 0x95, 0x24, /* Report Count (36) */ 413 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 414 0x85, 0x08, /* Report ID (8) */ 415 0x09, 0x25, /* Usage (0x25) */ 416 0x95, 0x03, /* Report Count (3) */ 417 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 418 0x85, 0x10, /* Report ID (16) */ 419 0x09, 0x26, /* Usage (0x26) */ 420 0x95, 0x04, /* Report Count (4) */ 421 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 422 0x85, 0x11, /* Report ID (17) */ 423 0x09, 0x27, /* Usage (0x27) */ 424 0x95, 0x02, /* Report Count (2) */ 425 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 426 0x85, 0x12, /* Report ID (18) */ 427 0x06, 0x02, 0xFF, /* Usage Page (Vendor Defined 0xFF02) */ 428 0x09, 0x21, /* Usage (0x21) */ 429 0x95, 0x0F, /* Report Count (15) */ 430 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 431 0x85, 0x13, /* Report ID (19) */ 432 0x09, 0x22, /* Usage (0x22) */ 433 0x95, 0x16, /* Report Count (22) */ 434 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 435 0x85, 0x14, /* Report ID (20) */ 436 0x06, 0x05, 0xFF, /* Usage Page (Vendor Defined 0xFF05) */ 437 0x09, 0x20, /* Usage (0x20) */ 438 0x95, 0x10, /* Report Count (16) */ 439 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 440 0x85, 0x15, /* Report ID (21) */ 441 0x09, 0x21, /* Usage (0x21) */ 442 0x95, 0x2C, /* Report Count (44) */ 443 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 444 0x06, 0x80, 0xFF, /* Usage Page (Vendor Defined 0xFF80) */ 445 0x85, 0x80, /* Report ID (-128) */ 446 0x09, 0x20, /* Usage (0x20) */ 447 0x95, 0x06, /* Report Count (6) */ 448 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 449 0x85, 0x81, /* Report ID (-127) */ 450 0x09, 0x21, /* Usage (0x21) */ 451 0x95, 0x06, /* Report Count (6) */ 452 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 453 0x85, 0x82, /* Report ID (-126) */ 454 0x09, 0x22, /* Usage (0x22) */ 455 0x95, 0x05, /* Report Count (5) */ 456 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 457 0x85, 0x83, /* Report ID (-125) */ 458 0x09, 0x23, /* Usage (0x23) */ 459 0x95, 0x01, /* Report Count (1) */ 460 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 461 0x85, 0x84, /* Report ID (-124) */ 462 0x09, 0x24, /* Usage (0x24) */ 463 0x95, 0x04, /* Report Count (4) */ 464 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 465 0x85, 0x85, /* Report ID (-123) */ 466 0x09, 0x25, /* Usage (0x25) */ 467 0x95, 0x06, /* Report Count (6) */ 468 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 469 0x85, 0x86, /* Report ID (-122) */ 470 0x09, 0x26, /* Usage (0x26) */ 471 0x95, 0x06, /* Report Count (6) */ 472 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 473 0x85, 0x87, /* Report ID (-121) */ 474 0x09, 0x27, /* Usage (0x27) */ 475 0x95, 0x23, /* Report Count (35) */ 476 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 477 0x85, 0x88, /* Report ID (-120) */ 478 0x09, 0x28, /* Usage (0x28) */ 479 0x95, 0x22, /* Report Count (34) */ 480 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 481 0x85, 0x89, /* Report ID (-119) */ 482 0x09, 0x29, /* Usage (0x29) */ 483 0x95, 0x02, /* Report Count (2) */ 484 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 485 0x85, 0x90, /* Report ID (-112) */ 486 0x09, 0x30, /* Usage (0x30) */ 487 0x95, 0x05, /* Report Count (5) */ 488 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 489 0x85, 0x91, /* Report ID (-111) */ 490 0x09, 0x31, /* Usage (0x31) */ 491 0x95, 0x03, /* Report Count (3) */ 492 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 493 0x85, 0x92, /* Report ID (-110) */ 494 0x09, 0x32, /* Usage (0x32) */ 495 0x95, 0x03, /* Report Count (3) */ 496 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 497 0x85, 0x93, /* Report ID (-109) */ 498 0x09, 0x33, /* Usage (0x33) */ 499 0x95, 0x0C, /* Report Count (12) */ 500 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 501 0x85, 0xA0, /* Report ID (-96) */ 502 0x09, 0x40, /* Usage (0x40) */ 503 0x95, 0x06, /* Report Count (6) */ 504 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 505 0x85, 0xA1, /* Report ID (-95) */ 506 0x09, 0x41, /* Usage (0x41) */ 507 0x95, 0x01, /* Report Count (1) */ 508 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 509 0x85, 0xA2, /* Report ID (-94) */ 510 0x09, 0x42, /* Usage (0x42) */ 511 0x95, 0x01, /* Report Count (1) */ 512 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 513 0x85, 0xA3, /* Report ID (-93) */ 514 0x09, 0x43, /* Usage (0x43) */ 515 0x95, 0x30, /* Report Count (48) */ 516 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 517 0x85, 0xA4, /* Report ID (-92) */ 518 0x09, 0x44, /* Usage (0x44) */ 519 0x95, 0x0D, /* Report Count (13) */ 520 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 521 0x85, 0xA5, /* Report ID (-91) */ 522 0x09, 0x45, /* Usage (0x45) */ 523 0x95, 0x15, /* Report Count (21) */ 524 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 525 0x85, 0xA6, /* Report ID (-90) */ 526 0x09, 0x46, /* Usage (0x46) */ 527 0x95, 0x15, /* Report Count (21) */ 528 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 529 0x85, 0xF0, /* Report ID (-16) */ 530 0x09, 0x47, /* Usage (0x47) */ 531 0x95, 0x3F, /* Report Count (63) */ 532 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 533 0x85, 0xF1, /* Report ID (-15) */ 534 0x09, 0x48, /* Usage (0x48) */ 535 0x95, 0x3F, /* Report Count (63) */ 536 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 537 0x85, 0xF2, /* Report ID (-14) */ 538 0x09, 0x49, /* Usage (0x49) */ 539 0x95, 0x0F, /* Report Count (15) */ 540 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 541 0x85, 0xA7, /* Report ID (-89) */ 542 0x09, 0x4A, /* Usage (0x4A) */ 543 0x95, 0x01, /* Report Count (1) */ 544 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 545 0x85, 0xA8, /* Report ID (-88) */ 546 0x09, 0x4B, /* Usage (0x4B) */ 547 0x95, 0x01, /* Report Count (1) */ 548 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 549 0x85, 0xA9, /* Report ID (-87) */ 550 0x09, 0x4C, /* Usage (0x4C) */ 551 0x95, 0x08, /* Report Count (8) */ 552 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 553 0x85, 0xAA, /* Report ID (-86) */ 554 0x09, 0x4E, /* Usage (0x4E) */ 555 0x95, 0x01, /* Report Count (1) */ 556 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 557 0x85, 0xAB, /* Report ID (-85) */ 558 0x09, 0x4F, /* Usage (0x4F) */ 559 0x95, 0x39, /* Report Count (57) */ 560 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 561 0x85, 0xAC, /* Report ID (-84) */ 562 0x09, 0x50, /* Usage (0x50) */ 563 0x95, 0x39, /* Report Count (57) */ 564 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 565 0x85, 0xAD, /* Report ID (-83) */ 566 0x09, 0x51, /* Usage (0x51) */ 567 0x95, 0x0B, /* Report Count (11) */ 568 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 569 0x85, 0xAE, /* Report ID (-82) */ 570 0x09, 0x52, /* Usage (0x52) */ 571 0x95, 0x01, /* Report Count (1) */ 572 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 573 0x85, 0xAF, /* Report ID (-81) */ 574 0x09, 0x53, /* Usage (0x53) */ 575 0x95, 0x02, /* Report Count (2) */ 576 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 577 0x85, 0xB0, /* Report ID (-80) */ 578 0x09, 0x54, /* Usage (0x54) */ 579 0x95, 0x3F, /* Report Count (63) */ 580 0xB1, 0x02, /* Feature (Data,Var,Abs) */ 581 0xC0, /* End Collection */ 582 }; 583 584 #define PS4DS_GYRO_RES_PER_DEG_S 1024 585 #define PS4DS_ACC_RES_PER_G 8192 586 #define PS4DS_MAX_TOUCHPAD_PACKETS 4 587 #define PS4DS_FEATURE_REPORT2_SIZE 37 588 #define PS4DS_OUTPUT_REPORT5_SIZE 32 589 #define PS4DS_OUTPUT_REPORT11_SIZE 78 590 591 static hidmap_cb_t ps4dshock_hat_switch_cb; 592 static hidmap_cb_t ps4dshock_final_cb; 593 static hidmap_cb_t ps4dsacc_data_cb; 594 static hidmap_cb_t ps4dsacc_tstamp_cb; 595 static hidmap_cb_t ps4dsacc_final_cb; 596 static hidmap_cb_t ps4dsmtp_data_cb; 597 static hidmap_cb_t ps4dsmtp_npackets_cb; 598 static hidmap_cb_t ps4dsmtp_final_cb; 599 600 struct ps4ds_out5 { 601 uint8_t features; 602 uint8_t reserved1; 603 uint8_t reserved2; 604 uint8_t rumble_right; 605 uint8_t rumble_left; 606 uint8_t led_color_r; 607 uint8_t led_color_g; 608 uint8_t led_color_b; 609 uint8_t led_delay_on; /* centiseconds */ 610 uint8_t led_delay_off; 611 } __attribute__((packed)); 612 613 static const struct ps4ds_led { 614 int r; 615 int g; 616 int b; 617 } ps4ds_leds[] = { 618 /* The first 4 entries match the PS4, other from Linux driver */ 619 { 0x00, 0x00, 0x40 }, /* Blue */ 620 { 0x40, 0x00, 0x00 }, /* Red */ 621 { 0x00, 0x40, 0x00 }, /* Green */ 622 { 0x20, 0x00, 0x20 }, /* Pink */ 623 { 0x02, 0x01, 0x00 }, /* Orange */ 624 { 0x00, 0x01, 0x01 }, /* Teal */ 625 { 0x01, 0x01, 0x01 } /* White */ 626 }; 627 628 enum ps4ds_led_state { 629 PS4DS_LED_OFF, 630 PS4DS_LED_ON, 631 PS4DS_LED_BLINKING, 632 PD4DS_LED_CNT, 633 }; 634 635 /* Map structure for accelerometer and gyro. */ 636 struct ps4ds_calib_data { 637 int32_t usage; 638 int32_t code; 639 int32_t res; 640 int32_t range; 641 /* Calibration data for accelerometer and gyro. */ 642 int16_t bias; 643 int32_t sens_numer; 644 int32_t sens_denom; 645 }; 646 647 enum { 648 PS4DS_TSTAMP, 649 PS4DS_CID1, 650 PS4DS_TIP1, 651 PS4DS_X1, 652 PS4DS_Y1, 653 PS4DS_CID2, 654 PS4DS_TIP2, 655 PS4DS_X2, 656 PS4DS_Y2, 657 PS4DS_NTPUSAGES, 658 }; 659 660 struct ps4dshock_softc { 661 struct hidmap hm; 662 663 bool is_bluetooth; 664 665 struct sx lock; 666 enum ps4ds_led_state led_state; 667 struct ps4ds_led led_color; 668 int led_delay_on; /* msecs */ 669 int led_delay_off; 670 671 int rumble_right; 672 int rumble_left; 673 }; 674 675 struct ps4dsacc_softc { 676 struct hidmap hm; 677 678 uint16_t hw_tstamp; 679 int32_t ev_tstamp; 680 681 struct ps4ds_calib_data calib_data[6]; 682 }; 683 684 struct ps4dsmtp_softc { 685 struct hidmap hm; 686 687 struct hid_location btn_loc; 688 u_int npackets; 689 int32_t *data_ptr; 690 int32_t data[PS4DS_MAX_TOUCHPAD_PACKETS * PS4DS_NTPUSAGES]; 691 692 bool do_tstamps; 693 uint8_t hw_tstamp; 694 int32_t ev_tstamp; 695 bool touch; 696 }; 697 698 #define PD4DSHOCK_OFFSET(field) offsetof(struct ps4dshock_softc, field) 699 enum { 700 PD4DSHOCK_SYSCTL_LED_STATE = PD4DSHOCK_OFFSET(led_state), 701 PD4DSHOCK_SYSCTL_LED_COLOR_R = PD4DSHOCK_OFFSET(led_color.r), 702 PD4DSHOCK_SYSCTL_LED_COLOR_G = PD4DSHOCK_OFFSET(led_color.g), 703 PD4DSHOCK_SYSCTL_LED_COLOR_B = PD4DSHOCK_OFFSET(led_color.b), 704 PD4DSHOCK_SYSCTL_LED_DELAY_ON = PD4DSHOCK_OFFSET(led_delay_on), 705 PD4DSHOCK_SYSCTL_LED_DELAY_OFF= PD4DSHOCK_OFFSET(led_delay_off), 706 #define PD4DSHOCK_SYSCTL_LAST PD4DSHOCK_SYSCTL_LED_DELAY_OFF 707 }; 708 709 #define PS4DS_MAP_BTN(number, code) \ 710 { HIDMAP_KEY(HUP_BUTTON, number, code) } 711 #define PS4DS_MAP_ABS(usage, code) \ 712 { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code) } 713 #define PS4DS_MAP_FLT(usage, code) \ 714 { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code), .flat = 15 } 715 #define PS4DS_MAP_VSW(usage, code) \ 716 { HIDMAP_SW(HUP_MICROSOFT, usage, code) } 717 #define PS4DS_MAP_GCB(usage, callback) \ 718 { HIDMAP_ANY_CB(HUP_GENERIC_DESKTOP, HUG_##usage, callback) } 719 #define PS4DS_MAP_VCB(usage, callback) \ 720 { HIDMAP_ANY_CB(HUP_MICROSOFT, usage, callback) } 721 #define PS4DS_FINALCB(cb) \ 722 { HIDMAP_FINAL_CB(&cb) } 723 724 static const struct hidmap_item ps4dshock_map[] = { 725 PS4DS_MAP_FLT(X, ABS_X), 726 PS4DS_MAP_FLT(Y, ABS_Y), 727 PS4DS_MAP_ABS(Z, ABS_Z), 728 PS4DS_MAP_FLT(RX, ABS_RX), 729 PS4DS_MAP_FLT(RY, ABS_RY), 730 PS4DS_MAP_ABS(RZ, ABS_RZ), 731 PS4DS_MAP_BTN(1, BTN_WEST), 732 PS4DS_MAP_BTN(2, BTN_SOUTH), 733 PS4DS_MAP_BTN(3, BTN_EAST), 734 PS4DS_MAP_BTN(4, BTN_NORTH), 735 PS4DS_MAP_BTN(5, BTN_TL), 736 PS4DS_MAP_BTN(6, BTN_TR), 737 PS4DS_MAP_BTN(7, BTN_TL2), 738 PS4DS_MAP_BTN(8, BTN_TR2), 739 PS4DS_MAP_BTN(9, BTN_SELECT), 740 PS4DS_MAP_BTN(10, BTN_START), 741 PS4DS_MAP_BTN(11, BTN_THUMBL), 742 PS4DS_MAP_BTN(12, BTN_THUMBR), 743 PS4DS_MAP_BTN(13, BTN_MODE), 744 /* Click button is handled by touchpad driver */ 745 /* PS4DS_MAP_BTN(14, BTN_LEFT), */ 746 PS4DS_MAP_GCB(HAT_SWITCH, ps4dshock_hat_switch_cb), 747 PS4DS_FINALCB( ps4dshock_final_cb), 748 }; 749 static const struct hidmap_item ps4dsacc_map[] = { 750 PS4DS_MAP_GCB(X, ps4dsacc_data_cb), 751 PS4DS_MAP_GCB(Y, ps4dsacc_data_cb), 752 PS4DS_MAP_GCB(Z, ps4dsacc_data_cb), 753 PS4DS_MAP_GCB(RX, ps4dsacc_data_cb), 754 PS4DS_MAP_GCB(RY, ps4dsacc_data_cb), 755 PS4DS_MAP_GCB(RZ, ps4dsacc_data_cb), 756 PS4DS_MAP_VCB(0x0021, ps4dsacc_tstamp_cb), 757 PS4DS_FINALCB( ps4dsacc_final_cb), 758 }; 759 static const struct hidmap_item ps4dshead_map[] = { 760 PS4DS_MAP_VSW(0x0020, SW_MICROPHONE_INSERT), 761 PS4DS_MAP_VSW(0x0021, SW_HEADPHONE_INSERT), 762 }; 763 static const struct hidmap_item ps4dsmtp_map[] = { 764 { HIDMAP_ABS_CB(HUP_MICROSOFT, 0x0021, ps4dsmtp_npackets_cb)}, 765 { HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_SCAN_TIME, ps4dsmtp_data_cb) }, 766 { HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_CONTACTID, ps4dsmtp_data_cb) }, 767 { HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_TIP_SWITCH, ps4dsmtp_data_cb) }, 768 { HIDMAP_ABS_CB(HUP_GENERIC_DESKTOP, HUG_X, ps4dsmtp_data_cb) }, 769 { HIDMAP_ABS_CB(HUP_GENERIC_DESKTOP, HUG_Y, ps4dsmtp_data_cb) }, 770 { HIDMAP_FINAL_CB( ps4dsmtp_final_cb) }, 771 }; 772 773 static const struct hid_device_id ps4dshock_devs[] = { 774 { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc), 775 HID_TLC(HUP_GENERIC_DESKTOP, HUG_GAME_PAD) }, 776 }; 777 static const struct hid_device_id ps4dsacc_devs[] = { 778 { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc), 779 HID_TLC(HUP_GENERIC_DESKTOP, HUG_MULTIAXIS_CNTROLLER) }, 780 }; 781 static const struct hid_device_id ps4dshead_devs[] = { 782 { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc), 783 HID_TLC(HUP_CONSUMER, HUC_HEADPHONE) }, 784 }; 785 static const struct hid_device_id ps4dsmtp_devs[] = { 786 { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc), 787 HID_TLC(HUP_DIGITIZERS, HUD_TOUCHPAD) }, 788 }; 789 790 static int 791 ps4dshock_hat_switch_cb(HIDMAP_CB_ARGS) 792 { 793 static const struct { int32_t x; int32_t y; } hat_switch_map[] = { 794 {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, 795 {-1, -1},{0, 0} 796 }; 797 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 798 u_int idx; 799 800 switch (HIDMAP_CB_GET_STATE()) { 801 case HIDMAP_CB_IS_ATTACHING: 802 evdev_support_event(evdev, EV_ABS); 803 evdev_support_abs(evdev, ABS_HAT0X, -1, 1, 0, 0, 0); 804 evdev_support_abs(evdev, ABS_HAT0Y, -1, 1, 0, 0, 0); 805 break; 806 807 case HIDMAP_CB_IS_RUNNING: 808 idx = MIN(nitems(hat_switch_map) - 1, (u_int)ctx.data); 809 evdev_push_abs(evdev, ABS_HAT0X, hat_switch_map[idx].x); 810 evdev_push_abs(evdev, ABS_HAT0Y, hat_switch_map[idx].y); 811 break; 812 813 default: 814 break; 815 } 816 817 return (0); 818 } 819 820 static int 821 ps4dshock_final_cb(HIDMAP_CB_ARGS) 822 { 823 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 824 825 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING) 826 evdev_support_prop(evdev, INPUT_PROP_DIRECT); 827 828 /* Do not execute callback at interrupt handler and detach */ 829 return (ENOSYS); 830 } 831 832 static int 833 ps4dsacc_data_cb(HIDMAP_CB_ARGS) 834 { 835 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 836 struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC(); 837 struct ps4ds_calib_data *calib; 838 u_int i; 839 840 switch (HIDMAP_CB_GET_STATE()) { 841 case HIDMAP_CB_IS_ATTACHING: 842 for (i = 0; i < nitems(sc->calib_data); i++) { 843 if (sc->calib_data[i].usage == ctx.hi->usage) { 844 evdev_support_abs(evdev, 845 sc->calib_data[i].code, 846 -sc->calib_data[i].range, 847 sc->calib_data[i].range, 16, 0, 848 sc->calib_data[i].res); 849 HIDMAP_CB_UDATA = &sc->calib_data[i]; 850 break; 851 } 852 } 853 break; 854 855 case HIDMAP_CB_IS_RUNNING: 856 calib = HIDMAP_CB_UDATA; 857 evdev_push_abs(evdev, calib->code, 858 ((int64_t)ctx.data - calib->bias) * calib->sens_numer / 859 calib->sens_denom); 860 break; 861 862 default: 863 break; 864 } 865 866 return (0); 867 } 868 869 static int 870 ps4dsacc_tstamp_cb(HIDMAP_CB_ARGS) 871 { 872 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 873 struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC(); 874 uint16_t tstamp; 875 876 switch (HIDMAP_CB_GET_STATE()) { 877 case HIDMAP_CB_IS_ATTACHING: 878 evdev_support_event(evdev, EV_MSC); 879 evdev_support_msc(evdev, MSC_TIMESTAMP); 880 break; 881 882 case HIDMAP_CB_IS_RUNNING: 883 /* Convert timestamp (in 5.33us unit) to timestamp_us */ 884 tstamp = (uint16_t)ctx.data; 885 sc->ev_tstamp += (uint16_t)(tstamp - sc->hw_tstamp) * 16 / 3; 886 sc->hw_tstamp = tstamp; 887 evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp); 888 break; 889 890 default: 891 break; 892 } 893 894 return (0); 895 } 896 897 static int 898 ps4dsacc_final_cb(HIDMAP_CB_ARGS) 899 { 900 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 901 902 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING) { 903 evdev_support_event(evdev, EV_ABS); 904 evdev_support_prop(evdev, INPUT_PROP_ACCELEROMETER); 905 } 906 /* Do not execute callback at interrupt handler and detach */ 907 return (ENOSYS); 908 } 909 910 static int 911 ps4dsmtp_npackets_cb(HIDMAP_CB_ARGS) 912 { 913 struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC(); 914 915 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) { 916 sc->npackets = MIN(PS4DS_MAX_TOUCHPAD_PACKETS,(u_int)ctx.data); 917 /* Reset pointer here as it is first usage in touchpad TLC */ 918 sc->data_ptr = sc->data; 919 } 920 921 return (0); 922 } 923 924 static int 925 ps4dsmtp_data_cb(HIDMAP_CB_ARGS) 926 { 927 struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC(); 928 929 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) { 930 *sc->data_ptr = ctx.data; 931 ++sc->data_ptr; 932 } 933 934 return (0); 935 } 936 937 static void 938 ps4dsmtp_push_packet(struct ps4dsmtp_softc *sc, struct evdev_dev *evdev, 939 int32_t *data) 940 { 941 uint8_t hw_tstamp, delta; 942 bool touch; 943 944 evdev_push_abs(evdev, ABS_MT_SLOT, 0); 945 if (data[PS4DS_TIP1] == 0) { 946 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID1]); 947 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X1]); 948 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y1]); 949 } else 950 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1); 951 evdev_push_abs(evdev, ABS_MT_SLOT, 1); 952 if (data[PS4DS_TIP2] == 0) { 953 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID2]); 954 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X2]); 955 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y2]); 956 } else 957 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1); 958 959 if (sc->do_tstamps) { 960 /* 961 * Export hardware timestamps in libinput-friendly way. 962 * Make timestamp counter 32-bit, scale up hardware 963 * timestamps to be on per 1usec basis and reset 964 * counter at the start of each touch. 965 */ 966 hw_tstamp = (uint8_t)data[PS4DS_TSTAMP]; 967 delta = hw_tstamp - sc->hw_tstamp; 968 sc->hw_tstamp = hw_tstamp; 969 touch = data[PS4DS_TIP1] == 0 || data[PS4DS_TIP2] == 0; 970 /* Hardware timestamp counter ticks in 682 usec interval. */ 971 if ((touch || sc->touch) && delta != 0) { 972 if (sc->touch) 973 sc->ev_tstamp += delta * 682; 974 evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp); 975 } 976 if (!touch) 977 sc->ev_tstamp = 0; 978 sc->touch = touch; 979 } 980 } 981 982 static int 983 ps4dsmtp_final_cb(HIDMAP_CB_ARGS) 984 { 985 struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC(); 986 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 987 int32_t *data; 988 989 switch (HIDMAP_CB_GET_STATE()) { 990 case HIDMAP_CB_IS_ATTACHING: 991 if (hid_test_quirk(hid_get_device_info(sc->hm.dev), 992 HQ_MT_TIMESTAMP)) 993 sc->do_tstamps = true; 994 /* 995 * Dualshock 4 touchpad TLC contained in fixed report 996 * descriptor is almost compatible with MS precission touchpad 997 * specs and hmt(4) driver. But... for some reasons "Click" 998 * button location was grouped with other GamePad buttons by 999 * touchpad designers so it belongs to GamePad TLC. Fix it with 1000 * direct reading of "Click" button value from interrupt frame. 1001 */ 1002 sc->btn_loc = (struct hid_location) { 1, 0, 49 }; 1003 evdev_support_event(evdev, EV_SYN); 1004 evdev_support_event(evdev, EV_KEY); 1005 evdev_support_event(evdev, EV_ABS); 1006 if (sc->do_tstamps) { 1007 evdev_support_event(evdev, EV_MSC); 1008 evdev_support_msc(evdev, MSC_TIMESTAMP); 1009 } 1010 evdev_support_key(evdev, BTN_LEFT); 1011 evdev_support_abs(evdev, ABS_MT_SLOT, 0, 1, 0, 0, 0); 1012 evdev_support_abs(evdev, ABS_MT_TRACKING_ID, -1, 127, 0, 0, 0); 1013 evdev_support_abs(evdev, ABS_MT_POSITION_X, 0, 1920, 0, 0, 30); 1014 evdev_support_abs(evdev, ABS_MT_POSITION_Y, 0, 942, 0, 0, 49); 1015 evdev_support_prop(evdev, INPUT_PROP_POINTER); 1016 evdev_support_prop(evdev, INPUT_PROP_BUTTONPAD); 1017 evdev_set_flag(evdev, EVDEV_FLAG_MT_STCOMPAT); 1018 break; 1019 1020 case HIDMAP_CB_IS_RUNNING: 1021 /* Only packets with ReportID=1 are accepted */ 1022 if (HIDMAP_CB_GET_RID() != 1) 1023 return (ENOTSUP); 1024 evdev_push_key(evdev, BTN_LEFT, 1025 HIDMAP_CB_GET_UDATA(&sc->btn_loc)); 1026 for (data = sc->data; 1027 data < sc->data + PS4DS_NTPUSAGES * sc->npackets; 1028 data += PS4DS_NTPUSAGES) { 1029 ps4dsmtp_push_packet(sc, evdev, data); 1030 evdev_sync(evdev); 1031 } 1032 break; 1033 1034 default: 1035 break; 1036 } 1037 1038 /* Do execute callback at interrupt handler and detach */ 1039 return (0); 1040 } 1041 1042 static int 1043 ps4dshock_write(struct ps4dshock_softc *sc) 1044 { 1045 hid_size_t osize = sc->is_bluetooth ? 1046 PS4DS_OUTPUT_REPORT11_SIZE : PS4DS_OUTPUT_REPORT5_SIZE; 1047 uint8_t buf[osize]; 1048 int offset; 1049 bool led_on, led_blinks; 1050 1051 memset(buf, 0, osize); 1052 buf[0] = sc->is_bluetooth ? 0x11 : 0x05; 1053 offset = sc->is_bluetooth ? 3 : 1; 1054 led_on = sc->led_state != PS4DS_LED_OFF; 1055 led_blinks = sc->led_state == PS4DS_LED_BLINKING; 1056 *(struct ps4ds_out5 *)(buf + offset) = (struct ps4ds_out5) { 1057 .features = 0x07, /* blink + LEDs + motor */ 1058 .rumble_right = sc->rumble_right, 1059 .rumble_left = sc->rumble_left, 1060 .led_color_r = led_on ? sc->led_color.r : 0, 1061 .led_color_g = led_on ? sc->led_color.g : 0, 1062 .led_color_b = led_on ? sc->led_color.b : 0, 1063 /* convert milliseconds to centiseconds */ 1064 .led_delay_on = led_blinks ? sc->led_delay_on / 10 : 0, 1065 .led_delay_off = led_blinks ? sc->led_delay_off / 10 : 0, 1066 }; 1067 1068 return (hid_write(sc->hm.dev, buf, osize)); 1069 } 1070 1071 /* Synaptics Touchpad */ 1072 static int 1073 ps4dshock_sysctl(SYSCTL_HANDLER_ARGS) 1074 { 1075 struct ps4dshock_softc *sc; 1076 int error, arg; 1077 1078 if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || 1079 oidp->oid_arg2 > PD4DSHOCK_SYSCTL_LAST) 1080 return (EINVAL); 1081 1082 sc = oidp->oid_arg1; 1083 sx_xlock(&sc->lock); 1084 1085 /* Read the current value. */ 1086 arg = *(int *)((char *)sc + oidp->oid_arg2); 1087 error = sysctl_handle_int(oidp, &arg, 0, req); 1088 1089 /* Sanity check. */ 1090 if (error || !req->newptr) 1091 goto unlock; 1092 1093 /* 1094 * Check that the new value is in the concerned node's range 1095 * of values. 1096 */ 1097 switch (oidp->oid_arg2) { 1098 case PD4DSHOCK_SYSCTL_LED_STATE: 1099 if (arg < 0 || arg >= PD4DS_LED_CNT) 1100 error = EINVAL; 1101 break; 1102 case PD4DSHOCK_SYSCTL_LED_COLOR_R: 1103 case PD4DSHOCK_SYSCTL_LED_COLOR_G: 1104 case PD4DSHOCK_SYSCTL_LED_COLOR_B: 1105 if (arg < 0 || arg > UINT8_MAX) 1106 error = EINVAL; 1107 break; 1108 case PD4DSHOCK_SYSCTL_LED_DELAY_ON: 1109 case PD4DSHOCK_SYSCTL_LED_DELAY_OFF: 1110 if (arg < 0 || arg > UINT8_MAX * 10) 1111 error = EINVAL; 1112 break; 1113 default: 1114 error = EINVAL; 1115 } 1116 1117 /* Update. */ 1118 if (error == 0) { 1119 *(int *)((char *)sc + oidp->oid_arg2) = arg; 1120 ps4dshock_write(sc); 1121 } 1122 unlock: 1123 sx_unlock(&sc->lock); 1124 1125 return (error); 1126 } 1127 1128 static void 1129 ps4dshock_identify(driver_t *driver, device_t parent) 1130 { 1131 1132 /* Overload PS4 DualShock gamepad rudimentary report descriptor */ 1133 if (HIDBUS_LOOKUP_ID(parent, ps4dshock_devs) != NULL) 1134 hid_set_report_descr(parent, ps4dshock_rdesc, 1135 sizeof(ps4dshock_rdesc)); 1136 } 1137 1138 static int 1139 ps4dshock_probe(device_t dev) 1140 { 1141 struct ps4dshock_softc *sc = device_get_softc(dev); 1142 1143 hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR); 1144 return ( 1145 HIDMAP_PROBE(&sc->hm, dev, ps4dshock_devs, ps4dshock_map, NULL) 1146 ); 1147 } 1148 1149 static int 1150 ps4dsacc_probe(device_t dev) 1151 { 1152 struct ps4dsacc_softc *sc = device_get_softc(dev); 1153 1154 hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR); 1155 return ( 1156 HIDMAP_PROBE(&sc->hm, dev, ps4dsacc_devs, ps4dsacc_map, "Sensors") 1157 ); 1158 } 1159 1160 static int 1161 ps4dshead_probe(device_t dev) 1162 { 1163 struct hidmap *hm = device_get_softc(dev); 1164 1165 hidmap_set_debug_var(hm, &HID_DEBUG_VAR); 1166 return ( 1167 HIDMAP_PROBE(hm, dev, ps4dshead_devs, ps4dshead_map, "Headset") 1168 ); 1169 } 1170 1171 static int 1172 ps4dsmtp_probe(device_t dev) 1173 { 1174 struct ps4dshock_softc *sc = device_get_softc(dev); 1175 1176 hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR); 1177 return ( 1178 HIDMAP_PROBE(&sc->hm, dev, ps4dsmtp_devs, ps4dsmtp_map, "Touchpad") 1179 ); 1180 } 1181 1182 static int 1183 ps4dshock_attach(device_t dev) 1184 { 1185 struct ps4dshock_softc *sc = device_get_softc(dev); 1186 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 1187 struct sysctl_oid *tree = device_get_sysctl_tree(dev); 1188 1189 sc->led_state = PS4DS_LED_ON; 1190 sc->led_color = ps4ds_leds[device_get_unit(dev) % nitems(ps4ds_leds)]; 1191 sc->led_delay_on = 500; /* 1 Hz */ 1192 sc->led_delay_off = 500; 1193 ps4dshock_write(sc); 1194 1195 sx_init(&sc->lock, "ps4dshock"); 1196 1197 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1198 "led_state", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1199 PD4DSHOCK_SYSCTL_LED_STATE, ps4dshock_sysctl, "I", 1200 "LED state: 0 - off, 1 - on, 2 - blinking."); 1201 1202 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1203 "led_color_r", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1204 PD4DSHOCK_SYSCTL_LED_COLOR_R, ps4dshock_sysctl, "I", 1205 "LED color. Red component."); 1206 1207 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1208 "led_color_g", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1209 PD4DSHOCK_SYSCTL_LED_COLOR_G, ps4dshock_sysctl, "I", 1210 "LED color. Green component."); 1211 1212 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1213 "led_color_b", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1214 PD4DSHOCK_SYSCTL_LED_COLOR_B, ps4dshock_sysctl, "I", 1215 "LED color. Blue component."); 1216 1217 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1218 "led_delay_on", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1219 PD4DSHOCK_SYSCTL_LED_DELAY_ON, ps4dshock_sysctl, "I", 1220 "LED blink. On delay, msecs."); 1221 1222 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1223 "led_delay_off", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1224 PD4DSHOCK_SYSCTL_LED_DELAY_OFF, ps4dshock_sysctl, "I", 1225 "LED blink. Off delay, msecs."); 1226 1227 return (hidmap_attach(&sc->hm)); 1228 } 1229 1230 static int 1231 ps4dsacc_attach(device_t dev) 1232 { 1233 struct ps4dsacc_softc *sc = device_get_softc(dev); 1234 uint8_t buf[PS4DS_FEATURE_REPORT2_SIZE]; 1235 int error, speed_2x, range_2g; 1236 1237 /* Read accelerometers and gyroscopes calibration data */ 1238 error = hid_get_report(dev, buf, sizeof(buf), NULL, 1239 HID_FEATURE_REPORT, 0x02); 1240 if (error) 1241 DPRINTF("get feature report failed, error=%d " 1242 "(ignored)\n", error); 1243 1244 DPRINTFN(5, "calibration data: %*D\n", (int)sizeof(buf), buf, " "); 1245 1246 /* 1247 * Set gyroscope calibration and normalization parameters. 1248 * Data values will be normalized to 1/ PS4DS_GYRO_RES_PER_DEG_S 1249 * degree/s. 1250 */ 1251 #define HGETW(w) ((int16_t)((w)[0] | (((uint16_t)((w)[1])) << 8))) 1252 speed_2x = HGETW(&buf[19]) + HGETW(&buf[21]); 1253 sc->calib_data[0].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RX); 1254 sc->calib_data[0].code = ABS_RX; 1255 sc->calib_data[0].range = PS4DS_GYRO_RES_PER_DEG_S * 2048; 1256 sc->calib_data[0].res = PS4DS_GYRO_RES_PER_DEG_S; 1257 sc->calib_data[0].bias = HGETW(&buf[1]); 1258 sc->calib_data[0].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S; 1259 sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[9]); 1260 /* BT case */ 1261 /* sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[13]); */ 1262 1263 sc->calib_data[1].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RY); 1264 sc->calib_data[1].code = ABS_RY; 1265 sc->calib_data[1].range = PS4DS_GYRO_RES_PER_DEG_S * 2048; 1266 sc->calib_data[1].res = PS4DS_GYRO_RES_PER_DEG_S; 1267 sc->calib_data[1].bias = HGETW(&buf[3]); 1268 sc->calib_data[1].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S; 1269 sc->calib_data[1].sens_denom = HGETW(&buf[11]) - HGETW(&buf[13]); 1270 /* BT case */ 1271 /* sc->calib_data[1].sens_denom = HGETW(&buf[9]) - HGETW(&buf[15]); */ 1272 1273 sc->calib_data[2].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RZ); 1274 sc->calib_data[2].code = ABS_RZ; 1275 sc->calib_data[2].range = PS4DS_GYRO_RES_PER_DEG_S * 2048; 1276 sc->calib_data[2].res = PS4DS_GYRO_RES_PER_DEG_S; 1277 sc->calib_data[2].bias = HGETW(&buf[5]); 1278 sc->calib_data[2].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S; 1279 sc->calib_data[2].sens_denom = HGETW(&buf[15]) - HGETW(&buf[17]); 1280 /* BT case */ 1281 /* sc->calib_data[2].sens_denom = HGETW(&buf[11]) - HGETW(&buf[17]); */ 1282 1283 /* 1284 * Set accelerometer calibration and normalization parameters. 1285 * Data values will be normalized to 1 / PS4DS_ACC_RES_PER_G G. 1286 */ 1287 range_2g = HGETW(&buf[23]) - HGETW(&buf[25]); 1288 sc->calib_data[3].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X); 1289 sc->calib_data[3].code = ABS_X; 1290 sc->calib_data[3].range = PS4DS_ACC_RES_PER_G * 4; 1291 sc->calib_data[3].res = PS4DS_ACC_RES_PER_G; 1292 sc->calib_data[3].bias = HGETW(&buf[23]) - range_2g / 2; 1293 sc->calib_data[3].sens_numer = 2 * PS4DS_ACC_RES_PER_G; 1294 sc->calib_data[3].sens_denom = range_2g; 1295 1296 range_2g = HGETW(&buf[27]) - HGETW(&buf[29]); 1297 sc->calib_data[4].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y); 1298 sc->calib_data[4].code = ABS_Y; 1299 sc->calib_data[4].range = PS4DS_ACC_RES_PER_G * 4; 1300 sc->calib_data[4].res = PS4DS_ACC_RES_PER_G; 1301 sc->calib_data[4].bias = HGETW(&buf[27]) - range_2g / 2; 1302 sc->calib_data[4].sens_numer = 2 * PS4DS_ACC_RES_PER_G; 1303 sc->calib_data[4].sens_denom = range_2g; 1304 1305 range_2g = HGETW(&buf[31]) - HGETW(&buf[33]); 1306 sc->calib_data[5].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z); 1307 sc->calib_data[5].code = ABS_Z; 1308 sc->calib_data[5].range = PS4DS_ACC_RES_PER_G * 4; 1309 sc->calib_data[5].res = PS4DS_ACC_RES_PER_G; 1310 sc->calib_data[5].bias = HGETW(&buf[31]) - range_2g / 2; 1311 sc->calib_data[5].sens_numer = 2 * PS4DS_ACC_RES_PER_G; 1312 sc->calib_data[5].sens_denom = range_2g; 1313 1314 return (hidmap_attach(&sc->hm)); 1315 } 1316 1317 static int 1318 ps4dshead_attach(device_t dev) 1319 { 1320 return (hidmap_attach(device_get_softc(dev))); 1321 } 1322 1323 static int 1324 ps4dsmtp_attach(device_t dev) 1325 { 1326 struct ps4dsmtp_softc *sc = device_get_softc(dev); 1327 1328 return (hidmap_attach(&sc->hm)); 1329 } 1330 1331 static int 1332 ps4dshock_detach(device_t dev) 1333 { 1334 struct ps4dshock_softc *sc = device_get_softc(dev); 1335 1336 hidmap_detach(&sc->hm); 1337 sc->led_state = PS4DS_LED_OFF; 1338 ps4dshock_write(sc); 1339 sx_destroy(&sc->lock); 1340 1341 return (0); 1342 } 1343 1344 static int 1345 ps4dsacc_detach(device_t dev) 1346 { 1347 struct ps4dsacc_softc *sc = device_get_softc(dev); 1348 1349 return (hidmap_detach(&sc->hm)); 1350 } 1351 1352 static int 1353 ps4dshead_detach(device_t dev) 1354 { 1355 return (hidmap_detach(device_get_softc(dev))); 1356 } 1357 1358 static int 1359 ps4dsmtp_detach(device_t dev) 1360 { 1361 struct ps4dsmtp_softc *sc = device_get_softc(dev); 1362 1363 return (hidmap_detach(&sc->hm)); 1364 } 1365 1366 static devclass_t ps4dshock_devclass; 1367 static devclass_t ps4dsacc_devclass; 1368 static devclass_t ps4dshead_devclass; 1369 static devclass_t ps4dsmtp_devclass; 1370 1371 static device_method_t ps4dshock_methods[] = { 1372 DEVMETHOD(device_identify, ps4dshock_identify), 1373 DEVMETHOD(device_probe, ps4dshock_probe), 1374 DEVMETHOD(device_attach, ps4dshock_attach), 1375 DEVMETHOD(device_detach, ps4dshock_detach), 1376 1377 DEVMETHOD_END 1378 }; 1379 static device_method_t ps4dsacc_methods[] = { 1380 DEVMETHOD(device_probe, ps4dsacc_probe), 1381 DEVMETHOD(device_attach, ps4dsacc_attach), 1382 DEVMETHOD(device_detach, ps4dsacc_detach), 1383 1384 DEVMETHOD_END 1385 }; 1386 static device_method_t ps4dshead_methods[] = { 1387 DEVMETHOD(device_probe, ps4dshead_probe), 1388 DEVMETHOD(device_attach, ps4dshead_attach), 1389 DEVMETHOD(device_detach, ps4dshead_detach), 1390 1391 DEVMETHOD_END 1392 }; 1393 static device_method_t ps4dsmtp_methods[] = { 1394 DEVMETHOD(device_probe, ps4dsmtp_probe), 1395 DEVMETHOD(device_attach, ps4dsmtp_attach), 1396 DEVMETHOD(device_detach, ps4dsmtp_detach), 1397 1398 DEVMETHOD_END 1399 }; 1400 1401 DEFINE_CLASS_0(ps4dsacc, ps4dsacc_driver, ps4dsacc_methods, 1402 sizeof(struct ps4dsacc_softc)); 1403 DRIVER_MODULE(ps4dsacc, hidbus, ps4dsacc_driver, ps4dsacc_devclass, NULL, 0); 1404 DEFINE_CLASS_0(ps4dshead, ps4dshead_driver, ps4dshead_methods, 1405 sizeof(struct hidmap)); 1406 DRIVER_MODULE(ps4dshead, hidbus, ps4dshead_driver, ps4dshead_devclass, NULL, 0); 1407 DEFINE_CLASS_0(ps4dsmtp, ps4dsmtp_driver, ps4dsmtp_methods, 1408 sizeof(struct ps4dsmtp_softc)); 1409 DRIVER_MODULE(ps4dsmtp, hidbus, ps4dsmtp_driver, ps4dsmtp_devclass, NULL, 0); 1410 DEFINE_CLASS_0(ps4dshock, ps4dshock_driver, ps4dshock_methods, 1411 sizeof(struct ps4dshock_softc)); 1412 DRIVER_MODULE(ps4dshock, hidbus, ps4dshock_driver, ps4dshock_devclass, NULL, 0); 1413 1414 MODULE_DEPEND(ps4dshock, hid, 1, 1, 1); 1415 MODULE_DEPEND(ps4dshock, hidbus, 1, 1, 1); 1416 MODULE_DEPEND(ps4dshock, hidmap, 1, 1, 1); 1417 MODULE_DEPEND(ps4dshock, evdev, 1, 1, 1); 1418 MODULE_VERSION(ps4dshock, 1); 1419 HID_PNP_INFO(ps4dshock_devs); 1420