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