1 /* $NetBSD: usbdi_util.c,v 1.84 2020/06/16 17:25:56 maxv 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.84 2020/06/16 17:25:56 maxv 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/usb_quirks.h> 54 #include <dev/usb/usbhist.h> 55 56 #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(usbdebug,1,FMT,A,B,C,D) 57 #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbdebug,N,FMT,A,B,C,D) 58 59 usbd_status 60 usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc) 61 { 62 usb_device_request_t req; 63 usbd_status err; 64 65 USBHIST_FUNC(); 66 USBHIST_CALLARGS(usbdebug, "type=%jd, index=%jd, len=%jd", 67 type, index, len, 0); 68 69 /* 70 * Provide hard-coded configuration descriptors 71 * for devices that may corrupt it. This cannot 72 * be done for device descriptors which are used 73 * to identify the device. 74 */ 75 if (type != UDESC_DEVICE && 76 dev->ud_quirks->uq_flags & UQ_DESC_CORRUPT) { 77 err = usbd_get_desc_fake(dev, type, index, len, desc); 78 goto out; 79 } 80 81 req.bmRequestType = UT_READ_DEVICE; 82 req.bRequest = UR_GET_DESCRIPTOR; 83 USETW2(req.wValue, type, index); 84 USETW(req.wIndex, 0); 85 USETW(req.wLength, len); 86 err = usbd_do_request(dev, &req, desc); 87 88 out: 89 return err; 90 } 91 92 usbd_status 93 usbd_get_config_desc(struct usbd_device *dev, int confidx, 94 usb_config_descriptor_t *d) 95 { 96 USBHIST_FUNC(); 97 USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0); 98 usbd_status err; 99 100 err = usbd_get_desc(dev, UDESC_CONFIG, confidx, 101 USB_CONFIG_DESCRIPTOR_SIZE, d); 102 if (err) 103 return err; 104 if (d->bDescriptorType != UDESC_CONFIG) { 105 DPRINTFN(1, "confidx=%jd, bad desc len=%jd type=%jd", 106 confidx, d->bLength, d->bDescriptorType, 0); 107 return USBD_INVAL; 108 } 109 return USBD_NORMAL_COMPLETION; 110 } 111 112 usbd_status 113 usbd_get_config_desc_full(struct usbd_device *dev, int conf, void *d, int size) 114 { 115 USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "conf=%jd", conf, 0, 0, 0); 116 117 return usbd_get_desc(dev, UDESC_CONFIG, conf, size, d); 118 } 119 120 usbd_status 121 usbd_get_bos_desc(struct usbd_device *dev, int confidx, 122 usb_bos_descriptor_t *d) 123 { 124 USBHIST_FUNC(); 125 USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0); 126 usbd_status err; 127 128 err = usbd_get_desc(dev, UDESC_BOS, confidx, 129 USB_BOS_DESCRIPTOR_SIZE, d); 130 if (err) 131 return err; 132 if (d->bDescriptorType != UDESC_BOS) { 133 DPRINTFN(1, "confidx=%jd, bad desc len=%jd type=%jd", 134 confidx, d->bLength, d->bDescriptorType, 0); 135 return USBD_INVAL; 136 } 137 return USBD_NORMAL_COMPLETION; 138 } 139 140 usbd_status 141 usbd_get_device_desc(struct usbd_device *dev, usb_device_descriptor_t *d) 142 { 143 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 144 145 return usbd_get_desc(dev, UDESC_DEVICE, 146 0, USB_DEVICE_DESCRIPTOR_SIZE, d); 147 } 148 149 /* 150 * Get the first 8 bytes of the device descriptor. 151 * Do as Windows does: try to read 64 bytes -- there are devices which 152 * recognize the initial descriptor fetch (before the control endpoint's 153 * MaxPacketSize is known by the host) by exactly this length. 154 */ 155 usbd_status 156 usbd_get_initial_ddesc(struct usbd_device *dev, usb_device_descriptor_t *desc) 157 { 158 USBHIST_FUNC(); 159 USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0); 160 usb_device_request_t req; 161 char buf[64]; 162 int res, actlen; 163 164 req.bmRequestType = UT_READ_DEVICE; 165 req.bRequest = UR_GET_DESCRIPTOR; 166 USETW2(req.wValue, UDESC_DEVICE, 0); 167 USETW(req.wIndex, 0); 168 USETW(req.wLength, 8); 169 res = usbd_do_request_flags(dev, &req, buf, USBD_SHORT_XFER_OK, 170 &actlen, USBD_DEFAULT_TIMEOUT); 171 if (res) 172 return res; 173 if (actlen < 8) 174 return USBD_SHORT_XFER; 175 memcpy(desc, buf, 8); 176 return USBD_NORMAL_COMPLETION; 177 } 178 179 usbd_status 180 usbd_get_string_desc(struct usbd_device *dev, int sindex, int langid, 181 usb_string_descriptor_t *sdesc, int *sizep) 182 { 183 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 184 usb_device_request_t req; 185 usbd_status err; 186 int actlen; 187 188 /* 189 * Pass a full-sized buffer to usbd_do_request_len(). At least 190 * one device has been seen returning additional data beyond the 191 * provided buffers (2-bytes written shortly after the request 192 * claims to have completed and returned the 2 byte header, 193 * corrupting other memory.) 194 */ 195 req.bmRequestType = UT_READ_DEVICE; 196 req.bRequest = UR_GET_DESCRIPTOR; 197 USETW2(req.wValue, UDESC_STRING, sindex); 198 USETW(req.wIndex, langid); 199 USETW(req.wLength, 2); /* only size byte first */ 200 err = usbd_do_request_len(dev, &req, sizeof(*sdesc), sdesc, 201 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); 202 if (err) 203 return err; 204 205 if (actlen < 2) 206 return USBD_SHORT_XFER; 207 208 if (sdesc->bLength > sizeof(*sdesc)) 209 return USBD_INVAL; 210 USETW(req.wLength, sdesc->bLength); /* the whole string */ 211 err = usbd_do_request_len(dev, &req, sizeof(*sdesc), sdesc, 212 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); 213 if (err) 214 return err; 215 216 if (actlen != sdesc->bLength) { 217 DPRINTF("expected %jd, got %jd", sdesc->bLength, actlen, 0, 0); 218 } 219 220 *sizep = actlen; 221 return USBD_NORMAL_COMPLETION; 222 } 223 224 /* -------------------------------------------------------------------------- */ 225 226 usbd_status 227 usbd_get_device_status(struct usbd_device *dev, usb_status_t *st) 228 { 229 USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 230 usb_device_request_t req; 231 232 req.bmRequestType = UT_READ_DEVICE; 233 req.bRequest = UR_GET_STATUS; 234 USETW(req.wValue, 0); 235 USETW(req.wIndex, 0); 236 USETW(req.wLength, sizeof(usb_status_t)); 237 return usbd_do_request(dev, &req, st); 238 } 239 240 usbd_status 241 usbd_get_hub_status(struct usbd_device *dev, usb_hub_status_t *st) 242 { 243 USBHIST_FUNC(); 244 USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0); 245 usb_device_request_t req; 246 247 req.bmRequestType = UT_READ_CLASS_DEVICE; 248 req.bRequest = UR_GET_STATUS; 249 USETW(req.wValue, 0); 250 USETW(req.wIndex, 0); 251 USETW(req.wLength, sizeof(usb_hub_status_t)); 252 return usbd_do_request(dev, &req, st); 253 } 254 255 usbd_status 256 usbd_get_port_status(struct usbd_device *dev, int port, usb_port_status_t *ps) 257 { 258 USBHIST_FUNC(); 259 USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd", 260 (uintptr_t)dev, port, 0, 0); 261 usb_device_request_t req; 262 263 req.bmRequestType = UT_READ_CLASS_OTHER; 264 req.bRequest = UR_GET_STATUS; 265 USETW(req.wValue, 0); 266 USETW(req.wIndex, port); 267 USETW(req.wLength, sizeof(*ps)); 268 return usbd_do_request(dev, &req, ps); 269 } 270 271 /* USB 3.1 10.16.2.6, 10.16.2.6.3 */ 272 usbd_status 273 usbd_get_port_status_ext(struct usbd_device *dev, int port, 274 usb_port_status_ext_t *pse) 275 { 276 USBHIST_FUNC(); 277 USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd", 278 (uintptr_t)dev, port, 0, 0); 279 usb_device_request_t req; 280 281 req.bmRequestType = UT_READ_CLASS_OTHER; 282 req.bRequest = UR_GET_STATUS; 283 USETW2(req.wValue, 0, UR_PST_EXT_PORT_STATUS); 284 USETW(req.wIndex, port); 285 USETW(req.wLength, sizeof(*pse)); 286 return usbd_do_request(dev, &req, pse); 287 } 288 289 /* -------------------------------------------------------------------------- */ 290 291 usbd_status 292 usbd_clear_hub_feature(struct usbd_device *dev, int sel) 293 { 294 USBHIST_FUNC(); 295 USBHIST_CALLARGS(usbdebug, "dev %#jx sel %jd", 296 (uintptr_t)dev, sel, 0, 0); 297 usb_device_request_t req; 298 299 req.bmRequestType = UT_WRITE_CLASS_DEVICE; 300 req.bRequest = UR_CLEAR_FEATURE; 301 USETW(req.wValue, sel); 302 USETW(req.wIndex, 0); 303 USETW(req.wLength, 0); 304 return usbd_do_request(dev, &req, 0); 305 } 306 307 usbd_status 308 usbd_set_hub_feature(struct usbd_device *dev, int sel) 309 { 310 USBHIST_FUNC(); 311 USBHIST_CALLARGS(usbdebug, 312 "dev %#jx sel %jd", (uintptr_t)dev, sel, 0, 0); 313 usb_device_request_t req; 314 315 req.bmRequestType = UT_WRITE_CLASS_DEVICE; 316 req.bRequest = UR_SET_FEATURE; 317 USETW(req.wValue, sel); 318 USETW(req.wIndex, 0); 319 USETW(req.wLength, 0); 320 return usbd_do_request(dev, &req, 0); 321 } 322 323 usbd_status 324 usbd_clear_port_feature(struct usbd_device *dev, int port, int sel) 325 { 326 USBHIST_FUNC(); 327 USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %jd", 328 (uintptr_t)dev, port, sel, 0); 329 usb_device_request_t req; 330 331 req.bmRequestType = UT_WRITE_CLASS_OTHER; 332 req.bRequest = UR_CLEAR_FEATURE; 333 USETW(req.wValue, sel); 334 USETW(req.wIndex, port); 335 USETW(req.wLength, 0); 336 return usbd_do_request(dev, &req, 0); 337 } 338 339 usbd_status 340 usbd_set_port_feature(struct usbd_device *dev, int port, int sel) 341 { 342 USBHIST_FUNC(); 343 USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %.d", 344 (uintptr_t)dev, sel, 0, 0); 345 usb_device_request_t req; 346 347 req.bmRequestType = UT_WRITE_CLASS_OTHER; 348 req.bRequest = UR_SET_FEATURE; 349 USETW(req.wValue, sel); 350 USETW(req.wIndex, port); 351 USETW(req.wLength, 0); 352 return usbd_do_request(dev, &req, 0); 353 } 354 355 usbd_status 356 usbd_set_port_u1_timeout(struct usbd_device *dev, int port, int timeout) 357 { 358 USBHIST_FUNC(); 359 USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %.d", 360 (uintptr_t)dev, port, timeout, 0); 361 usb_device_request_t req; 362 363 req.bmRequestType = UT_WRITE_CLASS_OTHER; 364 req.bRequest = UR_SET_FEATURE; 365 USETW(req.wValue, UHF_PORT_U1_TIMEOUT); 366 USETW2(req.wIndex, timeout, port); 367 USETW(req.wLength, 0); 368 return usbd_do_request(dev, &req, 0); 369 } 370 371 usbd_status 372 usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout) 373 { 374 USBHIST_FUNC(); 375 USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %jd", 376 (uintptr_t)dev, port, timeout, 0); 377 usb_device_request_t req; 378 379 req.bmRequestType = UT_WRITE_CLASS_OTHER; 380 req.bRequest = UR_SET_FEATURE; 381 USETW(req.wValue, UHF_PORT_U2_TIMEOUT); 382 USETW2(req.wIndex, timeout, port); 383 USETW(req.wLength, 0); 384 return usbd_do_request(dev, &req, 0); 385 } 386 387 usbd_status 388 usbd_clear_endpoint_feature(struct usbd_device *dev, int epaddr, int sel) 389 { 390 USBHIST_FUNC(); 391 USBHIST_CALLARGS(usbdebug, "dev %#jx epaddr %jd sel %jd", 392 (uintptr_t)dev, epaddr, sel, 0); 393 usb_device_request_t req; 394 395 req.bmRequestType = UT_WRITE_ENDPOINT; 396 req.bRequest = UR_CLEAR_FEATURE; 397 USETW(req.wValue, sel); 398 USETW(req.wIndex, epaddr); 399 USETW(req.wLength, 0); 400 return usbd_do_request(dev, &req, 0); 401 } 402 403 /* -------------------------------------------------------------------------- */ 404 405 usbd_status 406 usbd_get_config(struct usbd_device *dev, uint8_t *conf) 407 { 408 USBHIST_FUNC(); 409 USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0); 410 usb_device_request_t req; 411 412 req.bmRequestType = UT_READ_DEVICE; 413 req.bRequest = UR_GET_CONFIG; 414 USETW(req.wValue, 0); 415 USETW(req.wIndex, 0); 416 USETW(req.wLength, 1); 417 return usbd_do_request(dev, &req, conf); 418 } 419 420 usbd_status 421 usbd_set_config(struct usbd_device *dev, int conf) 422 { 423 USBHIST_FUNC(); 424 USBHIST_CALLARGS(usbdebug, "dev %#jx conf %jd", 425 (uintptr_t)dev, conf, 0, 0); 426 usb_device_request_t req; 427 428 req.bmRequestType = UT_WRITE_DEVICE; 429 req.bRequest = UR_SET_CONFIG; 430 USETW(req.wValue, conf); 431 USETW(req.wIndex, 0); 432 USETW(req.wLength, 0); 433 return usbd_do_request(dev, &req, 0); 434 } 435 436 usbd_status 437 usbd_set_address(struct usbd_device *dev, int addr) 438 { 439 USBHIST_FUNC(); 440 USBHIST_CALLARGS(usbdebug, "dev %#jx addr %jd", 441 (uintptr_t)dev, addr, 0, 0); 442 usb_device_request_t req; 443 444 req.bmRequestType = UT_WRITE_DEVICE; 445 req.bRequest = UR_SET_ADDRESS; 446 USETW(req.wValue, addr); 447 USETW(req.wIndex, 0); 448 USETW(req.wLength, 0); 449 return usbd_do_request(dev, &req, 0); 450 } 451 452 usbd_status 453 usbd_set_idle(struct usbd_interface *iface, int duration, int id) 454 { 455 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 456 struct usbd_device *dev; 457 usb_device_request_t req; 458 459 USBHIST_FUNC(); 460 USBHIST_CALLARGS(usbdebug, "duration %jd id %jd", duration, id, 0, 0); 461 462 if (ifd == NULL) 463 return USBD_IOERROR; 464 usbd_interface2device_handle(iface, &dev); 465 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 466 req.bRequest = UR_SET_IDLE; 467 USETW2(req.wValue, duration, id); 468 USETW(req.wIndex, ifd->bInterfaceNumber); 469 USETW(req.wLength, 0); 470 return usbd_do_request(dev, &req, 0); 471 } 472 473 /* -------------------------------------------------------------------------- */ 474 475 usbd_status 476 usbd_get_protocol(struct usbd_interface *iface, uint8_t *report) 477 { 478 usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 479 struct usbd_device *dev; 480 usb_device_request_t req; 481 482 USBHIST_FUNC(); 483 USBHIST_CALLARGS(usbdebug, "iface=%#jx, endpt=%jd", 484 (uintptr_t)iface, id->bInterfaceNumber, 0, 0); 485 486 if (id == NULL) 487 return USBD_IOERROR; 488 489 usbd_interface2device_handle(iface, &dev); 490 req.bmRequestType = UT_READ_CLASS_INTERFACE; 491 req.bRequest = UR_GET_PROTOCOL; 492 USETW(req.wValue, 0); 493 USETW(req.wIndex, id->bInterfaceNumber); 494 USETW(req.wLength, 1); 495 return usbd_do_request(dev, &req, report); 496 } 497 498 usbd_status 499 usbd_set_protocol(struct usbd_interface *iface, int report) 500 { 501 usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 502 struct usbd_device *dev; 503 usb_device_request_t req; 504 505 USBHIST_FUNC(); 506 USBHIST_CALLARGS(usbdebug, "iface=%#jx, report=%jd, endpt=%jd", 507 (uintptr_t)iface, report, id->bInterfaceNumber, 0); 508 509 if (id == NULL) 510 return USBD_IOERROR; 511 512 usbd_interface2device_handle(iface, &dev); 513 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 514 req.bRequest = UR_SET_PROTOCOL; 515 USETW(req.wValue, report); 516 USETW(req.wIndex, id->bInterfaceNumber); 517 USETW(req.wLength, 0); 518 return usbd_do_request(dev, &req, 0); 519 } 520 521 /* -------------------------------------------------------------------------- */ 522 523 usbd_status 524 usbd_set_report(struct usbd_interface *iface, int type, int id, void *data, 525 int len) 526 { 527 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 528 struct usbd_device *dev; 529 usb_device_request_t req; 530 531 USBHIST_FUNC(); 532 USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0); 533 534 if (ifd == NULL) 535 return USBD_IOERROR; 536 usbd_interface2device_handle(iface, &dev); 537 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 538 req.bRequest = UR_SET_REPORT; 539 USETW2(req.wValue, type, id); 540 USETW(req.wIndex, ifd->bInterfaceNumber); 541 USETW(req.wLength, len); 542 return usbd_do_request(dev, &req, data); 543 } 544 545 usbd_status 546 usbd_get_report(struct usbd_interface *iface, int type, int id, void *data, 547 int len) 548 { 549 usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 550 struct usbd_device *dev; 551 usb_device_request_t req; 552 553 USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0); 554 555 if (ifd == NULL) 556 return USBD_IOERROR; 557 usbd_interface2device_handle(iface, &dev); 558 req.bmRequestType = UT_READ_CLASS_INTERFACE; 559 req.bRequest = UR_GET_REPORT; 560 USETW2(req.wValue, type, id); 561 USETW(req.wIndex, ifd->bInterfaceNumber); 562 USETW(req.wLength, len); 563 return usbd_do_request(dev, &req, data); 564 } 565 566 usbd_status 567 usbd_get_report_descriptor(struct usbd_device *dev, int ifcno, 568 int size, void *d) 569 { 570 USBHIST_FUNC(); 571 USBHIST_CALLARGS(usbdebug, "dev %#jx ifcno %jd size %jd", 572 (uintptr_t)dev, ifcno, size, 0); 573 usb_device_request_t req; 574 575 req.bmRequestType = UT_READ_INTERFACE; 576 req.bRequest = UR_GET_DESCRIPTOR; 577 USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */ 578 USETW(req.wIndex, ifcno); 579 USETW(req.wLength, size); 580 return usbd_do_request(dev, &req, d); 581 } 582 583 /* -------------------------------------------------------------------------- */ 584 585 usb_hid_descriptor_t * 586 usbd_get_hid_descriptor(struct usbd_interface *ifc) 587 { 588 usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc); 589 struct usbd_device *dev; 590 usb_config_descriptor_t *cdesc; 591 usb_hid_descriptor_t *hd; 592 char *p, *end; 593 594 if (idesc == NULL) 595 return NULL; 596 usbd_interface2device_handle(ifc, &dev); 597 cdesc = usbd_get_config_descriptor(dev); 598 599 p = (char *)idesc + idesc->bLength; 600 end = (char *)cdesc + UGETW(cdesc->wTotalLength); 601 602 for (; p < end; p += hd->bLength) { 603 hd = (usb_hid_descriptor_t *)p; 604 if (p + hd->bLength <= end && 605 hd->bLength >= USB_HID_DESCRIPTOR_SIZE(0) && 606 hd->bDescriptorType == UDESC_HID) 607 return hd; 608 if (hd->bDescriptorType == UDESC_INTERFACE) 609 break; 610 } 611 return NULL; 612 } 613 614 usbd_status 615 usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep) 616 { 617 usb_interface_descriptor_t *id; 618 usb_hid_descriptor_t *hid; 619 struct usbd_device *dev; 620 usbd_status err; 621 622 usbd_interface2device_handle(ifc, &dev); 623 id = usbd_get_interface_descriptor(ifc); 624 if (id == NULL) 625 return USBD_INVAL; 626 hid = usbd_get_hid_descriptor(ifc); 627 if (hid == NULL) 628 return USBD_IOERROR; 629 *sizep = UGETW(hid->descrs[0].wDescriptorLength); 630 if (*sizep == 0) 631 return USBD_INVAL; 632 *descp = kmem_alloc(*sizep, KM_SLEEP); 633 err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 634 *sizep, *descp); 635 if (err) { 636 kmem_free(*descp, *sizep); 637 *descp = NULL; 638 return err; 639 } 640 return USBD_NORMAL_COMPLETION; 641 } 642 643 usbd_status 644 usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 645 uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 646 { 647 usbd_status err; 648 649 USBHIST_FUNC(); 650 USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0); 651 652 usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 653 err = usbd_sync_transfer_sig(xfer); 654 655 usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 656 DPRINTFN(1, "transferred %jd", *size, 0, 0, 0); 657 if (err) { 658 usbd_clear_endpoint_stall(pipe); 659 } 660 USBHIST_LOG(usbdebug, "<- done xfer %#jx err %jd", (uintptr_t)xfer, 661 err, 0, 0); 662 663 return err; 664 } 665 666 usbd_status 667 usbd_intr_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 668 uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 669 { 670 usbd_status err; 671 672 USBHIST_FUNC(); 673 USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0); 674 675 usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 676 677 err = usbd_sync_transfer_sig(xfer); 678 679 usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 680 681 DPRINTFN(1, "transferred %jd", *size, 0, 0, 0); 682 if (err) { 683 usbd_clear_endpoint_stall(pipe); 684 } 685 USBHIST_LOG(usbdebug, "<- done xfer %#jx err %jd", (uintptr_t)xfer, 686 err, 0, 0); 687 688 return err; 689 } 690 691 void 692 usb_detach_waitold(device_t dv) 693 { 694 USBHIST_FUNC(); 695 USBHIST_CALLARGS(usbdebug, "waiting for dv %#jx", 696 (uintptr_t)dv, 0, 0, 0); 697 698 if (tsleep(dv, PZERO, "usbdet", hz * 60)) /* XXXSMP ok */ 699 aprint_error_dev(dv, "usb_detach_waitold: didn't detach\n"); 700 DPRINTFN(1, "done", 0, 0, 0, 0); 701 } 702 703 void 704 usb_detach_wakeupold(device_t dv) 705 { 706 USBHIST_FUNC(); 707 USBHIST_CALLARGS(usbdebug, "for dv %#jx", (uintptr_t)dv, 0, 0, 0); 708 709 wakeup(dv); /* XXXSMP ok */ 710 } 711 712 /* -------------------------------------------------------------------------- */ 713 714 void 715 usb_desc_iter_init(struct usbd_device *dev, usbd_desc_iter_t *iter) 716 { 717 const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); 718 719 iter->cur = (const uByte *)cd; 720 iter->end = (const uByte *)cd + UGETW(cd->wTotalLength); 721 } 722 723 const usb_descriptor_t * 724 usb_desc_iter_peek(usbd_desc_iter_t *iter) 725 { 726 const usb_descriptor_t *desc; 727 728 if (iter->cur + sizeof(usb_descriptor_t) > iter->end) { 729 if (iter->cur != iter->end) 730 printf("%s: bad descriptor\n", __func__); 731 return NULL; 732 } 733 desc = (const usb_descriptor_t *)iter->cur; 734 if (desc->bLength < USB_DESCRIPTOR_SIZE) { 735 printf("%s: descriptor length too small\n", __func__); 736 return NULL; 737 } 738 if (iter->cur + desc->bLength > iter->end) { 739 printf("%s: descriptor length too large\n", __func__); 740 return NULL; 741 } 742 return desc; 743 } 744 745 const usb_descriptor_t * 746 usb_desc_iter_next(usbd_desc_iter_t *iter) 747 { 748 const usb_descriptor_t *desc = usb_desc_iter_peek(iter); 749 if (desc == NULL) 750 return NULL; 751 iter->cur += desc->bLength; 752 return desc; 753 } 754 755 /* Return the next interface descriptor, skipping over any other 756 * descriptors. Returns NULL at the end or on error. */ 757 const usb_interface_descriptor_t * 758 usb_desc_iter_next_interface(usbd_desc_iter_t *iter) 759 { 760 const usb_descriptor_t *desc; 761 762 while ((desc = usb_desc_iter_peek(iter)) != NULL && 763 desc->bDescriptorType != UDESC_INTERFACE) 764 { 765 usb_desc_iter_next(iter); 766 } 767 768 return (const usb_interface_descriptor_t *)usb_desc_iter_next(iter); 769 } 770 771 /* Returns the next non-interface descriptor, returning NULL when the 772 * next descriptor would be an interface descriptor. */ 773 const usb_descriptor_t * 774 usb_desc_iter_next_non_interface(usbd_desc_iter_t *iter) 775 { 776 const usb_descriptor_t *desc; 777 778 if ((desc = usb_desc_iter_peek(iter)) != NULL && 779 desc->bDescriptorType != UDESC_INTERFACE) 780 { 781 return usb_desc_iter_next(iter); 782 } else { 783 return NULL; 784 } 785 } 786 787 const usb_cdc_descriptor_t * 788 usb_find_desc(struct usbd_device *dev, int type, int subtype) 789 { 790 usbd_desc_iter_t iter; 791 const usb_cdc_descriptor_t *desc; 792 793 usb_desc_iter_init(dev, &iter); 794 for (;;) { 795 desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter); 796 if (!desc || (desc->bDescriptorType == type && 797 (subtype == USBD_CDCSUBTYPE_ANY || 798 subtype == desc->bDescriptorSubtype))) 799 break; 800 } 801 return desc; 802 } 803 804 /* same as usb_find_desc(), but searches only in the specified interface. */ 805 const usb_cdc_descriptor_t * 806 usb_find_desc_if(struct usbd_device *dev, int type, int subtype, 807 usb_interface_descriptor_t *id) 808 { 809 usbd_desc_iter_t iter; 810 const usb_cdc_descriptor_t *desc; 811 812 if (id == NULL) 813 return usb_find_desc(dev, type, subtype); 814 815 usb_desc_iter_init(dev, &iter); 816 817 iter.cur = (void *)id; /* start from the interface desc */ 818 usb_desc_iter_next(&iter); /* and skip it */ 819 820 while ((desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter)) 821 != NULL) { 822 if (desc->bDescriptorType == UDESC_INTERFACE) { 823 /* we ran into the next interface --- not found */ 824 return NULL; 825 } 826 if (desc->bDescriptorType == type && 827 (subtype == USBD_CDCSUBTYPE_ANY || 828 subtype == desc->bDescriptorSubtype)) 829 break; 830 } 831 return desc; 832 } 833