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