• Home
  • History
  • Annotate
  • only in this directory
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34/*
35 * HID spec: https://www.usb.org/sites/default/files/documents/hid1_11.pdf
36 */
37
38#include <sys/stdint.h>
39#include <sys/stddef.h>
40#include <sys/param.h>
41#include <sys/queue.h>
42#include <sys/types.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/bus.h>
46#include <sys/module.h>
47#include <sys/lock.h>
48#include <sys/mutex.h>
49#include <sys/condvar.h>
50#include <sys/sysctl.h>
51#include <sys/sx.h>
52#include <sys/unistd.h>
53#include <sys/callout.h>
54#include <sys/malloc.h>
55#include <sys/priv.h>
56#include <sys/conf.h>
57#include <sys/fcntl.h>
58
59#include <dev/evdev/input.h>
60
61#include <dev/hid/hid.h>
62#include <dev/hid/hidquirk.h>
63
64#include <dev/usb/usb.h>
65#include <dev/usb/usbdi.h>
66#include <dev/usb/usbdi_util.h>
67#include <dev/usb/usbhid.h>
68#include <dev/usb/usb_core.h>
69#include <dev/usb/usb_ioctl.h>
70#include <dev/usb/usb_util.h>
71
72#define	USB_DEBUG_VAR usbhid_debug
73#include <dev/usb/usb_debug.h>
74
75#include <dev/usb/quirk/usb_quirk.h>
76
77#include "hid_if.h"
78
79static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0, "USB usbhid");
80static int usbhid_enable = 0;
81SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, enable, CTLFLAG_RWTUN,
82    &usbhid_enable, 0, "Enable usbhid and prefer it to other USB HID drivers");
83#ifdef USB_DEBUG
84static int usbhid_debug = 0;
85SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, debug, CTLFLAG_RWTUN,
86    &usbhid_debug, 0, "Debug level");
87#endif
88
89/* Second set of USB transfers for polling mode */
90#define	POLL_XFER(xfer)	((xfer) + USBHID_N_TRANSFER)
91enum {
92	USBHID_INTR_OUT_DT,
93	USBHID_INTR_IN_DT,
94	USBHID_CTRL_DT,
95	USBHID_N_TRANSFER,
96};
97
98struct usbhid_xfer_ctx;
99typedef int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx);
100
101union usbhid_device_request {
102	struct {			/* INTR xfers */
103		uint16_t maxlen;
104		uint16_t actlen;
105	} intr;
106	struct usb_device_request ctrl;	/* CTRL xfers */
107};
108
109/* Syncronous USB transfer context */
110struct usbhid_xfer_ctx {
111	union usbhid_device_request req;
112	uint8_t *buf;
113	int error;
114	usbhid_callback_t *cb;
115	void *cb_ctx;
116	int waiters;
117	bool influx;
118};
119
120struct usbhid_softc {
121	hid_intr_t *sc_intr_handler;
122	void *sc_intr_ctx;
123	void *sc_intr_buf;
124
125	struct hid_device_info sc_hw;
126
127	struct mtx sc_mtx;
128	struct usb_config sc_config[USBHID_N_TRANSFER];
129	struct usb_xfer *sc_xfer[POLL_XFER(USBHID_N_TRANSFER)];
130	struct usbhid_xfer_ctx sc_xfer_ctx[POLL_XFER(USBHID_N_TRANSFER)];
131	bool sc_can_poll;
132
133	struct usb_device *sc_udev;
134	uint8_t	sc_iface_no;
135	uint8_t	sc_iface_index;
136};
137
138/* prototypes */
139
140static device_probe_t usbhid_probe;
141static device_attach_t usbhid_attach;
142static device_detach_t usbhid_detach;
143
144static usb_callback_t usbhid_intr_out_callback;
145static usb_callback_t usbhid_intr_in_callback;
146static usb_callback_t usbhid_ctrl_callback;
147
148static usbhid_callback_t usbhid_intr_handler_cb;
149static usbhid_callback_t usbhid_sync_wakeup_cb;
150
151static void
152usbhid_intr_out_callback(struct usb_xfer *xfer, usb_error_t error)
153{
154	struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
155	struct usb_page_cache *pc;
156	int len;
157
158	switch (USB_GET_STATE(xfer)) {
159	case USB_ST_TRANSFERRED:
160	case USB_ST_SETUP:
161tr_setup:
162		len = xfer_ctx->req.intr.maxlen;
163		if (len == 0) {
164			if (USB_IN_POLLING_MODE_FUNC())
165				xfer_ctx->error = 0;
166			return;
167		}
168		pc = usbd_xfer_get_frame(xfer, 0);
169		usbd_copy_in(pc, 0, xfer_ctx->buf, len);
170		usbd_xfer_set_frame_len(xfer, 0, len);
171		usbd_transfer_submit(xfer);
172		xfer_ctx->req.intr.maxlen = 0;
173		if (USB_IN_POLLING_MODE_FUNC())
174			return;
175		xfer_ctx->error = 0;
176		goto tr_exit;
177
178	default:			/* Error */
179		if (error != USB_ERR_CANCELLED) {
180			/* try to clear stall first */
181			usbd_xfer_set_stall(xfer);
182			goto tr_setup;
183		}
184		xfer_ctx->error = EIO;
185tr_exit:
186		(void)xfer_ctx->cb(xfer_ctx);
187		return;
188	}
189}
190
191static void
192usbhid_intr_in_callback(struct usb_xfer *xfer, usb_error_t error)
193{
194	struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
195	struct usb_page_cache *pc;
196	int actlen;
197
198	switch (USB_GET_STATE(xfer)) {
199	case USB_ST_TRANSFERRED:
200		DPRINTF("transferred!\n");
201
202		usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
203		pc = usbd_xfer_get_frame(xfer, 0);
204		usbd_copy_out(pc, 0, xfer_ctx->buf, actlen);
205		xfer_ctx->req.intr.actlen = actlen;
206		if (xfer_ctx->cb(xfer_ctx) != 0)
207			return;
208
209	case USB_ST_SETUP:
210re_submit:
211		usbd_xfer_set_frame_len(xfer, 0, xfer_ctx->req.intr.maxlen);
212		usbd_transfer_submit(xfer);
213		return;
214
215	default:			/* Error */
216		if (error != USB_ERR_CANCELLED) {
217			/* try to clear stall first */
218			usbd_xfer_set_stall(xfer);
219			goto re_submit;
220		}
221		return;
222	}
223}
224
225static void
226usbhid_ctrl_callback(struct usb_xfer *xfer, usb_error_t error)
227{
228	struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
229	struct usb_device_request *req = &xfer_ctx->req.ctrl;
230	struct usb_page_cache *pc;
231	int len = UGETW(req->wLength);
232	bool is_rd = (req->bmRequestType & UT_READ) != 0;
233
234	switch (USB_GET_STATE(xfer)) {
235	case USB_ST_SETUP:
236		if (!is_rd && len != 0) {
237			pc = usbd_xfer_get_frame(xfer, 1);
238			usbd_copy_in(pc, 0, xfer_ctx->buf, len);
239		}
240
241		pc = usbd_xfer_get_frame(xfer, 0);
242		usbd_copy_in(pc, 0, req, sizeof(*req));
243		usbd_xfer_set_frame_len(xfer, 0, sizeof(*req));
244		if (len != 0)
245			usbd_xfer_set_frame_len(xfer, 1, len);
246		usbd_xfer_set_frames(xfer, len != 0 ? 2 : 1);
247		usbd_transfer_submit(xfer);
248		return;
249
250	case USB_ST_TRANSFERRED:
251		if (is_rd && len != 0) {
252			pc = usbd_xfer_get_frame(xfer, 0);
253			usbd_copy_out(pc, sizeof(*req), xfer_ctx->buf, len);
254		}
255		xfer_ctx->error = 0;
256		goto tr_exit;
257
258	default:			/* Error */
259		/* bomb out */
260		DPRINTFN(1, "error=%s\n", usbd_errstr(error));
261		xfer_ctx->error = EIO;
262tr_exit:
263		(void)xfer_ctx->cb(xfer_ctx);
264		return;
265	}
266}
267
268static int
269usbhid_intr_handler_cb(struct usbhid_xfer_ctx *xfer_ctx)
270{
271	struct usbhid_softc *sc = xfer_ctx->cb_ctx;
272
273	sc->sc_intr_handler(sc->sc_intr_ctx, xfer_ctx->buf,
274	    xfer_ctx->req.intr.actlen);
275
276	return (0);
277}
278
279static int
280usbhid_sync_wakeup_cb(struct usbhid_xfer_ctx *xfer_ctx)
281{
282
283	if (!USB_IN_POLLING_MODE_FUNC())
284		wakeup(xfer_ctx->cb_ctx);
285
286	return (ECANCELED);
287}
288
289static const struct usb_config usbhid_config[USBHID_N_TRANSFER] = {
290
291	[USBHID_INTR_OUT_DT] = {
292		.type = UE_INTERRUPT,
293		.endpoint = UE_ADDR_ANY,
294		.direction = UE_DIR_OUT,
295		.flags = {.pipe_bof = 1,.proxy_buffer = 1},
296		.callback = &usbhid_intr_out_callback,
297	},
298	[USBHID_INTR_IN_DT] = {
299		.type = UE_INTERRUPT,
300		.endpoint = UE_ADDR_ANY,
301		.direction = UE_DIR_IN,
302		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1},
303		.callback = &usbhid_intr_in_callback,
304	},
305	[USBHID_CTRL_DT] = {
306		.type = UE_CONTROL,
307		.endpoint = 0x00,	/* Control pipe */
308		.direction = UE_DIR_ANY,
309		.flags = {.proxy_buffer = 1},
310		.callback = &usbhid_ctrl_callback,
311		.timeout = 1000,	/* 1 second */
312	},
313};
314
315static inline usb_frlength_t
316usbhid_xfer_max_len(struct usb_xfer *xfer)
317{
318	return (xfer == NULL ? 0 : usbd_xfer_max_len(xfer));
319}
320
321static inline int
322usbhid_xfer_check_len(struct usbhid_softc* sc, int xfer_idx, hid_size_t len)
323{
324	if (USB_IN_POLLING_MODE_FUNC())
325		xfer_idx = POLL_XFER(xfer_idx);
326	if (sc->sc_xfer[xfer_idx] == NULL)
327		return (ENODEV);
328	if (len > usbd_xfer_max_len(sc->sc_xfer[xfer_idx]))
329		return (ENOBUFS);
330	return (0);
331}
332
333static void
334usbhid_intr_setup(device_t dev, device_t child __unused, hid_intr_t intr,
335    void *context, struct hid_rdesc_info *rdesc)
336{
337	struct usbhid_softc* sc = device_get_softc(dev);
338	uint16_t n;
339	bool nowrite;
340	int error;
341
342	nowrite = hid_test_quirk(&sc->sc_hw, HQ_NOWRITE);
343
344	/*
345	 * Setup the USB transfers one by one, so they are memory independent
346	 * which allows for handling panics triggered by the HID drivers
347	 * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
348	 * keyboard driver was processing a key at the moment of panic.
349	 */
350	if (intr == NULL) {
351		if (sc->sc_can_poll)
352			return;
353		for (n = 0; n != USBHID_N_TRANSFER; n++) {
354			if (nowrite && n == USBHID_INTR_OUT_DT)
355				continue;
356			error = usbd_transfer_setup(sc->sc_udev,
357			    &sc->sc_iface_index, sc->sc_xfer + POLL_XFER(n),
358			    sc->sc_config + n, 1,
359			    (void *)(sc->sc_xfer_ctx + POLL_XFER(n)),
360			    &sc->sc_mtx);
361			if (error)
362				DPRINTF("xfer %d setup error=%s\n", n,
363				    usbd_errstr(error));
364		}
365		mtx_lock(&sc->sc_mtx);
366		if (sc->sc_xfer[USBHID_INTR_IN_DT] != NULL &&
367		    sc->sc_xfer[USBHID_INTR_IN_DT]->flags_int.started)
368			usbd_transfer_start(
369			    sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
370		mtx_unlock(&sc->sc_mtx);
371		sc->sc_can_poll = true;
372		return;
373	}
374
375	sc->sc_intr_handler = intr;
376	sc->sc_intr_ctx = context;
377	bcopy(usbhid_config, sc->sc_config, sizeof(usbhid_config));
378	bzero(sc->sc_xfer, sizeof(sc->sc_xfer));
379
380	/* Set buffer sizes to match HID report sizes */
381	sc->sc_config[USBHID_INTR_OUT_DT].bufsize = rdesc->osize;
382	sc->sc_config[USBHID_INTR_IN_DT].bufsize = rdesc->isize;
383	sc->sc_config[USBHID_CTRL_DT].bufsize =
384	    MAX(rdesc->isize, MAX(rdesc->osize, rdesc->fsize));
385
386	for (n = 0; n != USBHID_N_TRANSFER; n++) {
387		if (nowrite && n == USBHID_INTR_OUT_DT)
388			continue;
389		error = usbd_transfer_setup(sc->sc_udev, &sc->sc_iface_index,
390		    sc->sc_xfer + n, sc->sc_config + n, 1,
391		    (void *)(sc->sc_xfer_ctx + n), &sc->sc_mtx);
392		if (error)
393			DPRINTF("xfer %d setup error=%s\n", n,
394			    usbd_errstr(error));
395	}
396
397	rdesc->rdsize = usbhid_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]);
398	rdesc->grsize = usbhid_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]);
399	rdesc->srsize = rdesc->grsize;
400	rdesc->wrsize = nowrite ? rdesc->srsize :
401	    usbhid_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]);
402
403	sc->sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
404}
405
406static void
407usbhid_intr_unsetup(device_t dev, device_t child __unused)
408{
409	struct usbhid_softc* sc = device_get_softc(dev);
410
411	usbd_transfer_unsetup(sc->sc_xfer, USBHID_N_TRANSFER);
412	if (sc->sc_can_poll)
413		usbd_transfer_unsetup(
414		    sc->sc_xfer, POLL_XFER(USBHID_N_TRANSFER));
415	sc->sc_can_poll = false;
416	free(sc->sc_intr_buf, M_USBDEV);
417}
418
419static int
420usbhid_intr_start(device_t dev, device_t child __unused)
421{
422	struct usbhid_softc* sc = device_get_softc(dev);
423
424	if (sc->sc_xfer[USBHID_INTR_IN_DT] == NULL)
425		return (ENODEV);
426
427	mtx_lock(&sc->sc_mtx);
428	sc->sc_xfer_ctx[USBHID_INTR_IN_DT] = (struct usbhid_xfer_ctx) {
429		.req.intr.maxlen =
430		    usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
431		.cb = usbhid_intr_handler_cb,
432		.cb_ctx = sc,
433		.buf = sc->sc_intr_buf,
434	};
435	sc->sc_xfer_ctx[POLL_XFER(USBHID_INTR_IN_DT)] = (struct usbhid_xfer_ctx) {
436		.req.intr.maxlen =
437		    usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
438		.cb = usbhid_intr_handler_cb,
439		.cb_ctx = sc,
440		.buf = sc->sc_intr_buf,
441	};
442	usbd_transfer_start(sc->sc_xfer[USBHID_INTR_IN_DT]);
443	if (sc->sc_can_poll)
444		usbd_transfer_start(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
445	mtx_unlock(&sc->sc_mtx);
446
447	return (0);
448}
449
450static int
451usbhid_intr_stop(device_t dev, device_t child __unused)
452{
453	struct usbhid_softc* sc = device_get_softc(dev);
454
455	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_IN_DT]);
456	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_OUT_DT]);
457	if (sc->sc_can_poll)
458		usbd_transfer_drain(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
459
460	return (0);
461}
462
463static void
464usbhid_intr_poll(device_t dev, device_t child __unused)
465{
466	struct usbhid_softc* sc = device_get_softc(dev);
467
468	MPASS(sc->sc_can_poll);
469	usbd_transfer_poll(sc->sc_xfer + USBHID_INTR_IN_DT, 1);
470	usbd_transfer_poll(sc->sc_xfer + POLL_XFER(USBHID_INTR_IN_DT), 1);
471}
472
473/*
474 * HID interface
475 */
476static int
477usbhid_sync_xfer(struct usbhid_softc* sc, int xfer_idx,
478    union usbhid_device_request *req, void *buf)
479{
480	int error, timeout;
481	struct usbhid_xfer_ctx *xfer_ctx;
482
483	xfer_ctx = sc->sc_xfer_ctx + xfer_idx;
484
485	if (USB_IN_POLLING_MODE_FUNC()) {
486		xfer_ctx = POLL_XFER(xfer_ctx);
487		xfer_idx = POLL_XFER(xfer_idx);
488	} else {
489		mtx_lock(&sc->sc_mtx);
490		++xfer_ctx->waiters;
491		while (xfer_ctx->influx)
492			mtx_sleep(&xfer_ctx->waiters, &sc->sc_mtx, 0,
493			    "usbhid wt", 0);
494		--xfer_ctx->waiters;
495		xfer_ctx->influx = true;
496	}
497
498	xfer_ctx->buf = buf;
499	xfer_ctx->req = *req;
500	xfer_ctx->error = ETIMEDOUT;
501	xfer_ctx->cb = &usbhid_sync_wakeup_cb;
502	xfer_ctx->cb_ctx = xfer_ctx;
503	timeout = USB_DEFAULT_TIMEOUT;
504	usbd_transfer_start(sc->sc_xfer[xfer_idx]);
505
506	if (USB_IN_POLLING_MODE_FUNC())
507		while (timeout > 0 && xfer_ctx->error == ETIMEDOUT) {
508			usbd_transfer_poll(sc->sc_xfer + xfer_idx, 1);
509			DELAY(1000);
510			timeout--;
511		}
512	 else
513		msleep_sbt(xfer_ctx, &sc->sc_mtx, 0, "usbhid io",
514		    SBT_1MS * timeout, 0, C_HARDCLOCK);
515
516	/* Perform usbhid_write() asyncronously to improve pipelining */
517	if (USB_IN_POLLING_MODE_FUNC() || xfer_ctx->error != 0 ||
518	    sc->sc_config[xfer_idx].type != UE_INTERRUPT ||
519	    sc->sc_config[xfer_idx].direction != UE_DIR_OUT)
520		usbd_transfer_stop(sc->sc_xfer[xfer_idx]);
521	error = xfer_ctx->error;
522	if (error == 0)
523		*req = xfer_ctx->req;
524
525	if (!USB_IN_POLLING_MODE_FUNC()) {
526		xfer_ctx->influx = false;
527		if (xfer_ctx->waiters != 0)
528			wakeup_one(&xfer_ctx->waiters);
529		mtx_unlock(&sc->sc_mtx);
530	}
531
532	if (error)
533		DPRINTF("USB IO error:%d\n", error);
534
535	return (error);
536}
537
538static int
539usbhid_get_rdesc(device_t dev, device_t child __unused, void *buf,
540    hid_size_t len)
541{
542	struct usbhid_softc* sc = device_get_softc(dev);
543	int error;
544
545	error = usbd_req_get_report_descriptor(sc->sc_udev, NULL,
546	    buf, len, sc->sc_iface_index);
547
548	if (error)
549		DPRINTF("no report descriptor: %s\n", usbd_errstr(error));
550
551	return (error == 0 ? 0 : ENXIO);
552}
553
554static int
555usbhid_get_report(device_t dev, device_t child __unused, void *buf,
556    hid_size_t maxlen, hid_size_t *actlen, uint8_t type, uint8_t id)
557{
558	struct usbhid_softc* sc = device_get_softc(dev);
559	union usbhid_device_request req;
560	int error;
561
562	error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, maxlen);
563	if (error)
564		return (error);
565
566	req.ctrl.bmRequestType = UT_READ_CLASS_INTERFACE;
567	req.ctrl.bRequest = UR_GET_REPORT;
568	USETW2(req.ctrl.wValue, type, id);
569	req.ctrl.wIndex[0] = sc->sc_iface_no;
570	req.ctrl.wIndex[1] = 0;
571	USETW(req.ctrl.wLength, maxlen);
572
573	error = usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, buf);
574	if (!error && actlen != NULL)
575		*actlen = maxlen;
576
577	return (error);
578}
579
580static int
581usbhid_set_report(device_t dev, device_t child __unused, const void *buf,
582    hid_size_t len, uint8_t type, uint8_t id)
583{
584	struct usbhid_softc* sc = device_get_softc(dev);
585	union usbhid_device_request req;
586	int error;
587
588	error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, len);
589	if (error)
590		return (error);
591
592	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
593	req.ctrl.bRequest = UR_SET_REPORT;
594	USETW2(req.ctrl.wValue, type, id);
595	req.ctrl.wIndex[0] = sc->sc_iface_no;
596	req.ctrl.wIndex[1] = 0;
597	USETW(req.ctrl.wLength, len);
598
599	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req,
600	    __DECONST(void *, buf)));
601}
602
603static int
604usbhid_read(device_t dev, device_t child __unused, void *buf,
605    hid_size_t maxlen, hid_size_t *actlen)
606{
607	struct usbhid_softc* sc = device_get_softc(dev);
608	union usbhid_device_request req;
609	int error;
610
611	error = usbhid_xfer_check_len(sc, USBHID_INTR_IN_DT, maxlen);
612	if (error)
613		return (error);
614
615	req.intr.maxlen = maxlen;
616	error = usbhid_sync_xfer(sc, USBHID_INTR_IN_DT, &req, buf);
617	if (error == 0 && actlen != NULL)
618		*actlen = req.intr.actlen;
619
620	return (error);
621}
622
623static int
624usbhid_write(device_t dev, device_t child __unused, const void *buf,
625    hid_size_t len)
626{
627	struct usbhid_softc* sc = device_get_softc(dev);
628	union usbhid_device_request req;
629	int error;
630
631	error = usbhid_xfer_check_len(sc, USBHID_INTR_OUT_DT, len);
632	if (error)
633		return (error);
634
635	req.intr.maxlen = len;
636	return (usbhid_sync_xfer(sc, USBHID_INTR_OUT_DT, &req,
637	    __DECONST(void *, buf)));
638}
639
640static int
641usbhid_set_idle(device_t dev, device_t child __unused, uint16_t duration,
642    uint8_t id)
643{
644	struct usbhid_softc* sc = device_get_softc(dev);
645	union usbhid_device_request req;
646	int error;
647
648	error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, 0);
649	if (error)
650		return (error);
651
652	/* Duration is measured in 4 milliseconds per unit. */
653	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
654	req.ctrl.bRequest = UR_SET_IDLE;
655	USETW2(req.ctrl.wValue, (duration + 3) / 4, id);
656	req.ctrl.wIndex[0] = sc->sc_iface_no;
657	req.ctrl.wIndex[1] = 0;
658	USETW(req.ctrl.wLength, 0);
659
660	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
661}
662
663static int
664usbhid_set_protocol(device_t dev, device_t child __unused, uint16_t protocol)
665{
666	struct usbhid_softc* sc = device_get_softc(dev);
667	union usbhid_device_request req;
668	int error;
669
670	error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, 0);
671	if (error)
672		return (error);
673
674	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
675	req.ctrl.bRequest = UR_SET_PROTOCOL;
676	USETW(req.ctrl.wValue, protocol);
677	req.ctrl.wIndex[0] = sc->sc_iface_no;
678	req.ctrl.wIndex[1] = 0;
679	USETW(req.ctrl.wLength, 0);
680
681	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
682}
683
684static int
685usbhid_ioctl(device_t dev, device_t child __unused, unsigned long cmd,
686    uintptr_t data)
687{
688	struct usbhid_softc* sc = device_get_softc(dev);
689	struct usb_ctl_request *ucr;
690	union usbhid_device_request req;
691	int error;
692
693	switch (cmd) {
694	case USB_REQUEST:
695		ucr = (struct usb_ctl_request *)data;
696		req.ctrl = ucr->ucr_request;
697		error = usbhid_xfer_check_len(
698		    sc, USBHID_CTRL_DT, UGETW(req.ctrl.wLength));
699		if (error)
700			break;
701		error = usb_check_request(sc->sc_udev, &req.ctrl);
702		if (error)
703			break;
704		error = usbhid_sync_xfer(
705		    sc, USBHID_CTRL_DT, &req, ucr->ucr_data);
706		if (error == 0)
707			ucr->ucr_actlen = UGETW(req.ctrl.wLength);
708		break;
709	default:
710		error = EINVAL;
711	}
712
713	return (error);
714}
715
716static void
717usbhid_init_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
718{
719
720	hw->idBus = BUS_USB;
721	hw->idVendor = uaa->info.idVendor;
722	hw->idProduct = uaa->info.idProduct;
723	hw->idVersion = uaa->info.bcdDevice;
724
725	/* Set various quirks based on usb_attach_arg */
726	hid_add_dynamic_quirk(hw, USB_GET_DRIVER_INFO(uaa));
727}
728
729static void
730usbhid_fill_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
731{
732	struct usb_device *udev = uaa->device;
733	struct usb_interface *iface = uaa->iface;
734	struct usb_hid_descriptor *hid;
735	struct usb_endpoint *ep;
736
737	snprintf(hw->name, sizeof(hw->name), "%s %s",
738	    usb_get_manufacturer(udev), usb_get_product(udev));
739	strlcpy(hw->serial, usb_get_serial(udev), sizeof(hw->serial));
740
741	if (uaa->info.bInterfaceClass == UICLASS_HID &&
742	    iface != NULL && iface->idesc != NULL) {
743		hid = hid_get_descriptor_from_usb(
744		    usbd_get_config_descriptor(udev), iface->idesc);
745		if (hid != NULL)
746			hw->rdescsize =
747			    UGETW(hid->descrs[0].wDescriptorLength);
748	}
749
750	/* See if there is a interrupt out endpoint. */
751	ep = usbd_get_endpoint(udev, uaa->info.bIfaceIndex,
752	    usbhid_config + USBHID_INTR_OUT_DT);
753	if (ep == NULL || ep->methods == NULL)
754		hid_add_dynamic_quirk(hw, HQ_NOWRITE);
755}
756
757static const STRUCT_USB_HOST_ID usbhid_devs[] = {
758	/* the Xbox 360 gamepad doesn't use the HID class */
759	{USB_IFACE_CLASS(UICLASS_VENDOR),
760	 USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER),
761	 USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),
762	 USB_DRIVER_INFO(HQ_IS_XBOX360GP)},
763	/* HID keyboard with boot protocol support */
764	{USB_IFACE_CLASS(UICLASS_HID),
765	 USB_IFACE_SUBCLASS(UISUBCLASS_BOOT),
766	 USB_IFACE_PROTOCOL(UIPROTO_BOOT_KEYBOARD),
767	 USB_DRIVER_INFO(HQ_HAS_KBD_BOOTPROTO)},
768	/* HID mouse with boot protocol support */
769	{USB_IFACE_CLASS(UICLASS_HID),
770	 USB_IFACE_SUBCLASS(UISUBCLASS_BOOT),
771	 USB_IFACE_PROTOCOL(UIPROTO_MOUSE),
772	 USB_DRIVER_INFO(HQ_HAS_MS_BOOTPROTO)},
773	/* generic HID class */
774	{USB_IFACE_CLASS(UICLASS_HID), USB_DRIVER_INFO(HQ_NONE)},
775};
776
777static int
778usbhid_probe(device_t dev)
779{
780	struct usb_attach_arg *uaa = device_get_ivars(dev);
781	struct usbhid_softc *sc = device_get_softc(dev);
782	int error;
783
784	DPRINTFN(11, "\n");
785
786	if (usbhid_enable == 0)
787		return (ENXIO);
788
789	if (uaa->usb_mode != USB_MODE_HOST)
790		return (ENXIO);
791
792	error = usbd_lookup_id_by_uaa(usbhid_devs, sizeof(usbhid_devs), uaa);
793	if (error)
794		return (error);
795
796	if (usb_test_quirk(uaa, UQ_HID_IGNORE))
797		return (ENXIO);
798
799	/*
800	 * Setup temporary hid_device_info so that we can figure out some
801	 * basic quirks for this device.
802	 */
803	usbhid_init_device_info(uaa, &sc->sc_hw);
804
805	if (hid_test_quirk(&sc->sc_hw, HQ_HID_IGNORE))
806		return (ENXIO);
807
808	return (BUS_PROBE_DEFAULT + 1);
809}
810
811static int
812usbhid_attach(device_t dev)
813{
814	struct usb_attach_arg *uaa = device_get_ivars(dev);
815	struct usbhid_softc *sc = device_get_softc(dev);
816	device_t child;
817	int error = 0;
818
819	DPRINTFN(10, "sc=%p\n", sc);
820
821	device_set_usb_desc(dev);
822
823	sc->sc_udev = uaa->device;
824	sc->sc_iface_no = uaa->info.bIfaceNum;
825	sc->sc_iface_index = uaa->info.bIfaceIndex;
826
827	usbhid_fill_device_info(uaa, &sc->sc_hw);
828
829	error = usbd_req_set_idle(uaa->device, NULL,
830	    uaa->info.bIfaceIndex, 0, 0);
831	if (error)
832		DPRINTF("set idle failed, error=%s (ignored)\n",
833		    usbd_errstr(error));
834
835	mtx_init(&sc->sc_mtx, "usbhid lock", NULL, MTX_DEF);
836
837	child = device_add_child(dev, "hidbus", -1);
838	if (child == NULL) {
839		device_printf(dev, "Could not add hidbus device\n");
840		usbhid_detach(dev);
841		return (ENOMEM);
842	}
843
844	device_set_ivars(child, &sc->sc_hw);
845	error = bus_generic_attach(dev);
846	if (error) {
847		device_printf(dev, "failed to attach child: %d\n", error);
848		usbhid_detach(dev);
849		return (error);
850	}
851
852	return (0);			/* success */
853}
854
855static int
856usbhid_detach(device_t dev)
857{
858	struct usbhid_softc *sc = device_get_softc(dev);
859
860	device_delete_children(dev);
861	mtx_destroy(&sc->sc_mtx);
862
863	return (0);
864}
865
866static device_method_t usbhid_methods[] = {
867	DEVMETHOD(device_probe,		usbhid_probe),
868	DEVMETHOD(device_attach,	usbhid_attach),
869	DEVMETHOD(device_detach,	usbhid_detach),
870
871	DEVMETHOD(hid_intr_setup,	usbhid_intr_setup),
872	DEVMETHOD(hid_intr_unsetup,	usbhid_intr_unsetup),
873	DEVMETHOD(hid_intr_start,	usbhid_intr_start),
874	DEVMETHOD(hid_intr_stop,	usbhid_intr_stop),
875	DEVMETHOD(hid_intr_poll,	usbhid_intr_poll),
876
877	/* HID interface */
878	DEVMETHOD(hid_get_rdesc,	usbhid_get_rdesc),
879	DEVMETHOD(hid_read,		usbhid_read),
880	DEVMETHOD(hid_write,		usbhid_write),
881	DEVMETHOD(hid_get_report,	usbhid_get_report),
882	DEVMETHOD(hid_set_report,	usbhid_set_report),
883	DEVMETHOD(hid_set_idle,		usbhid_set_idle),
884	DEVMETHOD(hid_set_protocol,	usbhid_set_protocol),
885	DEVMETHOD(hid_ioctl,		usbhid_ioctl),
886
887	DEVMETHOD_END
888};
889
890static driver_t usbhid_driver = {
891	.name = "usbhid",
892	.methods = usbhid_methods,
893	.size = sizeof(struct usbhid_softc),
894};
895
896DRIVER_MODULE(usbhid, uhub, usbhid_driver, NULL, NULL);
897MODULE_DEPEND(usbhid, usb, 1, 1, 1);
898MODULE_DEPEND(usbhid, hid, 1, 1, 1);
899MODULE_DEPEND(usbhid, hidbus, 1, 1, 1);
900MODULE_VERSION(usbhid, 1);
901USB_PNP_HOST_INFO(usbhid_devs);
902