1 /* $NetBSD: usbdi_util.c,v 1.65 2016/04/23 10:15:32 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 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 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.65 2016/04/23 10:15:32 skrll Exp $"); 35 36 #ifdef _KERNEL_OPT 37 #include "opt_usb.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/kmem.h> 44 #include <sys/proc.h> 45 #include <sys/device.h> 46 #include <sys/bus.h> 47 48 #include <dev/usb/usb.h> 49 #include <dev/usb/usbhid.h> 50 #include <dev/usb/usbdi.h> 51 #include <dev/usb/usbdivar.h> 52 #include <dev/usb/usbdi_util.h> 53 #include <dev/usb/usbhist.h> 54 55 #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(usbdebug,1,FMT,A,B,C,D) 56 #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbdebug,N,FMT,A,B,C,D) 57 58 usbd_status 59 usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc) 60 { 61 usb_device_request_t req; 62 63 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 64 65 DPRINTFN(3,"type=%d, index=%d, len=%d", type, index, len, 0); 66 67 req.bmRequestType = UT_READ_DEVICE; 68 req.bRequest = UR_GET_DESCRIPTOR; 69 USETW2(req.wValue, type, index); 70 USETW(req.wIndex, 0); 71 USETW(req.wLength, len); 72 return usbd_do_request(dev, &req, desc); 73 } 74 75 usbd_status 76 usbd_get_config_desc(struct usbd_device *dev, int confidx, 77 usb_config_descriptor_t *d) 78 { 79 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 80 usbd_status err; 81 82 DPRINTFN(3, "confidx=%d", confidx, 0, 0, 0); 83 err = usbd_get_desc(dev, UDESC_CONFIG, confidx, 84 USB_CONFIG_DESCRIPTOR_SIZE, d); 85 if (err) 86 return err; 87 if (d->bDescriptorType != UDESC_CONFIG) { 88 DPRINTFN(1, "confidx=%d, bad desc len=%d type=%d", 89 confidx, d->bLength, d->bDescriptorType, 0); 90 return USBD_INVAL; 91 } 92 return USBD_NORMAL_COMPLETION; 93 } 94 95 usbd_status 96 usbd_get_config_desc_full(struct usbd_device *dev, int conf, void *d, int size) 97 { 98 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 99 100 DPRINTFN(3, "conf=%d", conf, 0, 0, 0); 101 return usbd_get_desc(dev, UDESC_CONFIG, conf, size, d); 102 } 103 104 usbd_status 105 usbd_get_bos_desc(struct usbd_device *dev, int confidx, 106 usb_bos_descriptor_t *d) 107 { 108 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 109 usbd_status err; 110 111 DPRINTFN(3, "confidx=%d", confidx, 0, 0, 0); 112 err = usbd_get_desc(dev, UDESC_BOS, confidx, 113 USB_BOS_DESCRIPTOR_SIZE, d); 114 if (err) 115 return (err); 116 if (d->bDescriptorType != UDESC_BOS) { 117 DPRINTFN(1, "confidx=%d, bad desc len=%d type=%d", 118 confidx, d->bLength, d->bDescriptorType, 0); 119 return USBD_INVAL; 120 } 121 return USBD_NORMAL_COMPLETION; 122 } 123 124 usbd_status 125 usbd_get_bos_desc_full(struct usbd_device *dev, int conf, void *d, int size) 126 { 127 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 128 129 DPRINTFN(3, "conf=%d", conf, 0, 0, 0); 130 return usbd_get_desc(dev, UDESC_BOS, conf, size, d); 131 } 132 133 usbd_status 134 usbd_get_device_desc(struct usbd_device *dev, usb_device_descriptor_t *d) 135 { 136 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 137 138 return (usbd_get_desc(dev, UDESC_DEVICE, 139 0, USB_DEVICE_DESCRIPTOR_SIZE, d)); 140 } 141 142 usbd_status 143 usbd_get_device_status(struct usbd_device *dev, usb_status_t *st) 144 { 145 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 146 usb_device_request_t req; 147 148 req.bmRequestType = UT_READ_DEVICE; 149 req.bRequest = UR_GET_STATUS; 150 USETW(req.wValue, 0); 151 USETW(req.wIndex, 0); 152 USETW(req.wLength, sizeof(usb_status_t)); 153 return usbd_do_request(dev, &req, st); 154 } 155 156 usbd_status 157 usbd_get_hub_status(struct usbd_device *dev, usb_hub_status_t *st) 158 { 159 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 160 usb_device_request_t req; 161 162 DPRINTF("dev %p", dev, 0, 0, 0); 163 req.bmRequestType = UT_READ_CLASS_DEVICE; 164 req.bRequest = UR_GET_STATUS; 165 USETW(req.wValue, 0); 166 USETW(req.wIndex, 0); 167 USETW(req.wLength, sizeof(usb_hub_status_t)); 168 return usbd_do_request(dev, &req, st); 169 } 170 171 usbd_status 172 usbd_set_address(struct usbd_device *dev, int addr) 173 { 174 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 175 usb_device_request_t req; 176 177 DPRINTF("dev %p addr %d", dev, addr, 0, 0); 178 req.bmRequestType = UT_WRITE_DEVICE; 179 req.bRequest = UR_SET_ADDRESS; 180 USETW(req.wValue, addr); 181 USETW(req.wIndex, 0); 182 USETW(req.wLength, 0); 183 return usbd_do_request(dev, &req, 0); 184 } 185 186 usbd_status 187 usbd_get_port_status(struct usbd_device *dev, int port, usb_port_status_t *ps) 188 { 189 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 190 usb_device_request_t req; 191 192 DPRINTF("dev %p port %d", dev, port, 0, 0); 193 req.bmRequestType = UT_READ_CLASS_OTHER; 194 req.bRequest = UR_GET_STATUS; 195 USETW(req.wValue, 0); 196 USETW(req.wIndex, port); 197 USETW(req.wLength, sizeof(*ps)); 198 return usbd_do_request(dev, &req, ps); 199 } 200 201 /* USB 3.1 10.16.2.6, 10.16.2.6.3 */ 202 usbd_status 203 usbd_get_port_status_ext(struct usbd_device *dev, int port, 204 usb_port_status_ext_t *pse) 205 { 206 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 207 usb_device_request_t req; 208 209 DPRINTF("dev %p port %d", dev, port, 0, 0); 210 req.bmRequestType = UT_READ_CLASS_OTHER; 211 req.bRequest = UR_GET_STATUS; 212 USETW2(req.wValue, 0, UR_PST_EXT_PORT_STATUS); 213 USETW(req.wIndex, port); 214 USETW(req.wLength, sizeof(*pse)); 215 return (usbd_do_request(dev, &req, pse)); 216 } 217 218 usbd_status 219 usbd_clear_hub_feature(struct usbd_device *dev, int sel) 220 { 221 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 222 usb_device_request_t req; 223 224 DPRINTF("dev %p sel %d", dev, sel, 0, 0); 225 req.bmRequestType = UT_WRITE_CLASS_DEVICE; 226 req.bRequest = UR_CLEAR_FEATURE; 227 USETW(req.wValue, sel); 228 USETW(req.wIndex, 0); 229 USETW(req.wLength, 0); 230 return usbd_do_request(dev, &req, 0); 231 } 232 233 usbd_status 234 usbd_set_hub_feature(struct usbd_device *dev, int sel) 235 { 236 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 237 usb_device_request_t req; 238 239 DPRINTF("dev %p sel %d", dev, sel, 0, 0); 240 req.bmRequestType = UT_WRITE_CLASS_DEVICE; 241 req.bRequest = UR_SET_FEATURE; 242 USETW(req.wValue, sel); 243 USETW(req.wIndex, 0); 244 USETW(req.wLength, 0); 245 return usbd_do_request(dev, &req, 0); 246 } 247 248 usbd_status 249 usbd_clear_port_feature(struct usbd_device *dev, int port, int sel) 250 { 251 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 252 usb_device_request_t req; 253 254 DPRINTF("dev %p port %d sel %d", dev, port, sel, 0); 255 req.bmRequestType = UT_WRITE_CLASS_OTHER; 256 req.bRequest = UR_CLEAR_FEATURE; 257 USETW(req.wValue, sel); 258 USETW(req.wIndex, port); 259 USETW(req.wLength, 0); 260 return usbd_do_request(dev, &req, 0); 261 } 262 263 usbd_status 264 usbd_set_port_feature(struct usbd_device *dev, int port, int sel) 265 { 266 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 267 usb_device_request_t req; 268 269 DPRINTF("dev %p port %d sel %d", dev, sel, 0, 0); 270 req.bmRequestType = UT_WRITE_CLASS_OTHER; 271 req.bRequest = UR_SET_FEATURE; 272 USETW(req.wValue, sel); 273 USETW(req.wIndex, port); 274 USETW(req.wLength, 0); 275 return usbd_do_request(dev, &req, 0); 276 } 277 278 usbd_status 279 usbd_set_port_u1_timeout(struct usbd_device *dev, int port, int timeout) 280 { 281 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 282 usb_device_request_t req; 283 284 DPRINTF("dev %p port %d timeout %d", dev, port, timeout, 0); 285 req.bmRequestType = UT_WRITE_CLASS_OTHER; 286 req.bRequest = UR_SET_FEATURE; 287 USETW(req.wValue, UHF_PORT_U1_TIMEOUT); 288 USETW2(req.wIndex, timeout, port); 289 USETW(req.wLength, 0); 290 return usbd_do_request(dev, &req, 0); 291 } 292 293 usbd_status 294 usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout) 295 { 296 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 297 usb_device_request_t req; 298 299 DPRINTF("dev %p port %d timeout %d", dev, port, timeout, 0); 300 req.bmRequestType = UT_WRITE_CLASS_OTHER; 301 req.bRequest = UR_SET_FEATURE; 302 USETW(req.wValue, UHF_PORT_U2_TIMEOUT); 303 USETW2(req.wIndex, timeout, port); 304 USETW(req.wLength, 0); 305 return usbd_do_request(dev, &req, 0); 306 } 307 308 usbd_status 309 usbd_get_protocol(struct usbd_interface *iface, uint8_t *report) 310 { 311 usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 312 struct usbd_device *dev; 313 usb_device_request_t req; 314 315 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 316 317 DPRINTFN(4, "iface=%p, endpt=%d", iface, id->bInterfaceNumber, 0, 0); 318 if (id == NULL) 319 return USBD_IOERROR; 320 usbd_interface2device_handle(iface, &dev); 321 req.bmRequestType = UT_READ_CLASS_INTERFACE; 322 req.bRequest = UR_GET_PROTOCOL; 323 USETW(req.wValue, 0); 324 USETW(req.wIndex, id->bInterfaceNumber); 325 USETW(req.wLength, 1); 326 return usbd_do_request(dev, &req, report); 327 } 328 329 usbd_status 330 usbd_set_protocol(struct usbd_interface *iface, int report) 331 { 332 usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 333 struct usbd_device *dev; 334 usb_device_request_t req; 335 336 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 337 338 DPRINTFN(4, "iface=%p, report=%d, endpt=%d", iface, report, 339 id->bInterfaceNumber, 0); 340 if (id == NULL) 341 return USBD_IOERROR; 342 usbd_interface2device_handle(iface, &dev); 343 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 344 req.bRequest = UR_SET_PROTOCOL; 345 USETW(req.wValue, report); 346 USETW(req.wIndex, id->bInterfaceNumber); 347 USETW(req.wLength, 0); 348 return usbd_do_request(dev, &req, 0); 349 } 350 351 usbd_status 352 usbd_set_report(struct usbd_interface *iface, int type, int id, void *data, 353 int len) 354 { 355 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 356 struct usbd_device *dev; 357 usb_device_request_t req; 358 359 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 360 361 DPRINTFN(4, "len=%d", len, 0, 0, 0); 362 if (ifd == NULL) 363 return USBD_IOERROR; 364 usbd_interface2device_handle(iface, &dev); 365 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 366 req.bRequest = UR_SET_REPORT; 367 USETW2(req.wValue, type, id); 368 USETW(req.wIndex, ifd->bInterfaceNumber); 369 USETW(req.wLength, len); 370 return usbd_do_request(dev, &req, data); 371 } 372 373 usbd_status 374 usbd_get_report(struct usbd_interface *iface, int type, int id, void *data, 375 int len) 376 { 377 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 378 struct usbd_device *dev; 379 usb_device_request_t req; 380 381 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 382 383 DPRINTFN(4, "len=%d", len, 0, 0, 0); 384 if (ifd == NULL) 385 return USBD_IOERROR; 386 usbd_interface2device_handle(iface, &dev); 387 req.bmRequestType = UT_READ_CLASS_INTERFACE; 388 req.bRequest = UR_GET_REPORT; 389 USETW2(req.wValue, type, id); 390 USETW(req.wIndex, ifd->bInterfaceNumber); 391 USETW(req.wLength, len); 392 return usbd_do_request(dev, &req, data); 393 } 394 395 usbd_status 396 usbd_set_idle(struct usbd_interface *iface, int duration, int id) 397 { 398 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 399 struct usbd_device *dev; 400 usb_device_request_t req; 401 402 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 403 404 DPRINTFN(4, "duration %d id %d", duration, id, 0, 0); 405 if (ifd == NULL) 406 return USBD_IOERROR; 407 usbd_interface2device_handle(iface, &dev); 408 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 409 req.bRequest = UR_SET_IDLE; 410 USETW2(req.wValue, duration, id); 411 USETW(req.wIndex, ifd->bInterfaceNumber); 412 USETW(req.wLength, 0); 413 return usbd_do_request(dev, &req, 0); 414 } 415 416 usbd_status 417 usbd_get_report_descriptor(struct usbd_device *dev, int ifcno, 418 int size, void *d) 419 { 420 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 421 usb_device_request_t req; 422 423 DPRINTF("dev %p ifcno %d size %d", dev, ifcno, size, 0); 424 req.bmRequestType = UT_READ_INTERFACE; 425 req.bRequest = UR_GET_DESCRIPTOR; 426 USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */ 427 USETW(req.wIndex, ifcno); 428 USETW(req.wLength, size); 429 return usbd_do_request(dev, &req, d); 430 } 431 432 usb_hid_descriptor_t * 433 usbd_get_hid_descriptor(struct usbd_interface *ifc) 434 { 435 usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc); 436 struct usbd_device *dev; 437 usb_config_descriptor_t *cdesc; 438 usb_hid_descriptor_t *hd; 439 char *p, *end; 440 441 if (idesc == NULL) 442 return NULL; 443 usbd_interface2device_handle(ifc, &dev); 444 cdesc = usbd_get_config_descriptor(dev); 445 446 p = (char *)idesc + idesc->bLength; 447 end = (char *)cdesc + UGETW(cdesc->wTotalLength); 448 449 for (; p < end; p += hd->bLength) { 450 hd = (usb_hid_descriptor_t *)p; 451 if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID) 452 return hd; 453 if (hd->bDescriptorType == UDESC_INTERFACE) 454 break; 455 } 456 return NULL; 457 } 458 459 usbd_status 460 usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep) 461 { 462 usb_interface_descriptor_t *id; 463 usb_hid_descriptor_t *hid; 464 struct usbd_device *dev; 465 usbd_status err; 466 467 usbd_interface2device_handle(ifc, &dev); 468 id = usbd_get_interface_descriptor(ifc); 469 if (id == NULL) 470 return USBD_INVAL; 471 hid = usbd_get_hid_descriptor(ifc); 472 if (hid == NULL) 473 return USBD_IOERROR; 474 *sizep = UGETW(hid->descrs[0].wDescriptorLength); 475 *descp = kmem_alloc(*sizep, KM_SLEEP); 476 if (*descp == NULL) 477 return USBD_NOMEM; 478 err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 479 *sizep, *descp); 480 if (err) { 481 kmem_free(*descp, *sizep); 482 *descp = NULL; 483 return err; 484 } 485 return USBD_NORMAL_COMPLETION; 486 } 487 488 usbd_status 489 usbd_get_config(struct usbd_device *dev, uint8_t *conf) 490 { 491 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 492 usb_device_request_t req; 493 494 DPRINTF("dev %p", dev, 0, 0, 0); 495 req.bmRequestType = UT_READ_DEVICE; 496 req.bRequest = UR_GET_CONFIG; 497 USETW(req.wValue, 0); 498 USETW(req.wIndex, 0); 499 USETW(req.wLength, 1); 500 return usbd_do_request(dev, &req, conf); 501 } 502 503 usbd_status 504 usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 505 uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 506 { 507 usbd_status err; 508 509 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 510 511 usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 512 DPRINTFN(1, "start transfer %d bytes", *size, 0, 0, 0); 513 err = usbd_sync_transfer_sig(xfer); 514 515 usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 516 DPRINTFN(1, "transferred %d", *size, 0, 0, 0); 517 if (err) { 518 usbd_clear_endpoint_stall(pipe); 519 } 520 USBHIST_LOG(usbdebug, "<- done xfer %p err %d", xfer, err, 0, 0); 521 522 return err; 523 } 524 525 usbd_status 526 usbd_intr_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 527 uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 528 { 529 usbd_status err; 530 531 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 532 533 usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 534 535 DPRINTFN(1, "start transfer %d bytes", *size, 0, 0, 0); 536 err = usbd_sync_transfer_sig(xfer); 537 538 usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 539 540 DPRINTFN(1, "transferred %d", *size, 0, 0, 0); 541 if (err) { 542 usbd_clear_endpoint_stall(pipe); 543 } 544 USBHIST_LOG(usbdebug, "<- done xfer %p err %d", xfer, err, 0, 0); 545 546 return err; 547 } 548 549 void 550 usb_detach_wait(device_t dv, kcondvar_t *cv, kmutex_t *lock) 551 { 552 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 553 554 DPRINTFN(1, "waiting for dv %p", dv, 0, 0, 0); 555 if (cv_timedwait(cv, lock, hz * 60)) // dv, PZERO, "usbdet", hz * 60 556 printf("usb_detach_wait: %s didn't detach\n", 557 device_xname(dv)); 558 DPRINTFN(1, "done", 0, 0, 0, 0); 559 } 560 561 void 562 usb_detach_broadcast(device_t dv, kcondvar_t *cv) 563 { 564 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 565 566 DPRINTFN(1, "for dv %p", dv, 0, 0, 0); 567 cv_broadcast(cv); 568 } 569 570 void 571 usb_detach_waitold(device_t dv) 572 { 573 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 574 575 DPRINTFN(1, "waiting for dv %p", dv, 0, 0, 0); 576 if (tsleep(dv, PZERO, "usbdet", hz * 60)) /* XXXSMP ok */ 577 printf("usb_detach_waitold: %s didn't detach\n", 578 device_xname(dv)); 579 DPRINTFN(1, "done", 0, 0, 0, 0); 580 } 581 582 void 583 usb_detach_wakeupold(device_t dv) 584 { 585 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 586 587 DPRINTFN(1, "for dv %p", dv, 0, 0, 0); 588 wakeup(dv); /* XXXSMP ok */ 589 } 590 591 const usb_cdc_descriptor_t * 592 usb_find_desc(struct usbd_device *dev, int type, int subtype) 593 { 594 usbd_desc_iter_t iter; 595 const usb_cdc_descriptor_t *desc; 596 597 usb_desc_iter_init(dev, &iter); 598 for (;;) { 599 desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter); 600 if (!desc || (desc->bDescriptorType == type && 601 (subtype == USBD_CDCSUBTYPE_ANY || 602 subtype == desc->bDescriptorSubtype))) 603 break; 604 } 605 return desc; 606 } 607 608 /* same as usb_find_desc(), but searches only in the specified interface. */ 609 const usb_cdc_descriptor_t * 610 usb_find_desc_if(struct usbd_device *dev, int type, int subtype, 611 usb_interface_descriptor_t *id) 612 { 613 usbd_desc_iter_t iter; 614 const usb_cdc_descriptor_t *desc; 615 616 if (id == NULL) 617 return usb_find_desc(dev, type, subtype); 618 619 usb_desc_iter_init(dev, &iter); 620 621 iter.cur = (void *)id; /* start from the interface desc */ 622 usb_desc_iter_next(&iter); /* and skip it */ 623 624 while ((desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter)) 625 != NULL) { 626 if (desc->bDescriptorType == UDESC_INTERFACE) { 627 /* we ran into the next interface --- not found */ 628 return NULL; 629 } 630 if (desc->bDescriptorType == type && 631 (subtype == USBD_CDCSUBTYPE_ANY || 632 subtype == desc->bDescriptorSubtype)) 633 break; 634 } 635 return desc; 636 } 637