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