1 /* $NetBSD: usbroothub.c,v 1.10 2021/07/21 06:35:45 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2004, 2011, 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, Jared D. McNeill (jmcneill@invisible.ca), 10 * Matthew R. Green (mrg@eterna.com.au) and Nick Hudson. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 2008 36 * Matthias Drochner. All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 * 58 */ 59 60 #include <sys/cdefs.h> 61 __KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.10 2021/07/21 06:35:45 skrll Exp $"); 62 63 #include <sys/param.h> 64 #include <sys/systm.h> /* for ostype */ 65 66 #include <dev/usb/usb.h> 67 #include <dev/usb/usbdi.h> 68 #include <dev/usb/usbdivar.h> 69 #include <dev/usb/usbroothub.h> 70 #include <dev/usb/usbhist.h> 71 72 extern int usbdebug; 73 74 /* helper functions for USB root hub emulation */ 75 76 static usbd_status roothub_ctrl_transfer(struct usbd_xfer *); 77 static usbd_status roothub_ctrl_start(struct usbd_xfer *); 78 static void roothub_ctrl_abort(struct usbd_xfer *); 79 static void roothub_ctrl_close(struct usbd_pipe *); 80 static void roothub_ctrl_done(struct usbd_xfer *); 81 static void roothub_noop(struct usbd_pipe *pipe); 82 83 const struct usbd_pipe_methods roothub_ctrl_methods = { 84 .upm_transfer = roothub_ctrl_transfer, 85 .upm_start = roothub_ctrl_start, 86 .upm_abort = roothub_ctrl_abort, 87 .upm_close = roothub_ctrl_close, 88 .upm_cleartoggle = roothub_noop, 89 .upm_done = roothub_ctrl_done, 90 }; 91 92 int 93 usb_makestrdesc(usb_string_descriptor_t *p, int l, const char *s) 94 { 95 int i; 96 97 if (l == 0) 98 return 0; 99 p->bLength = 2 * strlen(s) + 2; 100 if (l == 1) 101 return 1; 102 p->bDescriptorType = UDESC_STRING; 103 l -= 2; 104 /* poor man's utf-16le conversion */ 105 for (i = 0; s[i] && l > 1; i++, l -= 2) 106 USETW2(p->bString[i], 0, s[i]); 107 return 2 * i + 2; 108 } 109 110 int 111 usb_makelangtbl(usb_string_descriptor_t *p, int l) 112 { 113 114 if (l == 0) 115 return 0; 116 p->bLength = 4; 117 if (l == 1) 118 return 1; 119 p->bDescriptorType = UDESC_STRING; 120 if (l < 4) 121 return 2; 122 USETW(p->bString[0], 0x0409); /* english/US */ 123 return 4; 124 } 125 126 /* 127 * Data structures and routines to emulate the root hub. 128 */ 129 static const usb_device_descriptor_t usbroothub_devd1 = { 130 .bLength = sizeof(usb_device_descriptor_t), 131 .bDescriptorType = UDESC_DEVICE, 132 .bcdUSB = {0x00, 0x01}, 133 .bDeviceClass = UDCLASS_HUB, 134 .bDeviceSubClass = UDSUBCLASS_HUB, 135 .bDeviceProtocol = UDPROTO_FSHUB, 136 .bMaxPacketSize = 64, 137 .idVendor = {0}, 138 .idProduct = {0}, 139 .bcdDevice = {0x00, 0x01}, 140 .iManufacturer = 1, 141 .iProduct = 2, 142 .iSerialNumber = 0, 143 .bNumConfigurations = 1 144 }; 145 146 static const struct usb_roothub_descriptors usbroothub_confd1 = { 147 .urh_confd = { 148 .bLength = USB_CONFIG_DESCRIPTOR_SIZE, 149 .bDescriptorType = UDESC_CONFIG, 150 .wTotalLength = USETWD(sizeof(usbroothub_confd1)), 151 .bNumInterface = 1, 152 .bConfigurationValue = 1, 153 .iConfiguration = 0, 154 .bmAttributes = UC_ATTR_MBO | UC_SELF_POWERED, 155 .bMaxPower = 0, 156 }, 157 .urh_ifcd = { 158 .bLength = USB_INTERFACE_DESCRIPTOR_SIZE, 159 .bDescriptorType = UDESC_INTERFACE, 160 .bInterfaceNumber = 0, 161 .bAlternateSetting = 0, 162 .bNumEndpoints = 1, 163 .bInterfaceClass = UICLASS_HUB, 164 .bInterfaceSubClass = UISUBCLASS_HUB, 165 .bInterfaceProtocol = UIPROTO_FSHUB, 166 .iInterface = 0 167 }, 168 .urh_endpd = { 169 .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE, 170 .bDescriptorType = UDESC_ENDPOINT, 171 .bEndpointAddress = UE_DIR_IN | USBROOTHUB_INTR_ENDPT, 172 .bmAttributes = UE_INTERRUPT, 173 .wMaxPacketSize = USETWD(8), /* max packet */ 174 .bInterval = 255, 175 }, 176 }; 177 178 /* USB 3.0 10.15.1 */ 179 static const usb_device_descriptor_t usbroothub_devd3 = { 180 .bLength = sizeof(usb_device_descriptor_t), 181 .bDescriptorType = UDESC_DEVICE, 182 .bcdUSB = {0x00, 0x03}, 183 .bDeviceClass = UDCLASS_HUB, 184 .bDeviceSubClass = UDSUBCLASS_HUB, 185 .bDeviceProtocol = UDPROTO_SSHUB, 186 .bMaxPacketSize = 9, 187 .idVendor = {0}, 188 .idProduct = {0}, 189 .bcdDevice = {0x00, 0x01}, 190 .iManufacturer = 1, 191 .iProduct = 2, 192 .iSerialNumber = 0, 193 .bNumConfigurations = 1 194 }; 195 196 static const usb_device_descriptor_t usbroothub_devd2 = { 197 .bLength = sizeof(usb_device_descriptor_t), 198 .bDescriptorType = UDESC_DEVICE, 199 .bcdUSB = {0x00, 0x02}, 200 .bDeviceClass = UDCLASS_HUB, 201 .bDeviceSubClass = UDSUBCLASS_HUB, 202 .bDeviceProtocol = UDPROTO_HSHUBSTT, 203 .bMaxPacketSize = 64, 204 .idVendor = {0}, 205 .idProduct = {0}, 206 .bcdDevice = {0x00, 0x01}, 207 .iManufacturer = 1, 208 .iProduct = 2, 209 .iSerialNumber = 0, 210 .bNumConfigurations = 1 211 }; 212 213 static const usb_device_qualifier_t usbroothub_odevd2 = { 214 .bLength = USB_DEVICE_QUALIFIER_SIZE, 215 .bDescriptorType = UDESC_DEVICE_QUALIFIER, 216 .bcdUSB = {0x00, 0x02}, 217 .bDeviceClass = UDCLASS_HUB, 218 .bDeviceSubClass = UDSUBCLASS_HUB, 219 .bDeviceProtocol = UDPROTO_FSHUB, 220 .bMaxPacketSize0 = 64, 221 .bNumConfigurations = 1, 222 }; 223 224 static const struct usb_roothub_descriptors usbroothub_confd2 = { 225 .urh_confd = { 226 .bLength = USB_CONFIG_DESCRIPTOR_SIZE, 227 .bDescriptorType = UDESC_CONFIG, 228 .wTotalLength = USETWD(sizeof(usbroothub_confd2)), 229 .bNumInterface = 1, 230 .bConfigurationValue = 1, 231 .iConfiguration = 0, 232 .bmAttributes = UC_ATTR_MBO | UC_SELF_POWERED, 233 .bMaxPower = 0, 234 }, 235 .urh_ifcd = { 236 .bLength = USB_INTERFACE_DESCRIPTOR_SIZE, 237 .bDescriptorType = UDESC_INTERFACE, 238 .bInterfaceNumber = 0, 239 .bAlternateSetting = 0, 240 .bNumEndpoints = 1, 241 .bInterfaceClass = UICLASS_HUB, 242 .bInterfaceSubClass = UISUBCLASS_HUB, 243 .bInterfaceProtocol = UIPROTO_HSHUBSTT, 244 .iInterface = 0 245 }, 246 .urh_endpd = { 247 .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE, 248 .bDescriptorType = UDESC_ENDPOINT, 249 .bEndpointAddress = UE_DIR_IN | USBROOTHUB_INTR_ENDPT, 250 .bmAttributes = UE_INTERRUPT, 251 .wMaxPacketSize = USETWD(8), /* max packet */ 252 .bInterval = 12, 253 }, 254 }; 255 256 static const struct usb3_roothub_descriptors usbroothub_confd3 = { 257 .urh_confd = { 258 .bLength = USB_CONFIG_DESCRIPTOR_SIZE, 259 .bDescriptorType = UDESC_CONFIG, 260 .wTotalLength = USETWD(sizeof(usbroothub_confd3)), 261 .bNumInterface = 1, 262 .bConfigurationValue = 1, 263 .iConfiguration = 0, 264 .bmAttributes = UC_SELF_POWERED, /* 10.13.1 */ 265 .bMaxPower = 0, 266 }, 267 .urh_ifcd = { 268 .bLength = USB_INTERFACE_DESCRIPTOR_SIZE, 269 .bDescriptorType = UDESC_INTERFACE, 270 .bInterfaceNumber = 0, 271 .bAlternateSetting = 0, 272 .bNumEndpoints = 1, 273 .bInterfaceClass = UICLASS_HUB, 274 .bInterfaceSubClass = UISUBCLASS_HUB, 275 .bInterfaceProtocol = 0, /* UIPROTO_SSHUB ??? */ 276 .iInterface = 0 277 }, 278 .urh_endpd = { 279 .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE, 280 .bDescriptorType = UDESC_ENDPOINT, 281 .bEndpointAddress = UE_DIR_IN | USBROOTHUB_INTR_ENDPT, 282 .bmAttributes = UE_INTERRUPT, 283 .wMaxPacketSize = USETWD(2), /* max packet */ 284 .bInterval = 8, 285 }, 286 .urh_endpssd = { 287 .bLength = USB_ENDPOINT_SS_COMP_DESCRIPTOR_SIZE, 288 .bDescriptorType = UDESC_ENDPOINT_SS_COMP, 289 .bMaxBurst = 0, 290 .bmAttributes = 0, 291 .wBytesPerInterval = USETWD(2) 292 }, 293 }; 294 295 static const struct usb3_roothub_bos_descriptors usbroothub_bosd3 = { 296 .urh_bosd = { 297 .bLength = USB_BOS_DESCRIPTOR_SIZE, 298 .bDescriptorType = UDESC_BOS, 299 .wTotalLength = USETWD(sizeof(usbroothub_bosd3)), 300 .bNumDeviceCaps = 3, 301 }, 302 /* 9.6.2.1 USB 2.0 Extension */ 303 .urh_usb2extd = { 304 .bLength = USB_DEVCAP_USB2EXT_DESCRIPTOR_SIZE, 305 .bDescriptorType = 1, 306 .bDevCapabilityType = 2, 307 .bmAttributes[0] = 2, 308 }, 309 /* 9.6.2.2 Superspeed device capability */ 310 .urh_ssd = { 311 .bLength = USB_DEVCAP_SS_DESCRIPTOR_SIZE, 312 .bDescriptorType = UDESC_DEVICE_CAPABILITY, 313 .bDevCapabilityType = USB_DEVCAP_SUPER_SPEED, 314 .bmAttributes = 0, /* USB_DEVCAP_SS_LTM */ 315 .wSpeedsSupported = USETWD( 316 USB_DEVCAP_SS_SPEED_LS | USB_DEVCAP_SS_SPEED_FS | 317 USB_DEVCAP_SS_SPEED_HS | USB_DEVCAP_SS_SPEED_SS), 318 .bFunctionalitySupport = 8, /* SS is 3, i.e. 1 << 3? */ 319 .bU1DevExitLat = 255, /* Dummy... 0? */ 320 .wU2DevExitLat = USETWD(8), /* Also dummy... 0? */ 321 }, 322 /* 9.6.2.3 Container ID - see RFC 4122 */ 323 .urh_containerd = { 324 .bLength = USB_DEVCAP_CONTAINER_ID_DESCRIPTOR_SIZE, 325 .bDescriptorType = 1, 326 .bDevCapabilityType = 4, 327 .bReserved = 0, 328 // ContainerID will be zero 329 }, 330 }; 331 332 static const usb_hub_descriptor_t usbroothub_hubd = { 333 .bDescLength = USB_HUB_DESCRIPTOR_SIZE, 334 .bDescriptorType = UDESC_HUB, 335 .bNbrPorts = 1, 336 .wHubCharacteristics = USETWD(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL), 337 .bPwrOn2PwrGood = 50, 338 .bHubContrCurrent = 0, 339 .DeviceRemovable = {0}, /* port is removable */ 340 }; 341 342 /* 343 * Simulate a hardware hub by handling all the necessary requests. 344 */ 345 usbd_status 346 roothub_ctrl_transfer(struct usbd_xfer *xfer) 347 { 348 struct usbd_pipe *pipe = xfer->ux_pipe; 349 struct usbd_bus *bus = pipe->up_dev->ud_bus; 350 usbd_status err; 351 352 /* Insert last in queue. */ 353 mutex_enter(bus->ub_lock); 354 err = usb_insert_transfer(xfer); 355 mutex_exit(bus->ub_lock); 356 if (err) 357 return err; 358 359 /* Pipe isn't running, start first */ 360 return roothub_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); 361 } 362 363 static usbd_status 364 roothub_ctrl_start(struct usbd_xfer *xfer) 365 { 366 struct usbd_pipe *pipe = xfer->ux_pipe; 367 struct usbd_bus *bus = pipe->up_dev->ud_bus; 368 usb_device_request_t *req; 369 usbd_status err = USBD_IOERROR; /* XXX STALL? */ 370 uint16_t len, value; 371 int buflen, actlen = -1; 372 void *buf; 373 374 USBHIST_FUNC(); 375 376 KASSERT(xfer->ux_rqflags & URQ_REQUEST); 377 req = &xfer->ux_request; 378 379 len = UGETW(req->wLength); 380 value = UGETW(req->wValue); 381 382 USBHIST_CALLARGS(usbdebug, "type=%#jx request=%#jx len=%#jx value=%#jx", 383 req->bmRequestType, req->bRequest, len, value); 384 385 buf = len ? usbd_get_buffer(xfer) : NULL; 386 buflen = 0; 387 388 #define C(x,y) ((x) | ((y) << 8)) 389 switch (C(req->bRequest, req->bmRequestType)) { 390 case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): 391 case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): 392 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): 393 /* 394 * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops 395 * for the integrated root hub. 396 */ 397 break; 398 case C(UR_GET_CONFIG, UT_READ_DEVICE): 399 if (len > 0) { 400 uint8_t *out = buf; 401 402 *out = bus->ub_rhconf; 403 buflen = sizeof(*out); 404 } 405 break; 406 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): 407 USBHIST_LOG(usbdebug, "wValue=%#4jx", value, 0, 0, 0); 408 409 if (len == 0) 410 break; 411 switch (value) { 412 case C(0, UDESC_DEVICE): 413 if (bus->ub_revision >= USBREV_3_0) { 414 buflen = uimin(len, sizeof(usbroothub_devd3)); 415 memcpy(buf, &usbroothub_devd3, buflen); 416 } else if (bus->ub_revision == USBREV_2_0) { 417 buflen = uimin(len, sizeof(usbroothub_devd2)); 418 memcpy(buf, &usbroothub_devd2, buflen); 419 } else { 420 buflen = uimin(len, sizeof(usbroothub_devd1)); 421 memcpy(buf, &usbroothub_devd1, buflen); 422 } 423 break; 424 case C(0, UDESC_CONFIG): 425 if (bus->ub_revision >= USBREV_3_0) { 426 buflen = uimin(len, sizeof(usbroothub_confd3)); 427 memcpy(buf, &usbroothub_confd3, buflen); 428 } else if (bus->ub_revision == USBREV_2_0) { 429 buflen = uimin(len, sizeof(usbroothub_confd2)); 430 memcpy(buf, &usbroothub_confd2, buflen); 431 } else { 432 buflen = uimin(len, sizeof(usbroothub_confd1)); 433 memcpy(buf, &usbroothub_confd1, buflen); 434 } 435 break; 436 case C(0, UDESC_DEVICE_QUALIFIER): 437 if (bus->ub_revision == USBREV_2_0) { 438 /* 439 * We can't really operate at another speed, 440 * but the spec says we need this descriptor. 441 */ 442 buflen = uimin(len, sizeof(usbroothub_odevd2)); 443 memcpy(buf, &usbroothub_odevd2, buflen); 444 } else 445 goto fail; 446 break; 447 case C(0, UDESC_OTHER_SPEED_CONFIGURATION): 448 if (bus->ub_revision == USBREV_2_0) { 449 struct usb_roothub_descriptors confd; 450 451 /* 452 * We can't really operate at another speed, 453 * but the spec says we need this descriptor. 454 */ 455 buflen = uimin(len, sizeof(usbroothub_confd2)); 456 memcpy(&confd, &usbroothub_confd2, buflen); 457 confd.urh_confd.bDescriptorType = 458 UDESC_OTHER_SPEED_CONFIGURATION; 459 memcpy(buf, &confd, buflen); 460 } else 461 goto fail; 462 break; 463 case C(0, UDESC_BOS): 464 if (bus->ub_revision >= USBREV_3_0) { 465 buflen = uimin(len, sizeof(usbroothub_bosd3)); 466 memcpy(buf, &usbroothub_bosd3, buflen); 467 } else 468 goto fail; 469 break; 470 #define sd ((usb_string_descriptor_t *)buf) 471 case C(0, UDESC_STRING): 472 /* Language table */ 473 buflen = usb_makelangtbl(sd, len); 474 break; 475 case C(1, UDESC_STRING): 476 /* Vendor */ 477 buflen = usb_makestrdesc(sd, len, ostype); 478 break; 479 case C(2, UDESC_STRING): 480 /* Product */ 481 buflen = usb_makestrdesc(sd, len, "Root hub"); 482 break; 483 #undef sd 484 default: 485 /* Default to error */ 486 buflen = -1; 487 } 488 break; 489 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): 490 buflen = uimin(len, sizeof(usbroothub_hubd)); 491 memcpy(buf, &usbroothub_hubd, buflen); 492 break; 493 case C(UR_GET_INTERFACE, UT_READ_INTERFACE): 494 /* Get Interface, 9.4.4 */ 495 if (len > 0) { 496 uint8_t *out = buf; 497 498 *out = 0; 499 buflen = sizeof(*out); 500 } 501 break; 502 case C(UR_GET_STATUS, UT_READ_DEVICE): 503 /* Get Status from device, 9.4.5 */ 504 if (len > 1) { 505 usb_status_t *out = buf; 506 507 USETW(out->wStatus, UDS_SELF_POWERED); 508 buflen = sizeof(*out); 509 } 510 break; 511 case C(UR_GET_STATUS, UT_READ_INTERFACE): 512 case C(UR_GET_STATUS, UT_READ_ENDPOINT): 513 /* Get Status from interface, endpoint, 9.4.5 */ 514 if (len > 1) { 515 usb_status_t *out = buf; 516 517 USETW(out->wStatus, 0); 518 buflen = sizeof(*out); 519 } 520 break; 521 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): 522 /* Set Address, 9.4.6 */ 523 USBHIST_LOG(usbdebug, "UR_SET_ADDRESS, UT_WRITE_DEVICE: " 524 "addr %jd", value, 0, 0, 0); 525 if (value >= USB_MAX_DEVICES) { 526 goto fail; 527 } 528 bus->ub_rhaddr = value; 529 break; 530 case C(UR_SET_CONFIG, UT_WRITE_DEVICE): 531 /* Set Configuration, 9.4.7 */ 532 if (value != 0 && value != 1) { 533 goto fail; 534 } 535 bus->ub_rhconf = value; 536 break; 537 case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): 538 /* Set Descriptor, 9.4.8, not supported */ 539 break; 540 case C(UR_SET_FEATURE, UT_WRITE_DEVICE): 541 case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): 542 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): 543 /* Set Feature, 9.4.9, not supported */ 544 goto fail; 545 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): 546 /* Set Interface, 9.4.10, not supported */ 547 break; 548 case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): 549 /* Synch Frame, 9.4.11, not supported */ 550 break; 551 default: 552 /* Default to error */ 553 buflen = -1; 554 break; 555 } 556 557 actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen); 558 if (actlen < 0) 559 goto fail; 560 561 xfer->ux_actlen = actlen; 562 err = USBD_NORMAL_COMPLETION; 563 564 fail: 565 USBHIST_LOG(usbdebug, "xfer %#jx buflen %jd actlen %jd err %jd", 566 (uintptr_t)xfer, buflen, actlen, err); 567 568 xfer->ux_status = err; 569 mutex_enter(bus->ub_lock); 570 usb_transfer_complete(xfer); 571 mutex_exit(bus->ub_lock); 572 573 return USBD_NORMAL_COMPLETION; 574 } 575 576 /* Abort a root control request. */ 577 Static void 578 roothub_ctrl_abort(struct usbd_xfer *xfer) 579 { 580 581 /* Nothing to do, all transfers are synchronous. */ 582 } 583 584 /* Close the root pipe. */ 585 Static void 586 roothub_ctrl_close(struct usbd_pipe *pipe) 587 { 588 589 /* Nothing to do. */ 590 } 591 592 Static void 593 roothub_ctrl_done(struct usbd_xfer *xfer) 594 { 595 596 /* Nothing to do. */ 597 } 598 599 static void 600 roothub_noop(struct usbd_pipe *pipe) 601 { 602 603 } 604