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