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