1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/** 14 * @brief USB hub driver 15 * @see USB 2.0 spec, Chapter 11 16 */ 17#include "usbhub.h" 18 19#include <stdio.h> 20#include <string.h> 21 22#include <utils/util.h> 23 24#include "../services.h" 25 26#define HUBINT_RATE_MS 100 27 28#define HUB_ENABLE_IRQS 29 30/*** USB spec chapter 11 page 262 ***/ 31 32struct hub_desc { 33/// Number of bytes in this descriptor, including this byte. 34 uint8_t bDescLength; 35/// Descriptor Type, value: 0x29 for Hub Descriptor. 36#define DESCRIPTOR_TYPE_HUB 0x29 37 uint8_t bDescriptorType; 38/// Number of downstream ports that this hub supports. 39 uint8_t bNbrPorts; 40/// Hub characteristics. 41#define HUBCHAR_POWER_SWITCH_SINGLE BIT(0) 42#define HUBCHAR_POWER_SWITCH_NONE BIT(1) 43#define HUBCHAR_COMPOUND_DEVICE BIT(2) 44#define HUBCHAR_OVER_CURRENT_SINGLE BIT(3) 45#define HUBCHAR_OVER_CURRENT_NONE BIT(4) 46 uint16_t wHubCharacteristics; 47/// Time (in 2ms intervals) until power is stable after child port power on 48 uint8_t bPwrOn2PwrGood; 49/// Maximum current requirements of the hub controller 50 uint8_t bHubContrCurrent; 51 /* The size of the remaining fields depends on the number of ports 52 * Bit x will correspond to port x 53 * DeviceRemovable bitmap: 1-not removable. 54 * PortPwrCtrlMask bitmap: 1-requires manual power on (not ganged). 55 */ 56 uint8_t portcfg[64]; 57} __attribute__ ((packed)); 58 59/**************** 60 *** FEATURES *** 61 ****************/ 62static inline struct usbreq 63__clear_port_feature_req(uint16_t port, uint16_t feature) 64{ 65 struct usbreq r = { 66 .bmRequestType = (USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_OTHER), 67 .bRequest = CLR_FEATURE, 68 .wValue = feature, 69 .wIndex = port, 70 .wLength = 0 71 }; 72 return r; 73} 74 75static inline struct usbreq __clear_hub_feature_req(uint16_t feature) 76{ 77 struct usbreq r = { 78 .bmRequestType = (USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_DEVICE), 79 .bRequest = CLR_FEATURE, 80 .wValue = feature, 81 .wIndex = 0, 82 .wLength = 0 83 }; 84 return r; 85} 86 87static inline struct usbreq 88__set_port_feature_req(uint16_t port, uint16_t feature) 89{ 90 struct usbreq r = { 91 .bmRequestType = (USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_OTHER), 92 .bRequest = SET_FEATURE, 93 .wValue = feature, 94 .wIndex = port, 95 .wLength = 0 96 }; 97 return r; 98} 99 100static inline struct usbreq __set_hub_feature_req(uint16_t feature) 101{ 102 struct usbreq r = { 103 .bmRequestType = (USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_DEVICE), 104 .bRequest = SET_FEATURE, 105 .wValue = feature, 106 .wIndex = 0, 107 .wLength = 0 108 }; 109 return r; 110} 111 112static inline struct usbreq __get_port_status_req(uint16_t port) 113{ 114 struct usbreq r = { 115 .bmRequestType = (USB_DIR_IN | USB_TYPE_CLS | USB_RCPT_OTHER), 116 .bRequest = GET_STATUS, 117 .wValue = 0, 118 .wIndex = port, 119 .wLength = 4 120 }; 121 return r; 122} 123 124static inline struct usbreq __get_hub_status_req(void) 125{ 126 struct usbreq r = { 127 .bmRequestType = (USB_DIR_IN | USB_TYPE_CLS | USB_RCPT_DEVICE), 128 .bRequest = GET_STATUS, 129 .wValue = 0, 130 .wIndex = 0, 131 .wLength = 4 132 }; 133 return r; 134} 135 136static inline struct usbreq __get_hub_descriptor_req(void) 137{ 138 struct usbreq r = { 139 .bmRequestType = (USB_DIR_IN | USB_TYPE_CLS | USB_RCPT_DEVICE), 140 .bRequest = GET_DESCRIPTOR, 141 .wValue = DESCRIPTOR_TYPE_HUB << 8, 142 .wIndex = 0, 143 .wLength = sizeof(struct hub_desc) 144 }; 145 return r; 146} 147 148static inline struct usbreq __set_hub_descriptor_req(void) 149{ 150 struct usbreq r = { 151 .bmRequestType = (USB_DIR_OUT | USB_TYPE_CLS | USB_RCPT_DEVICE), 152 .bRequest = SET_DESCRIPTOR, 153 .wValue = DESCRIPTOR_TYPE_HUB << 8, 154 .wIndex = 0, 155 .wLength = sizeof(struct hub_desc) 156 }; 157 return r; 158} 159 160struct usb_hubem { 161 int hubem_nports; 162 int pwr_delay_ms; 163 int (*set_pf) (void *token, int port, enum port_feature feature); 164 int (*clr_pf) (void *token, int port, enum port_feature feature); 165 int (*get_pstat) (void *token, int port, struct port_status *ps); 166 void *token; 167}; 168 169static void _handle_port_change(usb_hub_t h, int port) 170{ 171 struct xact xact[2]; 172 struct usbreq *req; 173 struct port_status *sts; 174 uint16_t change, status; 175 int ret; 176 177 if (!h) { 178 ZF_LOGF("Invalid HUB\n"); 179 } 180 181 if (!port) { 182 ZF_LOGD("Error: check hub status!\n"); 183 return; 184 } 185 186 ZF_LOGD("Handle status change of port %d\n", port); 187 188 /* Get port status change */ 189 xact[0].type = PID_SETUP; 190 xact[0].len = sizeof(struct usbreq); 191 xact[1].type = PID_IN; 192 xact[1].len = sizeof(struct port_status); 193 194 ret = usb_alloc_xact(h->udev->dman, xact, 2); 195 if (ret) { 196 ZF_LOGF("Out of DMA memory\n"); 197 } 198 req = xact_get_vaddr(&xact[0]); 199 sts = xact_get_vaddr(&xact[1]); 200 201 *req = __get_port_status_req(port); 202 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 203 xact, 2, NULL, NULL); 204 if (ret < 0) { 205 ZF_LOGF("Transaction error\n"); 206 } 207 208 /* Cache the port status, because we need to clear it right away. */ 209 change = sts->wPortChange; 210 status = sts->wPortStatus; 211 212 ZF_LOGD("Status change (0x%x:0x%x) on port %d.\n", 213 change, status, port); 214 215 /* Attach and detach detect event */ 216 if (change & BIT(PORT_CONNECTION)) { 217 /* Clear the port connection status */ 218 *req = __clear_port_feature_req(port, C_PORT_CONNECTION); 219 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 220 xact, 1, NULL, NULL); 221 if (ret < 0) { 222 ZF_LOGF("Transaction error\n"); 223 } 224 225 if (status & BIT(PORT_CONNECTION)) { 226 ZF_LOGD("Port %d connected\n", port); 227 /* Wait for the device to stabilize, USB spec 9.1.2 */ 228 ps_mdelay(100); 229 230 /* Enable the connection by resetting the port */ 231 *req = __set_port_feature_req(port, PORT_RESET); 232 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 233 xact, 1, NULL, NULL); 234 if (ret < 0) { 235 ZF_LOGF("Transaction error\n"); 236 } 237 238 /* 239 * Wait for the hub to exit the resetting state, refer 240 * to USB spec 11.5.1.5 241 * We also need to re-read the port status, it's updated 242 * by the reset. 243 */ 244 *req = __get_port_status_req(port); 245 do { 246 ps_mdelay(10); 247 ret = 248 usbdev_schedule_xact(h->udev, 249 h->udev->ep_ctrl, xact, 250 2, NULL, NULL); 251 if (ret < 0) { 252 ZF_LOGF("Transaction error\n"); 253 } 254 255 status = sts->wPortStatus; 256 } while (status & BIT(PORT_RESET)); 257 258 /* Reset finished, clear reset status */ 259 *req = __clear_port_feature_req(port, C_PORT_RESET); 260 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 261 xact, 1, NULL, NULL); 262 if (ret < 0) { 263 ZF_LOGF("Transaction error\n"); 264 } 265 266 /* Create the new device */ 267 enum usb_speed speed; 268 struct usb_dev *new_dev = NULL; 269 usb_hub_t new_hub = NULL; 270 271 if (status & BIT(PORT_HIGH_SPEED)) { 272 speed = USBSPEED_HIGH; 273 } else if (status & BIT(PORT_LOW_SPEED)) { 274 speed = USBSPEED_LOW; 275 } else { 276 speed = USBSPEED_FULL; 277 } 278 279 ret = usb_new_device(h->udev, port, speed, &new_dev); 280 if (ret < 0) { 281 *req = __set_port_feature_req(port, PORT_RESET); 282 ret = 283 usbdev_schedule_xact(h->udev, 284 h->udev->ep_ctrl, xact, 285 1, NULL, NULL); 286 if (ret < 0) { 287 ZF_LOGF("Transaction error\n"); 288 } 289 if (new_dev) { 290 usbdev_disconnect(new_dev); 291 } 292 } else { 293 h->port[port - 1].udev = new_dev; 294 usb_hub_driver_bind(new_dev, &new_hub); 295 } 296 } else { 297 ZF_LOGD("Port %d disconnected\n", port); 298 *req = __set_port_feature_req(port, PORT_SUSPEND); 299 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 300 xact, 1, NULL, NULL); 301 if (ret < 0) { 302 ZF_LOGF("Transaction error\n"); 303 } 304 if (h->port[port - 1].udev) { 305 usbdev_disconnect(h->port[port - 1].udev); 306 h->port[port - 1].udev = NULL; 307 } 308 } 309 } 310 311 /* Port enable */ 312 if (change & BIT(PORT_ENABLE)) { 313 ZF_LOGD("Port %d enabled\n", port); 314 /* Clear the port connection status */ 315 *req = __clear_port_feature_req(port, C_PORT_CONNECTION); 316 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 317 xact, 1, NULL, NULL); 318 if (ret < 0) { 319 ZF_LOGF("Transaction error\n"); 320 } 321 } 322 323 /* Port suspend */ 324 if (change & BIT(PORT_SUSPEND)) { 325 ZF_LOGD("Port %d suspended\n", port); 326 /* Clear suspend status */ 327 *req = __clear_port_feature_req(port, C_PORT_SUSPEND); 328 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 329 xact, 1, NULL, NULL); 330 if (ret < 0) { 331 ZF_LOGF("Transaction error\n"); 332 } 333 } 334 335 /* Port over-current */ 336 if (change & BIT(PORT_OVER_CURRENT)) { 337 ZF_LOGD("Port %d over-current\n", port); 338 /* Clear over-current status */ 339 *req = __clear_port_feature_req(port, C_PORT_OVER_CURRENT); 340 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 341 xact, 1, NULL, NULL); 342 if (ret < 0) { 343 ZF_LOGF("Transaction error\n"); 344 } 345 } 346 347 /* Port reset */ 348 if (change & BIT(PORT_RESET)) { 349 ZF_LOGD("Port %d reset\n", port); 350 /* Clear reset status */ 351 *req = __clear_port_feature_req(port, C_PORT_RESET); 352 ret = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 353 xact, 1, NULL, NULL); 354 if (ret < 0) { 355 ZF_LOGF("Transaction error\n"); 356 } 357 } 358 359 usb_destroy_xact(h->udev->dman, xact, 2); 360} 361 362static int 363hub_irq_handler(void *token, enum usb_xact_status stat, int bytes_remaining) 364{ 365 usb_hub_t h = (usb_hub_t) token; 366 int i, j; 367 int handled = 0; 368 uint8_t *intbm; 369 int len = h->int_xact.len - bytes_remaining; 370 371 /* Check the status */ 372 if (stat != XACTSTAT_SUCCESS) { 373 ZF_LOGD("Received unsuccessful IRQ\n"); 374 return 1; 375 } 376 377 ZF_LOGD("Handling IRQ\n"); 378 379 intbm = h->intbm; 380 if (intbm != xact_get_vaddr(&h->int_xact)) { 381 ZF_LOGF("Invalid bitmap\n"); 382 } 383 for (i = 0; i < len; i++) { 384 /* Check if any bits have changed */ 385 if (intbm[i] == 0) { 386 continue; 387 } 388 /* Scan bitfield */ 389 for (j = 0; j < 8; j++) { 390 if ((1 << j) & intbm[i]) { 391 int port = i * 8 + j; 392 _handle_port_change(h, port); 393 handled++; 394 } 395 } 396 intbm[i] = 0; 397 } 398 if (!handled) { 399 ZF_LOGD("Spurious IRQ\n"); 400 } 401 402 usbdev_schedule_xact(h->udev, h->udev->ep[0], 403 &h->int_xact, 1, &hub_irq_handler, h); 404 return 0; 405} 406 407static int hub_config_cb(void *token, int cfg, int iface, struct anon_desc *d) 408{ 409 struct endpoint_desc *e; 410 usb_hub_t hub = (usb_hub_t)token; 411 412 if (!hub) { 413 ZF_LOGF("Invalid token\n"); 414 } 415 if (d) { 416 switch (d->bDescriptorType) { 417 case ENDPOINT: 418 e = (struct endpoint_desc*)d; 419 /* We just take the first endpoint */ 420 hub->int_ep = e->bEndpointAddress & 0xf; 421 hub->int_max_pkt = e->wMaxPacketSize; 422 hub->int_rate_ms = e->bInterval * 2; 423 hub->ifno = iface; 424 hub->cfgno = cfg; 425 break; 426 default: 427 /* Don't care */ 428 break; 429 } 430 return 0; 431 } else { 432 return 0; 433 } 434} 435 436int usb_hub_driver_bind(usb_dev_t *udev, usb_hub_t *hub) 437{ 438 usb_hub_t h; 439 struct usbreq *req; 440 struct hub_desc *hdesc; 441 struct xact xact[2]; 442 int err; 443 int i; 444 445 /* Check the class */ 446 if (usbdev_get_class(udev) != USB_CLASS_HUB) { 447 return -1; 448 } 449 450 /* Allocate memory */ 451 h = (usb_hub_t) usb_malloc(sizeof(*h)); 452 if (h == NULL) { 453 return -2; 454 } 455 memset(h, 0, sizeof(*h)); 456 h->udev = udev; 457 udev->dev_data = (struct udev_priv *)h; 458 459 /* Get hub descriptor for nports and power delay */ 460 ZF_LOGD("Get hub descriptor\n"); 461 xact[0].type = PID_SETUP; 462 xact[0].len = sizeof(*req); 463 xact[1].type = PID_IN; 464 xact[1].len = sizeof(*hdesc); 465 err = usb_alloc_xact(udev->dman, xact, 2); 466 if (err) { 467 ZF_LOGF("Out of DMA memory\n"); 468 } 469 req = xact_get_vaddr(&xact[0]); 470 *req = __get_hub_descriptor_req(); 471 err = usbdev_schedule_xact(udev, h->udev->ep_ctrl, xact, 2, NULL, NULL); 472 if (err < 0) { 473 usb_destroy_xact(udev->dman, xact, 2); 474 usb_free(h); 475 h = NULL; 476 return -1; 477 } 478 hdesc = xact_get_vaddr(&xact[1]); 479 h->nports = hdesc->bNbrPorts; 480 h->power_good_delay_ms = hdesc->bPwrOn2PwrGood * 2; 481 usb_destroy_xact(udev->dman, xact, 2); 482 h->port = (struct usb_hub_port *)usb_malloc(sizeof(*h->port) * h->nports); 483 if (!h->port) { 484 ZF_LOGF("Out of memory\n"); 485 } 486 memset(h->port, 0, sizeof(*h->port) * h->nports); 487 ZF_LOGD("Parsing config\n"); 488 h->int_ep = -1; 489 err = usbdev_parse_config(h->udev, &hub_config_cb, h); 490 if (err || h->int_ep == -1) { 491 usb_free(h); 492 h = NULL; 493 return -1; 494 } 495 ZF_LOGD("Configure HUB\n"); 496 xact[0].type = PID_SETUP; 497 xact[0].len = sizeof(*req); 498 499 err = usb_alloc_xact(h->udev->dman, xact, 1); 500 if (err) { 501 ZF_LOGE("Out of DMA memory\n"); 502 return -1; 503 } 504 req = xact_get_vaddr(&xact[0]); 505 *req = __set_configuration_req(h->cfgno); 506 507 err = usbdev_schedule_xact(udev, h->udev->ep_ctrl, xact, 1, NULL, NULL); 508 if (err < 0) { 509 usb_destroy_xact(udev->dman, xact, 1); 510 usb_free(h); 511 h = NULL; 512 return -1; 513 } 514 usb_destroy_xact(udev->dman, xact, 1); 515 516 /* Power up ports */ 517 xact[0].type = PID_SETUP; 518 xact[0].len = sizeof(*req); 519 520 usb_alloc_xact(h->udev->dman, xact, 1); 521 req = xact_get_vaddr(&xact[0]); 522 for (i = 1; i <= h->nports; i++) { 523 ZF_LOGD("Power on port %d\n", i); 524 *req = __set_port_feature_req(i, PORT_POWER); 525 err = usbdev_schedule_xact(h->udev, h->udev->ep_ctrl, 526 xact, 1, NULL, NULL); 527 if (err < 0) { 528 ZF_LOGF("Transaction error\n"); 529 } 530 } 531 ps_mdelay(h->power_good_delay_ms); 532 usb_destroy_xact(udev->dman, xact, 1); 533#if !defined(HUB_ENABLE_IRQS) 534 /* Setup ports */ 535 for (i = 1; i <= h->nports; i++) { 536 _handle_port_change(h, i); 537 } 538#endif 539#if defined(HUB_ENABLE_IRQS) 540 h->int_xact.type = PID_IN; 541 /* 542 * USB 2.0 spec[11.12.4] says the packet size should be (nport + 7)/8, but 543 * some hubs are known to send more data, which would cause a "babble". So 544 * we use maximum packet size instead, short packet does no harm. 545 */ 546 h->int_xact.len = h->int_max_pkt; 547 err = usb_alloc_xact(udev->dman, &h->int_xact, 1); 548 if (err) { 549 ZF_LOGF("Out of DMA memory\n"); 550 } 551 h->intbm = xact_get_vaddr(&h->int_xact); 552 ZF_LOGD("Registering for INT\n"); 553 /* FIXME: Search for the right ep */ 554 usbdev_schedule_xact(udev, udev->ep[0], 555 &h->int_xact, 1, &hub_irq_handler, h); 556#else 557 h->intbm = NULL; 558 h->int_xact.vaddr = NULL; 559 h->int_xact.paddr = 0; 560 h->int_xact.len = 0; 561 (void)hub_irq_handler; 562#endif 563 *hub = h; 564 565 return 0; 566} 567 568/********************* 569 *** Hub emulation *** 570 *********************/ 571 572static struct device_desc _hub_device_desc = { 573 .bLength = sizeof(struct device_desc), 574 .bDescriptorType = DEVICE, 575 .bcdUSB = 0x200, 576 .bDeviceClass = USB_CLASS_HUB, 577 .bDeviceSubClass = 0, 578 .bDeviceProtocol = 2, 579 .bMaxPacketSize0 = 64, 580 .idVendor = 0xFEED, 581 .idProduct = 0xBEEF, 582 .bcdDevice = 1234, 583 .iManufacturer = 0, 584 .iProduct = 0, 585 .iSerialNumber = 0, 586 .bNumConfigurations = 1 587}; 588 589static struct iface_desc _hub_iface_desc = { 590 .bLength = sizeof(_hub_iface_desc), 591 .bDescriptorType = INTERFACE, 592 .bInterfaceNumber = 0, 593 .bAlternateSetting = 0, 594 .bNumEndpoints = 1, 595 .bInterfaceClass = 9, 596 .bInterfaceSubClass = 0, 597 .bInterfaceProtocol = 1, 598 .iInterface = 0 599}; 600 601static struct endpoint_desc _hub_endpoint_desc = { 602 .bLength = sizeof(_hub_endpoint_desc), 603 .bDescriptorType = ENDPOINT, 604 .bEndpointAddress = 0x81, 605 .bmAttributes = 0x3, 606 .wMaxPacketSize = 0x1, 607 .bInterval = 0xc 608}; 609 610static struct config_desc _hub_config_desc = { 611 .bLength = sizeof(_hub_config_desc), 612 .bDescriptorType = CONFIGURATION, 613 .wTotalLength = sizeof(_hub_config_desc) + 614 sizeof(_hub_iface_desc) + sizeof(_hub_endpoint_desc), 615 .bNumInterfaces = 1, 616 .bConfigurationValue = 1, 617 .iConfigurationIndex = 0, 618 .bmAttributes = (1 << 7), 619 .bMaxPower = 100 /*mA */ / 2 620}; 621 622static struct hub_desc _hub_hub_desc = { 623 .bDescLength = 0x8, 624 .bDescriptorType = DESCRIPTOR_TYPE_HUB, 625 .bNbrPorts = 2, 626 .wHubCharacteristics = 0, 627 .bPwrOn2PwrGood = 0xff, 628 .bHubContrCurrent = 0, 629 .portcfg = {0} 630}; 631 632static int 633hubem_get_descriptor(usb_hubem_t dev, struct usbreq *req, void *buf, int len) 634{ 635 int act_len = 0; 636 int dtype = req->wValue >> 8; 637 switch (dtype) { 638 case DEVICE:{ 639 struct device_desc *ret = (struct device_desc *)buf; 640 ZF_LOGD("Get device descriptor\n"); 641 act_len = MIN(len, sizeof(*ret)); 642 memcpy(ret, &_hub_device_desc, act_len); 643 return act_len;} 644 case DESCRIPTOR_TYPE_HUB:{ 645 struct hub_desc *ret = (struct hub_desc *)buf; 646 int nregs = (dev->hubem_nports + 7) / 8; 647 int i; 648 ZF_LOGD("Get hub type descriptor\n"); 649 _hub_hub_desc.bNbrPorts = dev->hubem_nports; 650 _hub_hub_desc.bPwrOn2PwrGood = dev->pwr_delay_ms / 2; 651 _hub_hub_desc.bDescLength = 7 + nregs * 2; 652 for (i = 0; i < nregs; i++) { 653 _hub_hub_desc.portcfg[i] = 0; 654 _hub_hub_desc.portcfg[i + nregs] = 0; 655 } 656 act_len = MIN(_hub_hub_desc.bDescLength, len); 657 memcpy(ret, &_hub_hub_desc, act_len); 658 return act_len;} 659 case CONFIGURATION:{ 660 int cp_len; 661 int pos = 0; 662 int act_len; 663 ZF_LOGD("Get configuration descriptor\n"); 664 act_len = MIN(_hub_config_desc.wTotalLength, len); 665 /* Copy the config */ 666 cp_len = MIN(act_len - pos, _hub_config_desc.bLength); 667 memcpy(buf + pos, &_hub_config_desc, cp_len); 668 pos += cp_len; 669 /* Copy the iface */ 670 cp_len = MIN(act_len - pos, _hub_iface_desc.bLength); 671 memcpy(buf + pos, &_hub_iface_desc, cp_len); 672 pos += cp_len; 673 /* copy the endpoint */ 674 _hub_endpoint_desc.wMaxPacketSize = 675 (dev->hubem_nports + 7) / 8; 676 cp_len = MIN(act_len - pos, _hub_endpoint_desc.bLength); 677 memcpy(buf + pos, &_hub_endpoint_desc, cp_len); 678 pos += cp_len; 679 if (pos != act_len) { 680 ZF_LOGF("Invalid descriptor\n"); 681 } 682 return act_len;} 683 case INTERFACE:{ 684 int act_len; 685 ZF_LOGD("Get interface descriptor\n"); 686 act_len = MIN(_hub_iface_desc.bLength, len); 687 memcpy(buf, &_hub_iface_desc, act_len); 688 return act_len;} 689 case ENDPOINT:{ 690 int act_len; 691 ZF_LOGD("Get endpoint descriptor\n"); 692 act_len = MIN(_hub_endpoint_desc.bLength, len); 693 memcpy(buf, &_hub_endpoint_desc, act_len); 694 return act_len;} 695 case STRING: 696 case DEVICE_QUALIFIER: 697 case OTHER_SPEED_CONFIGURATION: 698 case INTERFACE_POWER: 699 default: 700 ZF_LOGD("Descriptor 0x%x not supported\n", dtype); 701 return -1; 702 } 703} 704 705static int hubem_feature(usb_hubem_t dev, struct usbreq *req) 706{ 707 int f = req->wValue; 708 int p = req->wIndex; 709 void *t = dev->token; 710 int ret; 711 switch (req->bRequest) { 712 case SET_FEATURE: 713 ZF_LOGD("Set feature %d -> port %d\n", f, p); 714 return dev->set_pf(t, p, f); 715 case CLR_FEATURE: 716 ZF_LOGD("Clear feature %d -> port %d\n", f, p); 717 return dev->clr_pf(t, p, f); 718 default: 719 printf("Unsupported feature: %d\n", f); 720 return -1; 721 } 722 return ret; 723} 724 725static int 726hubem_get_status(usb_hubem_t dev, struct usbreq *req, void *buf, int len) 727{ 728 int port = req->wIndex; 729 if (port == 0) { 730 /* Device status: self powered | remote wakeup */ 731 uint16_t stat = 0; 732 int act_len; 733 ZF_LOGD("Get Status: Device status\n"); 734 act_len = MIN(len, sizeof(stat)); 735 memcpy(buf, &stat, act_len); 736 return act_len; 737 } else if (port <= dev->hubem_nports) { 738 /* Port status */ 739 struct port_status *psts = (struct port_status *)buf; 740 int act_len = MIN(len, sizeof(*psts)); 741 if (len < sizeof(*psts)) { 742 ZF_LOGF("Invalid port status\n"); 743 } 744 if (dev->get_pstat(dev->token, port, psts)) { 745 ZF_LOGD 746 ("Get Status: Failed to read status for port %d\n", 747 port); 748 return -1; 749 } else { 750 ZF_LOGD("Get Status: Success s0x%x c0x%0x on port %d\n", 751 psts->wPortStatus, psts->wPortChange, port); 752 return act_len; 753 } 754 } else { 755 ZF_LOGD("Get Status: Invalid port (%d/%d)\n", port, 756 dev->hubem_nports); 757 return -1; 758 } 759} 760 761int 762hubem_process_xact(usb_hubem_t dev, struct xact *xact, int nxact, 763 usb_cb_t cb, void *t) 764{ 765 struct usbreq *req; 766 void *buf; 767 int buf_len; 768 int i; 769 int err; 770 771 for (err = 0, i = 0; !err && i < nxact; i++) { 772 if (xact[i].type != PID_SETUP) { 773 continue; 774 } 775 req = xact_get_vaddr(&xact[i]); 776 if (xact[i].len < sizeof(*req)) { 777 ZF_LOGF("Buffer too small\n"); 778 } 779 780 if (i + 1 < nxact && xact[i + 1].type != PID_SETUP) { 781 buf = xact_get_vaddr(&xact[i + 1]); 782 buf_len = xact[i + 1].len; 783 } else { 784 buf = NULL; 785 buf_len = 0; 786 } 787 switch (req->bRequest) { 788 case GET_STATUS: 789 return hubem_get_status(dev, req, buf, buf_len); 790 case GET_DESCRIPTOR: 791 return hubem_get_descriptor(dev, req, buf, buf_len); 792 case SET_CONFIGURATION: 793 ZF_LOGD("Unhandled transaction: SET_CONFIGURATION\n"); 794 break; 795 case SET_INTERFACE: 796 ZF_LOGD("Unhandled transaction: SET_INTERFACE\n"); 797 break; 798 case SET_ADDRESS: 799 ZF_LOGD("Unhandled transaction: SET_ADDRESS\n"); 800 break; 801 case CLR_FEATURE: 802 case SET_FEATURE: 803 err = hubem_feature(dev, req); 804 break; 805 default: 806 ZF_LOGE("Request code %d not supported\n", 807 req->bRequest); 808 } 809 } 810 if (cb) { 811 if (err >= 0) { 812 cb(t, XACTSTAT_SUCCESS, err); 813 } else { 814 cb(t, XACTSTAT_ERROR, err); 815 } 816 } 817 return err; 818} 819 820int 821usb_hubem_driver_init(void *token, int nports, int pwr_delay_ms, 822 int (*set_pf) (void *token, int port, 823 enum port_feature feature), 824 int (*clr_pf) (void *token, int port, 825 enum port_feature feature), 826 int (*get_pstat) (void *token, int port, 827 struct port_status *ps), 828 usb_hubem_t *hub) 829{ 830 831 usb_hubem_t h; 832 h = (usb_hubem_t) usb_malloc(sizeof(*h)); 833 if (h == NULL) { 834 ZF_LOGE("Out of memory\n"); 835 return -1; 836 } 837 838 h->token = token; 839 h->hubem_nports = nports; 840 h->pwr_delay_ms = pwr_delay_ms; 841 h->set_pf = set_pf; 842 h->clr_pf = clr_pf; 843 h->get_pstat = get_pstat; 844 *hub = h; 845 return 0; 846} 847