1 /* $NetBSD: uhid.c,v 1.46 2001/11/13 06:24:55 lukem Exp $ */
2
3 /* Also already merged from NetBSD:
4 * $NetBSD: uhid.c,v 1.54 2002/09/23 05:51:21 simonb Exp $
5 */
6
7 /*-
8 * SPDX-License-Identifier: BSD-2-Clause
9 *
10 * Copyright (c) 1998 The NetBSD Foundation, Inc.
11 * All rights reserved.
12 *
13 * This code is derived from software contributed to The NetBSD Foundation
14 * by Lennart Augustsson (lennart@augustsson.net) at
15 * Carlstedt Research & Technology.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
41 */
42
43 #include "opt_hid.h"
44
45 #include <sys/stdint.h>
46 #include <sys/stddef.h>
47 #include <sys/param.h>
48 #include <sys/queue.h>
49 #include <sys/types.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
52 #include <sys/bus.h>
53 #include <sys/module.h>
54 #include <sys/lock.h>
55 #include <sys/mutex.h>
56 #include <sys/condvar.h>
57 #include <sys/sysctl.h>
58 #include <sys/sx.h>
59 #include <sys/unistd.h>
60 #include <sys/callout.h>
61 #include <sys/malloc.h>
62 #include <sys/priv.h>
63 #include <sys/conf.h>
64 #include <sys/fcntl.h>
65
66 #include <dev/hid/hid.h>
67
68 #include "usbdevs.h"
69 #include <dev/usb/usb.h>
70 #include <dev/usb/usbdi.h>
71 #include <dev/usb/usbdi_util.h>
72 #include <dev/usb/usbhid.h>
73 #include <dev/usb/usb_ioctl.h>
74 #include <dev/usb/usb_generic.h>
75
76 #define USB_DEBUG_VAR uhid_debug
77 #include <dev/usb/usb_debug.h>
78
79 #include <dev/usb/input/usb_rdesc.h>
80 #include <dev/usb/quirk/usb_quirk.h>
81
82 #ifdef USB_DEBUG
83 static int uhid_debug = 0;
84
85 static SYSCTL_NODE(_hw_usb, OID_AUTO, uhid, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
86 "USB uhid");
87 SYSCTL_INT(_hw_usb_uhid, OID_AUTO, debug, CTLFLAG_RWTUN,
88 &uhid_debug, 0, "Debug level");
89 #endif
90
91 #define UHID_BSIZE 1024 /* bytes, buffer size */
92 #define UHID_FRAME_NUM 50 /* bytes, frame number */
93
94 enum {
95 UHID_INTR_DT_WR,
96 UHID_INTR_DT_RD,
97 UHID_CTRL_DT_WR,
98 UHID_CTRL_DT_RD,
99 UHID_N_TRANSFER,
100 };
101
102 struct uhid_softc {
103 struct usb_fifo_sc sc_fifo;
104 struct mtx sc_mtx;
105
106 struct usb_xfer *sc_xfer[UHID_N_TRANSFER];
107 struct usb_device *sc_udev;
108 void *sc_repdesc_ptr;
109
110 uint32_t sc_isize;
111 uint32_t sc_osize;
112 uint32_t sc_fsize;
113
114 uint16_t sc_repdesc_size;
115
116 uint8_t sc_iface_no;
117 uint8_t sc_iface_index;
118 uint8_t sc_iid;
119 uint8_t sc_oid;
120 uint8_t sc_fid;
121 uint8_t sc_flags;
122 #define UHID_FLAG_IMMED 0x01 /* set if read should be immediate */
123 #define UHID_FLAG_STATIC_DESC 0x04 /* set if report descriptors are
124 * static */
125 };
126
127 static const uint8_t uhid_xb360gp_report_descr[] = {UHID_XB360GP_REPORT_DESCR()};
128 static const uint8_t uhid_graphire_report_descr[] = {UHID_GRAPHIRE_REPORT_DESCR()};
129 static const uint8_t uhid_graphire3_4x5_report_descr[] = {UHID_GRAPHIRE3_4X5_REPORT_DESCR()};
130
131 /* prototypes */
132
133 static device_probe_t uhid_probe;
134 static device_attach_t uhid_attach;
135 static device_detach_t uhid_detach;
136
137 static usb_callback_t uhid_intr_write_callback;
138 static usb_callback_t uhid_intr_read_callback;
139 static usb_callback_t uhid_write_callback;
140 static usb_callback_t uhid_read_callback;
141
142 static usb_fifo_cmd_t uhid_start_read;
143 static usb_fifo_cmd_t uhid_stop_read;
144 static usb_fifo_cmd_t uhid_start_write;
145 static usb_fifo_cmd_t uhid_stop_write;
146 static usb_fifo_open_t uhid_open;
147 static usb_fifo_close_t uhid_close;
148 static usb_fifo_ioctl_t uhid_ioctl;
149 static usb_fifo_ioctl_t uhid_ioctl_post;
150
151 static struct usb_fifo_methods uhid_fifo_methods = {
152 .f_open = &uhid_open,
153 .f_close = &uhid_close,
154 .f_ioctl = &uhid_ioctl,
155 .f_ioctl_post = &uhid_ioctl_post,
156 .f_start_read = &uhid_start_read,
157 .f_stop_read = &uhid_stop_read,
158 .f_start_write = &uhid_start_write,
159 .f_stop_write = &uhid_stop_write,
160 .basename[0] = "uhid",
161 };
162
163 static void
uhid_intr_write_callback(struct usb_xfer * xfer,usb_error_t error)164 uhid_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
165 {
166 struct uhid_softc *sc = usbd_xfer_softc(xfer);
167 struct usb_page_cache *pc;
168 int actlen;
169
170 switch (USB_GET_STATE(xfer)) {
171 case USB_ST_TRANSFERRED:
172 case USB_ST_SETUP:
173 tr_setup:
174 pc = usbd_xfer_get_frame(xfer, 0);
175 if (usb_fifo_get_data(sc->sc_fifo.fp[USB_FIFO_TX], pc,
176 0, usbd_xfer_max_len(xfer), &actlen, 0)) {
177 usbd_xfer_set_frame_len(xfer, 0, actlen);
178 usbd_transfer_submit(xfer);
179 }
180 return;
181
182 default: /* Error */
183 if (error != USB_ERR_CANCELLED) {
184 /* try to clear stall first */
185 usbd_xfer_set_stall(xfer);
186 goto tr_setup;
187 }
188 return;
189 }
190 }
191
192 static void
uhid_intr_read_callback(struct usb_xfer * xfer,usb_error_t error)193 uhid_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
194 {
195 struct uhid_softc *sc = usbd_xfer_softc(xfer);
196 struct usb_page_cache *pc;
197 int actlen;
198
199 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
200
201 switch (USB_GET_STATE(xfer)) {
202 case USB_ST_TRANSFERRED:
203 DPRINTF("transferred!\n");
204
205 pc = usbd_xfer_get_frame(xfer, 0);
206
207 /*
208 * If the ID byte is non zero we allow descriptors
209 * having multiple sizes:
210 */
211 if ((actlen >= (int)sc->sc_isize) ||
212 ((actlen > 0) && (sc->sc_iid != 0))) {
213 /* limit report length to the maximum */
214 if (actlen > (int)sc->sc_isize)
215 actlen = sc->sc_isize;
216 usb_fifo_put_data(sc->sc_fifo.fp[USB_FIFO_RX], pc,
217 0, actlen, 1);
218
219 /*
220 * Do not do read-ahead, because this may lead
221 * to data loss!
222 */
223 return;
224 } else {
225 /* ignore it */
226 DPRINTF("ignored transfer, %d bytes\n", actlen);
227 }
228
229 case USB_ST_SETUP:
230 re_submit:
231 if (usb_fifo_put_bytes_max(
232 sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
233 usbd_xfer_set_frame_len(xfer, 0, sc->sc_isize);
234 usbd_transfer_submit(xfer);
235 }
236 return;
237
238 default: /* Error */
239 if (error != USB_ERR_CANCELLED) {
240 /* try to clear stall first */
241 usbd_xfer_set_stall(xfer);
242 goto re_submit;
243 }
244 return;
245 }
246 }
247
248 static void
uhid_fill_set_report(struct usb_device_request * req,uint8_t iface_no,uint8_t type,uint8_t id,uint16_t size)249 uhid_fill_set_report(struct usb_device_request *req, uint8_t iface_no,
250 uint8_t type, uint8_t id, uint16_t size)
251 {
252 req->bmRequestType = UT_WRITE_CLASS_INTERFACE;
253 req->bRequest = UR_SET_REPORT;
254 USETW2(req->wValue, type, id);
255 req->wIndex[0] = iface_no;
256 req->wIndex[1] = 0;
257 USETW(req->wLength, size);
258 }
259
260 static void
uhid_fill_get_report(struct usb_device_request * req,uint8_t iface_no,uint8_t type,uint8_t id,uint16_t size)261 uhid_fill_get_report(struct usb_device_request *req, uint8_t iface_no,
262 uint8_t type, uint8_t id, uint16_t size)
263 {
264 req->bmRequestType = UT_READ_CLASS_INTERFACE;
265 req->bRequest = UR_GET_REPORT;
266 USETW2(req->wValue, type, id);
267 req->wIndex[0] = iface_no;
268 req->wIndex[1] = 0;
269 USETW(req->wLength, size);
270 }
271
272 static void
uhid_write_callback(struct usb_xfer * xfer,usb_error_t error)273 uhid_write_callback(struct usb_xfer *xfer, usb_error_t error)
274 {
275 struct uhid_softc *sc = usbd_xfer_softc(xfer);
276 struct usb_device_request req;
277 struct usb_page_cache *pc;
278 uint32_t size = sc->sc_osize;
279 uint32_t actlen;
280 uint8_t id;
281
282 switch (USB_GET_STATE(xfer)) {
283 case USB_ST_TRANSFERRED:
284 case USB_ST_SETUP:
285 /* try to extract the ID byte */
286 if (sc->sc_oid) {
287 pc = usbd_xfer_get_frame(xfer, 0);
288 if (usb_fifo_get_data(sc->sc_fifo.fp[USB_FIFO_TX], pc,
289 0, 1, &actlen, 0)) {
290 if (actlen != 1) {
291 goto tr_error;
292 }
293 usbd_copy_out(pc, 0, &id, 1);
294
295 } else {
296 return;
297 }
298 if (size) {
299 size--;
300 }
301 } else {
302 id = 0;
303 }
304
305 pc = usbd_xfer_get_frame(xfer, 1);
306 if (usb_fifo_get_data(sc->sc_fifo.fp[USB_FIFO_TX], pc,
307 0, UHID_BSIZE, &actlen, 1)) {
308 if (actlen != size) {
309 goto tr_error;
310 }
311 uhid_fill_set_report
312 (&req, sc->sc_iface_no,
313 UHID_OUTPUT_REPORT, id, size);
314
315 pc = usbd_xfer_get_frame(xfer, 0);
316 usbd_copy_in(pc, 0, &req, sizeof(req));
317
318 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
319 usbd_xfer_set_frame_len(xfer, 1, size);
320 usbd_xfer_set_frames(xfer, size ? 2 : 1);
321 usbd_transfer_submit(xfer);
322 }
323 return;
324
325 default:
326 tr_error:
327 /* bomb out */
328 usb_fifo_get_data_error(sc->sc_fifo.fp[USB_FIFO_TX]);
329 return;
330 }
331 }
332
333 static void
uhid_read_callback(struct usb_xfer * xfer,usb_error_t error)334 uhid_read_callback(struct usb_xfer *xfer, usb_error_t error)
335 {
336 struct uhid_softc *sc = usbd_xfer_softc(xfer);
337 struct usb_device_request req;
338 struct usb_page_cache *pc;
339
340 pc = usbd_xfer_get_frame(xfer, 0);
341
342 switch (USB_GET_STATE(xfer)) {
343 case USB_ST_TRANSFERRED:
344 usb_fifo_put_data(sc->sc_fifo.fp[USB_FIFO_RX], pc, sizeof(req),
345 sc->sc_isize, 1);
346 return;
347
348 case USB_ST_SETUP:
349
350 if (usb_fifo_put_bytes_max(sc->sc_fifo.fp[USB_FIFO_RX]) > 0) {
351 uhid_fill_get_report
352 (&req, sc->sc_iface_no, UHID_INPUT_REPORT,
353 sc->sc_iid, sc->sc_isize);
354
355 usbd_copy_in(pc, 0, &req, sizeof(req));
356
357 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
358 usbd_xfer_set_frame_len(xfer, 1, sc->sc_isize);
359 usbd_xfer_set_frames(xfer, sc->sc_isize ? 2 : 1);
360 usbd_transfer_submit(xfer);
361 }
362 return;
363
364 default: /* Error */
365 /* bomb out */
366 usb_fifo_put_data_error(sc->sc_fifo.fp[USB_FIFO_RX]);
367 return;
368 }
369 }
370
371 static const struct usb_config uhid_config[UHID_N_TRANSFER] = {
372 [UHID_INTR_DT_WR] = {
373 .type = UE_INTERRUPT,
374 .endpoint = UE_ADDR_ANY,
375 .direction = UE_DIR_OUT,
376 .flags = {.pipe_bof = 1,.no_pipe_ok = 1, },
377 .bufsize = UHID_BSIZE,
378 .callback = &uhid_intr_write_callback,
379 },
380
381 [UHID_INTR_DT_RD] = {
382 .type = UE_INTERRUPT,
383 .endpoint = UE_ADDR_ANY,
384 .direction = UE_DIR_IN,
385 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
386 .bufsize = UHID_BSIZE,
387 .callback = &uhid_intr_read_callback,
388 },
389
390 [UHID_CTRL_DT_WR] = {
391 .type = UE_CONTROL,
392 .endpoint = 0x00, /* Control pipe */
393 .direction = UE_DIR_ANY,
394 .bufsize = sizeof(struct usb_device_request) + UHID_BSIZE,
395 .callback = &uhid_write_callback,
396 .timeout = 1000, /* 1 second */
397 },
398
399 [UHID_CTRL_DT_RD] = {
400 .type = UE_CONTROL,
401 .endpoint = 0x00, /* Control pipe */
402 .direction = UE_DIR_ANY,
403 .bufsize = sizeof(struct usb_device_request) + UHID_BSIZE,
404 .callback = &uhid_read_callback,
405 .timeout = 1000, /* 1 second */
406 },
407 };
408
409 static void
uhid_start_read(struct usb_fifo * fifo)410 uhid_start_read(struct usb_fifo *fifo)
411 {
412 struct uhid_softc *sc = usb_fifo_softc(fifo);
413
414 if (sc->sc_flags & UHID_FLAG_IMMED) {
415 usbd_transfer_start(sc->sc_xfer[UHID_CTRL_DT_RD]);
416 } else {
417 usbd_transfer_start(sc->sc_xfer[UHID_INTR_DT_RD]);
418 }
419 }
420
421 static void
uhid_stop_read(struct usb_fifo * fifo)422 uhid_stop_read(struct usb_fifo *fifo)
423 {
424 struct uhid_softc *sc = usb_fifo_softc(fifo);
425
426 usbd_transfer_stop(sc->sc_xfer[UHID_CTRL_DT_RD]);
427 usbd_transfer_stop(sc->sc_xfer[UHID_INTR_DT_RD]);
428 }
429
430 static void
uhid_start_write(struct usb_fifo * fifo)431 uhid_start_write(struct usb_fifo *fifo)
432 {
433 struct uhid_softc *sc = usb_fifo_softc(fifo);
434
435 if ((sc->sc_flags & UHID_FLAG_IMMED) ||
436 sc->sc_xfer[UHID_INTR_DT_WR] == NULL) {
437 usbd_transfer_start(sc->sc_xfer[UHID_CTRL_DT_WR]);
438 } else {
439 usbd_transfer_start(sc->sc_xfer[UHID_INTR_DT_WR]);
440 }
441 }
442
443 static void
uhid_stop_write(struct usb_fifo * fifo)444 uhid_stop_write(struct usb_fifo *fifo)
445 {
446 struct uhid_softc *sc = usb_fifo_softc(fifo);
447
448 usbd_transfer_stop(sc->sc_xfer[UHID_CTRL_DT_WR]);
449 usbd_transfer_stop(sc->sc_xfer[UHID_INTR_DT_WR]);
450 }
451
452 static int
uhid_get_report(struct uhid_softc * sc,uint8_t type,uint8_t id,void * kern_data,void * user_data,uint16_t len)453 uhid_get_report(struct uhid_softc *sc, uint8_t type,
454 uint8_t id, void *kern_data, void *user_data,
455 uint16_t len)
456 {
457 int err;
458 uint8_t free_data = 0;
459
460 if (kern_data == NULL) {
461 kern_data = malloc(len, M_USBDEV, M_WAITOK);
462 free_data = 1;
463 }
464 err = usbd_req_get_report(sc->sc_udev, NULL, kern_data,
465 len, sc->sc_iface_index, type, id);
466 if (err) {
467 err = ENXIO;
468 goto done;
469 }
470 if (user_data) {
471 /* dummy buffer */
472 err = copyout(kern_data, user_data, len);
473 if (err) {
474 goto done;
475 }
476 }
477 done:
478 if (free_data) {
479 free(kern_data, M_USBDEV);
480 }
481 return (err);
482 }
483
484 static int
uhid_set_report(struct uhid_softc * sc,uint8_t type,uint8_t id,void * kern_data,void * user_data,uint16_t len)485 uhid_set_report(struct uhid_softc *sc, uint8_t type,
486 uint8_t id, void *kern_data, void *user_data,
487 uint16_t len)
488 {
489 int err;
490 uint8_t free_data = 0;
491
492 if (kern_data == NULL) {
493 kern_data = malloc(len, M_USBDEV, M_WAITOK);
494 free_data = 1;
495 err = copyin(user_data, kern_data, len);
496 if (err) {
497 goto done;
498 }
499 }
500 err = usbd_req_set_report(sc->sc_udev, NULL, kern_data,
501 len, sc->sc_iface_index, type, id);
502 if (err) {
503 err = ENXIO;
504 goto done;
505 }
506 done:
507 if (free_data) {
508 free(kern_data, M_USBDEV);
509 }
510 return (err);
511 }
512
513 static int
uhid_open(struct usb_fifo * fifo,int fflags)514 uhid_open(struct usb_fifo *fifo, int fflags)
515 {
516 struct uhid_softc *sc = usb_fifo_softc(fifo);
517
518 /*
519 * The buffers are one byte larger than maximum so that one
520 * can detect too large read/writes and short transfers:
521 */
522 if (fflags & FREAD) {
523 /* reset flags */
524 mtx_lock(&sc->sc_mtx);
525 sc->sc_flags &= ~UHID_FLAG_IMMED;
526 mtx_unlock(&sc->sc_mtx);
527
528 if (usb_fifo_alloc_buffer(fifo,
529 sc->sc_isize + 1, UHID_FRAME_NUM)) {
530 return (ENOMEM);
531 }
532 }
533 if (fflags & FWRITE) {
534 if (usb_fifo_alloc_buffer(fifo,
535 sc->sc_osize + 1, UHID_FRAME_NUM)) {
536 return (ENOMEM);
537 }
538 }
539 return (0);
540 }
541
542 static void
uhid_close(struct usb_fifo * fifo,int fflags)543 uhid_close(struct usb_fifo *fifo, int fflags)
544 {
545 if (fflags & (FREAD | FWRITE)) {
546 usb_fifo_free_buffer(fifo);
547 }
548 }
549
550 static int
uhid_ioctl(struct usb_fifo * fifo,u_long cmd,void * addr,int fflags)551 uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
552 int fflags)
553 {
554 struct uhid_softc *sc = usb_fifo_softc(fifo);
555 struct usb_gen_descriptor *ugd;
556 #ifdef COMPAT_FREEBSD32
557 struct usb_gen_descriptor local_ugd;
558 struct usb_gen_descriptor32 *ugd32 = NULL;
559 #endif
560 uint32_t size;
561 int error = 0;
562 uint8_t id;
563
564 ugd = addr;
565 #ifdef COMPAT_FREEBSD32
566 switch (cmd) {
567 case USB_GET_REPORT_DESC32:
568 case USB_GET_REPORT32:
569 case USB_SET_REPORT32:
570 ugd32 = addr;
571 ugd = &local_ugd;
572 usb_gen_descriptor_from32(ugd, ugd32);
573 cmd = _IOC_NEWTYPE(cmd, struct usb_gen_descriptor);
574 break;
575 }
576 #endif
577
578 switch (cmd) {
579 case USB_GET_REPORT_DESC:
580 if (sc->sc_repdesc_size > ugd->ugd_maxlen) {
581 size = ugd->ugd_maxlen;
582 } else {
583 size = sc->sc_repdesc_size;
584 }
585 ugd->ugd_actlen = size;
586 if (ugd->ugd_data == NULL)
587 break; /* descriptor length only */
588 error = copyout(sc->sc_repdesc_ptr, ugd->ugd_data, size);
589 break;
590
591 case USB_SET_IMMED:
592 if (!(fflags & FREAD)) {
593 error = EPERM;
594 break;
595 }
596 if (*(int *)addr) {
597 /* do a test read */
598
599 error = uhid_get_report(sc, UHID_INPUT_REPORT,
600 sc->sc_iid, NULL, NULL, sc->sc_isize);
601 if (error) {
602 break;
603 }
604 mtx_lock(&sc->sc_mtx);
605 sc->sc_flags |= UHID_FLAG_IMMED;
606 mtx_unlock(&sc->sc_mtx);
607 } else {
608 mtx_lock(&sc->sc_mtx);
609 sc->sc_flags &= ~UHID_FLAG_IMMED;
610 mtx_unlock(&sc->sc_mtx);
611 }
612 break;
613
614 case USB_GET_REPORT:
615 if (!(fflags & FREAD)) {
616 error = EPERM;
617 break;
618 }
619 switch (ugd->ugd_report_type) {
620 case UHID_INPUT_REPORT:
621 size = sc->sc_isize;
622 id = sc->sc_iid;
623 break;
624 case UHID_OUTPUT_REPORT:
625 size = sc->sc_osize;
626 id = sc->sc_oid;
627 break;
628 case UHID_FEATURE_REPORT:
629 size = sc->sc_fsize;
630 id = sc->sc_fid;
631 break;
632 default:
633 return (EINVAL);
634 }
635 size = imin(ugd->ugd_maxlen, size);
636 if (id != 0)
637 error = copyin(ugd->ugd_data, &id, 1);
638 if (error == 0)
639 error = uhid_get_report(sc, ugd->ugd_report_type, id,
640 NULL, ugd->ugd_data, size);
641 ugd->ugd_actlen = size;
642 break;
643
644 case USB_SET_REPORT:
645 if (!(fflags & FWRITE)) {
646 error = EPERM;
647 break;
648 }
649 switch (ugd->ugd_report_type) {
650 case UHID_INPUT_REPORT:
651 size = sc->sc_isize;
652 id = sc->sc_iid;
653 break;
654 case UHID_OUTPUT_REPORT:
655 size = sc->sc_osize;
656 id = sc->sc_oid;
657 break;
658 case UHID_FEATURE_REPORT:
659 size = sc->sc_fsize;
660 id = sc->sc_fid;
661 break;
662 default:
663 return (EINVAL);
664 }
665 if (id != 0)
666 error = copyin(ugd->ugd_data, &id, 1);
667 if (error == 0)
668 error = uhid_set_report(sc, ugd->ugd_report_type, id,
669 NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size));
670 break;
671
672 case USB_GET_REPORT_ID:
673 *(int *)addr = 0; /* XXX: we only support reportid 0? */
674 break;
675
676 default:
677 error = ENOIOCTL;
678 break;
679 }
680 #ifdef COMPAT_FREEBSD32
681 if (ugd32 != NULL)
682 update_usb_gen_descriptor32(ugd32, ugd);
683 #endif
684 return (error);
685 }
686
687 static int
uhid_ioctl_post(struct usb_fifo * fifo,u_long cmd,void * addr,int fflags)688 uhid_ioctl_post(struct usb_fifo *fifo, u_long cmd, void *addr,
689 int fflags)
690 {
691 int error;
692
693 switch (cmd) {
694 case USB_GET_DEVICEINFO:
695 error = ugen_fill_deviceinfo(fifo, addr);
696 break;
697
698 default:
699 error = EINVAL;
700 break;
701 }
702 return (error);
703 }
704
705 static const STRUCT_USB_HOST_ID uhid_devs[] = {
706 /* generic HID class */
707 {USB_IFACE_CLASS(UICLASS_HID),},
708 /* the Xbox 360 gamepad doesn't use the HID class */
709 {USB_IFACE_CLASS(UICLASS_VENDOR),
710 USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER),
711 USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),},
712 };
713
714 static int
uhid_probe(device_t dev)715 uhid_probe(device_t dev)
716 {
717 struct usb_attach_arg *uaa = device_get_ivars(dev);
718 int error;
719 void *buf;
720 uint16_t len;
721
722 DPRINTFN(11, "\n");
723
724 if (uaa->usb_mode != USB_MODE_HOST)
725 return (ENXIO);
726
727 error = usbd_lookup_id_by_uaa(uhid_devs, sizeof(uhid_devs), uaa);
728 if (error)
729 return (error);
730
731 if (usb_test_quirk(uaa, UQ_HID_IGNORE))
732 return (ENXIO);
733
734 /*
735 * Don't attach to mouse and keyboard devices, hence then no
736 * "nomatch" event is generated and then ums and ukbd won't
737 * attach properly when loaded.
738 */
739 if ((uaa->info.bInterfaceClass == UICLASS_HID) &&
740 (uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) &&
741 (((uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD) &&
742 !usb_test_quirk(uaa, UQ_KBD_IGNORE)) ||
743 ((uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) &&
744 !usb_test_quirk(uaa, UQ_UMS_IGNORE))))
745 return (ENXIO);
746
747 /* Check for mandatory multitouch usages to give wmt(4) a chance */
748 if (!usb_test_quirk(uaa, UQ_WMT_IGNORE)) {
749 error = usbd_req_get_hid_desc(uaa->device, NULL,
750 &buf, &len, M_USBDEV, uaa->info.bIfaceIndex);
751 /* Let HID decscriptor-less devices to be handled at attach */
752 if (!error) {
753 if (hid_locate(buf, len,
754 HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX),
755 hid_feature, 0, NULL, NULL, NULL) &&
756 hid_locate(buf, len,
757 HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTID),
758 hid_input, 0, NULL, NULL, NULL)) {
759 free(buf, M_USBDEV);
760 return (ENXIO);
761 }
762 free(buf, M_USBDEV);
763 }
764 }
765
766 return (BUS_PROBE_GENERIC);
767 }
768
769 static int
uhid_attach(device_t dev)770 uhid_attach(device_t dev)
771 {
772 struct usb_attach_arg *uaa = device_get_ivars(dev);
773 struct uhid_softc *sc = device_get_softc(dev);
774 int unit = device_get_unit(dev);
775 int error = 0;
776
777 DPRINTFN(10, "sc=%p\n", sc);
778
779 device_set_usb_desc(dev);
780
781 mtx_init(&sc->sc_mtx, "uhid lock", NULL, MTX_DEF | MTX_RECURSE);
782
783 sc->sc_udev = uaa->device;
784
785 sc->sc_iface_no = uaa->info.bIfaceNum;
786 sc->sc_iface_index = uaa->info.bIfaceIndex;
787
788 error = usbd_transfer_setup(uaa->device,
789 &uaa->info.bIfaceIndex, sc->sc_xfer, uhid_config,
790 UHID_N_TRANSFER, sc, &sc->sc_mtx);
791
792 if (error) {
793 DPRINTF("error=%s\n", usbd_errstr(error));
794 goto detach;
795 }
796 if (uaa->info.idVendor == USB_VENDOR_WACOM) {
797 /* the report descriptor for the Wacom Graphire is broken */
798
799 if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE) {
800 sc->sc_repdesc_size = sizeof(uhid_graphire_report_descr);
801 sc->sc_repdesc_ptr = __DECONST(void *, &uhid_graphire_report_descr);
802 sc->sc_flags |= UHID_FLAG_STATIC_DESC;
803
804 } else if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE3_4X5) {
805 static uint8_t reportbuf[] = {2, 2, 2};
806
807 /*
808 * The Graphire3 needs 0x0202 to be written to
809 * feature report ID 2 before it'll start
810 * returning digitizer data.
811 */
812 error = usbd_req_set_report(uaa->device, NULL,
813 reportbuf, sizeof(reportbuf),
814 uaa->info.bIfaceIndex, UHID_FEATURE_REPORT, 2);
815
816 if (error) {
817 DPRINTF("set report failed, error=%s (ignored)\n",
818 usbd_errstr(error));
819 }
820 sc->sc_repdesc_size = sizeof(uhid_graphire3_4x5_report_descr);
821 sc->sc_repdesc_ptr = __DECONST(void *, &uhid_graphire3_4x5_report_descr);
822 sc->sc_flags |= UHID_FLAG_STATIC_DESC;
823 }
824 } else if ((uaa->info.bInterfaceClass == UICLASS_VENDOR) &&
825 (uaa->info.bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER) &&
826 (uaa->info.bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD)) {
827 static const uint8_t reportbuf[3] = {1, 3, 0};
828 /*
829 * Turn off the four LEDs on the gamepad which
830 * are blinking by default:
831 */
832 error = usbd_req_set_report(uaa->device, NULL,
833 __DECONST(void *, reportbuf), sizeof(reportbuf),
834 uaa->info.bIfaceIndex, UHID_OUTPUT_REPORT, 0);
835 if (error) {
836 DPRINTF("set output report failed, error=%s (ignored)\n",
837 usbd_errstr(error));
838 }
839 /* the Xbox 360 gamepad has no report descriptor */
840 sc->sc_repdesc_size = sizeof(uhid_xb360gp_report_descr);
841 sc->sc_repdesc_ptr = __DECONST(void *, &uhid_xb360gp_report_descr);
842 sc->sc_flags |= UHID_FLAG_STATIC_DESC;
843 }
844 if (sc->sc_repdesc_ptr == NULL) {
845 error = usbd_req_get_hid_desc(uaa->device, NULL,
846 &sc->sc_repdesc_ptr, &sc->sc_repdesc_size,
847 M_USBDEV, uaa->info.bIfaceIndex);
848
849 if (error) {
850 device_printf(dev, "no report descriptor\n");
851 goto detach;
852 }
853 }
854 error = usbd_req_set_idle(uaa->device, NULL,
855 uaa->info.bIfaceIndex, 0, 0);
856
857 if (error) {
858 DPRINTF("set idle failed, error=%s (ignored)\n",
859 usbd_errstr(error));
860 }
861 sc->sc_isize = hid_report_size_max
862 (sc->sc_repdesc_ptr, sc->sc_repdesc_size, hid_input, &sc->sc_iid);
863
864 sc->sc_osize = hid_report_size_max
865 (sc->sc_repdesc_ptr, sc->sc_repdesc_size, hid_output, &sc->sc_oid);
866
867 sc->sc_fsize = hid_report_size_max
868 (sc->sc_repdesc_ptr, sc->sc_repdesc_size, hid_feature, &sc->sc_fid);
869
870 if (sc->sc_isize > UHID_BSIZE) {
871 DPRINTF("input size is too large, "
872 "%d bytes (truncating)\n",
873 sc->sc_isize);
874 sc->sc_isize = UHID_BSIZE;
875 }
876 if (sc->sc_osize > UHID_BSIZE) {
877 DPRINTF("output size is too large, "
878 "%d bytes (truncating)\n",
879 sc->sc_osize);
880 sc->sc_osize = UHID_BSIZE;
881 }
882 if (sc->sc_fsize > UHID_BSIZE) {
883 DPRINTF("feature size is too large, "
884 "%d bytes (truncating)\n",
885 sc->sc_fsize);
886 sc->sc_fsize = UHID_BSIZE;
887 }
888
889 error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
890 &uhid_fifo_methods, &sc->sc_fifo,
891 unit, -1, uaa->info.bIfaceIndex,
892 UID_ROOT, GID_OPERATOR, 0644);
893 if (error) {
894 goto detach;
895 }
896 return (0); /* success */
897
898 detach:
899 uhid_detach(dev);
900 return (ENOMEM);
901 }
902
903 static int
uhid_detach(device_t dev)904 uhid_detach(device_t dev)
905 {
906 struct uhid_softc *sc = device_get_softc(dev);
907
908 usb_fifo_detach(&sc->sc_fifo);
909
910 usbd_transfer_unsetup(sc->sc_xfer, UHID_N_TRANSFER);
911
912 if (sc->sc_repdesc_ptr) {
913 if (!(sc->sc_flags & UHID_FLAG_STATIC_DESC)) {
914 free(sc->sc_repdesc_ptr, M_USBDEV);
915 }
916 }
917 mtx_destroy(&sc->sc_mtx);
918
919 return (0);
920 }
921
922 static device_method_t uhid_methods[] = {
923 DEVMETHOD(device_probe, uhid_probe),
924 DEVMETHOD(device_attach, uhid_attach),
925 DEVMETHOD(device_detach, uhid_detach),
926
927 DEVMETHOD_END
928 };
929
930 static driver_t uhid_driver = {
931 #ifdef HIDRAW_MAKE_UHID_ALIAS
932 .name = "hidraw",
933 #else
934 .name = "uhid",
935 #endif
936 .methods = uhid_methods,
937 .size = sizeof(struct uhid_softc),
938 };
939
940 DRIVER_MODULE(uhid, uhub, uhid_driver, NULL, NULL);
941 MODULE_DEPEND(uhid, usb, 1, 1, 1);
942 MODULE_DEPEND(uhid, hid, 1, 1, 1);
943 MODULE_VERSION(uhid, 1);
944 USB_PNP_HOST_INFO(uhid_devs);
945