1/* 2 * Copyright (c) 2007-2013 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10/* 11 * Copyright (c) 2007-2013 ETH Zurich. 12 * All rights reserved. 13 * 14 * This file is distributed under the terms in the attached LICENSE file. 15 * If you do not find this file, copies can be found by writing to: 16 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 17 */ 18 19#include <stdlib.h> 20#include <stdio.h> 21#include <barrelfish/barrelfish.h> 22 23#include <usb/usb.h> 24#include <usb/usb_descriptor.h> 25 26#include <usb_controller.h> 27#include <usb_hub.h> 28#include <usb_device.h> 29#include <usb_transfer.h> 30#include <usb_driver.h> 31 32static void usb_hub_intr_cb(struct usb_xfer *xfer, usb_error_t err); 33 34static const struct usb_xfer_config hub_config[USB_HUB_NUM_TRANSFERS] = { 35 [0] = { 36 .type = USB_ENDPOINT_TYPE_INTR, 37 .direction = USB_ENDPOINT_DIRECTION_ANY, 38 .endpoint = USB_ENDPOINT_ADDRESS_ANY, 39 .timeout = 0, 40 .flags = { 41 .short_xfer_ok = 1, 42 .pipe_on_falure = 1, 43 }, 44 .bufsize = 0, 45 .interval = USB_HUB_INTR_INTERVAL, 46 .usb_type = USB_TYPE_INTR, 47 .xfer_done_cb = &usb_hub_intr_cb 48 }, 49}; 50 51static uint8_t usb_hub_xplore_done = 1; 52 53static void usb_hub_intr_cb(struct usb_xfer *xfer, usb_error_t err) 54{ 55 if (err != USB_ERR_OK) { 56 USB_DEBUG("WARNING: hub intr transfer failed...\n"); 57 usb_transfer_start(xfer); 58 } 59 60 if (usb_hub_xplore_done) { 61 usb_hub_explore((xfer->device)); 62 } 63 usb_transfer_start(xfer); 64} 65 66struct usb_device *usb_hub_get_device(struct usb_hub *hub, 67 struct usb_hub_port *port) 68{ 69 return (hub->device->controller->devices[port->device_index]); 70} 71 72/** 73 * \brief checks if the hub device lies within an acceptable depdth, such that 74 * the attached USB devices have a specification conform depth 75 * 76 * \param device: device we want to check 77 * 78 * \return 0: the depth of the device in the tree lies withing the range 79 * 1: the depth of the device is too deep 80 */ 81static uint8_t usb_hub_too_deep(struct usb_device *device) 82{ 83 switch (device->speed) { 84 case USB_SPEED_FULL: 85 case USB_SPEED_LOW: 86 case USB_SPEED_HIGH: 87 /* revision 2.0 */ 88 if (device->depth > USB_HUB_MAX_DEPTH) { 89 return (1); 90 } 91 break; 92 case USB_SPEED_SUPER: 93 /* revision 3.0 */ 94 assert(!"Super Speed not supported"); 95 break; 96 default: 97 break; 98 } 99 return (0); 100} 101 102/** 103 * \brief this function reattaches the device on this port and reads out the 104 * device information and does the basic initialization such as 105 * assigning an address 106 * 107 * \param hub the hub to attach the device 108 * \param portno the number of the port to attach the device 109 * 110 * \return USB_ERR_OK on success 111 * USB_ERR_XX on failure 112 */ 113static usb_error_t usb_hub_reattach_port(struct usb_hub *hub, uint8_t portno) 114{ 115 USB_DEBUG_TR_ENTER; 116 usb_error_t err = USB_ERR_OK; 117 uint8_t timeout = 0; 118 119 struct usb_device *child = usb_hub_get_device(hub, 120 hub->ports + (portno - 1)); 121 struct usb_hub_port_status ps; 122 while (1) { 123 124 err = usb_hub_clear_port_feature(hub->device, 125 USB_HUB_FEATURE_C_PORT_CONNECTION, portno); 126 if (err) { 127 break; 128 } 129 130 err = usb_hub_get_port_status(hub->device, portno, &ps); 131 if (err) { 132 USB_DEBUG("ERROR: could not get port status. Port=%u", portno); 133 break; 134 } 135 136 if (!ps.wPortStatus.connection) { 137 debug_printf("Device detached from [Hub: %u, Port: %u].\n", 138 hub->device->device_address, portno); 139 if (child != NULL) { 140 /* free up the device to restart fresh */ 141 usb_device_free(child, 0); 142 child = NULL; 143 } 144 break; 145 } 146 147 /* check for the power on the port */ 148 if (!ps.wPortStatus.power_state) { 149 USB_DEBUG("WARNING: Connected port %u has no power!\n", portno); 150 } 151 152 if (!ps.wPortStatus.device_mode) { 153 if (ps.wPortStatus.suspend) { 154 USB_DEBUG("Port %u is suspended. Wake up.\n", portno); 155 err = usb_hub_clear_port_feature(hub->device, 156 USB_HUB_FEATURE_PORT_SUSPEND, portno); 157 lib_usb_wait(USB_DELAY_PORT_POWERUP); 158 } 159 160 err = usb_hub_reset_port(hub->device, portno); 161 if (err != USB_ERR_OK) { 162 USB_DEBUG("WARNING: port reset failed.\n"); 163 break; 164 } 165 166 err = usb_hub_get_port_status(hub->device, portno, &ps); 167 if (err != USB_ERR_OK) { 168 USB_DEBUG("ERROR: Could not read port status (%u)\n", portno); 169 break; 170 } 171 172 if (ps.wPortChange.connect || !ps.wPortStatus.connection) { 173 if (timeout) { 174 USB_DEBUG("WARTNING: timed out. " 175 "Giving up port reset...\n"); 176 break; 177 } 178 timeout = 1; 179 continue; 180 } 181 } 182 183 /* 184 * figuring out the device speed, this depends on the hub speed 185 * and the port status fields 186 */ 187 usb_speed_t speed = hub->device->speed; 188 switch (hub->device->speed) { 189 case USB_SPEED_HIGH: 190 if (ps.wPortStatus.is_hs) { 191 speed = USB_SPEED_HIGH; 192 USB_DEBUG_DEV("device speed is HS -> HIGH SPEED\n"); 193 } else if (ps.wPortStatus.is_ls) { 194 USB_DEBUG_DEV("device speed is HS -> LOW SPEED\n"); 195 speed = USB_SPEED_LOW; 196 } else { 197 USB_DEBUG_DEV("device speed is HS -> FULL SPEED\n"); 198 speed = USB_SPEED_FULL; 199 } 200 break; 201 202 case USB_SPEED_FULL: 203 if (ps.wPortStatus.is_ls) { 204 speed = USB_SPEED_LOW; 205 USB_DEBUG_DEV("device speed is FS -> LOW SPEED\n"); 206 } else { 207 speed = USB_SPEED_FULL; 208 USB_DEBUG_DEV("device speed is FS -> FULL SPEED\n"); 209 } 210 break; 211 case USB_SPEED_LOW: 212 USB_DEBUG_DEV("device speed is LS -> LOW SPEED\n"); 213 speed = USB_SPEED_LOW; 214 break; 215 case USB_SPEED_SUPER: 216 assert(!"NYI: SUPER SPEED DEVICES"); 217 break; 218 default: 219 /* same speed as parent */ 220 break; 221 } 222 223 if (speed == USB_SPEED_SUPER) { 224 /* here goes some special handling for super speeds */ 225 assert(!"NYI: super speed timeout handling\n"); 226 } 227 228 usb_mode_t mode = USB_MODE_HOST; 229 if (ps.wPortStatus.device_mode) { 230 USB_DEBUG_DEV("new device in DEVICE_MODE\n"); 231 mode = USB_MODE_DEVICE; 232 } 233 debug_printf("New device attached on [Hub: %u, Port: %u]\n", 234 hub->device->device_address, portno); 235 child = usb_device_alloc(hub->device->controller, hub->device, 236 hub->device->depth + 1, portno - 1, portno, speed, mode); 237 if (child == NULL) { 238 USB_DEBUG("ERROR: Could not allocate a new device!\n"); 239 return (USB_ERR_NOMEM); 240 } 241 242 usb_driver_start(child); 243 244 return (USB_ERR_OK); 245 } 246 247 if (child != NULL) { 248 usb_device_free(child, 0); 249 child = NULL; 250 } 251 252 if (err == USB_ERR_OK) { 253 if (ps.wPortStatus.enabled) { 254 err = usb_hub_clear_port_feature(hub->device, 255 USB_HUB_FEATURE_PORT_ENABLE, portno); 256 } 257 } 258 if (err) { 259 USB_DEBUG("WARNING: Device problem, disabling port\n"); 260 } 261 return (err); 262} 263 264static usb_error_t usb_hub_suspend_resume_port(struct usb_hub *hub, 265 uint8_t portno) 266{ 267 assert(!"NYI: don't support suspend / resume at the moment.\n"); 268 return (USB_ERR_OK); 269} 270 271/** 272 * \brief initializes a new USB hub device and checks for attached devices 273 * 274 * \param hub_device the USB device which is a hub 275 * 276 * \return USB_ERR_OK on success 277 * USB_ERR_XX on failure 278 */ 279usb_error_t usb_hub_init(struct usb_device *hub_device) 280{ 281 USB_DEBUG_TR_ENTER; 282 283 struct usb_device *parent_hub = hub_device->parent_hub; 284 usb_error_t err; 285 286 USB_DEBUG_DEV("initializing hub device...\n"); 287 288 /* check if the hub has an appropriate depth */ 289 if (usb_hub_too_deep(hub_device)) { 290 USB_DEBUG("Hub is too deep!. Ignored. \n"); 291 /* TODO: err */ 292 return (USB_ERR_TOO_DEEP); 293 } 294 295 if (!(hub_device->flags.self_powered) && parent_hub 296 && (!parent_hub->flags.self_powered)) { 297 /* 298 * note: bus powered hubs cannot be connected to other 299 * bus powered hubs. 300 */ 301 USB_DEBUG("WARNING: insufficient power.\n"); 302 /* TODO: ERR */ 303 return (USB_ERR_INVAL); 304 } 305 306 struct usb_hub_descriptor desc; 307 308 uint8_t nports = 0; 309 uint16_t powerdelay = 0; 310 311 switch (hub_device->speed) { 312 case USB_SPEED_LOW: 313 case USB_SPEED_FULL: 314 case USB_SPEED_HIGH: 315 err = usb_hub_get_hub_descriptor(hub_device, 1, &desc); 316 if (err != USB_ERR_OK) { 317 USB_DEBUG("ERROR: could not get hub descriptor \n"); 318 return (err); 319 } 320 /* get the number of ports */ 321 nports = desc.bNbrPorts; 322 323 if (nports > 127) { 324 USB_DEBUG("WARNING: invalid port count\n"); 325 return (USB_ERR_INVAL); 326 } 327 328 /* get the power delay */ 329 powerdelay = USB_HUB_POWER_ON_DELAY(&desc); 330 331 /* 332 * we just got the first byte of data for the ports, so we 333 * have to get more data if the port count is bigger than 334 * the first byte i.e. 8 335 */ 336 if (nports >= 8) { 337 err = usb_hub_get_hub_descriptor(hub_device, nports, &desc); 338 339 if (err != USB_ERR_OK) { 340 debug_printf("ERROR: could not get hub descriptor \n"); 341 return (err); 342 } 343 344 if (desc.bNbrPorts != nports) { 345 debug_printf("ERROR: Volatile port count?? \n"); 346 return (USB_ERR_INVAL); 347 } 348 } 349 break; 350 351 case USB_SPEED_SUPER: 352 assert(!"NYI: super speed not supported\n"); 353 break; 354 default: 355 debug_printf("ERROR: Invalid device speed!\n"); 356 return (USB_ERR_INVAL); 357 break; 358 } 359 360 USB_DEBUG_DEV("Found hub device: Num ports = %u\n", desc.bNbrPorts); 361 362 if (nports == 0) { 363 debug_printf("ERROR: hub has no ports\n"); 364 return (USB_ERR_IOERROR); 365 /* TODO: ERROR */ 366 } 367 368 struct usb_hub *hub = malloc( 369 sizeof(struct usb_hub) + (sizeof(usb_hub_port_t) * nports)); 370 371 if (hub == NULL) { 372 debug_printf("ERROR: Could not allocate memory for hub struct\n"); 373 return (USB_ERR_NOMEM); 374 } 375 376 /* do the binding */ 377 hub_device->hub = hub; 378 hub->device = hub_device; 379 380 hub->num_ports = nports; 381 382 if (hub_device->flags.self_powered) { 383 hub->portpower = USB_POWER_MAX; 384 } else { 385 hub->portpower = USB_POWER_MIN; 386 } 387 388 /* setup the interrupt pipe */ 389 if (USB_DEVICE_IS_ROOTHUB(hub_device)) { 390 /* 391 * the root hub is special, it needs no interrupt transfer 392 */ 393 USB_DEBUG_DEV("device was the root hub \n"); 394 err = USB_ERR_OK; 395 } else { 396 USB_DEBUG_DEV("device was an attached hub \n"); 397 err = usb_transfer_setup(hub_device, 0, &hub->xfers[0], hub_config); 398 } 399 if (err != USB_ERR_OK) { 400 debug_printf("Could not setup the interrupt transfer\n"); 401 free(hub); 402 return (err); 403 } 404 405 lib_usb_wait(USB_DELAY_PORT_POWERUP); 406 407 uint8_t portno = 0; 408 uint8_t removable = 0; 409 410 /* enumerate the devices and setup the data structures */ 411 for (uint8_t portindex = 0; portindex < nports; portindex++) { 412 struct usb_hub_port *port = hub->ports + portindex; 413 414 port->device_index = 0; 415 port->restarts = 0; 416 417 /* the port number (1 based) is the port index (0 based) + 1 */ 418 portno = portindex + 1; 419 420 switch (hub_device->speed) { 421 case USB_SPEED_LOW: 422 case USB_SPEED_FULL: 423 case USB_SPEED_HIGH: 424 if (USB_HUB_DEVICE_REMOVABLE(&desc, portno)) { 425 removable++; 426 } 427 break; 428 case USB_SPEED_SUPER: 429 assert(!"NYI: super speed\n"); 430 break; 431 default: 432 debug_printf("WARNING: unknown speed, " 433 "assuming device removable\n"); 434 removable++; 435 break; 436 } 437 438 if (err == USB_ERR_OK) { 439 /* all fine we can turn on the power on that port */ 440 err = usb_hub_set_port_feature(hub_device, 441 USB_HUB_FEATURE_PORT_POWER, portno); 442 } 443 444 if (err != USB_ERR_OK) { 445 debug_printf("WARNING: could not power on the port\n"); 446 } 447 448 /* wait for powerdelay ms till the power power is good */ 449 lib_usb_wait(powerdelay); 450 } 451 452 /* start the interrupt transfer */ 453 if (hub->xfers[0] != NULL) { 454 USB_DEBUG_DEV("starting hub interrupt transfer\n"); 455 usb_transfer_start(hub->xfers[0]); 456 } 457 458 return (USB_ERR_OK); 459} 460 461/** 462 * \brief this function is called upon removal of the USB hub device. 463 * All the child devices need to be removed 464 * 465 * \brief hub_device the USB device (hub) which is removed 466 * 467 * \return USB_ERR_OK on success 468 * USB_ERR_XX on failure 469 */ 470usb_error_t usb_hub_deinit(struct usb_device *hub_device) 471{ 472 return (USB_ERR_OK); 473} 474 475/** 476 * \brief this function is called when a port hub change event is detected. 477 * all the ports are explored and the devices are identified 478 * 479 * \param usb_device the hub to explore 480 * 481 * \return USB_ERR_OK on success 482 * USB_ERR_XX on failure 483 */ 484usb_error_t usb_hub_explore(struct usb_device *hub_device) 485{ 486 usb_error_t err; 487 488 struct usb_hub *hub = hub_device->hub; 489 490 usb_hub_xplore_done = 0; 491 492 if (hub == NULL) { 493 USB_DEBUG("ERROR: hub_explore() - bad context.\n"); 494 return (USB_ERR_BAD_CONTEXT); 495 } 496 497 /* 498 * if the USB hub is too deep in the USB device tree, then the attached 499 * USB devices have a depth which would not be USB specification conform, 500 * so if this is the case, skip the exploration process at this stage. 501 */ 502 if (usb_hub_too_deep(hub_device)) { 503 USB_DEBUG("WARNING: hub_explore() - too deep.\n"); 504 return (USB_ERR_TOO_DEEP); 505 } 506 507 /* start exploring the ports by loop over the ports */ 508 509 usb_hub_port_t *port = NULL; 510 uint8_t portno = 0; 511 struct usb_hub_port_status ps; 512 513 USB_DEBUG_DEV( 514 "exploring ports of hub [%03u]...\n", hub_device->device_address); 515 516 for (uint32_t i = 0; i < hub->num_ports; i++) { 517 port = hub->ports + i; 518 portno = i + 1; 519 520 err = usb_hub_get_port_status(hub->device, portno, &ps); 521 if (err != USB_ERR_OK) { 522 USB_DEBUG( 523 "WARNING: Could not read port status. Hub gone?%s\n", usb_get_error_string(err)); 524 break; 525 } 526 527 /* check if we have a port over current condition */ 528 if (ps.wPortChange.over_current) { 529 USB_DEBUG_DEV( 530 "NOTICE: Over current condition on port %u.\n", portno); 531 err = usb_hub_clear_port_feature(hub->device, 532 USB_HUB_FEATURE_C_PORT_OVER_CURRENT, portno); 533 if (err != USB_ERR_OK) { 534 USB_DEBUG( 535 "WARNING: Could not clear port feature. Hub gone?\n"); 536 break; 537 } 538 } 539 540 /* 541 * check if the port got disabled, this indicates an error condition 542 * on the port 543 */ 544 if (ps.wPortChange.disabled) { 545 USB_DEBUG_DEV("WARNING: Port %i got disabled.\n", i); 546 err = usb_hub_clear_port_feature(hub->device, 547 USB_HUB_FEATURE_C_PORT_ENABLE, portno); 548 if (err != USB_ERR_OK) { 549 debug_printf( 550 "WARNING: Could not clear port feature. Hub gone?\n"); 551 break; 552 } 553 554 if (ps.wPortChange.connect) { 555 USB_DEBUG_DEV("NOTICE: Device on ort %u is gone.\n", i); 556 /* the device is gone, ignore the port error */ 557 558 } else if (ps.wPortStatus.enabled) { 559 USB_DEBUG( 560 "WARNING: illegal enable change on port %u\n", portno); 561 } else { 562 if (port->restarts == USB_HUB_MAX_RESTARTS) { 563 USB_DEBUG("WARNING: too many restarts on port %"PRIu32".\n ", i); 564 } else { 565 ps.wPortChange.connect = 1; 566 port->restarts++; 567 } 568 } 569 } 570 571 if (ps.wPortChange.connect) { 572 err = usb_hub_reattach_port(hub, portno); 573 if (err != USB_ERR_OK) { 574 debug_printf("WARNING: Could not reattach port. Hub gone?\n"); 575 break; 576 } 577 } 578 579 if (ps.wPortChange.resumed || ps.wPortChange.linkstate) { 580 USB_DEBUG_DEV("NOTICE: suspend/resume device on port %i.\n", i); 581 err = usb_hub_suspend_resume_port(hub, portno); 582 if (err != USB_ERR_OK) { 583 debug_printf("WARNING: Could not resume the port. Hub gone?\n"); 584 break; 585 } 586 } 587 588 struct usb_host_controller *hc = hub_device->controller; 589 struct usb_device *child = hc->devices[port->device_index]; 590 591 if (child != NULL && child->hub != NULL) { 592 USB_DEBUG_DEV("Device on port %u is a hub. Exploring...\n", portno); 593 err = usb_hub_explore(child); 594 usb_hub_xplore_done = 0; 595 } 596 597 if (err != USB_ERR_OK) { 598 /* no device is present, just continue */ 599 continue; 600 } 601 602 port->restarts = 0; 603 604 } 605 606 usb_hub_xplore_done = 1; 607 608 return (USB_ERR_OK); 609} 610 611static uint8_t usb_hub_find_slot(uint16_t *ptr, uint8_t start, uint8_t end, 612 uint8_t mask) 613{ 614 uint16_t min = (uint16_t)-1; 615 uint8_t slot = 0; 616 for (uint8_t cs = start; cs < end; cs++) { 617 uint16_t sum = 0; 618 619 for (uint8_t bw = cs; bw < end; bw++) { 620 if (mask & (1U << (bw - cs))) { 621 sum += ptr[bw]; 622 } 623 } 624 625 if (min >= sum) { 626 min = sum; 627 slot = cs; 628 } 629 630 if (mask & (1U << (end - 1 - cs))) { 631 break; 632 } 633 } 634 return (slot); 635} 636 637uint8_t usb_hub_bandwidth_adjust(struct usb_device *dev, uint16_t length, 638 uint8_t slot, uint8_t mask) 639{ 640 struct usb_host_controller *hc = dev->controller; 641 struct usb_hub *hub = dev->parent_hs_hub->hub; 642 assert(hub != NULL); 643 644 switch (dev->speed) { 645 case USB_SPEED_LOW: 646 case USB_SPEED_FULL: 647 if (dev->speed == USB_SPEED_LOW) { 648 length *= 8; 649 } 650 assert(dev->parent_hs_hub != NULL); 651 652 if (slot >= 8) { 653 slot = usb_hub_find_slot(hub->uframe_usage, 4, 6, mask); 654 } 655 656 for (uint32_t cs = slot; cs < 8; cs++) { 657 if (mask & (1U << (cs - slot))) { 658 hub->uframe_usage[cs] += length; 659 hc->uframe_usage[cs] += length; 660 } 661 } 662 break; 663 default: 664 if (slot >= 8) { 665 slot = usb_hub_find_slot(hub->uframe_usage, 8, 6, mask); 666 } 667 for (uint32_t cs = slot; cs < 8; cs++) { 668 if (mask & (1U << (cs - slot))) { 669 hc->uframe_usage[cs] += length; 670 } 671 } 672 break; 673 } 674 return (slot); 675} 676 677void usb_hub_bandwidth_alloc(struct usb_xfer *xfer) 678{ 679 struct usb_device *dev = xfer->device; 680 681 xfer->endpoint->ref_bandwidth++; 682 if (xfer->endpoint->ref_bandwidth != 1) { 683 /* the bandwidth for this transfer is already allocated... */ 684 return; 685 } 686 687 uint8_t slot, mask; 688 689 switch (xfer->type) { 690 case USB_TYPE_INTR: 691 mask = 0x01; 692 slot = usb_hub_bandwidth_adjust(dev, xfer->max_frame_size, 8, mask); 693 xfer->endpoint->hs_uframe = slot; 694 xfer->endpoint->hs_smask = mask << slot; 695 696 switch (xfer->device->speed) { 697 case USB_SPEED_LOW: 698 case USB_SPEED_FULL: 699 xfer->endpoint->hs_cmask = (-(0x04 << slot)) & 0xFE; 700 break; 701 default: 702 xfer->endpoint->hs_cmask = 0x00; 703 break; 704 } 705 706 break; 707 case USB_TYPE_ISOC: 708 switch (xfer->frame_shift) { 709 case 0: 710 mask = 0xFF; 711 break; 712 case 1: 713 mask = 0x55; 714 break; 715 case 2: 716 mask = 0x11; 717 break; 718 default: 719 mask = 0x01; 720 break; 721 722 } 723 slot = usb_hub_bandwidth_adjust(dev, xfer->max_frame_size, 8, mask); 724 xfer->endpoint->hs_uframe = slot; 725 xfer->endpoint->hs_smask = mask << slot; 726 xfer->endpoint->hs_cmask = 0; 727 break; 728 default: 729 xfer->endpoint->hs_uframe = 0; 730 xfer->endpoint->hs_smask = 0; 731 xfer->endpoint->hs_cmask = 0; 732 break; 733 } 734} 735 736void usb_hub_bandwidth_free(struct usb_xfer *xfer) 737{ 738 739 struct usb_device *dev; 740 uint8_t slot; 741 uint8_t mask; 742 743 dev = xfer->device; 744 745 xfer->endpoint->ref_bandwidth--; 746 if (xfer->endpoint->ref_bandwidth != 0) { 747 /* the allocated bandwidth is still needed.. */ 748 return; 749 } 750 751 switch (xfer->type) { 752 case USB_TYPE_INTR: 753 case USB_TYPE_ISOC: 754 755 slot = xfer->endpoint->hs_uframe; 756 mask = xfer->endpoint->hs_smask; 757 758 759 usb_hub_bandwidth_adjust(dev, -(xfer->max_frame_size), slot, 760 mask >> slot); 761 762 xfer->endpoint->hs_uframe = 0; 763 xfer->endpoint->hs_cmask = 0; 764 xfer->endpoint->hs_smask = 0; 765 break; 766 767 default: 768 break; 769 } 770} 771 772/** 773 * 774 */ 775usb_error_t usb_hub_query_info(struct usb_hub *hub, uint8_t *ret_nports, 776 uint8_t *ret_tt) 777{ 778 struct usb_hub_descriptor desc; 779 usb_error_t err = USB_ERR_OK; 780 781 uint8_t nports = 0; 782 uint8_t tt = 0; 783 784 switch (hub->device->speed) { 785 case USB_SPEED_LOW: 786 case USB_SPEED_HIGH: 787 case USB_SPEED_FULL: 788 err = usb_hub_get_hub_descriptor(hub->device, 1, &desc); 789 if (err) { 790 debug_printf("ERROR: Failed to get hub descriptor\n"); 791 break; 792 } 793 nports = desc.bNbrPorts; 794 if (nports > 127) { 795 nports = 127; 796 } 797 if (hub->device->speed == USB_SPEED_HIGH) { 798 tt = desc.wHubCharacteristics.tt_think_time; 799 } 800 break; 801 case USB_SPEED_SUPER: 802 assert(!"NYI: super speed hub\n"); 803 break; 804 default: 805 break; 806 } 807 808 if (ret_nports != NULL) { 809 *ret_nports = nports; 810 } 811 812 if (ret_tt != NULL) { 813 *ret_tt = tt; 814 } 815 816 return (err); 817} 818 819void usb_hub_root_interrupt(struct usb_host_controller *hc) 820{ 821 USB_DEBUG_TR("usb_hub_root_interrupt()\n"); 822 if (hc == NULL) { 823 debug_printf("WARNING: No host controller\n"); 824 return; 825 } 826 if ((hc->devices == NULL) || (hc->root_hub == NULL)) { 827 debug_printf("WARNING: No root hub\n"); 828 return; 829 } 830 if (usb_hub_explore(hc->root_hub) != USB_ERR_OK) { 831 debug_printf("WARNING: explore failed\n"); 832 } 833} 834