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