xref: /freebsd/sys/dev/usb/input/wmt.c (revision ca48e43ba9ee73a07cdbad8365117793b01273bb)
1 /*-
2  * Copyright (c) 2014-2017 Vladimir Kondratyev <wulf@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 /*
28  * MS Windows 7/8/10 compatible USB HID Multi-touch Device driver.
29  * https://msdn.microsoft.com/en-us/library/windows/hardware/jj151569(v=vs.85).aspx
30  * https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
31  */
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/conf.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/mutex.h>
41 #include <sys/stddef.h>
42 #include <sys/sysctl.h>
43 #include <sys/systm.h>
44 
45 #include <dev/hid/hid.h>
46 
47 #include "usbdevs.h"
48 #include <dev/usb/usb.h>
49 #include <dev/usb/usbdi.h>
50 #include <dev/usb/usbdi_util.h>
51 #include <dev/usb/usbhid.h>
52 
53 #include <dev/usb/quirk/usb_quirk.h>
54 
55 #include <dev/evdev/evdev.h>
56 #include <dev/evdev/input.h>
57 
58 #define	USB_DEBUG_VAR wmt_debug
59 #include <dev/usb/usb_debug.h>
60 
61 static SYSCTL_NODE(_hw_usb, OID_AUTO, wmt, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
62     "USB MSWindows 7/8/10 compatible Multi-touch Device");
63 #ifdef USB_DEBUG
64 static int wmt_debug = 0;
65 SYSCTL_INT(_hw_usb_wmt, OID_AUTO, debug, CTLFLAG_RWTUN,
66     &wmt_debug, 1, "Debug level");
67 #endif
68 static bool wmt_timestamps = 0;
69 SYSCTL_BOOL(_hw_usb_wmt, OID_AUTO, timestamps, CTLFLAG_RDTUN,
70     &wmt_timestamps, 1, "Enable hardware timestamp reporting");
71 
72 #define	WMT_BSIZE	1024	/* bytes, buffer size */
73 #define	WMT_BTN_MAX	8	/* Number of buttons supported */
74 
75 enum {
76 	WMT_INTR_DT,
77 	WMT_N_TRANSFER,
78 };
79 
80 enum wmt_type {
81 	WMT_TYPE_UNKNOWN = 0,	/* HID report descriptor is not probed */
82 	WMT_TYPE_UNSUPPORTED,	/* Repdescr does not belong to MT device */
83 	WMT_TYPE_TOUCHPAD,
84 	WMT_TYPE_TOUCHSCREEN,
85 };
86 
87 enum wmt_input_mode {
88 	WMT_INPUT_MODE_MOUSE =		0x0,
89 	WMT_INPUT_MODE_MT_TOUCHSCREEN =	0x2,
90 	WMT_INPUT_MODE_MT_TOUCHPAD =	0x3,
91 };
92 
93 enum {
94 	WMT_TIP_SWITCH =	ABS_MT_INDEX(ABS_MT_TOOL_TYPE),
95 	WMT_WIDTH =		ABS_MT_INDEX(ABS_MT_TOUCH_MAJOR),
96 	WMT_HEIGHT =		ABS_MT_INDEX(ABS_MT_TOUCH_MINOR),
97 	WMT_ORIENTATION =	ABS_MT_INDEX(ABS_MT_ORIENTATION),
98 	WMT_X =			ABS_MT_INDEX(ABS_MT_POSITION_X),
99 	WMT_Y =			ABS_MT_INDEX(ABS_MT_POSITION_Y),
100 	WMT_CONTACTID =		ABS_MT_INDEX(ABS_MT_TRACKING_ID),
101 	WMT_PRESSURE =		ABS_MT_INDEX(ABS_MT_PRESSURE),
102 	WMT_IN_RANGE =		ABS_MT_INDEX(ABS_MT_DISTANCE),
103 	WMT_CONFIDENCE =	ABS_MT_INDEX(ABS_MT_BLOB_ID),
104 	WMT_TOOL_X =		ABS_MT_INDEX(ABS_MT_TOOL_X),
105 	WMT_TOOL_Y =		ABS_MT_INDEX(ABS_MT_TOOL_Y),
106 };
107 
108 #define	WMT_N_USAGES	MT_CNT
109 #define	WMT_NO_USAGE	-1
110 
111 struct wmt_hid_map_item {
112 	char		name[5];
113 	int32_t 	usage;		/* HID usage */
114 	bool		reported;	/* Item value is passed to evdev */
115 	bool		required;	/* Required for MT Digitizers */
116 };
117 
118 static const struct wmt_hid_map_item wmt_hid_map[WMT_N_USAGES] = {
119 	[WMT_TIP_SWITCH] = {
120 		.name = "TIP",
121 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH),
122 		.reported = false,
123 		.required = true,
124 	},
125 	[WMT_WIDTH] = {
126 		.name = "WDTH",
127 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_WIDTH),
128 		.reported = true,
129 		.required = false,
130 	},
131 	[WMT_HEIGHT] = {
132 		.name = "HGHT",
133 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_HEIGHT),
134 		.reported = true,
135 		.required = false,
136 	},
137 	[WMT_ORIENTATION] = {
138 		.name = "ORIE",
139 		.usage = WMT_NO_USAGE,
140 		.reported = true,
141 		.required = false,
142 	},
143 	[WMT_X] = {
144 		.name = "X",
145 		.usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
146 		.reported = true,
147 		.required = true,
148 	},
149 	[WMT_Y] = {
150 		.name = "Y",
151 		.usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
152 		.reported = true,
153 		.required = true,
154 	},
155 	[WMT_CONTACTID] = {
156 		.name = "C_ID",
157 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTID),
158 		.reported = true,
159 		.required = true,
160 	},
161 	[WMT_PRESSURE] = {
162 		.name = "PRES",
163 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_PRESSURE),
164 		.reported = true,
165 		.required = false,
166 	},
167 	[WMT_IN_RANGE] = {
168 		.name = "RANG",
169 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_IN_RANGE),
170 		.reported = true,
171 		.required = false,
172 	},
173 	[WMT_CONFIDENCE] = {
174 		.name = "CONF",
175 		.usage = HID_USAGE2(HUP_DIGITIZERS, HUD_CONFIDENCE),
176 		.reported = false,
177 		.required = false,
178 	},
179 	[WMT_TOOL_X] = {	/* Shares HID usage with WMT_X */
180 		.name = "TL_X",
181 		.usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
182 		.reported = true,
183 		.required = false,
184 	},
185 	[WMT_TOOL_Y] = {	/* Shares HID usage with WMT_Y */
186 		.name = "TL_Y",
187 		.usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
188 		.reported = true,
189 		.required = false,
190 	},
191 };
192 
193 struct wmt_absinfo {
194 	int32_t			min;
195 	int32_t			max;
196 	int32_t			res;
197 };
198 
199 struct wmt_softc {
200 	device_t		dev;
201 	enum wmt_type		type;
202 
203 	int32_t			cont_count_max;
204 	struct mtx		mtx;
205 	struct wmt_absinfo	ai[WMT_N_USAGES];
206 	struct hid_location	locs[MAX_MT_SLOTS][WMT_N_USAGES];
207 	struct hid_location	cont_count_loc;
208 	struct hid_location	btn_loc[WMT_BTN_MAX];
209 	struct hid_location	int_btn_loc;
210 	struct hid_location	scan_time_loc;
211 	int32_t			scan_time_max;
212 	int32_t			scan_time;
213 	int32_t			timestamp;
214 	bool			touch;
215 	bool			prev_touch;
216 
217 	struct usb_xfer		*xfer[WMT_N_TRANSFER];
218 	struct evdev_dev	*evdev;
219 
220 	union evdev_mt_slot	slot_data;
221 	uint8_t			caps[howmany(WMT_N_USAGES, 8)];
222 	uint8_t			buttons[howmany(WMT_BTN_MAX, 8)];
223 	uint32_t		isize;
224 	uint32_t		nconts_per_report;
225 	uint32_t		nconts_todo;
226 	uint32_t		report_len;
227 	uint8_t			report_id;
228 	uint32_t		max_button;
229 	bool			has_int_button;
230 	bool			is_clickpad;
231 	bool			do_timestamps;
232 
233 	struct hid_location	cont_max_loc;
234 	uint32_t		cont_max_rlen;
235 	uint8_t			cont_max_rid;
236 	struct hid_location	btn_type_loc;
237 	uint32_t		btn_type_rlen;
238 	uint8_t			btn_type_rid;
239 	uint32_t		thqa_cert_rlen;
240 	uint8_t			thqa_cert_rid;
241 	struct hid_location	input_mode_loc;
242 	uint32_t		input_mode_rlen;
243 	uint8_t			input_mode_rid;
244 
245 	uint8_t			buf[WMT_BSIZE] __aligned(4);
246 };
247 
248 #define	WMT_FOREACH_USAGE(caps, usage)			\
249 	for ((usage) = 0; (usage) < WMT_N_USAGES; ++(usage))	\
250 		if (isset((caps), (usage)))
251 
252 static enum wmt_type wmt_hid_parse(struct wmt_softc *, const void *, uint16_t);
253 static int wmt_set_input_mode(struct wmt_softc *, enum wmt_input_mode);
254 
255 static usb_callback_t	wmt_intr_callback;
256 
257 static device_probe_t	wmt_probe;
258 static device_attach_t	wmt_attach;
259 static device_detach_t	wmt_detach;
260 
261 static evdev_open_t	wmt_ev_open;
262 static evdev_close_t	wmt_ev_close;
263 
264 static const struct evdev_methods wmt_evdev_methods = {
265 	.ev_open = &wmt_ev_open,
266 	.ev_close = &wmt_ev_close,
267 };
268 
269 static const struct usb_config wmt_config[WMT_N_TRANSFER] = {
270 	[WMT_INTR_DT] = {
271 		.type = UE_INTERRUPT,
272 		.endpoint = UE_ADDR_ANY,
273 		.direction = UE_DIR_IN,
274 		.flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
275 		.bufsize = WMT_BSIZE,
276 		.callback = &wmt_intr_callback,
277 	},
278 };
279 
280 static int
wmt_probe(device_t dev)281 wmt_probe(device_t dev)
282 {
283 	struct usb_attach_arg *uaa = device_get_ivars(dev);
284 	struct wmt_softc *sc = device_get_softc(dev);
285 	void *d_ptr;
286 	uint16_t d_len;
287 	int err;
288 
289 	if (uaa->usb_mode != USB_MODE_HOST)
290 		return (ENXIO);
291 
292 	if (uaa->info.bInterfaceClass != UICLASS_HID)
293 		return (ENXIO);
294 
295 	if (usb_test_quirk(uaa, UQ_WMT_IGNORE))
296 		return (ENXIO);
297 
298 	err = usbd_req_get_hid_desc(uaa->device, NULL,
299 	    &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex);
300 	if (err)
301 		return (ENXIO);
302 
303 	/* Check if report descriptor belongs to a HID multitouch device */
304 	if (sc->type == WMT_TYPE_UNKNOWN)
305 		sc->type = wmt_hid_parse(sc, d_ptr, d_len);
306 	if (sc->type != WMT_TYPE_UNSUPPORTED)
307 		err = BUS_PROBE_DEFAULT;
308 	else
309 		err = ENXIO;
310 
311 	/* Check HID report length */
312 	if (sc->type != WMT_TYPE_UNSUPPORTED &&
313 	    (sc->isize <= 0 || sc->isize > WMT_BSIZE)) {
314 		DPRINTF("Input size invalid or too large: %d\n", sc->isize);
315 		err = ENXIO;
316 	}
317 
318 	free(d_ptr, M_TEMP);
319 	return (err);
320 }
321 
322 static int
wmt_attach(device_t dev)323 wmt_attach(device_t dev)
324 {
325 	struct usb_attach_arg *uaa = device_get_ivars(dev);
326 	struct wmt_softc *sc = device_get_softc(dev);
327 	uint32_t cont_count_max;
328 	int nbuttons, btn;
329 	size_t i;
330 	int err;
331 
332 	device_set_usb_desc(dev);
333 	sc->dev = dev;
334 
335 	/* Fetch and parse "Contact count maximum" feature report */
336 	if (sc->cont_max_rlen > 0 && sc->cont_max_rlen <= WMT_BSIZE) {
337 		err = usbd_req_get_report(uaa->device, NULL, sc->buf,
338 		    sc->cont_max_rlen, uaa->info.bIfaceIndex,
339 		    UHID_FEATURE_REPORT, sc->cont_max_rid);
340 		if (err == USB_ERR_NORMAL_COMPLETION) {
341 			cont_count_max = hid_get_udata(sc->buf + 1,
342 			    sc->cont_max_rlen - 1, &sc->cont_max_loc);
343 			/*
344 			 * Feature report is a primary source of
345 			 * 'Contact Count Maximum'
346 			 */
347 			if (cont_count_max > 0)
348 				sc->cont_count_max = cont_count_max;
349 		} else
350 			DPRINTF("usbd_req_get_report error=(%s)\n",
351 			    usbd_errstr(err));
352 	} else
353 		DPRINTF("Feature report %hhu size invalid or too large: %u\n",
354 		    sc->cont_max_rid, sc->cont_max_rlen);
355 
356 	/* Fetch and parse "Button type" feature report */
357 	if (sc->btn_type_rlen > 1 && sc->btn_type_rlen <= WMT_BSIZE &&
358 	    sc->btn_type_rid != sc->cont_max_rid) {
359 		bzero(sc->buf, sc->btn_type_rlen);
360 		err = usbd_req_get_report(uaa->device, NULL, sc->buf,
361 		    sc->btn_type_rlen, uaa->info.bIfaceIndex,
362 		    UHID_FEATURE_REPORT, sc->btn_type_rid);
363 	}
364 	if (sc->btn_type_rlen > 1) {
365 		if (err == 0)
366 			sc->is_clickpad = hid_get_udata(sc->buf + 1,
367 			    sc->btn_type_rlen - 1, &sc->btn_type_loc) == 0;
368 		else
369 			DPRINTF("usbd_req_get_report error=%d\n", err);
370 	}
371 
372 	/* Fetch THQA certificate to enable some devices like WaveShare */
373 	if (sc->thqa_cert_rlen > 0 && sc->thqa_cert_rlen <= WMT_BSIZE &&
374 	    sc->thqa_cert_rid != sc->cont_max_rid)
375 		(void)usbd_req_get_report(uaa->device, NULL, sc->buf,
376 		    sc->thqa_cert_rlen, uaa->info.bIfaceIndex,
377 		    UHID_FEATURE_REPORT, sc->thqa_cert_rid);
378 
379 	/* Switch touchpad in to absolute multitouch mode */
380 	if (sc->type == WMT_TYPE_TOUCHPAD) {
381 		err = wmt_set_input_mode(sc, WMT_INPUT_MODE_MT_TOUCHPAD);
382 		if (err != 0)
383 			DPRINTF("Failed to set input mode: %d\n", err);
384 	}
385 
386 	/* Cap contact count maximum to MAX_MT_SLOTS */
387 	if (sc->cont_count_max > MAX_MT_SLOTS) {
388 		DPRINTF("Hardware reported %d contacts while only %d is "
389 		    "supported\n", (int)sc->cont_count_max, MAX_MT_SLOTS);
390 		sc->cont_count_max = MAX_MT_SLOTS;
391 	}
392 
393 	if (/*usb_test_quirk(hw, UQ_MT_TIMESTAMP) ||*/ wmt_timestamps)
394 		sc->do_timestamps = true;
395 
396 	mtx_init(&sc->mtx, "wmt lock", NULL, MTX_DEF);
397 
398 	err = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex,
399 	    sc->xfer, wmt_config, WMT_N_TRANSFER, sc, &sc->mtx);
400 	if (err != USB_ERR_NORMAL_COMPLETION) {
401 		DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(err));
402 		goto detach;
403 	}
404 
405 	sc->evdev = evdev_alloc();
406 	evdev_set_name(sc->evdev, device_get_desc(dev));
407 	evdev_set_phys(sc->evdev, device_get_nameunit(dev));
408 	evdev_set_id(sc->evdev, BUS_USB, uaa->info.idVendor,
409 	    uaa->info.idProduct, 0);
410 	evdev_set_serial(sc->evdev, usb_get_serial(uaa->device));
411 	evdev_set_methods(sc->evdev, sc, &wmt_evdev_methods);
412 	evdev_set_flag(sc->evdev, EVDEV_FLAG_MT_STCOMPAT);
413 	switch (sc->type) {
414 	case WMT_TYPE_TOUCHSCREEN:
415 		evdev_support_prop(sc->evdev, INPUT_PROP_DIRECT);
416 		break;
417 	case WMT_TYPE_TOUCHPAD:
418 		evdev_support_prop(sc->evdev, INPUT_PROP_POINTER);
419 		if (sc->is_clickpad)
420 			evdev_support_prop(sc->evdev, INPUT_PROP_BUTTONPAD);
421 		break;
422 	default:
423 		KASSERT(0, ("wmt_attach: unsupported touch device type"));
424 	}
425 	evdev_support_event(sc->evdev, EV_SYN);
426 	evdev_support_event(sc->evdev, EV_ABS);
427 	if (sc->do_timestamps) {
428 		evdev_support_event(sc->evdev, EV_MSC);
429 		evdev_support_msc(sc->evdev, MSC_TIMESTAMP);
430 	}
431 	nbuttons = 0;
432 	if (sc->max_button != 0 || sc->has_int_button) {
433 		evdev_support_event(sc->evdev, EV_KEY);
434 		if (sc->has_int_button)
435 			evdev_support_key(sc->evdev, BTN_LEFT);
436 		for (btn = 0; btn < sc->max_button; ++btn) {
437 			if (isset(sc->buttons, btn)) {
438 				evdev_support_key(sc->evdev, BTN_MOUSE + btn);
439 				nbuttons++;
440 			}
441 		}
442 	}
443 	evdev_support_abs(sc->evdev,
444 	    ABS_MT_SLOT, 0, sc->cont_count_max - 1, 0, 0, 0);
445 	WMT_FOREACH_USAGE(sc->caps, i) {
446 		if (wmt_hid_map[i].reported)
447 			evdev_support_abs(sc->evdev, ABS_MT_FIRST + i,
448 			    sc->ai[i].min, sc->ai[i].max, 0, 0, sc->ai[i].res);
449 	}
450 
451 	err = evdev_register_mtx(sc->evdev, &sc->mtx);
452 	if (err)
453 		goto detach;
454 
455 	/* Announce information about the touch device */
456 	device_printf(sc->dev, "Multitouch %s with %d external button%s%s\n",
457 	    sc->type == WMT_TYPE_TOUCHSCREEN ? "touchscreen" : "touchpad",
458 	    nbuttons, nbuttons != 1 ? "s" : "",
459 	    sc->is_clickpad ? ", click-pad" : "");
460 	device_printf(sc->dev,
461 	    "%d contacts and [%s%s%s%s%s]. Report range [%d:%d] - [%d:%d]\n",
462 	    (int)sc->cont_count_max,
463 	    isset(sc->caps, WMT_IN_RANGE) ? "R" : "",
464 	    isset(sc->caps, WMT_CONFIDENCE) ? "C" : "",
465 	    isset(sc->caps, WMT_WIDTH) ? "W" : "",
466 	    isset(sc->caps, WMT_HEIGHT) ? "H" : "",
467 	    isset(sc->caps, WMT_PRESSURE) ? "P" : "",
468 	    (int)sc->ai[WMT_X].min, (int)sc->ai[WMT_Y].min,
469 	    (int)sc->ai[WMT_X].max, (int)sc->ai[WMT_Y].max);
470 
471 	return (0);
472 
473 detach:
474 	wmt_detach(dev);
475 	return (ENXIO);
476 }
477 
478 static int
wmt_detach(device_t dev)479 wmt_detach(device_t dev)
480 {
481 	struct wmt_softc *sc = device_get_softc(dev);
482 
483 	evdev_free(sc->evdev);
484 	usbd_transfer_unsetup(sc->xfer, WMT_N_TRANSFER);
485 	mtx_destroy(&sc->mtx);
486 	return (0);
487 }
488 
489 static void
wmt_process_report(struct wmt_softc * sc,uint8_t * buf,int len)490 wmt_process_report(struct wmt_softc *sc, uint8_t *buf, int len)
491 {
492 	size_t usage;
493 	union evdev_mt_slot *slot_data;
494 	uint32_t cont, btn;
495 	uint32_t cont_count;
496 	uint32_t width;
497 	uint32_t height;
498 	uint32_t int_btn = 0;
499 	uint32_t left_btn = 0;
500 	int slot;
501 	uint32_t scan_time;
502 	int32_t delta;
503 
504 	/*
505 	 * "In Parallel mode, devices report all contact information in a
506 	 * single packet. Each physical contact is represented by a logical
507 	 * collection that is embedded in the top-level collection."
508 	 *
509 	 * Since additional contacts that were not present will still be in the
510 	 * report with contactid=0 but contactids are zero-based, find
511 	 * contactcount first.
512 	 */
513 	cont_count = hid_get_udata(buf, len, &sc->cont_count_loc);
514 	/*
515 	 * "In Hybrid mode, the number of contacts that can be reported in one
516 	 * report is less than the maximum number of contacts that the device
517 	 * supports. For example, a device that supports a maximum of
518 	 * 4 concurrent physical contacts, can set up its top-level collection
519 	 * to deliver a maximum of two contacts in one report. If four contact
520 	 * points are present, the device can break these up into two serial
521 	 * reports that deliver two contacts each.
522 	 *
523 	 * "When a device delivers data in this manner, the Contact Count usage
524 	 * value in the first report should reflect the total number of
525 	 * contacts that are being delivered in the hybrid reports. The other
526 	 * serial reports should have a contact count of zero (0)."
527 	 */
528 	if (cont_count != 0)
529 		sc->nconts_todo = cont_count;
530 
531 #ifdef USB_DEBUG
532 	DPRINTFN(6, "cont_count:%2u", (unsigned)cont_count);
533 	if (wmt_debug >= 6) {
534 		WMT_FOREACH_USAGE(sc->caps, usage) {
535 			if (wmt_hid_map[usage].usage != WMT_NO_USAGE)
536 				printf(" %-4s", wmt_hid_map[usage].name);
537 		}
538 		printf("\n");
539 	}
540 #endif
541 
542 	/* Find the number of contacts reported in current report */
543 	cont_count = MIN(sc->nconts_todo, sc->nconts_per_report);
544 
545 	/* Use protocol Type B for reporting events */
546 	for (cont = 0; cont < cont_count; cont++) {
547 		slot_data = &sc->slot_data;
548 		bzero(slot_data, sizeof(sc->slot_data));
549 		WMT_FOREACH_USAGE(sc->caps, usage) {
550 			if (sc->locs[cont][usage].size > 0)
551 				slot_data->val[usage] = hid_get_udata(
552 				    buf, len, &sc->locs[cont][usage]);
553 		}
554 
555 		slot = evdev_mt_id_to_slot(sc->evdev, slot_data->id);
556 
557 #ifdef USB_DEBUG
558 		DPRINTFN(6, "cont%01x: data = ", cont);
559 		if (wmt_debug >= 6) {
560 			WMT_FOREACH_USAGE(sc->caps, usage) {
561 				if (wmt_hid_map[usage].usage != WMT_NO_USAGE)
562 					printf("%04x ", slot_data->val[usage]);
563 			}
564 			printf("slot = %d\n", slot);
565 		}
566 #endif
567 
568 		if (slot == -1) {
569 			DPRINTF("Slot overflow for contact_id %u\n",
570 			    (unsigned)slot_data->id);
571 			continue;
572 		}
573 
574 		if (slot_data->val[WMT_TIP_SWITCH] != 0 &&
575 		    !(isset(sc->caps, WMT_CONFIDENCE) &&
576 		      slot_data->val[WMT_CONFIDENCE] == 0)) {
577 			/* This finger is in proximity of the sensor */
578 			sc->touch = true;
579 			slot_data->dist = !slot_data->val[WMT_IN_RANGE];
580 			/* Divided by two to match visual scale of touch */
581 			width = slot_data->val[WMT_WIDTH] >> 1;
582 			height = slot_data->val[WMT_HEIGHT] >> 1;
583 			slot_data->ori = width > height;
584 			slot_data->maj = MAX(width, height);
585 			slot_data->min = MIN(width, height);
586 		} else
587 			slot_data = NULL;
588 
589 		evdev_mt_push_slot(sc->evdev, slot, slot_data);
590 	}
591 
592 	sc->nconts_todo -= cont_count;
593 	if (sc->do_timestamps && sc->nconts_todo == 0) {
594 		/* HUD_SCAN_TIME is measured in 100us, convert to us. */
595 		scan_time = hid_get_udata(buf, len, &sc->scan_time_loc);
596 		if (sc->prev_touch) {
597 			delta = scan_time - sc->scan_time;
598 			if (delta < 0)
599 				delta += sc->scan_time_max;
600 		} else
601 			delta = 0;
602 		sc->scan_time = scan_time;
603 		sc->timestamp += delta * 100;
604 		evdev_push_msc(sc->evdev, MSC_TIMESTAMP, sc->timestamp);
605 		sc->prev_touch = sc->touch;
606 		sc->touch = false;
607 		if (!sc->prev_touch)
608 			sc->timestamp = 0;
609 	}
610 	if (sc->nconts_todo == 0) {
611 		/* Report both the click and external left btns as BTN_LEFT */
612 		if (sc->has_int_button)
613 			int_btn = hid_get_data(buf, len, &sc->int_btn_loc);
614 		if (isset(sc->buttons, 0))
615 			left_btn = hid_get_data(buf, len, &sc->btn_loc[0]);
616 		if (sc->has_int_button || isset(sc->buttons, 0))
617 			evdev_push_key(sc->evdev, BTN_LEFT,
618 			    (int_btn != 0) | (left_btn != 0));
619 		for (btn = 1; btn < sc->max_button; ++btn) {
620 			if (isset(sc->buttons, btn))
621 				evdev_push_key(sc->evdev, BTN_MOUSE + btn,
622 				    hid_get_data(buf,
623 						 len,
624 						 &sc->btn_loc[btn]) != 0);
625 		}
626 		evdev_sync(sc->evdev);
627 	}
628 }
629 
630 static void
wmt_intr_callback(struct usb_xfer * xfer,usb_error_t error)631 wmt_intr_callback(struct usb_xfer *xfer, usb_error_t error)
632 {
633 	struct wmt_softc *sc = usbd_xfer_softc(xfer);
634 	struct usb_page_cache *pc;
635 	uint8_t *buf = sc->buf;
636 	int len;
637 
638 	usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
639 
640 	switch (USB_GET_STATE(xfer)) {
641 	case USB_ST_TRANSFERRED:
642 		pc = usbd_xfer_get_frame(xfer, 0);
643 
644 		DPRINTFN(6, "sc=%p actlen=%d\n", sc, len);
645 
646 		if (len >= (int)sc->report_len ||
647 		    (len > 0 && sc->report_id != 0)) {
648 			/* Limit report length to the maximum */
649 			if (len > (int)sc->report_len)
650 				len = sc->report_len;
651 
652 			usbd_copy_out(pc, 0, buf, len);
653 
654 			/* Ignore irrelevant reports */
655 			if (sc->report_id && *buf != sc->report_id)
656 				goto tr_ignore;
657 
658 			/* Make sure we don't process old data */
659 			if (len < sc->report_len)
660 				bzero(buf + len, sc->report_len - len);
661 
662 			/* Strip leading "report ID" byte */
663 			if (sc->report_id) {
664 				len--;
665 				buf++;
666 			}
667 
668 			wmt_process_report(sc, buf, len);
669 		} else {
670 tr_ignore:
671 			DPRINTF("Ignored transfer, %d bytes\n", len);
672 		}
673 
674 	case USB_ST_SETUP:
675 tr_setup:
676 		usbd_xfer_set_frame_len(xfer, 0, sc->isize);
677 		usbd_transfer_submit(xfer);
678 		break;
679 	default:
680 		if (error != USB_ERR_CANCELLED) {
681 			/* Try clear stall first */
682 			usbd_xfer_set_stall(xfer);
683 			goto tr_setup;
684 		}
685 		break;
686 	}
687 }
688 
689 static void
wmt_ev_close_11(struct evdev_dev * evdev,void * ev_softc)690 wmt_ev_close_11(struct evdev_dev *evdev, void *ev_softc)
691 {
692 	struct wmt_softc *sc = ev_softc;
693 
694 	mtx_assert(&sc->mtx, MA_OWNED);
695 	usbd_transfer_stop(sc->xfer[WMT_INTR_DT]);
696 }
697 
698 static int
wmt_ev_open_11(struct evdev_dev * evdev,void * ev_softc)699 wmt_ev_open_11(struct evdev_dev *evdev, void *ev_softc)
700 {
701 	struct wmt_softc *sc = ev_softc;
702 
703 	mtx_assert(&sc->mtx, MA_OWNED);
704 	usbd_transfer_start(sc->xfer[WMT_INTR_DT]);
705 
706 	return (0);
707 }
708 
709 static int
wmt_ev_close(struct evdev_dev * evdev)710 wmt_ev_close(struct evdev_dev *evdev)
711 {
712 	struct wmt_softc *sc = evdev_get_softc(evdev);
713 
714 	wmt_ev_close_11(evdev, sc);
715 
716 	return (0);
717 }
718 
719 static int
wmt_ev_open(struct evdev_dev * evdev)720 wmt_ev_open(struct evdev_dev *evdev)
721 {
722 	struct wmt_softc *sc = evdev_get_softc(evdev);
723 
724 	return (wmt_ev_open_11(evdev, sc));
725 
726 }
727 
728 static enum wmt_type
wmt_hid_parse(struct wmt_softc * sc,const void * d_ptr,uint16_t d_len)729 wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len)
730 {
731 	struct hid_item hi;
732 	struct hid_data *hd;
733 	size_t i;
734 	size_t cont = 0;
735 	enum wmt_type type = WMT_TYPE_UNSUPPORTED;
736 	uint32_t left_btn, btn;
737 	int32_t cont_count_max = 0;
738 	uint8_t report_id = 0;
739 	bool touch_coll = false;
740 	bool finger_coll = false;
741 	bool cont_count_found = false;
742 	bool scan_time_found = false;
743 	bool has_int_button = false;
744 
745 #define WMT_HI_ABSOLUTE(hi)	\
746 	(((hi).flags & (HIO_CONST|HIO_VARIABLE|HIO_RELATIVE)) == HIO_VARIABLE)
747 #define	HUMS_THQA_CERT	0xC5
748 
749 	/* Parse features for maximum contact count */
750 	hd = hid_start_parse(d_ptr, d_len, 1 << hid_feature);
751 	while (hid_get_item(hd, &hi)) {
752 		switch (hi.kind) {
753 		case hid_collection:
754 			if (hi.collevel == 1 && hi.usage ==
755 			    HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)) {
756 				touch_coll = true;
757 				type = WMT_TYPE_TOUCHSCREEN;
758 				left_btn = 1;
759 				break;
760 			}
761 			if (hi.collevel == 1 && hi.usage ==
762 			    HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHPAD)) {
763 				touch_coll = true;
764 				type = WMT_TYPE_TOUCHPAD;
765 				left_btn = 2;
766 			}
767 			break;
768 		case hid_endcollection:
769 			if (hi.collevel == 0 && touch_coll)
770 				touch_coll = false;
771 			break;
772 		case hid_feature:
773 			if (hi.collevel == 1 && touch_coll && hi.usage ==
774 			      HID_USAGE2(HUP_MICROSOFT, HUMS_THQA_CERT)) {
775 				sc->thqa_cert_rid = hi.report_ID;
776 				break;
777 			}
778 			if (hi.collevel == 1 && touch_coll && hi.usage ==
779 			    HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX)) {
780 				cont_count_max = hi.logical_maximum;
781 				sc->cont_max_rid = hi.report_ID;
782 				sc->cont_max_loc = hi.loc;
783 				break;
784 			}
785 			if (hi.collevel == 1 && touch_coll && hi.usage ==
786 			    HID_USAGE2(HUP_DIGITIZERS, HUD_BUTTON_TYPE)) {
787 				sc->btn_type_rid = hi.report_ID;
788 				sc->btn_type_loc = hi.loc;
789 			}
790 			break;
791 		default:
792 			break;
793 		}
794 	}
795 	hid_end_parse(hd);
796 
797 	if (type == WMT_TYPE_UNSUPPORTED)
798 		return (WMT_TYPE_UNSUPPORTED);
799 	/* Maximum contact count is required usage */
800 	if (sc->cont_max_rid == 0)
801 		return (WMT_TYPE_UNSUPPORTED);
802 
803 	touch_coll = false;
804 
805 	/* Parse input for other parameters */
806 	hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
807 	while (hid_get_item(hd, &hi)) {
808 		switch (hi.kind) {
809 		case hid_collection:
810 			if (hi.collevel == 1 && hi.usage ==
811 			    HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN))
812 				touch_coll = true;
813 			else if (touch_coll && hi.collevel == 2 &&
814 			    (report_id == 0 || report_id == hi.report_ID) &&
815 			    hi.usage == HID_USAGE2(HUP_DIGITIZERS, HUD_FINGER))
816 				finger_coll = true;
817 			break;
818 		case hid_endcollection:
819 			if (hi.collevel == 1 && finger_coll) {
820 				finger_coll = false;
821 				cont++;
822 			} else if (hi.collevel == 0 && touch_coll)
823 				touch_coll = false;
824 			break;
825 		case hid_input:
826 			/*
827 			 * Ensure that all usages are located within the same
828 			 * report and proper collection.
829 			 */
830 			if (WMT_HI_ABSOLUTE(hi) && touch_coll &&
831 			    (report_id == 0 || report_id == hi.report_ID))
832 				report_id = hi.report_ID;
833 			else
834 				break;
835 
836 			if (hi.collevel == 1 && left_btn == 2 &&
837 			    hi.usage == HID_USAGE2(HUP_BUTTON, 1)) {
838 				has_int_button = true;
839 				sc->int_btn_loc = hi.loc;
840 				break;
841 			}
842 			if (hi.collevel == 1 &&
843 			    hi.usage >= HID_USAGE2(HUP_BUTTON, left_btn) &&
844 			    hi.usage <= HID_USAGE2(HUP_BUTTON, WMT_BTN_MAX)) {
845 				btn = (hi.usage & 0xFFFF) - left_btn;
846 				setbit(sc->buttons, btn);
847 				sc->btn_loc[btn] = hi.loc;
848 				if (btn >= sc->max_button)
849 					sc->max_button = btn + 1;
850 				break;
851 			}
852 			if (hi.collevel == 1 && hi.usage ==
853 			    HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTCOUNT)) {
854 				cont_count_found = true;
855 				sc->cont_count_loc = hi.loc;
856 				break;
857 			}
858 			/* Scan time is required but clobbered by evdev */
859 			if (hi.collevel == 1 && hi.usage ==
860 			    HID_USAGE2(HUP_DIGITIZERS, HUD_SCAN_TIME)) {
861 				scan_time_found = true;
862 				sc->scan_time_loc = hi.loc;
863 				sc->scan_time_max = hi.logical_maximum;
864 				break;
865 			}
866 
867 			if (!finger_coll || hi.collevel != 2)
868 				break;
869 			if (cont >= MAX_MT_SLOTS) {
870 				DPRINTF("Finger %zu ignored\n", cont);
871 				break;
872 			}
873 
874 			for (i = 0; i < WMT_N_USAGES; i++) {
875 				if (hi.usage == wmt_hid_map[i].usage) {
876 					/*
877 					 * HUG_X usage is an array mapped to
878 					 * both ABS_MT_POSITION and ABS_MT_TOOL
879 					 * events. So don`t stop search if we
880 					 * already have HUG_X mapping done.
881 					 */
882 					if (sc->locs[cont][i].size)
883 						continue;
884 					sc->locs[cont][i] = hi.loc;
885 					/*
886 					 * Hid parser returns valid logical and
887 					 * physical sizes for first finger only
888 					 * at least on ElanTS 0x04f3:0x0012.
889 					 */
890 					if (cont > 0)
891 						break;
892 					setbit(sc->caps, i);
893 					sc->ai[i] = (struct wmt_absinfo) {
894 					    .max = hi.logical_maximum,
895 					    .min = hi.logical_minimum,
896 					    .res = hid_item_resolution(&hi),
897 					};
898 					break;
899 				}
900 			}
901 			break;
902 		default:
903 			break;
904 		}
905 	}
906 	hid_end_parse(hd);
907 
908 	/* Check for required HID Usages */
909 	if (!cont_count_found || !scan_time_found || cont == 0)
910 		return (WMT_TYPE_UNSUPPORTED);
911 	for (i = 0; i < WMT_N_USAGES; i++) {
912 		if (wmt_hid_map[i].required && isclr(sc->caps, i))
913 			return (WMT_TYPE_UNSUPPORTED);
914 	}
915 
916 	/* Touchpads must have at least one button */
917 	if (type == WMT_TYPE_TOUCHPAD && !sc->max_button && !has_int_button)
918 		return (WMT_TYPE_UNSUPPORTED);
919 
920 	/*
921 	 * According to specifications 'Contact Count Maximum' should be read
922 	 * from Feature Report rather than from HID descriptor. Set sane
923 	 * default value now to handle the case of 'Get Report' request failure
924 	 */
925 	if (cont_count_max < 1)
926 		cont_count_max = cont;
927 
928 	/* Report touch orientation if both width and height are supported */
929 	if (isset(sc->caps, WMT_WIDTH) && isset(sc->caps, WMT_HEIGHT)) {
930 		setbit(sc->caps, WMT_ORIENTATION);
931 		sc->ai[WMT_ORIENTATION].max = 1;
932 	}
933 
934 	sc->isize = hid_report_size_max(d_ptr, d_len, hid_input, NULL);
935 	sc->report_len = hid_report_size(d_ptr, d_len, hid_input,
936 	    report_id);
937 	sc->cont_max_rlen = hid_report_size(d_ptr, d_len, hid_feature,
938 	    sc->cont_max_rid);
939 	if (sc->btn_type_rid > 0)
940 		sc->btn_type_rlen = hid_report_size(d_ptr, d_len,
941 		    hid_feature, sc->btn_type_rid);
942 	if (sc->thqa_cert_rid > 0)
943 		sc->thqa_cert_rlen = hid_report_size(d_ptr, d_len,
944 		    hid_feature, sc->thqa_cert_rid);
945 
946 	sc->report_id = report_id;
947 	sc->nconts_per_report = cont;
948 	sc->has_int_button = has_int_button;
949 	sc->cont_count_max = cont_count_max;
950 
951 	return (type);
952 }
953 
954 static int
wmt_set_input_mode(struct wmt_softc * sc,enum wmt_input_mode mode)955 wmt_set_input_mode(struct wmt_softc *sc, enum wmt_input_mode mode)
956 {
957 	struct usb_attach_arg *uaa = device_get_ivars(sc->dev);
958 	int err;
959 
960 	if (sc->input_mode_rlen < 3 || sc->input_mode_rlen > WMT_BSIZE) {
961 		DPRINTF("Feature report %hhu size invalid or too large: %u\n",
962 		    sc->input_mode_rid, sc->input_mode_rlen);
963 		return (USB_ERR_BAD_BUFSIZE);
964 	}
965 
966 	/* Input Mode report is not strictly required to be readable */
967 	err = usbd_req_get_report(uaa->device, NULL, sc->buf,
968 	    sc->input_mode_rlen, uaa->info.bIfaceIndex,
969 	    UHID_FEATURE_REPORT, sc->input_mode_rid);
970 	if (err != USB_ERR_NORMAL_COMPLETION)
971 		bzero(sc->buf + 1, sc->input_mode_rlen - 1);
972 
973 	sc->buf[0] = sc->input_mode_rid;
974 	hid_put_udata(sc->buf + 1, sc->input_mode_rlen - 1,
975 	    &sc->input_mode_loc, mode);
976 	err = usbd_req_set_report(uaa->device, NULL, sc->buf,
977 	    sc->input_mode_rlen, uaa->info.bIfaceIndex,
978 	    UHID_FEATURE_REPORT, sc->input_mode_rid);
979 
980 	return (err);
981 }
982 
983 static const STRUCT_USB_HOST_ID wmt_devs[] = {
984 	/* generic HID class w/o boot interface */
985 	{USB_IFACE_CLASS(UICLASS_HID),
986 	 USB_IFACE_SUBCLASS(0),},
987 };
988 
989 static device_method_t wmt_methods[] = {
990 	DEVMETHOD(device_probe, wmt_probe),
991 	DEVMETHOD(device_attach, wmt_attach),
992 	DEVMETHOD(device_detach, wmt_detach),
993 
994 	DEVMETHOD_END
995 };
996 
997 static driver_t wmt_driver = {
998 	.name = "wmt",
999 	.methods = wmt_methods,
1000 	.size = sizeof(struct wmt_softc),
1001 };
1002 
1003 DRIVER_MODULE(wmt, uhub, wmt_driver, NULL, NULL);
1004 MODULE_DEPEND(wmt, usb, 1, 1, 1);
1005 MODULE_DEPEND(wmt, hid, 1, 1, 1);
1006 MODULE_DEPEND(wmt, evdev, 1, 1, 1);
1007 MODULE_VERSION(wmt, 1);
1008 USB_PNP_HOST_INFO(wmt_devs);
1009