Changeset e5ccfd1 in mainline
- Timestamp:
- 2011-04-07T06:55:22Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d7f3040
- Parents:
- a209648
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/usbhub.c
ra209648 re5ccfd1 57 57 usb_speed_t speed); 58 58 59 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev); 60 61 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info); 62 63 static int usb_hub_set_configuration(usb_hub_info_t * hub_info); 64 65 static int usb_hub_release_default_address(usb_hub_info_t * hub); 66 67 static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port, 68 usb_speed_t speed); 69 70 static void usb_hub_finalize_add_device(usb_hub_info_t * hub, 71 uint16_t port, usb_speed_t speed); 72 73 static void usb_hub_removed_device( 74 usb_hub_info_t * hub, uint16_t port); 75 76 static void usb_hub_port_over_current(usb_hub_info_t * hub, 77 uint16_t port, uint32_t status); 78 79 static void usb_hub_process_interrupt(usb_hub_info_t * hub, 80 uint16_t port); 81 82 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 83 usb_hub_status_t status); 84 85 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 86 usb_hub_status_t status); 87 88 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info); 89 90 static int initialize_non_removable(usb_hub_info_t * hub_info, 91 unsigned int port); 92 59 93 static int usb_hub_trigger_connecting_non_removable_devices( 60 94 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 61 95 62 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);63 64 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);65 66 static int usb_hub_set_configuration(usb_hub_info_t * hub_info);67 68 69 static int usb_hub_trigger_connecting_non_removable_devices(70 usb_hub_info_t * hub,71 usb_hub_descriptor_t * descriptor);72 73 static int usb_hub_release_default_address(usb_hub_info_t * hub);74 75 static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,76 usb_speed_t speed);77 78 static void usb_hub_finalize_add_device(usb_hub_info_t * hub,79 uint16_t port, usb_speed_t speed);80 81 static void usb_hub_removed_device(82 usb_hub_info_t * hub, uint16_t port);83 84 static void usb_hub_port_over_current(usb_hub_info_t * hub,85 uint16_t port, uint32_t status);86 87 static void usb_hub_process_interrupt(usb_hub_info_t * hub,88 uint16_t port);89 90 static int usb_process_hub_over_current(usb_hub_info_t * hub_info,91 usb_hub_status_t status);92 93 static int usb_process_hub_power_change(usb_hub_info_t * hub_info,94 usb_hub_status_t status);95 96 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);97 98 static int initialize_non_removable(usb_hub_info_t * hub_info,99 unsigned int port);100 96 101 97 /** … … 121 117 return 0; 122 118 } 123 124 /// \TODO set_port_feature use 125 /// \TODO unmess code 119 /// \TODO malloc checking 126 120 127 121 //********************************************* … … 447 441 } 448 442 443 /** 444 * release default address used by given hub 445 * 446 * Also unsets hub->is_default_address_used. Convenience wrapper function. 447 * @note hub->connection MUST be open for communication 448 * @param hub hub representation 449 * @return error code 450 */ 451 static int usb_hub_release_default_address(usb_hub_info_t * hub) { 452 int opResult = usb_hc_release_default_address(&hub->connection); 453 if (opResult != EOK) { 454 usb_log_error("could not release default address, errno %d\n", 455 opResult); 456 return opResult; 457 } 458 hub->is_default_address_used = false; 459 return EOK; 460 } 461 462 /** 463 * Reset the port with new device and reserve the default address. 464 * @param hub hub representation 465 * @param port port number, starting from 1 466 * @param speed transfer speed of attached device, one of low, full or high 467 * @return error code 468 */ 469 static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port, 470 usb_speed_t speed) { 471 //if this hub already uses default address, it cannot request it once more 472 if (hub->is_default_address_used) return EREFUSED; 473 usb_log_debug("some connection changed\n"); 474 assert(hub->control_pipe->hc_phone); 475 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 476 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 477 if (opResult != EOK) { 478 usb_log_warning("could not clear port-change-connection flag\n"); 479 } 480 usb_device_request_setup_packet_t request; 481 482 //get default address 483 opResult = usb_hc_reserve_default_address(&hub->connection, speed); 484 485 if (opResult != EOK) { 486 usb_log_warning("cannot assign default address, it is probably " 487 "used %d\n", 488 opResult); 489 return opResult; 490 } 491 hub->is_default_address_used = true; 492 //reset port 493 usb_hub_set_reset_port_request(&request, port); 494 opResult = usb_pipe_control_write( 495 hub->control_pipe, 496 &request, sizeof (usb_device_request_setup_packet_t), 497 NULL, 0 498 ); 499 if (opResult != EOK) { 500 usb_log_error("something went wrong when reseting a port %d\n", 501 opResult); 502 usb_hub_release_default_address(hub); 503 } 504 return opResult; 505 } 506 507 /** 508 * Finalize adding new device after port reset 509 * 510 * Set device`s address and start it`s driver. 511 * @param hub hub representation 512 * @param port port number, starting from 1 513 * @param speed transfer speed of attached device, one of low, full or high 514 */ 515 static void usb_hub_finalize_add_device(usb_hub_info_t * hub, 516 uint16_t port, usb_speed_t speed) { 517 518 int opResult; 519 usb_log_debug("finalizing add device\n"); 520 opResult = usb_hub_clear_port_feature(hub->control_pipe, 521 port, USB_HUB_FEATURE_C_PORT_RESET); 522 523 if (opResult != EOK) { 524 usb_log_error("failed to clear port reset feature\n"); 525 usb_hub_release_default_address(hub); 526 return; 527 } 528 //create connection to device 529 usb_pipe_t new_device_pipe; 530 usb_device_connection_t new_device_connection; 531 usb_device_connection_initialize_on_default_address( 532 &new_device_connection, 533 &hub->connection 534 ); 535 usb_pipe_initialize_default_control( 536 &new_device_pipe, 537 &new_device_connection); 538 usb_pipe_probe_default_control(&new_device_pipe); 539 540 /* Request address from host controller. */ 541 usb_address_t new_device_address = usb_hc_request_address( 542 &hub->connection, 543 speed 544 ); 545 if (new_device_address < 0) { 546 usb_log_error("failed to get free USB address\n"); 547 opResult = new_device_address; 548 usb_hub_release_default_address(hub); 549 return; 550 } 551 usb_log_debug("setting new address %d\n", new_device_address); 552 //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT, 553 // new_device_address); 554 usb_pipe_start_session(&new_device_pipe); 555 opResult = usb_request_set_address(&new_device_pipe, 556 new_device_address); 557 usb_pipe_end_session(&new_device_pipe); 558 if (opResult != EOK) { 559 usb_log_error("could not set address for new device %d\n", 560 opResult); 561 usb_hub_release_default_address(hub); 562 return; 563 } 564 565 //opResult = usb_hub_release_default_address(hc); 566 opResult = usb_hub_release_default_address(hub); 567 if (opResult != EOK) { 568 return; 569 } 570 571 devman_handle_t child_handle; 572 //?? 573 opResult = usb_device_register_child_in_devman(new_device_address, 574 hub->connection.hc_handle, hub->usb_device->ddf_dev, 575 &child_handle, 576 NULL, NULL, NULL); 577 578 if (opResult != EOK) { 579 usb_log_error("could not start driver for new device %d\n", 580 opResult); 581 return; 582 } 583 hub->attached_devs[port].handle = child_handle; 584 hub->attached_devs[port].address = new_device_address; 585 586 //opResult = usb_drv_bind_address(hc, new_device_address, child_handle); 587 opResult = usb_hc_register_device( 588 &hub->connection, 589 &hub->attached_devs[port]); 590 if (opResult != EOK) { 591 usb_log_error("could not assign address of device in hcd %d\n", 592 opResult); 593 return; 594 } 595 usb_log_info("Detected new device on `%s' (port %d), " \ 596 "address %d (handle %llu).\n", 597 hub->usb_device->ddf_dev->name, (int) port, 598 new_device_address, child_handle); 599 } 600 601 /** 602 * routine called when a device on port has been removed 603 * 604 * If the device on port had default address, it releases default address. 605 * Otherwise does not do anything, because DDF does not allow to remove device 606 * from it`s device tree. 607 * @param hub hub representation 608 * @param port port number, starting from 1 609 */ 610 static void usb_hub_removed_device( 611 usb_hub_info_t * hub, uint16_t port) { 612 613 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 614 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 615 if (opResult != EOK) { 616 usb_log_warning("could not clear port-change-connection flag\n"); 617 } 618 /** \TODO remove device from device manager - not yet implemented in 619 * devide manager 620 */ 621 622 //close address 623 if (hub->attached_devs[port].address != 0) { 624 /*uncomment this code to use it when DDF allows device removal 625 opResult = usb_hc_unregister_device( 626 &hub->connection, 627 hub->attached_devs[port].address); 628 if(opResult != EOK) { 629 dprintf(USB_LOG_LEVEL_WARNING, "could not release " 630 "address of " 631 "removed device: %d", opResult); 632 } 633 hub->attached_devs[port].address = 0; 634 hub->attached_devs[port].handle = 0; 635 */ 636 } else { 637 usb_log_warning("this is strange, disconnected device had " 638 "no address\n"); 639 //device was disconnected before it`s port was reset - 640 //return default address 641 usb_hub_release_default_address(hub); 642 } 643 } 644 645 /** 646 * Process over current condition on port. 647 * 648 * Turn off the power on the port. 649 * 650 * @param hub hub representation 651 * @param port port number, starting from 1 652 */ 653 static void usb_hub_port_over_current(usb_hub_info_t * hub, 654 uint16_t port, uint32_t status) { 655 int opResult; 656 if(usb_port_over_current(&status)){ 657 opResult = usb_hub_clear_port_feature(hub->control_pipe, 658 port, USB_HUB_FEATURE_PORT_POWER); 659 if (opResult != EOK) { 660 usb_log_error("cannot power off port %d; %d\n", 661 port, opResult); 662 } 663 }else{ 664 opResult = usb_hub_set_port_feature(hub->control_pipe, 665 port, USB_HUB_FEATURE_PORT_POWER); 666 if (opResult != EOK) { 667 usb_log_error("cannot power on port %d; %d\n", 668 port, opResult); 669 } 670 } 671 } 672 673 /** 674 * Process interrupts on given hub port 675 * 676 * Accepts connection, over current and port reset change. 677 * @param hub hub representation 678 * @param port port number, starting from 1 679 */ 680 static void usb_hub_process_interrupt(usb_hub_info_t * hub, 681 uint16_t port) { 682 usb_log_debug("interrupt at port %d\n", port); 683 //determine type of change 684 usb_pipe_t *pipe = hub->control_pipe; 685 686 int opResult; 687 688 usb_port_status_t status; 689 size_t rcvd_size; 690 usb_device_request_setup_packet_t request; 691 //int opResult; 692 usb_hub_set_port_status_request(&request, port); 693 //endpoint 0 694 695 opResult = usb_pipe_control_read( 696 pipe, 697 &request, sizeof (usb_device_request_setup_packet_t), 698 &status, 4, &rcvd_size 699 ); 700 if (opResult != EOK) { 701 usb_log_error("could not get port status\n"); 702 return; 703 } 704 if (rcvd_size != sizeof (usb_port_status_t)) { 705 usb_log_error("received status has incorrect size\n"); 706 return; 707 } 708 //something connected/disconnected 709 if (usb_port_connect_change(&status)) { 710 usb_log_debug("connection change on port\n"); 711 if (usb_port_dev_connected(&status)) { 712 usb_log_debug("some connection changed\n"); 713 usb_hub_init_add_device(hub, port, 714 usb_port_speed(&status)); 715 } else { 716 usb_hub_removed_device(hub, port); 717 } 718 } 719 //over current 720 if (usb_port_overcurrent_change(&status)) { 721 //check if it was not auto-resolved 722 usb_log_debug("overcurrent change on port\n"); 723 usb_hub_port_over_current(hub, port, status); 724 } 725 //port reset 726 if (usb_port_reset_completed(&status)) { 727 usb_log_debug("port reset complete\n"); 728 if (usb_port_enabled(&status)) { 729 usb_hub_finalize_add_device(hub, port, 730 usb_port_speed(&status)); 731 } else { 732 usb_log_warning("port reset, but port still not " 733 "enabled\n"); 734 } 735 } 736 usb_log_debug("status x%x : %d\n ", status, status); 737 738 usb_port_set_connect_change(&status, false); 739 usb_port_set_reset(&status, false); 740 usb_port_set_reset_completed(&status, false); 741 usb_port_set_dev_connected(&status, false); 742 usb_port_set_overcurrent_change(&status,false); 743 /// \TODO what about port power change? 744 if (status >> 16) { 745 usb_log_info("there was some unsupported change on port %d: %X\n", 746 port, status); 747 748 } 749 } 750 751 /** 752 * process hub over current change 753 * 754 * This means either to power off the hub or power it on. 755 * @param hub_info hub instance 756 * @param status hub status bitmask 757 * @return error code 758 */ 759 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 760 usb_hub_status_t status) 761 { 762 int opResult; 763 if(usb_hub_over_current(&status)){ 764 opResult = usb_hub_clear_feature(hub_info->control_pipe, 765 USB_HUB_FEATURE_PORT_POWER); 766 if (opResult != EOK) { 767 usb_log_error("cannot power off hub: %d\n", 768 opResult); 769 } 770 }else{ 771 opResult = usb_hub_set_feature(hub_info->control_pipe, 772 USB_HUB_FEATURE_PORT_POWER); 773 if (opResult != EOK) { 774 usb_log_error("cannot power on hub: %d\n", 775 opResult); 776 } 777 } 778 return opResult; 779 } 780 781 /** 782 * process hub power change 783 * 784 * If the power has been lost, reestablish it. 785 * If it was reestablished, re-power all ports. 786 * @param hub_info hub instance 787 * @param status hub status bitmask 788 * @return error code 789 */ 790 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 791 usb_hub_status_t status) 792 { 793 int opResult; 794 if(usb_hub_local_power_lost(&status)){ 795 //restart power on hub 796 opResult = usb_hub_set_feature(hub_info->control_pipe, 797 USB_HUB_FEATURE_PORT_POWER); 798 if (opResult != EOK) { 799 usb_log_error("cannot power on hub: %d\n", 800 opResult); 801 } 802 }else{//power reestablished on hub- restart ports 803 int port; 804 for(port=0;port<hub_info->port_count;++port){ 805 opResult = usb_hub_set_port_feature( 806 hub_info->control_pipe, 807 port, USB_HUB_FEATURE_PORT_POWER); 808 if (opResult != EOK) { 809 usb_log_error("cannot power on port %d; %d\n", 810 port, opResult); 811 } 812 } 813 } 814 return opResult; 815 } 816 817 /** 818 * process hub interrupts 819 * 820 * The change can be either in the over-current condition or 821 * local-power lost condition. 822 * @param hub_info hub instance 823 */ 824 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info){ 825 usb_log_debug("global interrupt on a hub\n"); 826 usb_pipe_t *pipe = hub_info->control_pipe; 827 int opResult; 828 829 usb_port_status_t status; 830 size_t rcvd_size; 831 usb_device_request_setup_packet_t request; 832 //int opResult; 833 usb_hub_set_hub_status_request(&request); 834 //endpoint 0 835 836 opResult = usb_pipe_control_read( 837 pipe, 838 &request, sizeof (usb_device_request_setup_packet_t), 839 &status, 4, &rcvd_size 840 ); 841 if (opResult != EOK) { 842 usb_log_error("could not get hub status\n"); 843 return; 844 } 845 if (rcvd_size != sizeof (usb_port_status_t)) { 846 usb_log_error("received status has incorrect size\n"); 847 return; 848 } 849 //port reset 850 if (usb_hub_over_current_change(&status)) { 851 usb_process_hub_over_current(hub_info,status); 852 } 853 if (usb_hub_local_power_change(&status)) { 854 usb_process_hub_power_change(hub_info,status); 855 } 856 } 857 858 //-----------attempts to solve non-removable------------------------ 859 //-----------attempts to solve non-removable------------------------ 860 //-----------attempts to solve non-removable------------------------ 861 //-----------attempts to solve non-removable------------------------ 862 863 /** 864 * this is an attempt to initialize non-removable devices in the hub 865 * 866 * @param hub_info hub instance 867 * @param port port number, counting from 1 868 * @return error code 869 */ 870 static int initialize_non_removable(usb_hub_info_t * hub_info, 871 unsigned int port) { 872 int opResult; 873 usb_log_debug("there is not pluged in non-removable device on " 874 "port %d\n", port 875 ); 876 //usb_hub_init_add_device(hub_info, port, usb_port_speed(&status)); 877 usb_port_status_t status; 878 size_t rcvd_size; 879 usb_device_request_setup_packet_t request; 880 //int opResult; 881 usb_hub_set_port_status_request(&request, port); 882 //endpoint 0 883 884 opResult = usb_pipe_control_read( 885 hub_info->control_pipe, 886 &request, sizeof (usb_device_request_setup_packet_t), 887 &status, 4, &rcvd_size 888 ); 889 if (opResult != EOK) { 890 usb_log_error("could not get port status %d\n", opResult); 891 return opResult; 892 } 893 if (rcvd_size != sizeof (usb_port_status_t)) { 894 usb_log_error("received status has incorrect size\n"); 895 return opResult; 896 } 897 usb_log_debug("port status %d, x%x\n", status, status); 898 if (usb_port_dev_connected(&status)) { 899 usb_log_debug("there is connected device on this port\n"); 900 }else{ 901 usb_log_debug("the non-removable device is not connected\n"); 902 } 903 if (!hub_info->is_default_address_used) 904 usb_hub_init_add_device(hub_info, port, 905 usb_port_speed(&status)); 906 return opResult; 907 } 449 908 450 909 /** … … 467 926 uint8_t * non_removable_dev_bitmap = descriptor->devices_removable; 468 927 int port; 469 928 #if 0 470 929 opResult = usb_request_set_configuration(hub->control_pipe, 471 930 1); … … 475 934 return opResult; 476 935 } 477 #if 0 936 478 937 for (port = 1; port <= descriptor->ports_count; ++port) { 479 938 bool is_non_removable = … … 590 1049 usb_log_debug("some connection changed\n"); 591 1050 } 1051 if(usb_port_dev_connected(&status)){ 1052 usb_log_debug("device connected on port\n"); 1053 } 592 1054 usb_log_debug("status: %s\n", usb_debug_str_buffer( 593 1055 (uint8_t *) & status, 4, 4)); 594 1056 } 595 1057 } 596 1058 async_usleep(1000*1000*10); 597 1059 return EOK; 598 1060 } 599 1061 600 /**601 * release default address used by given hub602 *603 * Also unsets hub->is_default_address_used. Convenience wrapper function.604 * @note hub->connection MUST be open for communication605 * @param hub hub representation606 * @return error code607 */608 static int usb_hub_release_default_address(usb_hub_info_t * hub) {609 int opResult = usb_hc_release_default_address(&hub->connection);610 if (opResult != EOK) {611 usb_log_error("could not release default address, errno %d\n",612 opResult);613 return opResult;614 }615 hub->is_default_address_used = false;616 return EOK;617 }618 619 /**620 * Reset the port with new device and reserve the default address.621 * @param hub hub representation622 * @param port port number, starting from 1623 * @param speed transfer speed of attached device, one of low, full or high624 * @return error code625 */626 static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,627 usb_speed_t speed) {628 //if this hub already uses default address, it cannot request it once more629 if (hub->is_default_address_used) return EREFUSED;630 usb_log_debug("some connection changed\n");631 assert(hub->control_pipe->hc_phone);632 int opResult = usb_hub_clear_port_feature(hub->control_pipe,633 port, USB_HUB_FEATURE_C_PORT_CONNECTION);634 if (opResult != EOK) {635 usb_log_warning("could not clear port-change-connection flag\n");636 }637 usb_device_request_setup_packet_t request;638 639 //get default address640 opResult = usb_hc_reserve_default_address(&hub->connection, speed);641 642 if (opResult != EOK) {643 usb_log_warning("cannot assign default address, it is probably "644 "used %d\n",645 opResult);646 return opResult;647 }648 hub->is_default_address_used = true;649 //reset port650 usb_hub_set_reset_port_request(&request, port);651 opResult = usb_pipe_control_write(652 hub->control_pipe,653 &request, sizeof (usb_device_request_setup_packet_t),654 NULL, 0655 );656 if (opResult != EOK) {657 usb_log_error("something went wrong when reseting a port %d\n",658 opResult);659 usb_hub_release_default_address(hub);660 }661 return opResult;662 }663 664 /**665 * Finalize adding new device after port reset666 *667 * Set device`s address and start it`s driver.668 * @param hub hub representation669 * @param port port number, starting from 1670 * @param speed transfer speed of attached device, one of low, full or high671 */672 static void usb_hub_finalize_add_device(usb_hub_info_t * hub,673 uint16_t port, usb_speed_t speed) {674 675 int opResult;676 usb_log_debug("finalizing add device\n");677 opResult = usb_hub_clear_port_feature(hub->control_pipe,678 port, USB_HUB_FEATURE_C_PORT_RESET);679 680 if (opResult != EOK) {681 usb_log_error("failed to clear port reset feature\n");682 usb_hub_release_default_address(hub);683 return;684 }685 //create connection to device686 usb_pipe_t new_device_pipe;687 usb_device_connection_t new_device_connection;688 usb_device_connection_initialize_on_default_address(689 &new_device_connection,690 &hub->connection691 );692 usb_pipe_initialize_default_control(693 &new_device_pipe,694 &new_device_connection);695 usb_pipe_probe_default_control(&new_device_pipe);696 697 /* Request address from host controller. */698 usb_address_t new_device_address = usb_hc_request_address(699 &hub->connection,700 speed701 );702 if (new_device_address < 0) {703 usb_log_error("failed to get free USB address\n");704 opResult = new_device_address;705 usb_hub_release_default_address(hub);706 return;707 }708 usb_log_debug("setting new address %d\n", new_device_address);709 //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,710 // new_device_address);711 usb_pipe_start_session(&new_device_pipe);712 opResult = usb_request_set_address(&new_device_pipe,713 new_device_address);714 usb_pipe_end_session(&new_device_pipe);715 if (opResult != EOK) {716 usb_log_error("could not set address for new device %d\n",717 opResult);718 usb_hub_release_default_address(hub);719 return;720 }721 722 //opResult = usb_hub_release_default_address(hc);723 opResult = usb_hub_release_default_address(hub);724 if (opResult != EOK) {725 return;726 }727 728 devman_handle_t child_handle;729 //??730 opResult = usb_device_register_child_in_devman(new_device_address,731 hub->connection.hc_handle, hub->usb_device->ddf_dev,732 &child_handle,733 NULL, NULL, NULL);734 735 if (opResult != EOK) {736 usb_log_error("could not start driver for new device %d\n",737 opResult);738 return;739 }740 hub->attached_devs[port].handle = child_handle;741 hub->attached_devs[port].address = new_device_address;742 743 //opResult = usb_drv_bind_address(hc, new_device_address, child_handle);744 opResult = usb_hc_register_device(745 &hub->connection,746 &hub->attached_devs[port]);747 if (opResult != EOK) {748 usb_log_error("could not assign address of device in hcd %d\n",749 opResult);750 return;751 }752 usb_log_info("Detected new device on `%s' (port %d), " \753 "address %d (handle %llu).\n",754 hub->usb_device->ddf_dev->name, (int) port,755 new_device_address, child_handle);756 }757 758 /**759 * routine called when a device on port has been removed760 *761 * If the device on port had default address, it releases default address.762 * Otherwise does not do anything, because DDF does not allow to remove device763 * from it`s device tree.764 * @param hub hub representation765 * @param port port number, starting from 1766 */767 static void usb_hub_removed_device(768 usb_hub_info_t * hub, uint16_t port) {769 770 int opResult = usb_hub_clear_port_feature(hub->control_pipe,771 port, USB_HUB_FEATURE_C_PORT_CONNECTION);772 if (opResult != EOK) {773 usb_log_warning("could not clear port-change-connection flag\n");774 }775 /** \TODO remove device from device manager - not yet implemented in776 * devide manager777 */778 779 //close address780 if (hub->attached_devs[port].address != 0) {781 /*uncomment this code to use it when DDF allows device removal782 opResult = usb_hc_unregister_device(783 &hub->connection,784 hub->attached_devs[port].address);785 if(opResult != EOK) {786 dprintf(USB_LOG_LEVEL_WARNING, "could not release "787 "address of "788 "removed device: %d", opResult);789 }790 hub->attached_devs[port].address = 0;791 hub->attached_devs[port].handle = 0;792 */793 } else {794 usb_log_warning("this is strange, disconnected device had "795 "no address\n");796 //device was disconnected before it`s port was reset -797 //return default address798 usb_hub_release_default_address(hub);799 }800 }801 802 /**803 * Process over current condition on port.804 *805 * Turn off the power on the port.806 *807 * @param hub hub representation808 * @param port port number, starting from 1809 */810 static void usb_hub_port_over_current(usb_hub_info_t * hub,811 uint16_t port, uint32_t status) {812 /// \todo no, this is not proper sollution813 /// get affected ports814 /// power them off815 /// wait until there over-current is cleared816 /// power them on817 818 int opResult;819 if(usb_port_over_current(&status)){820 opResult = usb_hub_clear_port_feature(hub->control_pipe,821 port, USB_HUB_FEATURE_PORT_POWER);822 if (opResult != EOK) {823 usb_log_error("cannot power off port %d; %d\n",824 port, opResult);825 }826 }else{827 opResult = usb_hub_set_port_feature(hub->control_pipe,828 port, USB_HUB_FEATURE_PORT_POWER);829 if (opResult != EOK) {830 usb_log_error("cannot power on port %d; %d\n",831 port, opResult);832 }833 }834 }835 836 /**837 * Process interrupts on given hub port838 *839 * Accepts connection, over current and port reset change.840 * @param hub hub representation841 * @param port port number, starting from 1842 */843 static void usb_hub_process_interrupt(usb_hub_info_t * hub,844 uint16_t port) {845 usb_log_debug("interrupt at port %d\n", port);846 //determine type of change847 usb_pipe_t *pipe = hub->control_pipe;848 849 int opResult;850 851 usb_port_status_t status;852 size_t rcvd_size;853 usb_device_request_setup_packet_t request;854 //int opResult;855 usb_hub_set_port_status_request(&request, port);856 //endpoint 0857 858 opResult = usb_pipe_control_read(859 pipe,860 &request, sizeof (usb_device_request_setup_packet_t),861 &status, 4, &rcvd_size862 );863 if (opResult != EOK) {864 usb_log_error("could not get port status\n");865 return;866 }867 if (rcvd_size != sizeof (usb_port_status_t)) {868 usb_log_error("received status has incorrect size\n");869 return;870 }871 //something connected/disconnected872 if (usb_port_connect_change(&status)) {873 usb_log_debug("connection change on port\n");874 if (usb_port_dev_connected(&status)) {875 usb_log_debug("some connection changed\n");876 usb_hub_init_add_device(hub, port,877 usb_port_speed(&status));878 } else {879 usb_hub_removed_device(hub, port);880 }881 }882 //over current883 if (usb_port_overcurrent_change(&status)) {884 //check if it was not auto-resolved885 usb_log_debug("overcurrent change on port\n");886 usb_hub_port_over_current(hub, port, status);887 }888 //port reset889 if (usb_port_reset_completed(&status)) {890 usb_log_debug("port reset complete\n");891 if (usb_port_enabled(&status)) {892 usb_hub_finalize_add_device(hub, port,893 usb_port_speed(&status));894 } else {895 usb_log_warning("port reset, but port still not "896 "enabled\n");897 }898 }899 usb_log_debug("status x%x : %d\n ", status, status);900 901 usb_port_set_connect_change(&status, false);902 usb_port_set_reset(&status, false);903 usb_port_set_reset_completed(&status, false);904 usb_port_set_dev_connected(&status, false);905 if (status >> 16) {906 usb_log_info("there was some unsupported change on port %d: %X\n",907 port, status);908 909 }910 }911 912 /**913 * process hub over current change914 *915 * This means either to power off the hub or power it on.916 * @param hub_info hub instance917 * @param status hub status bitmask918 * @return error code919 */920 static int usb_process_hub_over_current(usb_hub_info_t * hub_info,921 usb_hub_status_t status)922 {923 int opResult;924 if(usb_hub_over_current(&status)){925 opResult = usb_hub_clear_feature(hub_info->control_pipe,926 USB_HUB_FEATURE_PORT_POWER);927 if (opResult != EOK) {928 usb_log_error("cannot power off hub: %d\n",929 opResult);930 }931 }else{932 opResult = usb_hub_set_feature(hub_info->control_pipe,933 USB_HUB_FEATURE_PORT_POWER);934 if (opResult != EOK) {935 usb_log_error("cannot power on hub: %d\n",936 opResult);937 }938 }939 return opResult;940 }941 942 /**943 * process hub power change944 *945 * If the power has been lost, reestablish it.946 * If it was reestablished, re-power all ports.947 * @param hub_info hub instance948 * @param status hub status bitmask949 * @return error code950 */951 static int usb_process_hub_power_change(usb_hub_info_t * hub_info,952 usb_hub_status_t status)953 {954 int opResult;955 if(usb_hub_local_power_lost(&status)){956 //restart power on hub957 opResult = usb_hub_set_feature(hub_info->control_pipe,958 USB_HUB_FEATURE_PORT_POWER);959 if (opResult != EOK) {960 usb_log_error("cannot power on hub: %d\n",961 opResult);962 }963 }else{//power reestablished on hub- restart ports964 int port;965 for(port=0;port<hub_info->port_count;++port){966 opResult = usb_hub_set_port_feature(967 hub_info->control_pipe,968 port, USB_HUB_FEATURE_PORT_POWER);969 if (opResult != EOK) {970 usb_log_error("cannot power on port %d; %d\n",971 port, opResult);972 }973 }974 }975 return opResult;976 }977 978 /**979 * process hub interrupts980 *981 * The change can be either in the over-current condition or982 * local-power lost condition.983 * @param hub_info hub instance984 */985 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info){986 usb_log_debug("global interrupt on a hub\n");987 usb_pipe_t *pipe = hub_info->control_pipe;988 int opResult;989 990 usb_port_status_t status;991 size_t rcvd_size;992 usb_device_request_setup_packet_t request;993 //int opResult;994 usb_hub_set_hub_status_request(&request);995 //endpoint 0996 997 opResult = usb_pipe_control_read(998 pipe,999 &request, sizeof (usb_device_request_setup_packet_t),1000 &status, 4, &rcvd_size1001 );1002 if (opResult != EOK) {1003 usb_log_error("could not get hub status\n");1004 return;1005 }1006 if (rcvd_size != sizeof (usb_port_status_t)) {1007 usb_log_error("received status has incorrect size\n");1008 return;1009 }1010 //port reset1011 if (usb_hub_over_current_change(&status)) {1012 usb_process_hub_over_current(hub_info,status);1013 }1014 if (usb_hub_local_power_change(&status)) {1015 usb_process_hub_power_change(hub_info,status);1016 }1017 }1018 1019 /**1020 * this is an attempt to initialize non-removable devices in the hub1021 *1022 * @param hub_info hub instance1023 * @param port port number, counting from 11024 * @return error code1025 */1026 static int initialize_non_removable(usb_hub_info_t * hub_info,1027 unsigned int port) {1028 int opResult;1029 usb_log_debug("there is not pluged in non-removable device on "1030 "port %d\n", port1031 );1032 //usb_hub_init_add_device(hub_info, port, usb_port_speed(&status));1033 usb_port_status_t status;1034 size_t rcvd_size;1035 usb_device_request_setup_packet_t request;1036 //int opResult;1037 usb_hub_set_port_status_request(&request, port);1038 //endpoint 01039 1040 opResult = usb_pipe_control_read(1041 hub_info->control_pipe,1042 &request, sizeof (usb_device_request_setup_packet_t),1043 &status, 4, &rcvd_size1044 );1045 if (opResult != EOK) {1046 usb_log_error("could not get port status %d\n", opResult);1047 return opResult;1048 }1049 if (rcvd_size != sizeof (usb_port_status_t)) {1050 usb_log_error("received status has incorrect size\n");1051 return opResult;1052 }1053 usb_log_debug("port status %d, x%x\n", status, status);1054 if (usb_port_dev_connected(&status)) {1055 usb_log_debug("there is connected device on this port\n");1056 }1057 if (!hub_info->is_default_address_used)1058 usb_hub_init_add_device(hub_info, port,1059 usb_port_speed(&status));1060 return opResult;1061 }1062 1063 1064 1062 1065 1063 /**
Note:
See TracChangeset
for help on using the changeset viewer.