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 } 812 813 return (0); 814 } 815 816 static int 817 ps4dshock_final_cb(HIDMAP_CB_ARGS) 818 { 819 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 820 821 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING) 822 evdev_support_prop(evdev, INPUT_PROP_DIRECT); 823 824 /* Do not execute callback at interrupt handler and detach */ 825 return (ENOSYS); 826 } 827 828 static int 829 ps4dsacc_data_cb(HIDMAP_CB_ARGS) 830 { 831 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 832 struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC(); 833 struct ps4ds_calib_data *calib; 834 u_int i; 835 836 switch (HIDMAP_CB_GET_STATE()) { 837 case HIDMAP_CB_IS_ATTACHING: 838 for (i = 0; i < nitems(sc->calib_data); i++) { 839 if (sc->calib_data[i].usage == ctx.hi->usage) { 840 evdev_support_abs(evdev, 841 sc->calib_data[i].code, 842 -sc->calib_data[i].range, 843 sc->calib_data[i].range, 16, 0, 844 sc->calib_data[i].res); 845 HIDMAP_CB_UDATA = &sc->calib_data[i]; 846 break; 847 } 848 } 849 break; 850 851 case HIDMAP_CB_IS_RUNNING: 852 calib = HIDMAP_CB_UDATA; 853 evdev_push_abs(evdev, calib->code, 854 ((int64_t)ctx.data - calib->bias) * calib->sens_numer / 855 calib->sens_denom); 856 break; 857 } 858 859 return (0); 860 } 861 862 static int 863 ps4dsacc_tstamp_cb(HIDMAP_CB_ARGS) 864 { 865 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 866 struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC(); 867 uint16_t tstamp; 868 869 switch (HIDMAP_CB_GET_STATE()) { 870 case HIDMAP_CB_IS_ATTACHING: 871 evdev_support_event(evdev, EV_MSC); 872 evdev_support_msc(evdev, MSC_TIMESTAMP); 873 break; 874 875 case HIDMAP_CB_IS_RUNNING: 876 /* Convert timestamp (in 5.33us unit) to timestamp_us */ 877 tstamp = (uint16_t)ctx.data; 878 sc->ev_tstamp += (uint16_t)(tstamp - sc->hw_tstamp) * 16 / 3; 879 sc->hw_tstamp = tstamp; 880 evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp); 881 break; 882 } 883 884 return (0); 885 } 886 887 static int 888 ps4dsacc_final_cb(HIDMAP_CB_ARGS) 889 { 890 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 891 892 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING) { 893 evdev_support_event(evdev, EV_ABS); 894 evdev_support_prop(evdev, INPUT_PROP_ACCELEROMETER); 895 } 896 /* Do not execute callback at interrupt handler and detach */ 897 return (ENOSYS); 898 } 899 900 static int 901 ps4dsmtp_npackets_cb(HIDMAP_CB_ARGS) 902 { 903 struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC(); 904 905 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) { 906 sc->npackets = MIN(PS4DS_MAX_TOUCHPAD_PACKETS,(u_int)ctx.data); 907 /* Reset pointer here as it is first usage in touchpad TLC */ 908 sc->data_ptr = sc->data; 909 } 910 911 return (0); 912 } 913 914 static int 915 ps4dsmtp_data_cb(HIDMAP_CB_ARGS) 916 { 917 struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC(); 918 919 if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) { 920 *sc->data_ptr = ctx.data; 921 ++sc->data_ptr; 922 } 923 924 return (0); 925 } 926 927 static void 928 ps4dsmtp_push_packet(struct ps4dsmtp_softc *sc, struct evdev_dev *evdev, 929 int32_t *data) 930 { 931 uint8_t hw_tstamp, delta; 932 bool touch; 933 934 evdev_push_abs(evdev, ABS_MT_SLOT, 0); 935 if (data[PS4DS_TIP1] == 0) { 936 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID1]); 937 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X1]); 938 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y1]); 939 } else 940 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1); 941 evdev_push_abs(evdev, ABS_MT_SLOT, 1); 942 if (data[PS4DS_TIP2] == 0) { 943 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID2]); 944 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X2]); 945 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y2]); 946 } else 947 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1); 948 949 if (sc->do_tstamps) { 950 /* 951 * Export hardware timestamps in libinput-friendly way. 952 * Make timestamp counter 32-bit, scale up hardware 953 * timestamps to be on per 1usec basis and reset 954 * counter at the start of each touch. 955 */ 956 hw_tstamp = (uint8_t)data[PS4DS_TSTAMP]; 957 delta = hw_tstamp - sc->hw_tstamp; 958 sc->hw_tstamp = hw_tstamp; 959 touch = data[PS4DS_TIP1] == 0 || data[PS4DS_TIP2] == 0; 960 /* Hardware timestamp counter ticks in 682 usec interval. */ 961 if ((touch || sc->touch) && delta != 0) { 962 if (sc->touch) 963 sc->ev_tstamp += delta * 682; 964 evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp); 965 } 966 if (!touch) 967 sc->ev_tstamp = 0; 968 sc->touch = touch; 969 } 970 } 971 972 static int 973 ps4dsmtp_final_cb(HIDMAP_CB_ARGS) 974 { 975 struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC(); 976 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); 977 int32_t *data; 978 979 switch (HIDMAP_CB_GET_STATE()) { 980 case HIDMAP_CB_IS_ATTACHING: 981 if (hid_test_quirk(hid_get_device_info(sc->hm.dev), 982 HQ_MT_TIMESTAMP)) 983 sc->do_tstamps = true; 984 /* 985 * Dualshock 4 touchpad TLC contained in fixed report 986 * descriptor is almost compatible with MS precission touchpad 987 * specs and hmt(4) driver. But... for some reasons "Click" 988 * button location was grouped with other GamePad buttons by 989 * touchpad designers so it belongs to GamePad TLC. Fix it with 990 * direct reading of "Click" button value from interrupt frame. 991 */ 992 sc->btn_loc = (struct hid_location) { 1, 0, 49 }; 993 evdev_support_event(evdev, EV_SYN); 994 evdev_support_event(evdev, EV_KEY); 995 evdev_support_event(evdev, EV_ABS); 996 if (sc->do_tstamps) { 997 evdev_support_event(evdev, EV_MSC); 998 evdev_support_msc(evdev, MSC_TIMESTAMP); 999 } 1000 evdev_support_key(evdev, BTN_LEFT); 1001 evdev_support_abs(evdev, ABS_MT_SLOT, 0, 1, 0, 0, 0); 1002 evdev_support_abs(evdev, ABS_MT_TRACKING_ID, -1, 127, 0, 0, 0); 1003 evdev_support_abs(evdev, ABS_MT_POSITION_X, 0, 1920, 0, 0, 30); 1004 evdev_support_abs(evdev, ABS_MT_POSITION_Y, 0, 942, 0, 0, 49); 1005 evdev_support_prop(evdev, INPUT_PROP_POINTER); 1006 evdev_support_prop(evdev, INPUT_PROP_BUTTONPAD); 1007 evdev_set_flag(evdev, EVDEV_FLAG_MT_STCOMPAT); 1008 break; 1009 1010 case HIDMAP_CB_IS_RUNNING: 1011 /* Only packets with ReportID=1 are accepted */ 1012 if (HIDMAP_CB_GET_RID() != 1) 1013 return (ENOTSUP); 1014 evdev_push_key(evdev, BTN_LEFT, 1015 HIDMAP_CB_GET_UDATA(&sc->btn_loc)); 1016 for (data = sc->data; 1017 data < sc->data + PS4DS_NTPUSAGES * sc->npackets; 1018 data += PS4DS_NTPUSAGES) { 1019 ps4dsmtp_push_packet(sc, evdev, data); 1020 evdev_sync(evdev); 1021 } 1022 break; 1023 } 1024 1025 /* Do execute callback at interrupt handler and detach */ 1026 return (0); 1027 } 1028 1029 static int 1030 ps4dshock_write(struct ps4dshock_softc *sc) 1031 { 1032 hid_size_t osize = sc->is_bluetooth ? 1033 PS4DS_OUTPUT_REPORT11_SIZE : PS4DS_OUTPUT_REPORT5_SIZE; 1034 uint8_t buf[osize]; 1035 int offset; 1036 bool led_on, led_blinks; 1037 1038 memset(buf, 0, osize); 1039 buf[0] = sc->is_bluetooth ? 0x11 : 0x05; 1040 offset = sc->is_bluetooth ? 3 : 1; 1041 led_on = sc->led_state != PS4DS_LED_OFF; 1042 led_blinks = sc->led_state == PS4DS_LED_BLINKING; 1043 *(struct ps4ds_out5 *)(buf + offset) = (struct ps4ds_out5) { 1044 .features = 0x07, /* blink + LEDs + motor */ 1045 .rumble_right = sc->rumble_right, 1046 .rumble_left = sc->rumble_left, 1047 .led_color_r = led_on ? sc->led_color.r : 0, 1048 .led_color_g = led_on ? sc->led_color.g : 0, 1049 .led_color_b = led_on ? sc->led_color.b : 0, 1050 /* convert milliseconds to centiseconds */ 1051 .led_delay_on = led_blinks ? sc->led_delay_on / 10 : 0, 1052 .led_delay_off = led_blinks ? sc->led_delay_off / 10 : 0, 1053 }; 1054 1055 return (hid_write(sc->hm.dev, buf, osize)); 1056 } 1057 1058 /* Synaptics Touchpad */ 1059 static int 1060 ps4dshock_sysctl(SYSCTL_HANDLER_ARGS) 1061 { 1062 struct ps4dshock_softc *sc; 1063 int error, arg; 1064 1065 if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || 1066 oidp->oid_arg2 > PD4DSHOCK_SYSCTL_LAST) 1067 return (EINVAL); 1068 1069 sc = oidp->oid_arg1; 1070 sx_xlock(&sc->lock); 1071 1072 /* Read the current value. */ 1073 arg = *(int *)((char *)sc + oidp->oid_arg2); 1074 error = sysctl_handle_int(oidp, &arg, 0, req); 1075 1076 /* Sanity check. */ 1077 if (error || !req->newptr) 1078 goto unlock; 1079 1080 /* 1081 * Check that the new value is in the concerned node's range 1082 * of values. 1083 */ 1084 switch (oidp->oid_arg2) { 1085 case PD4DSHOCK_SYSCTL_LED_STATE: 1086 if (arg < 0 || arg >= PD4DS_LED_CNT) 1087 error = EINVAL; 1088 break; 1089 case PD4DSHOCK_SYSCTL_LED_COLOR_R: 1090 case PD4DSHOCK_SYSCTL_LED_COLOR_G: 1091 case PD4DSHOCK_SYSCTL_LED_COLOR_B: 1092 if (arg < 0 || arg > UINT8_MAX) 1093 error = EINVAL; 1094 break; 1095 case PD4DSHOCK_SYSCTL_LED_DELAY_ON: 1096 case PD4DSHOCK_SYSCTL_LED_DELAY_OFF: 1097 if (arg < 0 || arg > UINT8_MAX * 10) 1098 error = EINVAL; 1099 break; 1100 default: 1101 error = EINVAL; 1102 } 1103 1104 /* Update. */ 1105 if (error == 0) { 1106 *(int *)((char *)sc + oidp->oid_arg2) = arg; 1107 ps4dshock_write(sc); 1108 } 1109 unlock: 1110 sx_unlock(&sc->lock); 1111 1112 return (error); 1113 } 1114 1115 static void 1116 ps4dshock_identify(driver_t *driver, device_t parent) 1117 { 1118 1119 /* Overload PS4 DualShock gamepad rudimentary report descriptor */ 1120 if (HIDBUS_LOOKUP_ID(parent, ps4dshock_devs) != NULL) 1121 hid_set_report_descr(parent, ps4dshock_rdesc, 1122 sizeof(ps4dshock_rdesc)); 1123 } 1124 1125 static int 1126 ps4dshock_probe(device_t dev) 1127 { 1128 struct ps4dshock_softc *sc = device_get_softc(dev); 1129 1130 hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR); 1131 return ( 1132 HIDMAP_PROBE(&sc->hm, dev, ps4dshock_devs, ps4dshock_map, NULL) 1133 ); 1134 } 1135 1136 static int 1137 ps4dsacc_probe(device_t dev) 1138 { 1139 struct ps4dsacc_softc *sc = device_get_softc(dev); 1140 1141 hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR); 1142 return ( 1143 HIDMAP_PROBE(&sc->hm, dev, ps4dsacc_devs, ps4dsacc_map, "Sensors") 1144 ); 1145 } 1146 1147 static int 1148 ps4dshead_probe(device_t dev) 1149 { 1150 struct hidmap *hm = device_get_softc(dev); 1151 1152 hidmap_set_debug_var(hm, &HID_DEBUG_VAR); 1153 return ( 1154 HIDMAP_PROBE(hm, dev, ps4dshead_devs, ps4dshead_map, "Headset") 1155 ); 1156 } 1157 1158 static int 1159 ps4dsmtp_probe(device_t dev) 1160 { 1161 struct ps4dshock_softc *sc = device_get_softc(dev); 1162 1163 hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR); 1164 return ( 1165 HIDMAP_PROBE(&sc->hm, dev, ps4dsmtp_devs, ps4dsmtp_map, "Touchpad") 1166 ); 1167 } 1168 1169 static int 1170 ps4dshock_attach(device_t dev) 1171 { 1172 struct ps4dshock_softc *sc = device_get_softc(dev); 1173 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 1174 struct sysctl_oid *tree = device_get_sysctl_tree(dev); 1175 1176 sc->led_state = PS4DS_LED_ON; 1177 sc->led_color = ps4ds_leds[device_get_unit(dev) % nitems(ps4ds_leds)]; 1178 sc->led_delay_on = 500; /* 1 Hz */ 1179 sc->led_delay_off = 500; 1180 ps4dshock_write(sc); 1181 1182 sx_init(&sc->lock, "ps4dshock"); 1183 1184 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1185 "led_state", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1186 PD4DSHOCK_SYSCTL_LED_STATE, ps4dshock_sysctl, "I", 1187 "LED state: 0 - off, 1 - on, 2 - blinking."); 1188 1189 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1190 "led_color_r", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1191 PD4DSHOCK_SYSCTL_LED_COLOR_R, ps4dshock_sysctl, "I", 1192 "LED color. Red component."); 1193 1194 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1195 "led_color_g", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1196 PD4DSHOCK_SYSCTL_LED_COLOR_G, ps4dshock_sysctl, "I", 1197 "LED color. Green component."); 1198 1199 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1200 "led_color_b", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1201 PD4DSHOCK_SYSCTL_LED_COLOR_B, ps4dshock_sysctl, "I", 1202 "LED color. Blue component."); 1203 1204 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1205 "led_delay_on", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1206 PD4DSHOCK_SYSCTL_LED_DELAY_ON, ps4dshock_sysctl, "I", 1207 "LED blink. On delay, msecs."); 1208 1209 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1210 "led_delay_off", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc, 1211 PD4DSHOCK_SYSCTL_LED_DELAY_OFF, ps4dshock_sysctl, "I", 1212 "LED blink. Off delay, msecs."); 1213 1214 return (hidmap_attach(&sc->hm)); 1215 } 1216 1217 static int 1218 ps4dsacc_attach(device_t dev) 1219 { 1220 struct ps4dsacc_softc *sc = device_get_softc(dev); 1221 uint8_t buf[PS4DS_FEATURE_REPORT2_SIZE]; 1222 int error, speed_2x, range_2g; 1223 1224 /* Read accelerometers and gyroscopes calibration data */ 1225 error = hid_get_report(dev, buf, sizeof(buf), NULL, 1226 HID_FEATURE_REPORT, 0x02); 1227 if (error) 1228 DPRINTF("get feature report failed, error=%d " 1229 "(ignored)\n", error); 1230 1231 DPRINTFN(5, "calibration data: %*D\n", (int)sizeof(buf), buf, " "); 1232 1233 /* 1234 * Set gyroscope calibration and normalization parameters. 1235 * Data values will be normalized to 1/ PS4DS_GYRO_RES_PER_DEG_S 1236 * degree/s. 1237 */ 1238 #define HGETW(w) ((int16_t)((w)[0] | (((uint16_t)((w)[1])) << 8))) 1239 speed_2x = HGETW(&buf[19]) + HGETW(&buf[21]); 1240 sc->calib_data[0].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RX); 1241 sc->calib_data[0].code = ABS_RX; 1242 sc->calib_data[0].range = PS4DS_GYRO_RES_PER_DEG_S * 2048; 1243 sc->calib_data[0].res = PS4DS_GYRO_RES_PER_DEG_S; 1244 sc->calib_data[0].bias = HGETW(&buf[1]); 1245 sc->calib_data[0].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S; 1246 sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[9]); 1247 /* BT case */ 1248 /* sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[13]); */ 1249 1250 sc->calib_data[1].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RY); 1251 sc->calib_data[1].code = ABS_RY; 1252 sc->calib_data[1].range = PS4DS_GYRO_RES_PER_DEG_S * 2048; 1253 sc->calib_data[1].res = PS4DS_GYRO_RES_PER_DEG_S; 1254 sc->calib_data[1].bias = HGETW(&buf[3]); 1255 sc->calib_data[1].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S; 1256 sc->calib_data[1].sens_denom = HGETW(&buf[11]) - HGETW(&buf[13]); 1257 /* BT case */ 1258 /* sc->calib_data[1].sens_denom = HGETW(&buf[9]) - HGETW(&buf[15]); */ 1259 1260 sc->calib_data[2].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RZ); 1261 sc->calib_data[2].code = ABS_RZ; 1262 sc->calib_data[2].range = PS4DS_GYRO_RES_PER_DEG_S * 2048; 1263 sc->calib_data[2].res = PS4DS_GYRO_RES_PER_DEG_S; 1264 sc->calib_data[2].bias = HGETW(&buf[5]); 1265 sc->calib_data[2].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S; 1266 sc->calib_data[2].sens_denom = HGETW(&buf[15]) - HGETW(&buf[17]); 1267 /* BT case */ 1268 /* sc->calib_data[2].sens_denom = HGETW(&buf[11]) - HGETW(&buf[17]); */ 1269 1270 /* 1271 * Set accelerometer calibration and normalization parameters. 1272 * Data values will be normalized to 1 / PS4DS_ACC_RES_PER_G G. 1273 */ 1274 range_2g = HGETW(&buf[23]) - HGETW(&buf[25]); 1275 sc->calib_data[3].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X); 1276 sc->calib_data[3].code = ABS_X; 1277 sc->calib_data[3].range = PS4DS_ACC_RES_PER_G * 4; 1278 sc->calib_data[3].res = PS4DS_ACC_RES_PER_G; 1279 sc->calib_data[3].bias = HGETW(&buf[23]) - range_2g / 2; 1280 sc->calib_data[3].sens_numer = 2 * PS4DS_ACC_RES_PER_G; 1281 sc->calib_data[3].sens_denom = range_2g; 1282 1283 range_2g = HGETW(&buf[27]) - HGETW(&buf[29]); 1284 sc->calib_data[4].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y); 1285 sc->calib_data[4].code = ABS_Y; 1286 sc->calib_data[4].range = PS4DS_ACC_RES_PER_G * 4; 1287 sc->calib_data[4].res = PS4DS_ACC_RES_PER_G; 1288 sc->calib_data[4].bias = HGETW(&buf[27]) - range_2g / 2; 1289 sc->calib_data[4].sens_numer = 2 * PS4DS_ACC_RES_PER_G; 1290 sc->calib_data[4].sens_denom = range_2g; 1291 1292 range_2g = HGETW(&buf[31]) - HGETW(&buf[33]); 1293 sc->calib_data[5].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z); 1294 sc->calib_data[5].code = ABS_Z; 1295 sc->calib_data[5].range = PS4DS_ACC_RES_PER_G * 4; 1296 sc->calib_data[5].res = PS4DS_ACC_RES_PER_G; 1297 sc->calib_data[5].bias = HGETW(&buf[31]) - range_2g / 2; 1298 sc->calib_data[5].sens_numer = 2 * PS4DS_ACC_RES_PER_G; 1299 sc->calib_data[5].sens_denom = range_2g; 1300 1301 return (hidmap_attach(&sc->hm)); 1302 } 1303 1304 static int 1305 ps4dshead_attach(device_t dev) 1306 { 1307 return (hidmap_attach(device_get_softc(dev))); 1308 } 1309 1310 static int 1311 ps4dsmtp_attach(device_t dev) 1312 { 1313 struct ps4dsmtp_softc *sc = device_get_softc(dev); 1314 1315 return (hidmap_attach(&sc->hm)); 1316 } 1317 1318 static int 1319 ps4dshock_detach(device_t dev) 1320 { 1321 struct ps4dshock_softc *sc = device_get_softc(dev); 1322 1323 hidmap_detach(&sc->hm); 1324 sc->led_state = PS4DS_LED_OFF; 1325 ps4dshock_write(sc); 1326 sx_destroy(&sc->lock); 1327 1328 return (0); 1329 } 1330 1331 static int 1332 ps4dsacc_detach(device_t dev) 1333 { 1334 struct ps4dsacc_softc *sc = device_get_softc(dev); 1335 1336 return (hidmap_detach(&sc->hm)); 1337 } 1338 1339 static int 1340 ps4dshead_detach(device_t dev) 1341 { 1342 return (hidmap_detach(device_get_softc(dev))); 1343 } 1344 1345 static int 1346 ps4dsmtp_detach(device_t dev) 1347 { 1348 struct ps4dsmtp_softc *sc = device_get_softc(dev); 1349 1350 return (hidmap_detach(&sc->hm)); 1351 } 1352 1353 static devclass_t ps4dshock_devclass; 1354 static devclass_t ps4dsacc_devclass; 1355 static devclass_t ps4dshead_devclass; 1356 static devclass_t ps4dsmtp_devclass; 1357 1358 static device_method_t ps4dshock_methods[] = { 1359 DEVMETHOD(device_identify, ps4dshock_identify), 1360 DEVMETHOD(device_probe, ps4dshock_probe), 1361 DEVMETHOD(device_attach, ps4dshock_attach), 1362 DEVMETHOD(device_detach, ps4dshock_detach), 1363 1364 DEVMETHOD_END 1365 }; 1366 static device_method_t ps4dsacc_methods[] = { 1367 DEVMETHOD(device_probe, ps4dsacc_probe), 1368 DEVMETHOD(device_attach, ps4dsacc_attach), 1369 DEVMETHOD(device_detach, ps4dsacc_detach), 1370 1371 DEVMETHOD_END 1372 }; 1373 static device_method_t ps4dshead_methods[] = { 1374 DEVMETHOD(device_probe, ps4dshead_probe), 1375 DEVMETHOD(device_attach, ps4dshead_attach), 1376 DEVMETHOD(device_detach, ps4dshead_detach), 1377 1378 DEVMETHOD_END 1379 }; 1380 static device_method_t ps4dsmtp_methods[] = { 1381 DEVMETHOD(device_probe, ps4dsmtp_probe), 1382 DEVMETHOD(device_attach, ps4dsmtp_attach), 1383 DEVMETHOD(device_detach, ps4dsmtp_detach), 1384 1385 DEVMETHOD_END 1386 }; 1387 1388 DEFINE_CLASS_0(ps4dsacc, ps4dsacc_driver, ps4dsacc_methods, 1389 sizeof(struct ps4dsacc_softc)); 1390 DRIVER_MODULE(ps4dsacc, hidbus, ps4dsacc_driver, ps4dsacc_devclass, NULL, 0); 1391 DEFINE_CLASS_0(ps4dshead, ps4dshead_driver, ps4dshead_methods, 1392 sizeof(struct hidmap)); 1393 DRIVER_MODULE(ps4dshead, hidbus, ps4dshead_driver, ps4dshead_devclass, NULL, 0); 1394 DEFINE_CLASS_0(ps4dsmtp, ps4dsmtp_driver, ps4dsmtp_methods, 1395 sizeof(struct ps4dsmtp_softc)); 1396 DRIVER_MODULE(ps4dsmtp, hidbus, ps4dsmtp_driver, ps4dsmtp_devclass, NULL, 0); 1397 DEFINE_CLASS_0(ps4dshock, ps4dshock_driver, ps4dshock_methods, 1398 sizeof(struct ps4dshock_softc)); 1399 DRIVER_MODULE(ps4dshock, hidbus, ps4dshock_driver, ps4dshock_devclass, NULL, 0); 1400 1401 MODULE_DEPEND(ps4dshock, hid, 1, 1, 1); 1402 MODULE_DEPEND(ps4dshock, hidbus, 1, 1, 1); 1403 MODULE_DEPEND(ps4dshock, hidmap, 1, 1, 1); 1404 MODULE_DEPEND(ps4dshock, evdev, 1, 1, 1); 1405 MODULE_VERSION(ps4dshock, 1); 1406 HID_PNP_INFO(ps4dshock_devs); 1407