1 /* $NetBSD: uhidev.c,v 1.81 2021/08/07 16:19:17 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. 5 * All rights reserved. 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 and Matthew R. Green (mrg@eterna.com.au). 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 /* 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.81 2021/08/07 16:19:17 thorpej Exp $"); 39 40 #ifdef _KERNEL_OPT 41 #include "opt_usb.h" 42 #endif 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 47 #include <sys/conf.h> 48 #include <sys/device.h> 49 #include <sys/ioctl.h> 50 #include <sys/kernel.h> 51 #include <sys/kmem.h> 52 #include <sys/lwp.h> 53 #include <sys/rndsource.h> 54 #include <sys/signalvar.h> 55 #include <sys/systm.h> 56 57 #include <dev/usb/usb.h> 58 #include <dev/usb/usbhid.h> 59 60 #include <dev/usb/usbdevs.h> 61 #include <dev/usb/usbdi.h> 62 #include <dev/usb/usbdi_util.h> 63 #include <dev/usb/usb_quirks.h> 64 65 #include <dev/usb/uhidev.h> 66 #include <dev/hid/hid.h> 67 68 /* Report descriptor for broken Wacom Graphire */ 69 #include <dev/usb/ugraphire_rdesc.h> 70 /* Report descriptor for game controllers in "XInput" mode */ 71 #include <dev/usb/xinput_rdesc.h> 72 /* Report descriptor for Xbox One controllers */ 73 #include <dev/usb/x1input_rdesc.h> 74 75 #include "locators.h" 76 77 #ifdef UHIDEV_DEBUG 78 #define DPRINTF(x) if (uhidevdebug) printf x 79 #define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x 80 int uhidevdebug = 0; 81 #else 82 #define DPRINTF(x) 83 #define DPRINTFN(n,x) 84 #endif 85 86 Static void uhidev_intr(struct usbd_xfer *, void *, usbd_status); 87 88 Static int uhidev_maxrepid(void *, int); 89 Static int uhidevprint(void *, const char *); 90 91 static int uhidev_match(device_t, cfdata_t, void *); 92 static void uhidev_attach(device_t, device_t, void *); 93 static void uhidev_childdet(device_t, device_t); 94 static int uhidev_detach(device_t, int); 95 static int uhidev_activate(device_t, enum devact); 96 97 CFATTACH_DECL2_NEW(uhidev, sizeof(struct uhidev_softc), uhidev_match, 98 uhidev_attach, uhidev_detach, uhidev_activate, NULL, uhidev_childdet); 99 100 static int 101 uhidev_match(device_t parent, cfdata_t match, void *aux) 102 { 103 struct usbif_attach_arg *uiaa = aux; 104 105 /* Game controllers in "XInput" mode */ 106 if (USBIF_IS_XINPUT(uiaa)) 107 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 108 /* Xbox One controllers */ 109 if (USBIF_IS_X1INPUT(uiaa) && uiaa->uiaa_ifaceno == 0) 110 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 111 112 if (uiaa->uiaa_class != UICLASS_HID) 113 return UMATCH_NONE; 114 if (usbd_get_quirks(uiaa->uiaa_device)->uq_flags & UQ_HID_IGNORE) 115 return UMATCH_NONE; 116 return UMATCH_IFACECLASS_GENERIC; 117 } 118 119 static void 120 uhidev_attach(device_t parent, device_t self, void *aux) 121 { 122 struct uhidev_softc *sc = device_private(self); 123 struct usbif_attach_arg *uiaa = aux; 124 struct usbd_interface *iface = uiaa->uiaa_iface; 125 usb_interface_descriptor_t *id; 126 usb_endpoint_descriptor_t *ed; 127 struct uhidev_attach_arg uha; 128 device_t dev; 129 struct uhidev *csc; 130 int maxinpktsize, size, nrepid, repid, repsz; 131 int *repsizes; 132 int i; 133 void *desc; 134 const void *descptr; 135 usbd_status err; 136 char *devinfop; 137 int locs[UHIDBUSCF_NLOCS]; 138 139 sc->sc_dev = self; 140 sc->sc_udev = uiaa->uiaa_device; 141 sc->sc_iface = iface; 142 143 aprint_naive("\n"); 144 aprint_normal("\n"); 145 146 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 147 cv_init(&sc->sc_cv, "uhidev"); 148 sc->sc_writelock = NULL; 149 sc->sc_configlock = NULL; 150 151 id = usbd_get_interface_descriptor(iface); 152 153 devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); 154 aprint_normal_dev(self, "%s, iclass %d/%d\n", 155 devinfop, id->bInterfaceClass, id->bInterfaceSubClass); 156 usbd_devinfo_free(devinfop); 157 158 if (!pmf_device_register(self, NULL, NULL)) 159 aprint_error_dev(self, "couldn't establish power handler\n"); 160 161 if (uiaa->uiaa_vendor == USB_VENDOR_WACOM) { 162 if (uiaa->uiaa_product == USB_PRODUCT_WACOM_XD0912U) { 163 /* 164 * Wacom Intuos2 (XD-0912-U) requires longer idle time to 165 * initialize the device with 0x0202. 166 */ 167 DELAY(500000); 168 } 169 } 170 (void)usbd_set_idle(iface, 0, 0); 171 172 if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_NO_SET_PROTO) == 0) 173 (void)usbd_set_protocol(iface, 1); 174 175 maxinpktsize = 0; 176 sc->sc_iep_addr = sc->sc_oep_addr = -1; 177 for (i = 0; i < id->bNumEndpoints; i++) { 178 ed = usbd_interface2endpoint_descriptor(iface, i); 179 if (ed == NULL) { 180 aprint_error_dev(self, 181 "could not read endpoint descriptor\n"); 182 sc->sc_dying = 1; 183 return; 184 } 185 186 DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d " 187 "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" 188 " bInterval=%d\n", 189 ed->bLength, ed->bDescriptorType, 190 ed->bEndpointAddress & UE_ADDR, 191 UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", 192 ed->bmAttributes & UE_XFERTYPE, 193 UGETW(ed->wMaxPacketSize), ed->bInterval)); 194 195 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 196 (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { 197 maxinpktsize = UGETW(ed->wMaxPacketSize); 198 sc->sc_iep_addr = ed->bEndpointAddress; 199 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 200 (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { 201 sc->sc_oep_addr = ed->bEndpointAddress; 202 } else { 203 aprint_verbose_dev(self, "endpoint %d: ignored\n", i); 204 } 205 } 206 207 /* 208 * Check that we found an input interrupt endpoint. The output interrupt 209 * endpoint is optional 210 */ 211 if (sc->sc_iep_addr == -1) { 212 aprint_error_dev(self, "no input interrupt endpoint\n"); 213 sc->sc_dying = 1; 214 return; 215 } 216 217 /* XXX need to extend this */ 218 descptr = NULL; 219 if (uiaa->uiaa_vendor == USB_VENDOR_WACOM) { 220 static uByte reportbuf[3]; 221 222 /* The report descriptor for the Wacom Graphire is broken. */ 223 switch (uiaa->uiaa_product) { 224 case USB_PRODUCT_WACOM_GRAPHIRE3_4X5: 225 case USB_PRODUCT_WACOM_GRAPHIRE3_6X8: 226 case USB_PRODUCT_WACOM_GRAPHIRE4_4X5: /* The 6x8 too? */ 227 /* 228 * The Graphire3 needs 0x0202 to be written to 229 * feature report ID 2 before it'll start 230 * returning digitizer data. 231 */ 232 reportbuf[0] = 0x02; 233 reportbuf[1] = 0x02; 234 usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 2, 235 &reportbuf, 2); 236 237 size = sizeof(uhid_graphire3_4x5_report_descr); 238 descptr = uhid_graphire3_4x5_report_descr; 239 break; 240 case USB_PRODUCT_WACOM_GRAPHIRE: 241 case USB_PRODUCT_WACOM_GRAPHIRE2: 242 case USB_PRODUCT_WACOM_XD0912U: 243 case USB_PRODUCT_WACOM_CTH690K0: 244 reportbuf[0] = 0x02; 245 reportbuf[1] = 0x02; 246 usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 2, 247 &reportbuf, 2); 248 break; 249 default: 250 /* Keep descriptor */ 251 break; 252 } 253 } 254 if (USBIF_IS_XINPUT(uiaa)) { 255 size = sizeof(uhid_xinput_report_descr); 256 descptr = uhid_xinput_report_descr; 257 } 258 if (USBIF_IS_X1INPUT(uiaa)) { 259 sc->sc_flags |= UHIDEV_F_XB1; 260 size = sizeof(uhid_x1input_report_descr); 261 descptr = uhid_x1input_report_descr; 262 } 263 264 if (descptr) { 265 desc = kmem_alloc(size, KM_SLEEP); 266 err = USBD_NORMAL_COMPLETION; 267 memcpy(desc, descptr, size); 268 } else { 269 desc = NULL; 270 err = usbd_read_report_desc(uiaa->uiaa_iface, &desc, &size); 271 } 272 if (err) { 273 aprint_error_dev(self, "no report descriptor\n"); 274 sc->sc_dying = 1; 275 return; 276 } 277 278 if (uiaa->uiaa_vendor == USB_VENDOR_HOSIDEN && 279 uiaa->uiaa_product == USB_PRODUCT_HOSIDEN_PPP) { 280 static uByte reportbuf[] = { 1 }; 281 /* 282 * This device was sold by Konami with its ParaParaParadise 283 * game for PlayStation2. It needs to be "turned on" 284 * before it will send any reports. 285 */ 286 287 usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 0, 288 &reportbuf, sizeof(reportbuf)); 289 } 290 291 if (uiaa->uiaa_vendor == USB_VENDOR_LOGITECH && 292 uiaa->uiaa_product == USB_PRODUCT_LOGITECH_CBT44 && size == 0xb1) { 293 uint8_t *data = desc; 294 /* 295 * This device has a odd USAGE_MINIMUM value that would 296 * cause the multimedia keys to have their usage number 297 * shifted up one usage. Adjust so the usages are sane. 298 */ 299 300 if (data[0x56] == 0x19 && data[0x57] == 0x01 && 301 data[0x58] == 0x2a && data[0x59] == 0x8c) 302 data[0x57] = 0x00; 303 } 304 305 /* 306 * Enable the Six Axis and DualShock 3 controllers. 307 * See http://ps3.jim.sh/sixaxis/usb/ 308 */ 309 if (uiaa->uiaa_vendor == USB_VENDOR_SONY && 310 uiaa->uiaa_product == USB_PRODUCT_SONY_PS3CONTROLLER) { 311 usb_device_request_t req; 312 char data[17]; 313 int actlen; 314 315 req.bmRequestType = UT_READ_CLASS_INTERFACE; 316 req.bRequest = 1; 317 USETW(req.wValue, 0x3f2); 318 USETW(req.wIndex, 0); 319 USETW(req.wLength, sizeof(data)); 320 321 usbd_do_request_flags(sc->sc_udev, &req, data, 322 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); 323 } 324 325 sc->sc_repdesc = desc; 326 sc->sc_repdesc_size = size; 327 328 uha.uiaa = uiaa; 329 nrepid = uhidev_maxrepid(desc, size); 330 if (nrepid < 0) 331 return; 332 if (nrepid > 0) 333 aprint_normal_dev(self, "%d report ids\n", nrepid); 334 nrepid++; 335 repsizes = kmem_alloc(nrepid * sizeof(*repsizes), KM_SLEEP); 336 sc->sc_subdevs = kmem_zalloc(nrepid * sizeof(sc->sc_subdevs[0]), 337 KM_SLEEP); 338 339 /* Just request max packet size for the interrupt pipe */ 340 sc->sc_isize = maxinpktsize; 341 sc->sc_nrepid = nrepid; 342 343 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 344 345 for (repid = 0; repid < nrepid; repid++) { 346 repsz = hid_report_size(desc, size, hid_input, repid); 347 DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz)); 348 repsizes[repid] = repsz; 349 } 350 351 DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); 352 353 uha.parent = sc; 354 for (repid = 0; repid < nrepid; repid++) { 355 DPRINTF(("uhidev_match: try repid=%d\n", repid)); 356 if (hid_report_size(desc, size, hid_input, repid) == 0 && 357 hid_report_size(desc, size, hid_output, repid) == 0 && 358 hid_report_size(desc, size, hid_feature, repid) == 0) { 359 ; /* already NULL in sc->sc_subdevs[repid] */ 360 } else { 361 uha.reportid = repid; 362 locs[UHIDBUSCF_REPORTID] = repid; 363 364 dev = config_found(self, &uha, uhidevprint, 365 CFARGS(.submatch = config_stdsubmatch, 366 .locators = locs)); 367 sc->sc_subdevs[repid] = dev; 368 if (dev != NULL) { 369 csc = device_private(dev); 370 csc->sc_in_rep_size = repsizes[repid]; 371 #ifdef DIAGNOSTIC 372 DPRINTF(("uhidev_match: repid=%d dev=%p\n", 373 repid, dev)); 374 if (csc->sc_intr == NULL) { 375 kmem_free(repsizes, 376 nrepid * sizeof(*repsizes)); 377 aprint_error_dev(self, 378 "sc_intr == NULL\n"); 379 return; 380 } 381 #endif 382 rnd_attach_source(&csc->rnd_source, 383 device_xname(dev), 384 RND_TYPE_TTY, 385 RND_FLAG_DEFAULT); 386 } 387 } 388 } 389 kmem_free(repsizes, nrepid * sizeof(*repsizes)); 390 391 return; 392 } 393 394 int 395 uhidev_maxrepid(void *buf, int len) 396 { 397 struct hid_data *d; 398 struct hid_item h; 399 int maxid; 400 401 maxid = -1; 402 h.report_ID = 0; 403 for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) 404 if ((int)h.report_ID > maxid) 405 maxid = h.report_ID; 406 hid_end_parse(d); 407 return maxid; 408 } 409 410 int 411 uhidevprint(void *aux, const char *pnp) 412 { 413 struct uhidev_attach_arg *uha = aux; 414 415 if (pnp) 416 aprint_normal("uhid at %s", pnp); 417 if (uha->reportid != 0) 418 aprint_normal(" reportid %d", uha->reportid); 419 return UNCONF; 420 } 421 422 static int 423 uhidev_activate(device_t self, enum devact act) 424 { 425 struct uhidev_softc *sc = device_private(self); 426 427 switch (act) { 428 case DVACT_DEACTIVATE: 429 sc->sc_dying = 1; 430 return 0; 431 default: 432 return EOPNOTSUPP; 433 } 434 } 435 436 static void 437 uhidev_childdet(device_t self, device_t child) 438 { 439 int i; 440 struct uhidev_softc *sc = device_private(self); 441 442 for (i = 0; i < sc->sc_nrepid; i++) { 443 if (sc->sc_subdevs[i] == child) 444 break; 445 } 446 KASSERT(i < sc->sc_nrepid); 447 sc->sc_subdevs[i] = NULL; 448 } 449 450 static int 451 uhidev_detach(device_t self, int flags) 452 { 453 struct uhidev_softc *sc = device_private(self); 454 int i, rv; 455 struct uhidev *csc; 456 457 DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); 458 459 /* Notify that we are going away. */ 460 mutex_enter(&sc->sc_lock); 461 sc->sc_dying = 1; 462 cv_broadcast(&sc->sc_cv); 463 mutex_exit(&sc->sc_lock); 464 465 /* 466 * Try to detach all our children. If anything fails, bail. 467 * Failure can happen if this is from drvctl -d; of course, if 468 * this is a USB device being yanked, flags will have 469 * DETACH_FORCE and the children will not have the option of 470 * refusing detachment. 471 */ 472 for (i = 0; i < sc->sc_nrepid; i++) { 473 if (sc->sc_subdevs[i] == NULL) 474 continue; 475 /* 476 * XXX rnd_detach_source should go in uhidev_childdet, 477 * but the struct krndsource lives in the child's 478 * softc, which is gone by the time of childdet. The 479 * parent uhidev_softc should be changed to allocate 480 * the struct krndsource, not the child. 481 */ 482 csc = device_private(sc->sc_subdevs[i]); 483 rnd_detach_source(&csc->rnd_source); 484 rv = config_detach(sc->sc_subdevs[i], flags); 485 if (rv) { 486 rnd_attach_source(&csc->rnd_source, 487 device_xname(sc->sc_dev), 488 RND_TYPE_TTY, RND_FLAG_DEFAULT); 489 mutex_enter(&sc->sc_lock); 490 sc->sc_dying = 0; 491 mutex_exit(&sc->sc_lock); 492 return rv; 493 } 494 } 495 496 KASSERTMSG(sc->sc_refcnt == 0, 497 "%s: %d refs remain", device_xname(sc->sc_dev), sc->sc_refcnt); 498 KASSERT(sc->sc_opipe == NULL); 499 KASSERT(sc->sc_ipipe == NULL); 500 KASSERT(sc->sc_ibuf == NULL); 501 502 if (sc->sc_repdesc != NULL) { 503 kmem_free(sc->sc_repdesc, sc->sc_repdesc_size); 504 sc->sc_repdesc = NULL; 505 } 506 if (sc->sc_subdevs != NULL) { 507 int nrepid = sc->sc_nrepid; 508 kmem_free(sc->sc_subdevs, nrepid * sizeof(sc->sc_subdevs[0])); 509 sc->sc_subdevs = NULL; 510 } 511 512 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 513 514 pmf_device_deregister(self); 515 KASSERT(sc->sc_configlock == NULL); 516 KASSERT(sc->sc_writelock == NULL); 517 cv_destroy(&sc->sc_cv); 518 mutex_destroy(&sc->sc_lock); 519 520 return rv; 521 } 522 523 void 524 uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 525 { 526 struct uhidev_softc *sc = addr; 527 device_t cdev; 528 struct uhidev *scd; 529 u_char *p; 530 u_int rep; 531 uint32_t cc; 532 533 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 534 535 #ifdef UHIDEV_DEBUG 536 if (uhidevdebug > 5) { 537 uint32_t i; 538 539 DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc)); 540 DPRINTF(("uhidev_intr: data =")); 541 for (i = 0; i < cc; i++) 542 DPRINTF((" %02x", sc->sc_ibuf[i])); 543 DPRINTF(("\n")); 544 } 545 #endif 546 547 if (status == USBD_CANCELLED) 548 return; 549 550 if (status != USBD_NORMAL_COMPLETION) { 551 DPRINTF(("%s: interrupt status=%d\n", device_xname(sc->sc_dev), 552 status)); 553 usbd_clear_endpoint_stall_async(sc->sc_ipipe); 554 return; 555 } 556 557 p = sc->sc_ibuf; 558 if (sc->sc_nrepid != 1) 559 rep = *p++, cc--; 560 else 561 rep = 0; 562 if (rep >= sc->sc_nrepid) { 563 printf("uhidev_intr: bad repid %d\n", rep); 564 return; 565 } 566 cdev = sc->sc_subdevs[rep]; 567 if (!cdev) 568 return; 569 scd = device_private(cdev); 570 DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n", 571 rep, scd, scd ? scd->sc_state : 0)); 572 if (!(scd->sc_state & UHIDEV_OPEN)) 573 return; 574 #ifdef UHIDEV_DEBUG 575 if (scd->sc_in_rep_size != cc) { 576 DPRINTF(("%s: expected %d bytes, got %d\n", 577 device_xname(sc->sc_dev), scd->sc_in_rep_size, cc)); 578 } 579 #endif 580 if (cc == 0) { 581 DPRINTF(("%s: 0-length input ignored\n", 582 device_xname(sc->sc_dev))); 583 return; 584 } 585 rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf)); 586 scd->sc_intr(scd, p, cc); 587 } 588 589 void 590 uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size) 591 { 592 *desc = sc->sc_repdesc; 593 *size = sc->sc_repdesc_size; 594 } 595 596 static int 597 uhidev_config_enter(struct uhidev_softc *sc) 598 { 599 int error; 600 601 KASSERT(mutex_owned(&sc->sc_lock)); 602 603 for (;;) { 604 if (sc->sc_dying) 605 return ENXIO; 606 if (sc->sc_configlock == NULL) 607 break; 608 error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); 609 if (error) 610 return error; 611 } 612 613 sc->sc_configlock = curlwp; 614 return 0; 615 } 616 617 static void 618 uhidev_config_enter_nointr(struct uhidev_softc *sc) 619 { 620 621 KASSERT(mutex_owned(&sc->sc_lock)); 622 623 while (sc->sc_configlock) 624 cv_wait(&sc->sc_cv, &sc->sc_lock); 625 sc->sc_configlock = curlwp; 626 } 627 628 static void 629 uhidev_config_exit(struct uhidev_softc *sc) 630 { 631 632 KASSERT(mutex_owned(&sc->sc_lock)); 633 KASSERTMSG(sc->sc_configlock == curlwp, "%s: migrated from %p to %p", 634 device_xname(sc->sc_dev), curlwp, sc->sc_configlock); 635 636 sc->sc_configlock = NULL; 637 cv_broadcast(&sc->sc_cv); 638 } 639 640 /* 641 * uhidev_open_pipes(sc) 642 * 643 * Ensure the pipes of the softc are open. Caller must hold 644 * sc_lock, which may be released and reacquired. 645 */ 646 static int 647 uhidev_open_pipes(struct uhidev_softc *sc) 648 { 649 usbd_status err; 650 int error; 651 652 KASSERT(mutex_owned(&sc->sc_lock)); 653 654 /* If the device is dying, refuse. */ 655 if (sc->sc_dying) 656 return ENXIO; 657 658 /* 659 * If the pipes are already open, just increment the reference 660 * count, or fail if it would overflow. 661 */ 662 if (sc->sc_refcnt) { 663 if (sc->sc_refcnt == INT_MAX) 664 return EBUSY; 665 sc->sc_refcnt++; 666 return 0; 667 } 668 669 /* 670 * If there's no input data to prepare, don't bother with the 671 * pipes. We assume any device that does output also does 672 * input; if you have a device where this is wrong, then 673 * uhidev_write will fail gracefully (it checks sc->sc_opipe), 674 * and you can use that device to test the changes needed to 675 * open the output pipe here. 676 */ 677 if (sc->sc_isize == 0) 678 return 0; 679 680 /* 681 * Lock the configuration and release sc_lock we may sleep to 682 * allocate. If someone else got in first, we're done; 683 * otherwise open the pipes. 684 */ 685 error = uhidev_config_enter(sc); 686 if (error) 687 goto out; 688 if (sc->sc_refcnt) { 689 if (sc->sc_refcnt == INT_MAX) { 690 error = EBUSY; 691 } else { 692 sc->sc_refcnt++; 693 error = 0; 694 } 695 goto out0; 696 } 697 mutex_exit(&sc->sc_lock); 698 699 /* Allocate an input buffer. */ 700 sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP); 701 702 /* Set up input interrupt pipe. */ 703 DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize, 704 sc->sc_iep_addr)); 705 706 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, 707 USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, 708 sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL); 709 if (err != USBD_NORMAL_COMPLETION) { 710 DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " 711 "error=%d\n", err)); 712 error = EIO; 713 goto out1; 714 } 715 716 /* 717 * Set up output interrupt pipe if an output interrupt endpoint 718 * exists. 719 */ 720 if (sc->sc_oep_addr != -1) { 721 DPRINTF(("uhidev_open: oep=0x%02x\n", sc->sc_oep_addr)); 722 723 err = usbd_open_pipe(sc->sc_iface, sc->sc_oep_addr, 724 0, &sc->sc_opipe); 725 726 if (err != USBD_NORMAL_COMPLETION) { 727 DPRINTF(("uhidev_open: usbd_open_pipe failed, " 728 "error=%d\n", err)); 729 error = EIO; 730 goto out2; 731 } 732 DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe)); 733 734 error = usbd_create_xfer(sc->sc_opipe, UHIDEV_OSIZE, 0, 0, 735 &sc->sc_oxfer); 736 if (error) { 737 DPRINTF(("uhidev_open: couldn't allocate an xfer\n")); 738 goto out3; 739 } 740 741 if (sc->sc_flags & UHIDEV_F_XB1) { 742 uint8_t init_data[] = { 0x05, 0x20 }; 743 int init_data_len = sizeof(init_data); 744 err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0, 745 USBD_NO_TIMEOUT, init_data, &init_data_len); 746 if (err != USBD_NORMAL_COMPLETION) { 747 DPRINTF(("uhidev_open: xb1 init failed, " 748 "error=%d\n", err)); 749 error = EIO; 750 goto out4; 751 } 752 } 753 } 754 755 /* Success! */ 756 mutex_enter(&sc->sc_lock); 757 KASSERTMSG(sc->sc_refcnt == 0, "%d refs spuriously acquired", 758 sc->sc_refcnt); 759 sc->sc_refcnt++; 760 goto out0; 761 762 out4: if (sc->sc_oxfer) { 763 usbd_abort_pipe(sc->sc_opipe); 764 usbd_destroy_xfer(sc->sc_oxfer); 765 sc->sc_oxfer = NULL; 766 } 767 out3: if (sc->sc_opipe) { 768 usbd_close_pipe(sc->sc_opipe); 769 sc->sc_opipe = NULL; 770 } 771 out2: if (sc->sc_ipipe) { 772 usbd_abort_pipe(sc->sc_ipipe); 773 usbd_close_pipe(sc->sc_ipipe); 774 sc->sc_ipipe = NULL; 775 } 776 out1: kmem_free(sc->sc_ibuf, sc->sc_isize); 777 sc->sc_ibuf = NULL; 778 mutex_enter(&sc->sc_lock); 779 out0: KASSERT(mutex_owned(&sc->sc_lock)); 780 uhidev_config_exit(sc); 781 out: KASSERT(mutex_owned(&sc->sc_lock)); 782 return error; 783 } 784 785 static void 786 uhidev_close_pipes(struct uhidev_softc *sc) 787 { 788 789 KASSERT(mutex_owned(&sc->sc_lock)); 790 KASSERTMSG(sc->sc_refcnt > 0, "%s: refcnt fouled: %d", 791 device_xname(sc->sc_dev), sc->sc_refcnt); 792 793 /* If this isn't the last reference, just decrement. */ 794 if (sc->sc_refcnt > 1) { 795 sc->sc_refcnt--; 796 return; 797 } 798 799 /* 800 * Lock the configuration and release sc_lock so we may sleep 801 * to free memory. We're not waiting for anyone to allocate or 802 * free anything. 803 */ 804 uhidev_config_enter_nointr(sc); 805 806 /* 807 * If someone else acquired a reference while we were waiting 808 * for the config lock, nothing more for us to do. 809 */ 810 if (sc->sc_refcnt > 1) { 811 sc->sc_refcnt--; 812 uhidev_config_exit(sc); 813 return; 814 } 815 816 /* 817 * We're the last reference and committed to closing the pipes. 818 * Decrement the reference count before we release the lock -- 819 * access to the pipes is allowed as long as the reference 820 * count is positive, so this forces all new opens to wait 821 * until the config lock is released. 822 */ 823 KASSERTMSG(sc->sc_refcnt == 1, "%s: refcnt fouled: %d", 824 device_xname(sc->sc_dev), sc->sc_refcnt); 825 sc->sc_refcnt--; 826 mutex_exit(&sc->sc_lock); 827 828 if (sc->sc_oxfer) { 829 usbd_abort_pipe(sc->sc_opipe); 830 usbd_destroy_xfer(sc->sc_oxfer); 831 sc->sc_oxfer = NULL; 832 } 833 if (sc->sc_opipe) { 834 usbd_close_pipe(sc->sc_opipe); 835 sc->sc_opipe = NULL; 836 } 837 if (sc->sc_ipipe) { 838 usbd_abort_pipe(sc->sc_ipipe); 839 usbd_close_pipe(sc->sc_ipipe); 840 sc->sc_ipipe = NULL; 841 } 842 kmem_free(sc->sc_ibuf, sc->sc_isize); 843 sc->sc_ibuf = NULL; 844 845 mutex_enter(&sc->sc_lock); 846 uhidev_config_exit(sc); 847 KASSERTMSG(sc->sc_refcnt == 0, "%s: refcnt fouled: %d", 848 device_xname(sc->sc_dev), sc->sc_refcnt); 849 } 850 851 int 852 uhidev_open(struct uhidev *scd) 853 { 854 struct uhidev_softc *sc = scd->sc_parent; 855 int error; 856 857 mutex_enter(&sc->sc_lock); 858 859 DPRINTF(("uhidev_open(%s, report %d = %s): state=%x refcnt=%d\n", 860 device_xname(sc->sc_dev), 861 scd->sc_report_id, 862 device_xname(scd->sc_dev), 863 scd->sc_state, 864 sc->sc_refcnt)); 865 866 /* Mark the report id open. This is an exclusive lock. */ 867 if (scd->sc_state & UHIDEV_OPEN) { 868 error = EBUSY; 869 goto fail0; 870 } 871 scd->sc_state |= UHIDEV_OPEN; 872 873 /* Open the pipes which are shared by all report ids. */ 874 error = uhidev_open_pipes(sc); 875 if (error) 876 goto fail1; 877 878 mutex_exit(&sc->sc_lock); 879 880 /* Success! */ 881 return 0; 882 883 fail2: __unused 884 uhidev_close_pipes(sc); 885 fail1: KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 886 "%s: report id %d: closed while opening", 887 device_xname(sc->sc_dev), scd->sc_report_id); 888 scd->sc_state &= ~UHIDEV_OPEN; 889 fail0: mutex_exit(&sc->sc_lock); 890 return error; 891 } 892 893 void 894 uhidev_stop(struct uhidev *scd) 895 { 896 struct uhidev_softc *sc = scd->sc_parent; 897 bool abort = false; 898 899 mutex_enter(&sc->sc_lock); 900 if (sc->sc_writereportid == scd->sc_report_id) 901 abort = true; 902 mutex_exit(&sc->sc_lock); 903 904 if (abort && sc->sc_opipe) 905 usbd_abort_pipe(sc->sc_opipe); 906 } 907 908 void 909 uhidev_close(struct uhidev *scd) 910 { 911 struct uhidev_softc *sc = scd->sc_parent; 912 913 mutex_enter(&sc->sc_lock); 914 915 DPRINTF(("uhidev_close(%s, report %d = %s): state=%x refcnt=%d\n", 916 device_xname(sc->sc_dev), 917 scd->sc_report_id, 918 device_xname(scd->sc_dev), 919 scd->sc_state, 920 sc->sc_refcnt)); 921 922 KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 923 "%s: report id %d: unpaired close", 924 device_xname(sc->sc_dev), scd->sc_report_id); 925 uhidev_close_pipes(sc); 926 KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 927 "%s: report id %d: closed while closing", 928 device_xname(sc->sc_dev), scd->sc_report_id); 929 scd->sc_state &= ~UHIDEV_OPEN; 930 931 mutex_exit(&sc->sc_lock); 932 } 933 934 usbd_status 935 uhidev_set_report(struct uhidev *scd, int type, void *data, int len) 936 { 937 char *buf; 938 usbd_status retstat; 939 940 if (scd->sc_report_id == 0) 941 return usbd_set_report(scd->sc_parent->sc_iface, type, 942 scd->sc_report_id, data, len); 943 944 buf = kmem_alloc(len + 1, KM_SLEEP); 945 buf[0] = scd->sc_report_id; 946 memcpy(buf+1, data, len); 947 948 retstat = usbd_set_report(scd->sc_parent->sc_iface, type, 949 scd->sc_report_id, buf, len + 1); 950 951 kmem_free(buf, len + 1); 952 953 return retstat; 954 } 955 956 usbd_status 957 uhidev_get_report(struct uhidev *scd, int type, void *data, int len) 958 { 959 return usbd_get_report(scd->sc_parent->sc_iface, type, 960 scd->sc_report_id, data, len); 961 } 962 963 usbd_status 964 uhidev_write(struct uhidev_softc *sc, void *data, int len) 965 { 966 usbd_status err; 967 968 DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len)); 969 970 if (sc->sc_opipe == NULL) 971 return USBD_INVAL; 972 973 mutex_enter(&sc->sc_lock); 974 KASSERT(sc->sc_refcnt); 975 for (;;) { 976 if (sc->sc_dying) { 977 err = USBD_IOERROR; 978 goto out; 979 } 980 if (sc->sc_writelock == NULL) 981 break; 982 if (cv_wait_sig(&sc->sc_cv, &sc->sc_lock)) { 983 err = USBD_INTERRUPTED; 984 goto out; 985 } 986 } 987 sc->sc_writelock = curlwp; 988 mutex_exit(&sc->sc_lock); 989 990 #ifdef UHIDEV_DEBUG 991 if (uhidevdebug > 50) { 992 993 uint32_t i; 994 uint8_t *d = data; 995 996 DPRINTF(("uhidev_write: data =")); 997 for (i = 0; i < len; i++) 998 DPRINTF((" %02x", d[i])); 999 DPRINTF(("\n")); 1000 } 1001 #endif 1002 err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0, 1003 USBD_NO_TIMEOUT, data, &len); 1004 1005 mutex_enter(&sc->sc_lock); 1006 KASSERT(sc->sc_refcnt); 1007 KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p", 1008 device_xname(sc->sc_dev), curlwp, sc->sc_writelock); 1009 sc->sc_writelock = NULL; 1010 cv_broadcast(&sc->sc_cv); 1011 out: mutex_exit(&sc->sc_lock); 1012 return err; 1013 } 1014