1 /* $NetBSD: uhidev.c,v 1.80 2021/04/24 23:36:59 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.80 2021/04/24 23:36:59 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 CFARG_SUBMATCH, config_stdsubmatch, 366 CFARG_LOCATORS, locs, 367 CFARG_EOL); 368 sc->sc_subdevs[repid] = dev; 369 if (dev != NULL) { 370 csc = device_private(dev); 371 csc->sc_in_rep_size = repsizes[repid]; 372 #ifdef DIAGNOSTIC 373 DPRINTF(("uhidev_match: repid=%d dev=%p\n", 374 repid, dev)); 375 if (csc->sc_intr == NULL) { 376 kmem_free(repsizes, 377 nrepid * sizeof(*repsizes)); 378 aprint_error_dev(self, 379 "sc_intr == NULL\n"); 380 return; 381 } 382 #endif 383 rnd_attach_source(&csc->rnd_source, 384 device_xname(dev), 385 RND_TYPE_TTY, 386 RND_FLAG_DEFAULT); 387 } 388 } 389 } 390 kmem_free(repsizes, nrepid * sizeof(*repsizes)); 391 392 return; 393 } 394 395 int 396 uhidev_maxrepid(void *buf, int len) 397 { 398 struct hid_data *d; 399 struct hid_item h; 400 int maxid; 401 402 maxid = -1; 403 h.report_ID = 0; 404 for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) 405 if ((int)h.report_ID > maxid) 406 maxid = h.report_ID; 407 hid_end_parse(d); 408 return maxid; 409 } 410 411 int 412 uhidevprint(void *aux, const char *pnp) 413 { 414 struct uhidev_attach_arg *uha = aux; 415 416 if (pnp) 417 aprint_normal("uhid at %s", pnp); 418 if (uha->reportid != 0) 419 aprint_normal(" reportid %d", uha->reportid); 420 return UNCONF; 421 } 422 423 static int 424 uhidev_activate(device_t self, enum devact act) 425 { 426 struct uhidev_softc *sc = device_private(self); 427 428 switch (act) { 429 case DVACT_DEACTIVATE: 430 sc->sc_dying = 1; 431 return 0; 432 default: 433 return EOPNOTSUPP; 434 } 435 } 436 437 static void 438 uhidev_childdet(device_t self, device_t child) 439 { 440 int i; 441 struct uhidev_softc *sc = device_private(self); 442 443 for (i = 0; i < sc->sc_nrepid; i++) { 444 if (sc->sc_subdevs[i] == child) 445 break; 446 } 447 KASSERT(i < sc->sc_nrepid); 448 sc->sc_subdevs[i] = NULL; 449 } 450 451 static int 452 uhidev_detach(device_t self, int flags) 453 { 454 struct uhidev_softc *sc = device_private(self); 455 int i, rv; 456 struct uhidev *csc; 457 458 DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); 459 460 /* Notify that we are going away. */ 461 mutex_enter(&sc->sc_lock); 462 sc->sc_dying = 1; 463 cv_broadcast(&sc->sc_cv); 464 mutex_exit(&sc->sc_lock); 465 466 /* 467 * Try to detach all our children. If anything fails, bail. 468 * Failure can happen if this is from drvctl -d; of course, if 469 * this is a USB device being yanked, flags will have 470 * DETACH_FORCE and the children will not have the option of 471 * refusing detachment. 472 */ 473 for (i = 0; i < sc->sc_nrepid; i++) { 474 if (sc->sc_subdevs[i] == NULL) 475 continue; 476 /* 477 * XXX rnd_detach_source should go in uhidev_childdet, 478 * but the struct krndsource lives in the child's 479 * softc, which is gone by the time of childdet. The 480 * parent uhidev_softc should be changed to allocate 481 * the struct krndsource, not the child. 482 */ 483 csc = device_private(sc->sc_subdevs[i]); 484 rnd_detach_source(&csc->rnd_source); 485 rv = config_detach(sc->sc_subdevs[i], flags); 486 if (rv) { 487 rnd_attach_source(&csc->rnd_source, 488 device_xname(sc->sc_dev), 489 RND_TYPE_TTY, RND_FLAG_DEFAULT); 490 mutex_enter(&sc->sc_lock); 491 sc->sc_dying = 0; 492 mutex_exit(&sc->sc_lock); 493 return rv; 494 } 495 } 496 497 KASSERTMSG(sc->sc_refcnt == 0, 498 "%s: %d refs remain", device_xname(sc->sc_dev), sc->sc_refcnt); 499 KASSERT(sc->sc_opipe == NULL); 500 KASSERT(sc->sc_ipipe == NULL); 501 KASSERT(sc->sc_ibuf == NULL); 502 503 if (sc->sc_repdesc != NULL) { 504 kmem_free(sc->sc_repdesc, sc->sc_repdesc_size); 505 sc->sc_repdesc = NULL; 506 } 507 if (sc->sc_subdevs != NULL) { 508 int nrepid = sc->sc_nrepid; 509 kmem_free(sc->sc_subdevs, nrepid * sizeof(sc->sc_subdevs[0])); 510 sc->sc_subdevs = NULL; 511 } 512 513 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 514 515 pmf_device_deregister(self); 516 KASSERT(sc->sc_configlock == NULL); 517 KASSERT(sc->sc_writelock == NULL); 518 cv_destroy(&sc->sc_cv); 519 mutex_destroy(&sc->sc_lock); 520 521 return rv; 522 } 523 524 void 525 uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 526 { 527 struct uhidev_softc *sc = addr; 528 device_t cdev; 529 struct uhidev *scd; 530 u_char *p; 531 u_int rep; 532 uint32_t cc; 533 534 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 535 536 #ifdef UHIDEV_DEBUG 537 if (uhidevdebug > 5) { 538 uint32_t i; 539 540 DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc)); 541 DPRINTF(("uhidev_intr: data =")); 542 for (i = 0; i < cc; i++) 543 DPRINTF((" %02x", sc->sc_ibuf[i])); 544 DPRINTF(("\n")); 545 } 546 #endif 547 548 if (status == USBD_CANCELLED) 549 return; 550 551 if (status != USBD_NORMAL_COMPLETION) { 552 DPRINTF(("%s: interrupt status=%d\n", device_xname(sc->sc_dev), 553 status)); 554 usbd_clear_endpoint_stall_async(sc->sc_ipipe); 555 return; 556 } 557 558 p = sc->sc_ibuf; 559 if (sc->sc_nrepid != 1) 560 rep = *p++, cc--; 561 else 562 rep = 0; 563 if (rep >= sc->sc_nrepid) { 564 printf("uhidev_intr: bad repid %d\n", rep); 565 return; 566 } 567 cdev = sc->sc_subdevs[rep]; 568 if (!cdev) 569 return; 570 scd = device_private(cdev); 571 DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n", 572 rep, scd, scd ? scd->sc_state : 0)); 573 if (!(scd->sc_state & UHIDEV_OPEN)) 574 return; 575 #ifdef UHIDEV_DEBUG 576 if (scd->sc_in_rep_size != cc) { 577 DPRINTF(("%s: expected %d bytes, got %d\n", 578 device_xname(sc->sc_dev), scd->sc_in_rep_size, cc)); 579 } 580 #endif 581 if (cc == 0) { 582 DPRINTF(("%s: 0-length input ignored\n", 583 device_xname(sc->sc_dev))); 584 return; 585 } 586 rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf)); 587 scd->sc_intr(scd, p, cc); 588 } 589 590 void 591 uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size) 592 { 593 *desc = sc->sc_repdesc; 594 *size = sc->sc_repdesc_size; 595 } 596 597 static int 598 uhidev_config_enter(struct uhidev_softc *sc) 599 { 600 int error; 601 602 KASSERT(mutex_owned(&sc->sc_lock)); 603 604 for (;;) { 605 if (sc->sc_dying) 606 return ENXIO; 607 if (sc->sc_configlock == NULL) 608 break; 609 error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); 610 if (error) 611 return error; 612 } 613 614 sc->sc_configlock = curlwp; 615 return 0; 616 } 617 618 static void 619 uhidev_config_enter_nointr(struct uhidev_softc *sc) 620 { 621 622 KASSERT(mutex_owned(&sc->sc_lock)); 623 624 while (sc->sc_configlock) 625 cv_wait(&sc->sc_cv, &sc->sc_lock); 626 sc->sc_configlock = curlwp; 627 } 628 629 static void 630 uhidev_config_exit(struct uhidev_softc *sc) 631 { 632 633 KASSERT(mutex_owned(&sc->sc_lock)); 634 KASSERTMSG(sc->sc_configlock == curlwp, "%s: migrated from %p to %p", 635 device_xname(sc->sc_dev), curlwp, sc->sc_configlock); 636 637 sc->sc_configlock = NULL; 638 cv_broadcast(&sc->sc_cv); 639 } 640 641 /* 642 * uhidev_open_pipes(sc) 643 * 644 * Ensure the pipes of the softc are open. Caller must hold 645 * sc_lock, which may be released and reacquired. 646 */ 647 static int 648 uhidev_open_pipes(struct uhidev_softc *sc) 649 { 650 usbd_status err; 651 int error; 652 653 KASSERT(mutex_owned(&sc->sc_lock)); 654 655 /* If the device is dying, refuse. */ 656 if (sc->sc_dying) 657 return ENXIO; 658 659 /* 660 * If the pipes are already open, just increment the reference 661 * count, or fail if it would overflow. 662 */ 663 if (sc->sc_refcnt) { 664 if (sc->sc_refcnt == INT_MAX) 665 return EBUSY; 666 sc->sc_refcnt++; 667 return 0; 668 } 669 670 /* 671 * If there's no input data to prepare, don't bother with the 672 * pipes. We assume any device that does output also does 673 * input; if you have a device where this is wrong, then 674 * uhidev_write will fail gracefully (it checks sc->sc_opipe), 675 * and you can use that device to test the changes needed to 676 * open the output pipe here. 677 */ 678 if (sc->sc_isize == 0) 679 return 0; 680 681 /* 682 * Lock the configuration and release sc_lock we may sleep to 683 * allocate. If someone else got in first, we're done; 684 * otherwise open the pipes. 685 */ 686 error = uhidev_config_enter(sc); 687 if (error) 688 goto out; 689 if (sc->sc_refcnt) { 690 if (sc->sc_refcnt == INT_MAX) { 691 error = EBUSY; 692 } else { 693 sc->sc_refcnt++; 694 error = 0; 695 } 696 goto out0; 697 } 698 mutex_exit(&sc->sc_lock); 699 700 /* Allocate an input buffer. */ 701 sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP); 702 703 /* Set up input interrupt pipe. */ 704 DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize, 705 sc->sc_iep_addr)); 706 707 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, 708 USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, 709 sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL); 710 if (err != USBD_NORMAL_COMPLETION) { 711 DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " 712 "error=%d\n", err)); 713 error = EIO; 714 goto out1; 715 } 716 717 /* 718 * Set up output interrupt pipe if an output interrupt endpoint 719 * exists. 720 */ 721 if (sc->sc_oep_addr != -1) { 722 DPRINTF(("uhidev_open: oep=0x%02x\n", sc->sc_oep_addr)); 723 724 err = usbd_open_pipe(sc->sc_iface, sc->sc_oep_addr, 725 0, &sc->sc_opipe); 726 727 if (err != USBD_NORMAL_COMPLETION) { 728 DPRINTF(("uhidev_open: usbd_open_pipe failed, " 729 "error=%d\n", err)); 730 error = EIO; 731 goto out2; 732 } 733 DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe)); 734 735 error = usbd_create_xfer(sc->sc_opipe, UHIDEV_OSIZE, 0, 0, 736 &sc->sc_oxfer); 737 if (error) { 738 DPRINTF(("uhidev_open: couldn't allocate an xfer\n")); 739 goto out3; 740 } 741 742 if (sc->sc_flags & UHIDEV_F_XB1) { 743 uint8_t init_data[] = { 0x05, 0x20 }; 744 int init_data_len = sizeof(init_data); 745 err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0, 746 USBD_NO_TIMEOUT, init_data, &init_data_len); 747 if (err != USBD_NORMAL_COMPLETION) { 748 DPRINTF(("uhidev_open: xb1 init failed, " 749 "error=%d\n", err)); 750 error = EIO; 751 goto out4; 752 } 753 } 754 } 755 756 /* Success! */ 757 mutex_enter(&sc->sc_lock); 758 KASSERTMSG(sc->sc_refcnt == 0, "%d refs spuriously acquired", 759 sc->sc_refcnt); 760 sc->sc_refcnt++; 761 goto out0; 762 763 out4: if (sc->sc_oxfer) { 764 usbd_abort_pipe(sc->sc_opipe); 765 usbd_destroy_xfer(sc->sc_oxfer); 766 sc->sc_oxfer = NULL; 767 } 768 out3: if (sc->sc_opipe) { 769 usbd_close_pipe(sc->sc_opipe); 770 sc->sc_opipe = NULL; 771 } 772 out2: if (sc->sc_ipipe) { 773 usbd_abort_pipe(sc->sc_ipipe); 774 usbd_close_pipe(sc->sc_ipipe); 775 sc->sc_ipipe = NULL; 776 } 777 out1: kmem_free(sc->sc_ibuf, sc->sc_isize); 778 sc->sc_ibuf = NULL; 779 mutex_enter(&sc->sc_lock); 780 out0: KASSERT(mutex_owned(&sc->sc_lock)); 781 uhidev_config_exit(sc); 782 out: KASSERT(mutex_owned(&sc->sc_lock)); 783 return error; 784 } 785 786 static void 787 uhidev_close_pipes(struct uhidev_softc *sc) 788 { 789 790 KASSERT(mutex_owned(&sc->sc_lock)); 791 KASSERTMSG(sc->sc_refcnt > 0, "%s: refcnt fouled: %d", 792 device_xname(sc->sc_dev), sc->sc_refcnt); 793 794 /* If this isn't the last reference, just decrement. */ 795 if (sc->sc_refcnt > 1) { 796 sc->sc_refcnt--; 797 return; 798 } 799 800 /* 801 * Lock the configuration and release sc_lock so we may sleep 802 * to free memory. We're not waiting for anyone to allocate or 803 * free anything. 804 */ 805 uhidev_config_enter_nointr(sc); 806 807 /* 808 * If someone else acquired a reference while we were waiting 809 * for the config lock, nothing more for us to do. 810 */ 811 if (sc->sc_refcnt > 1) { 812 sc->sc_refcnt--; 813 uhidev_config_exit(sc); 814 return; 815 } 816 817 /* 818 * We're the last reference and committed to closing the pipes. 819 * Decrement the reference count before we release the lock -- 820 * access to the pipes is allowed as long as the reference 821 * count is positive, so this forces all new opens to wait 822 * until the config lock is released. 823 */ 824 KASSERTMSG(sc->sc_refcnt == 1, "%s: refcnt fouled: %d", 825 device_xname(sc->sc_dev), sc->sc_refcnt); 826 sc->sc_refcnt--; 827 mutex_exit(&sc->sc_lock); 828 829 if (sc->sc_oxfer) { 830 usbd_abort_pipe(sc->sc_opipe); 831 usbd_destroy_xfer(sc->sc_oxfer); 832 sc->sc_oxfer = NULL; 833 } 834 if (sc->sc_opipe) { 835 usbd_close_pipe(sc->sc_opipe); 836 sc->sc_opipe = NULL; 837 } 838 if (sc->sc_ipipe) { 839 usbd_abort_pipe(sc->sc_ipipe); 840 usbd_close_pipe(sc->sc_ipipe); 841 sc->sc_ipipe = NULL; 842 } 843 kmem_free(sc->sc_ibuf, sc->sc_isize); 844 sc->sc_ibuf = NULL; 845 846 mutex_enter(&sc->sc_lock); 847 uhidev_config_exit(sc); 848 KASSERTMSG(sc->sc_refcnt == 0, "%s: refcnt fouled: %d", 849 device_xname(sc->sc_dev), sc->sc_refcnt); 850 } 851 852 int 853 uhidev_open(struct uhidev *scd) 854 { 855 struct uhidev_softc *sc = scd->sc_parent; 856 int error; 857 858 mutex_enter(&sc->sc_lock); 859 860 DPRINTF(("uhidev_open(%s, report %d = %s): state=%x refcnt=%d\n", 861 device_xname(sc->sc_dev), 862 scd->sc_report_id, 863 device_xname(scd->sc_dev), 864 scd->sc_state, 865 sc->sc_refcnt)); 866 867 /* Mark the report id open. This is an exclusive lock. */ 868 if (scd->sc_state & UHIDEV_OPEN) { 869 error = EBUSY; 870 goto fail0; 871 } 872 scd->sc_state |= UHIDEV_OPEN; 873 874 /* Open the pipes which are shared by all report ids. */ 875 error = uhidev_open_pipes(sc); 876 if (error) 877 goto fail1; 878 879 mutex_exit(&sc->sc_lock); 880 881 /* Success! */ 882 return 0; 883 884 fail2: __unused 885 uhidev_close_pipes(sc); 886 fail1: KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 887 "%s: report id %d: closed while opening", 888 device_xname(sc->sc_dev), scd->sc_report_id); 889 scd->sc_state &= ~UHIDEV_OPEN; 890 fail0: mutex_exit(&sc->sc_lock); 891 return error; 892 } 893 894 void 895 uhidev_stop(struct uhidev *scd) 896 { 897 struct uhidev_softc *sc = scd->sc_parent; 898 bool abort = false; 899 900 mutex_enter(&sc->sc_lock); 901 if (sc->sc_writereportid == scd->sc_report_id) 902 abort = true; 903 mutex_exit(&sc->sc_lock); 904 905 if (abort && sc->sc_opipe) 906 usbd_abort_pipe(sc->sc_opipe); 907 } 908 909 void 910 uhidev_close(struct uhidev *scd) 911 { 912 struct uhidev_softc *sc = scd->sc_parent; 913 914 mutex_enter(&sc->sc_lock); 915 916 DPRINTF(("uhidev_close(%s, report %d = %s): state=%x refcnt=%d\n", 917 device_xname(sc->sc_dev), 918 scd->sc_report_id, 919 device_xname(scd->sc_dev), 920 scd->sc_state, 921 sc->sc_refcnt)); 922 923 KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 924 "%s: report id %d: unpaired close", 925 device_xname(sc->sc_dev), scd->sc_report_id); 926 uhidev_close_pipes(sc); 927 KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 928 "%s: report id %d: closed while closing", 929 device_xname(sc->sc_dev), scd->sc_report_id); 930 scd->sc_state &= ~UHIDEV_OPEN; 931 932 mutex_exit(&sc->sc_lock); 933 } 934 935 usbd_status 936 uhidev_set_report(struct uhidev *scd, int type, void *data, int len) 937 { 938 char *buf; 939 usbd_status retstat; 940 941 if (scd->sc_report_id == 0) 942 return usbd_set_report(scd->sc_parent->sc_iface, type, 943 scd->sc_report_id, data, len); 944 945 buf = kmem_alloc(len + 1, KM_SLEEP); 946 buf[0] = scd->sc_report_id; 947 memcpy(buf+1, data, len); 948 949 retstat = usbd_set_report(scd->sc_parent->sc_iface, type, 950 scd->sc_report_id, buf, len + 1); 951 952 kmem_free(buf, len + 1); 953 954 return retstat; 955 } 956 957 usbd_status 958 uhidev_get_report(struct uhidev *scd, int type, void *data, int len) 959 { 960 return usbd_get_report(scd->sc_parent->sc_iface, type, 961 scd->sc_report_id, data, len); 962 } 963 964 usbd_status 965 uhidev_write(struct uhidev_softc *sc, void *data, int len) 966 { 967 usbd_status err; 968 969 DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len)); 970 971 if (sc->sc_opipe == NULL) 972 return USBD_INVAL; 973 974 mutex_enter(&sc->sc_lock); 975 KASSERT(sc->sc_refcnt); 976 for (;;) { 977 if (sc->sc_dying) { 978 err = USBD_IOERROR; 979 goto out; 980 } 981 if (sc->sc_writelock == NULL) 982 break; 983 if (cv_wait_sig(&sc->sc_cv, &sc->sc_lock)) { 984 err = USBD_INTERRUPTED; 985 goto out; 986 } 987 } 988 sc->sc_writelock = curlwp; 989 mutex_exit(&sc->sc_lock); 990 991 #ifdef UHIDEV_DEBUG 992 if (uhidevdebug > 50) { 993 994 uint32_t i; 995 uint8_t *d = data; 996 997 DPRINTF(("uhidev_write: data =")); 998 for (i = 0; i < len; i++) 999 DPRINTF((" %02x", d[i])); 1000 DPRINTF(("\n")); 1001 } 1002 #endif 1003 err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0, 1004 USBD_NO_TIMEOUT, data, &len); 1005 1006 mutex_enter(&sc->sc_lock); 1007 KASSERT(sc->sc_refcnt); 1008 KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p", 1009 device_xname(sc->sc_dev), curlwp, sc->sc_writelock); 1010 sc->sc_writelock = NULL; 1011 cv_broadcast(&sc->sc_cv); 1012 out: mutex_exit(&sc->sc_lock); 1013 return err; 1014 } 1015