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