1 /* 2 * Minix3 USB hub driver implementation 3 */ 4 5 #include <string.h> /* memset */ 6 #include <stdint.h> 7 #include <time.h> /* nanosleep */ 8 9 #include <ddekit/thread.h> 10 #include <minix/sef.h> 11 #include <minix/sysutil.h> /* panic */ 12 #include <minix/usb.h> /* usb_ctrlrequest TODO: remove me */ 13 14 #include "common.h" 15 #include "urb_helper.h" 16 17 18 /*---------------------------* 19 * declared functions * 20 *---------------------------*/ 21 /* TODO: these are missing from DDE header files */ 22 extern void ddekit_minix_wait_exit(void); 23 extern void ddekit_shutdown(void); 24 25 /* SEF related functions */ 26 static int hub_sef_hdlr(int, sef_init_info_t *); 27 static void hub_signal_handler(int); 28 29 /* DDEKit IPC related */ 30 static void ddekit_usb_task(void *); 31 32 /* DDEKit's USB driver callbacks */ 33 static void usb_driver_completion(void *); 34 static void usb_driver_connect(struct ddekit_usb_dev *, unsigned int); 35 static void usb_driver_disconnect(struct ddekit_usb_dev *); 36 37 /* Hub driver main task */ 38 static void hub_task(void *); 39 40 41 /*---------------------------* 42 * class specific stuff * 43 *---------------------------*/ 44 #define HUB_PACKED __attribute__((__packed__)) 45 46 /* How often to check for changes */ 47 #define USB_HUB_POLLING_INTERVAL 1000 48 49 /* Max number of hub ports */ 50 #define USB_HUB_PORT_LIMIT 8 51 52 /* Limits number of communication retries (when needed) */ 53 #define USB_HUB_MAX_TRIES 3 54 55 /* How long to wait between retries, in case of reset error (in nanoseconds) */ 56 #define USB_HUB_RESET_DELAY 200000000 /* 200ms */ 57 58 /* Hub descriptor type */ 59 #define USB_HUB_DESCRIPTOR_TYPE 0x29 60 61 /* Hub descriptor structure */ 62 typedef struct HUB_PACKED hub_descriptor { 63 64 uint8_t bDescLength; 65 uint8_t bDescriptorType; 66 uint8_t bNbrPorts; 67 uint16_t wHubCharacteristics; 68 uint8_t bPwrOn2PwrGood; 69 uint8_t bHubContrCurrent; 70 /* Remaining variable length fields are ignored for now */ 71 } 72 hub_descriptor; 73 74 /* Hub port status structure, as defined in USB 2.0 document */ 75 typedef struct HUB_PACKED hub_port_status { 76 77 uint32_t PORT_CONNECTION : 1; 78 uint32_t PORT_ENABLE : 1; 79 uint32_t PORT_SUSPEND : 1; 80 uint32_t PORT_OVER_CURRENT : 1; 81 uint32_t PORT_RESET : 1; 82 uint32_t RESERVED1 : 3; 83 84 uint32_t PORT_POWER : 1; 85 uint32_t PORT_LOW_SPEED : 1; 86 uint32_t PORT_HIGH_SPEED : 1; 87 uint32_t PORT_TEST : 1; 88 uint32_t PORT_INDICATOR : 1; 89 uint32_t RESERVED2 : 3; 90 91 uint32_t C_PORT_CONNECTION : 1; 92 uint32_t C_PORT_ENABLE : 1; 93 uint32_t C_PORT_SUSPEND : 1; 94 uint32_t C_PORT_OVER_CURRENT : 1; 95 uint32_t C_PORT_RESET : 1; 96 uint32_t RESERVED3 : 11; 97 } 98 hub_port_status; 99 100 /* Hub Class Feature Selectors */ 101 typedef enum { 102 103 C_HUB_LOCAL_POWER = 0 , 104 C_HUB_OVER_CURRENT = 1 , 105 PORT_CONNECTION = 0 , 106 PORT_ENABLE = 1 , 107 PORT_SUSPEND = 2 , 108 PORT_OVER_CURRENT = 3 , 109 PORT_RESET = 4 , 110 PORT_POWER = 8 , 111 PORT_LOW_SPEED = 9 , 112 C_PORT_CONNECTION = 16, 113 C_PORT_ENABLE = 17, 114 C_PORT_SUSPEND = 18, 115 C_PORT_OVER_CURRENT = 19, 116 C_PORT_RESET = 20, 117 PORT_TEST = 21, 118 PORT_INDICATOR = 22 119 } 120 class_feature; 121 122 /* Hub Class Request Codes */ 123 typedef enum { 124 125 GET_STATUS = 0 , 126 CLEAR_FEATURE = 1 , 127 RESERVED1 = 2 , 128 SET_FEATURE = 3 , 129 RESERVED2 = 4 , 130 RESERVED3 = 5 , 131 GET_DESCRIPTOR = 6 , 132 SET_DESCRIPTOR = 7 , 133 CLEAR_TT_BUFFER = 8 , 134 RESET_TT = 9 , 135 GET_TT_STATE = 10, 136 STOP_TT = 11 137 } 138 class_code; 139 140 /* Hub port connection state */ 141 typedef enum { 142 143 HUB_PORT_DISCONN = 0, 144 HUB_PORT_CONN = 1, 145 HUB_PORT_ERROR = 2 146 } 147 port_conn; 148 149 /* Hub port connection changes */ 150 typedef enum { 151 152 HUB_CHANGE_NONE = 0, /* Nothing changed since last poll */ 153 HUB_CHANGE_CONN = 1, /* Device was just connected */ 154 HUB_CHANGE_DISCONN= 2, /* Device was just disconnected */ 155 HUB_CHANGE_STATUS_ERR = 3, /* Port status mismatch */ 156 HUB_CHANGE_COM_ERR = 4 /* Something wrong happened to driver */ 157 } 158 port_change; 159 160 /* Hub get class specific descriptor call */ 161 static int hub_get_descriptor(hub_descriptor *); 162 163 /* Hub Set/ClearPortFeature call */ 164 static int hub_port_feature(int, class_code, class_feature); 165 166 /* Hub GetPortStatus call */ 167 static int hub_get_port_status(int, hub_port_status *); 168 169 /* Handle port status change */ 170 static port_change hub_handle_change(int, hub_port_status *); 171 172 /* Handle port connection */ 173 static int hub_handle_connection(int, hub_port_status *); 174 175 /* Handle port disconnection */ 176 static int hub_handle_disconnection(int); 177 178 179 /*---------------------------* 180 * defined variables * 181 *---------------------------*/ 182 /* USB hub driver state */ 183 typedef struct hub_state { 184 185 hub_descriptor descriptor; /* Class specific descriptor */ 186 struct ddekit_usb_dev * dev; /* DDEKit device */ 187 int num_ports; /* Number of hub ports */ 188 port_conn conn[USB_HUB_PORT_LIMIT]; /* Map of connected ports */ 189 } 190 hub_state; 191 192 /* Current hub driver state */ 193 static hub_state driver_state; 194 195 /* USB callback structure */ 196 static struct ddekit_usb_driver usb_driver = { 197 .completion = usb_driver_completion, 198 .connect = usb_driver_connect, 199 .disconnect = usb_driver_disconnect 200 }; 201 202 /* Semaphore used to block hub thread to 203 * allow DDE dispatcher operation */ 204 static ddekit_sem_t * hub_sem = NULL; 205 206 /* USB hub thread */ 207 ddekit_thread_t * hub_thread = NULL; 208 209 /* DDEKit USB message handling thread */ 210 ddekit_thread_t * ddekit_usb_thread = NULL; 211 212 213 /*---------------------------* 214 * defined functions * 215 *---------------------------*/ 216 /*===========================================================================* 217 * main * 218 *===========================================================================*/ 219 int 220 main(int argc, char * argv[]) 221 { 222 HUB_MSG("Starting driver... (built: %s %s)", __DATE__, __TIME__); 223 224 /* Store arguments for future parsing */ 225 env_setargs(argc, argv); 226 227 /* Clear current state */ 228 memset(&driver_state, 0, sizeof(driver_state)); 229 230 /* Initialize SEF related callbacks */ 231 sef_setcb_init_fresh(hub_sef_hdlr); 232 sef_setcb_init_lu(hub_sef_hdlr); 233 sef_setcb_init_restart(hub_sef_hdlr); 234 sef_setcb_signal_handler(hub_signal_handler); 235 236 /* Initialize DDEkit (involves sef_startup()) */ 237 ddekit_init(); 238 HUB_DEBUG_MSG("DDEkit ready..."); 239 240 /* Semaphore initialization */ 241 hub_sem = ddekit_sem_init(0); 242 if (NULL == hub_sem) 243 panic("Initializing USB hub semaphore, failed!"); 244 245 /* Starting hub thread */ 246 hub_thread = ddekit_thread_create(hub_task, NULL, "hub_task"); 247 if (NULL == hub_thread) 248 panic("Initializing USB hub thread failed!"); 249 250 HUB_DEBUG_MSG("USB HUB task ready..."); 251 252 /* Run USB IPC task to collect messages */ 253 ddekit_usb_thread = ddekit_thread_create(ddekit_usb_task, NULL, 254 "ddekit_task" ); 255 if (NULL == ddekit_usb_thread) 256 panic("Initializing ddekit_usb_thread failed!"); 257 258 HUB_DEBUG_MSG("USB IPC task ready..."); 259 260 /* Block and wait until exit signal is received */ 261 ddekit_minix_wait_exit(); 262 HUB_DEBUG_MSG("Exiting..."); 263 264 /* Release objects that were explicitly allocated above */ 265 ddekit_thread_terminate(ddekit_usb_thread); 266 ddekit_thread_terminate(hub_thread); 267 ddekit_sem_deinit(hub_sem); 268 269 /* TODO: No ddekit_deinit for proper cleanup? */ 270 271 HUB_DEBUG_MSG("Cleanup completed..."); 272 273 return EXIT_SUCCESS; 274 } 275 276 277 /*===========================================================================* 278 * hub_sef_hdlr * 279 *===========================================================================*/ 280 static int 281 hub_sef_hdlr(int type, sef_init_info_t * UNUSED(info)) 282 { 283 HUB_DEBUG_DUMP; 284 285 switch (type) { 286 case SEF_INIT_FRESH: 287 return EXIT_SUCCESS; 288 case SEF_INIT_LU: 289 case SEF_INIT_RESTART: 290 HUB_MSG("Only 'fresh' SEF initialization supported"); 291 break; 292 default: 293 HUB_MSG("Illegal SEF type"); 294 break; 295 } 296 297 return EXIT_FAILURE; 298 } 299 300 301 /*===========================================================================* 302 * hub_signal_handler * 303 *===========================================================================*/ 304 static void 305 hub_signal_handler(int this_signal) 306 { 307 HUB_DEBUG_DUMP; 308 309 HUB_MSG("Handling signal 0x%X", this_signal); 310 311 /* TODO: Any signal means shutdown for now (it may be OK anyway) */ 312 /* Try graceful DDEKit exit */ 313 ddekit_shutdown(); 314 315 /* Unreachable, when ddekit_shutdown works correctly */ 316 panic("Calling ddekit_shutdown failed!"); 317 } 318 319 320 /*===========================================================================* 321 * ddekit_usb_task * 322 *===========================================================================*/ 323 static void 324 ddekit_usb_task(void * UNUSED(arg)) 325 { 326 HUB_DEBUG_DUMP; 327 328 /* TODO: This call was meant to return 'int' but loops forever instead, 329 * so no return value is checked */ 330 ddekit_usb_init(&usb_driver, NULL, NULL); 331 } 332 333 334 /*===========================================================================* 335 * usb_driver_completion * 336 *===========================================================================*/ 337 static void 338 usb_driver_completion(void * UNUSED(priv)) 339 { 340 HUB_DEBUG_DUMP; 341 342 /* Last request was completed so allow continuing 343 * execution from place where semaphore was downed */ 344 ddekit_sem_up(hub_sem); 345 } 346 347 348 /*===========================================================================* 349 * usb_driver_connect * 350 *===========================================================================*/ 351 static void 352 usb_driver_connect(struct ddekit_usb_dev * dev, unsigned int interfaces) 353 { 354 HUB_DEBUG_DUMP; 355 356 if (NULL != driver_state.dev) 357 panic("HUB device driver can be connected only once!"); 358 359 /* Clear current state */ 360 memset(&driver_state, 0, sizeof(driver_state)); 361 362 /* Hold host information for future use */ 363 driver_state.dev = dev; 364 365 /* Let driver logic work */ 366 ddekit_sem_up(hub_sem); 367 } 368 369 370 /*===========================================================================* 371 * usb_driver_disconnect * 372 *===========================================================================*/ 373 static void 374 usb_driver_disconnect(struct ddekit_usb_dev * UNUSED(dev)) 375 { 376 HUB_DEBUG_DUMP; 377 378 if (NULL == driver_state.dev) 379 panic("HUB device driver was never connected!"); 380 381 /* Discard connected device information */ 382 driver_state.dev = NULL; 383 } 384 385 386 /*===========================================================================* 387 * hub_task * 388 *===========================================================================*/ 389 static void 390 hub_task(void * UNUSED(arg)) 391 { 392 hub_port_status port_status; 393 hub_state * s; 394 hub_descriptor * d; 395 int port; 396 397 HUB_DEBUG_DUMP; 398 399 /* For short */ 400 s = &(driver_state); 401 d = &(s->descriptor); 402 403 /* Wait for connection */ 404 ddekit_sem_down(hub_sem); 405 406 if (hub_get_descriptor(d)) { 407 HUB_MSG("Getting hub descriptor failed"); 408 goto HUB_ERROR; 409 } 410 411 /* Output hub descriptor in debug mode */ 412 HUB_DEBUG_MSG("bDescLength %4X", d->bDescLength); 413 HUB_DEBUG_MSG("bDescriptorType %4X", d->bDescriptorType); 414 HUB_DEBUG_MSG("bNbrPorts %4X", d->bNbrPorts); 415 HUB_DEBUG_MSG("wHubCharacteristics %4X", d->wHubCharacteristics); 416 HUB_DEBUG_MSG("bPwrOn2PwrGood %4X", d->bPwrOn2PwrGood); 417 HUB_DEBUG_MSG("bHubContrCurrent %4X", d->bHubContrCurrent); 418 419 /* Check for sane number of ports... */ 420 if (d->bNbrPorts > USB_HUB_PORT_LIMIT) { 421 HUB_MSG("Too many hub ports declared: %d", d->bNbrPorts); 422 goto HUB_ERROR; 423 } 424 425 /* ...and reassign */ 426 s->num_ports = (int)d->bNbrPorts; 427 428 /* Initialize all available ports starting 429 * from 1, as defined by USB 2.0 document */ 430 for (port = 1; port <= s->num_ports; port++) { 431 if (hub_port_feature(port, SET_FEATURE, PORT_POWER)) { 432 HUB_MSG("Powering port%d failed", port); 433 goto HUB_ERROR; 434 } 435 } 436 437 /* 438 * Connection polling loop 439 */ 440 for (;;) { 441 for (port = 1; port <= s->num_ports; port++) { 442 443 /* Ignore previously blocked ports */ 444 if (HUB_PORT_ERROR == s->conn[port]) { 445 HUB_DEBUG_MSG("Blocked hub port ignored"); 446 continue; 447 } 448 449 /* Get port status */ 450 if (hub_get_port_status(port, &port_status)) { 451 HUB_MSG("Reading port%d status failed", port); 452 goto HUB_ERROR; 453 } 454 455 /* Resolve port changes */ 456 switch (hub_handle_change(port, &port_status)) { 457 458 case HUB_CHANGE_NONE: 459 break; 460 461 case HUB_CHANGE_CONN: 462 s->conn[port] = HUB_PORT_CONN; 463 break; 464 465 case HUB_CHANGE_DISCONN: 466 s->conn[port] = HUB_PORT_DISCONN; 467 break; 468 469 case HUB_CHANGE_STATUS_ERR: 470 /* Turn off port */ 471 if (hub_port_feature(port, 472 CLEAR_FEATURE, 473 PORT_POWER)) { 474 HUB_MSG("Halting port%d " 475 "failed", port); 476 goto HUB_ERROR; 477 } 478 /* Block this port forever */ 479 s->conn[port] = HUB_PORT_ERROR; 480 481 HUB_MSG("Port%d status ERROR", port); 482 HUB_MSG("Port%d will be blocked, until " 483 "hub is detached", port); 484 485 break; 486 487 case HUB_CHANGE_COM_ERR: 488 /* Serious error, hang */ 489 HUB_MSG("Handling port%d " 490 "change failed", port); 491 goto HUB_ERROR; 492 } 493 } 494 495 ddekit_thread_msleep(USB_HUB_POLLING_INTERVAL); 496 HUB_DEBUG_MSG("Polling USB hub for status change"); 497 } 498 499 return; 500 501 HUB_ERROR: 502 for (;;) { 503 /* Hang till removed by devmand */ 504 HUB_MSG("Hub driver error occurred, hanging up"); 505 ddekit_sem_down(hub_sem); 506 } 507 } 508 509 510 /*===========================================================================* 511 * hub_get_descriptor * 512 *===========================================================================*/ 513 static int 514 hub_get_descriptor(hub_descriptor * descriptor) 515 { 516 /* URB to be send */ 517 struct ddekit_usb_urb urb; 518 519 /* Setup buffer to be attached */ 520 struct usb_ctrlrequest setup_buf; 521 522 /* Control EP configuration */ 523 urb_ep_config ep_conf; 524 525 HUB_DEBUG_DUMP; 526 527 /* Initialize EP configuration */ 528 ep_conf.ep_num = 0; 529 ep_conf.direction = DDEKIT_USB_IN; 530 ep_conf.type = DDEKIT_USB_TRANSFER_CTL; 531 ep_conf.max_packet_size = 0; 532 ep_conf.interval = 0; 533 534 /* Reset URB and assign given values */ 535 init_urb(&urb, driver_state.dev, &ep_conf); 536 537 /* Clear setup data */ 538 memset(&setup_buf, 0, sizeof(setup_buf)); 539 540 /* Class get hub descriptor request */ 541 setup_buf.bRequestType = 0xA0; 542 setup_buf.bRequest = 0x06; 543 setup_buf.wValue = USB_HUB_DESCRIPTOR_TYPE << 8; 544 setup_buf.wIndex = 0x00; 545 setup_buf.wLength = sizeof(*descriptor); 546 547 /* Attach buffers to URB */ 548 attach_urb_data(&urb, URB_BUF_TYPE_SETUP, 549 &setup_buf, sizeof(setup_buf)); 550 attach_urb_data(&urb, URB_BUF_TYPE_DATA, 551 descriptor, sizeof(*descriptor)); 552 553 /* Send and wait for response */ 554 if (blocking_urb_submit(&urb, hub_sem, URB_SUBMIT_CHECK_LEN)) { 555 HUB_MSG("Submitting HUB URB failed"); 556 return EXIT_FAILURE; 557 } else { 558 HUB_DEBUG_MSG("HUB descriptor received"); 559 return EXIT_SUCCESS; 560 } 561 } 562 563 564 /*===========================================================================* 565 * hub_port_feature * 566 *===========================================================================*/ 567 static int 568 hub_port_feature(int port_num, class_code code, class_feature feature) 569 { 570 /* URB to be send */ 571 struct ddekit_usb_urb urb; 572 573 /* Setup buffer to be attached */ 574 struct usb_ctrlrequest setup_buf; 575 576 /* Control EP configuration */ 577 urb_ep_config ep_conf; 578 579 HUB_DEBUG_DUMP; 580 581 /* TODO: Add more checks when needed */ 582 if (!((port_num <= driver_state.num_ports) && (port_num > 0))) 583 return EXIT_FAILURE; 584 585 if (!((code == SET_FEATURE) || (code == CLEAR_FEATURE))) 586 return EXIT_FAILURE; 587 588 if (!((feature == PORT_RESET) || (feature == PORT_POWER) || 589 (feature == C_PORT_CONNECTION) || (feature == C_PORT_RESET))) 590 return EXIT_FAILURE; 591 592 /* Initialize EP configuration */ 593 ep_conf.ep_num = 0; 594 ep_conf.direction = DDEKIT_USB_OUT; 595 ep_conf.type = DDEKIT_USB_TRANSFER_CTL; 596 ep_conf.max_packet_size = 0; 597 ep_conf.interval = 0; 598 599 /* Reset URB and assign given values */ 600 init_urb(&urb, driver_state.dev, &ep_conf); 601 602 /* Clear setup data */ 603 memset(&setup_buf, 0, sizeof(setup_buf)); 604 605 /* Standard get endpoint request */ 606 setup_buf.bRequestType = 0x23; 607 setup_buf.bRequest = (u8_t)code; 608 setup_buf.wValue = (u16_t)feature; 609 setup_buf.wIndex = (u16_t)port_num; 610 setup_buf.wLength = 0; 611 612 /* Attach buffers to URB */ 613 attach_urb_data(&urb, URB_BUF_TYPE_SETUP, 614 &setup_buf, sizeof(setup_buf)); 615 616 /* Send and wait for response */ 617 if (blocking_urb_submit(&urb, hub_sem, URB_SUBMIT_CHECK_LEN)) { 618 HUB_MSG("Submitting HUB URB failed"); 619 return EXIT_FAILURE; 620 } else { 621 HUB_DEBUG_MSG("PortFeature operation completed"); 622 return EXIT_SUCCESS; 623 } 624 } 625 626 627 /*===========================================================================* 628 * hub_get_port_status * 629 *===========================================================================*/ 630 static int 631 hub_get_port_status(int port_num, hub_port_status * p) 632 { 633 /* URB to be send */ 634 struct ddekit_usb_urb urb; 635 636 /* Setup buffer to be attached */ 637 struct usb_ctrlrequest setup_buf; 638 639 /* Control EP configuration */ 640 urb_ep_config ep_conf; 641 642 HUB_DEBUG_DUMP; 643 644 if (!((port_num <= driver_state.num_ports) && (port_num > 0))) 645 return EXIT_FAILURE; 646 647 /* Initialize EP configuration */ 648 ep_conf.ep_num = 0; 649 ep_conf.direction = DDEKIT_USB_IN; 650 ep_conf.type = DDEKIT_USB_TRANSFER_CTL; 651 ep_conf.max_packet_size = 0; 652 ep_conf.interval = 0; 653 654 /* Reset URB and assign given values */ 655 init_urb(&urb, driver_state.dev, &ep_conf); 656 657 /* Clear setup data */ 658 memset(&setup_buf, 0, sizeof(setup_buf)); 659 660 /* Standard get endpoint request */ 661 setup_buf.bRequestType = 0xA3; 662 setup_buf.bRequest = (u8_t)GET_STATUS; 663 setup_buf.wValue = 0x00; 664 setup_buf.wIndex = (u16_t)port_num; 665 setup_buf.wLength = sizeof(*p); 666 667 /* Attach buffers to URB */ 668 attach_urb_data(&urb, URB_BUF_TYPE_SETUP, 669 &setup_buf, sizeof(setup_buf)); 670 attach_urb_data(&urb, URB_BUF_TYPE_DATA, 671 p, sizeof(*p)); 672 673 /* Send and wait for response */ 674 if (blocking_urb_submit(&urb, hub_sem, URB_SUBMIT_CHECK_LEN)) { 675 HUB_MSG("Submitting HUB URB failed"); 676 return EXIT_FAILURE; 677 } else { 678 HUB_DEBUG_MSG("Port%d status: ", port_num); 679 HUB_DEBUG_MSG("PORT_CONNECTION %01X", p->PORT_CONNECTION); 680 HUB_DEBUG_MSG("PORT_ENABLE %01X", p->PORT_ENABLE); 681 HUB_DEBUG_MSG("PORT_POWER %01X", p->PORT_POWER); 682 HUB_DEBUG_MSG("C_PORT_CONNECTION %01X", p->C_PORT_CONNECTION); 683 HUB_DEBUG_MSG("C_PORT_ENABLE %01X", p->C_PORT_ENABLE); 684 return EXIT_SUCCESS; 685 } 686 } 687 688 689 /*===========================================================================* 690 * hub_handle_change * 691 *===========================================================================*/ 692 static port_change 693 hub_handle_change(int port_num, hub_port_status * status) 694 { 695 port_conn * c; 696 697 HUB_DEBUG_DUMP; 698 699 /* Possible combinations: */ 700 /* Change = status->C_PORT_CONNECTION (hub connection change bit) 701 * Local = driver_state.conn[port_num] (local connection status) 702 * Remote = status->PORT_CONNECTION (hub connection status) */ 703 /* 704 Case Change Local Remote Description 705 1. 1 1 1 Polling mismatch (quick disconn-conn) 706 2. 1 1 0 Just disconnected 707 3. 1 0 1 Just connected 708 4. 1 0 0 Polling mismatch (quick conn-disconn) 709 5. 0 1 1 Still connected 710 6. 0 1 0 Serious ERROR 711 7. 0 0 1 Serious ERROR 712 8. 0 0 0 Still disconnected 713 */ 714 715 /* Reassign for code cleanliness */ 716 c = driver_state.conn; 717 718 /* Resolve combination */ 719 if (status->C_PORT_CONNECTION) { 720 721 /* C_PORT_CONNECTION was set, so clear change bit 722 * to allow further polling */ 723 if (hub_port_feature(port_num, CLEAR_FEATURE, 724 C_PORT_CONNECTION)) { 725 HUB_MSG("Clearing port%d change bit failed", port_num); 726 return HUB_CHANGE_COM_ERR; 727 } 728 729 if (HUB_PORT_CONN == c[port_num]) { 730 if (status->PORT_CONNECTION) { 731 732 /* 733 * 1 734 */ 735 /* Make hub disconnect and connect again */ 736 if (hub_handle_disconnection(port_num) || 737 hub_handle_connection(port_num, status)) 738 return HUB_CHANGE_STATUS_ERR; 739 else 740 return HUB_CHANGE_CONN; 741 742 } else { 743 744 /* 745 * 2 746 */ 747 /* Handle disconnection */ 748 if (hub_handle_disconnection(port_num)) 749 return HUB_CHANGE_STATUS_ERR; 750 else 751 return HUB_CHANGE_DISCONN; 752 753 } 754 } else if (HUB_PORT_DISCONN == c[port_num]) { 755 if (status->PORT_CONNECTION) { 756 757 /* 758 * 3 759 */ 760 /* Handle connection */ 761 if (hub_handle_connection(port_num, status)) 762 return HUB_CHANGE_STATUS_ERR; 763 else 764 return HUB_CHANGE_CONN; 765 766 } else { 767 768 /* 769 * 4 770 */ 771 /* Since we were disconnected before and 772 * are disconnected now, additional handling 773 * may be ignored */ 774 return HUB_CHANGE_NONE; 775 776 } 777 } 778 } else { 779 if (HUB_PORT_CONN == c[port_num]) { 780 if (status->PORT_CONNECTION) { 781 782 /* 783 * 5 784 */ 785 /* Connected (nothing changed) */ 786 return HUB_CHANGE_NONE; 787 788 } else { 789 790 /* 791 * 6 792 */ 793 /* Serious status error */ 794 return HUB_CHANGE_STATUS_ERR; 795 796 } 797 } else if (HUB_PORT_DISCONN == c[port_num]) { 798 if (status->PORT_CONNECTION) { 799 800 /* 801 * 7 802 */ 803 /* Serious status error */ 804 return HUB_CHANGE_STATUS_ERR; 805 806 } else { 807 808 /* 809 * 8 810 */ 811 /* Disconnected (nothing changed) */ 812 return HUB_CHANGE_NONE; 813 814 } 815 } 816 } 817 818 return HUB_CHANGE_COM_ERR; 819 } 820 821 822 /*===========================================================================* 823 * hub_handle_connection * 824 *===========================================================================*/ 825 static int 826 hub_handle_connection(int port_num, hub_port_status * status) 827 { 828 struct timespec wait_time; 829 int reset_tries; 830 long port_speed; 831 832 HUB_DEBUG_DUMP; 833 834 HUB_MSG("Device connected to port%d", port_num); 835 836 /* This should never happen if power-off works as intended */ 837 if (status->C_PORT_RESET) { 838 HUB_MSG("Unexpected reset state for port%d", port_num); 839 return EXIT_FAILURE; 840 } 841 842 /* Start reset signaling for this port */ 843 if (hub_port_feature(port_num, SET_FEATURE, PORT_RESET)) { 844 HUB_MSG("Resetting port%d failed", port_num); 845 return EXIT_FAILURE; 846 } 847 848 reset_tries = 0; 849 wait_time.tv_sec = 0; 850 wait_time.tv_nsec = USB_HUB_RESET_DELAY; 851 852 /* Wait for reset completion */ 853 while (!status->C_PORT_RESET) { 854 /* To avoid endless loop */ 855 if (reset_tries >= USB_HUB_MAX_TRIES) { 856 HUB_MSG("Port%d reset took too long", port_num); 857 return EXIT_FAILURE; 858 } 859 860 /* Get port status again */ 861 if (hub_get_port_status(port_num, status)) { 862 HUB_MSG("Reading port%d status failed", port_num); 863 return EXIT_FAILURE; 864 } 865 866 reset_tries++; 867 868 /* Ignore potential signal interruption (no return value check), 869 * since it causes driver termination anyway */ 870 if (nanosleep(&wait_time, NULL)) 871 HUB_MSG("Calling nanosleep() failed"); 872 } 873 874 /* Reset completed */ 875 HUB_DEBUG_MSG("Port%d reset complete", port_num); 876 877 /* Dump full status for analysis (high-speed, ...) */ 878 HUB_DEBUG_MSG("C_PORT_CONNECTION %1X", status->C_PORT_CONNECTION ); 879 HUB_DEBUG_MSG("C_PORT_ENABLE %1X", status->C_PORT_ENABLE ); 880 HUB_DEBUG_MSG("C_PORT_OVER_CURRENT %1X", status->C_PORT_OVER_CURRENT); 881 HUB_DEBUG_MSG("C_PORT_RESET %1X", status->C_PORT_RESET ); 882 HUB_DEBUG_MSG("C_PORT_SUSPEND %1X", status->C_PORT_SUSPEND ); 883 HUB_DEBUG_MSG("PORT_CONNECTION %1X", status->PORT_CONNECTION ); 884 HUB_DEBUG_MSG("PORT_ENABLE %1X", status->PORT_ENABLE ); 885 HUB_DEBUG_MSG("PORT_HIGH_SPEED %1X", status->PORT_HIGH_SPEED ); 886 HUB_DEBUG_MSG("PORT_INDICATOR %1X", status->PORT_INDICATOR ); 887 HUB_DEBUG_MSG("PORT_LOW_SPEED %1X", status->PORT_LOW_SPEED ); 888 HUB_DEBUG_MSG("PORT_OVER_CURRENT %1X", status->PORT_OVER_CURRENT ); 889 HUB_DEBUG_MSG("PORT_POWER %1X", status->PORT_POWER ); 890 HUB_DEBUG_MSG("PORT_RESET %1X", status->PORT_RESET ); 891 HUB_DEBUG_MSG("PORT_SUSPEND %1X", status->PORT_SUSPEND ); 892 HUB_DEBUG_MSG("PORT_TEST %1X", status->PORT_TEST ); 893 894 /* Clear reset change bit for further devices */ 895 if (hub_port_feature(port_num, CLEAR_FEATURE, C_PORT_RESET)) { 896 HUB_MSG("Clearing port%d reset bit failed", port_num); 897 return EXIT_FAILURE; 898 } 899 900 /* Should never happen */ 901 if (!status->PORT_CONNECTION || !status->PORT_ENABLE) { 902 HUB_MSG("Port%d unexpectedly unavailable", port_num); 903 return EXIT_FAILURE; 904 } 905 906 /* Determine port speed from status bits */ 907 if (status->PORT_LOW_SPEED) { 908 if (status->PORT_HIGH_SPEED) { 909 HUB_MSG("Port%d has invalid speed flags", port_num); 910 return EXIT_FAILURE; 911 } else 912 port_speed = (long)DDEKIT_HUB_PORT_LS_CONN; 913 } else { 914 if (status->PORT_HIGH_SPEED) 915 port_speed = (long)DDEKIT_HUB_PORT_HS_CONN; 916 else 917 port_speed = (long)DDEKIT_HUB_PORT_FS_CONN; 918 } 919 920 /* Signal to HCD that port has device connected at given speed */ 921 return ddekit_usb_info(driver_state.dev, port_speed, (long)port_num); 922 } 923 924 925 /*===========================================================================* 926 * hub_handle_disconnection * 927 *===========================================================================*/ 928 static int 929 hub_handle_disconnection(int port_num) 930 { 931 HUB_DEBUG_DUMP; 932 933 HUB_MSG("Device disconnected from port%d", port_num); 934 935 return ddekit_usb_info(driver_state.dev, (long)DDEKIT_HUB_PORT_DISCONN, 936 (long)port_num); 937 } 938