Changeset e5ccfd1 in mainline


Ignore:
Timestamp:
2011-04-07T06:55:22Z (13 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d7f3040
Parents:
a209648
Message:

fix attepmt #1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhub/usbhub.c

    ra209648 re5ccfd1  
    5757        usb_speed_t speed);
    5858
     59static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
     60
     61static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
     62
     63static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
     64
     65static int usb_hub_release_default_address(usb_hub_info_t * hub);
     66
     67static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,
     68        usb_speed_t speed);
     69
     70static void usb_hub_finalize_add_device(usb_hub_info_t * hub,
     71        uint16_t port, usb_speed_t speed);
     72
     73static void usb_hub_removed_device(
     74        usb_hub_info_t * hub, uint16_t port);
     75
     76static void usb_hub_port_over_current(usb_hub_info_t * hub,
     77        uint16_t port, uint32_t status);
     78
     79static void usb_hub_process_interrupt(usb_hub_info_t * hub,
     80        uint16_t port);
     81
     82static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     83        usb_hub_status_t status);
     84
     85static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     86        usb_hub_status_t status);
     87
     88static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
     89
     90static int initialize_non_removable(usb_hub_info_t * hub_info,
     91        unsigned int port);
     92
    5993static int usb_hub_trigger_connecting_non_removable_devices(
    6094        usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor);
    6195
    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);
    10096
    10197/**
     
    121117        return 0;
    122118}
    123 
    124 /// \TODO set_port_feature use
    125 /// \TODO unmess code
     119/// \TODO malloc checking
    126120
    127121//*********************************************
     
    447441}
    448442
     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 */
     451static 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 */
     469static 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 */
     515static 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 */
     610static 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 */
     653static 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 */
     680static 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 */
     759static 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 */
     790static 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 */
     824static 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 */
     870static 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}
    449908
    450909/**
     
    467926        uint8_t * non_removable_dev_bitmap = descriptor->devices_removable;
    468927        int port;
    469 
     928#if 0
    470929        opResult = usb_request_set_configuration(hub->control_pipe,
    471930                1);
     
    475934                return opResult;
    476935        }
    477 #if 0
     936
    478937        for (port = 1; port <= descriptor->ports_count; ++port) {
    479938                bool is_non_removable =
     
    5901049                                usb_log_debug("some connection changed\n");
    5911050                        }
     1051                        if(usb_port_dev_connected(&status)){
     1052                                usb_log_debug("device connected on port\n");
     1053                        }
    5921054                        usb_log_debug("status: %s\n", usb_debug_str_buffer(
    5931055                                (uint8_t *) & status, 4, 4));
    5941056                }
    5951057        }
    596 
     1058        async_usleep(1000*1000*10);
    5971059        return EOK;
    5981060}
    5991061
    600 /**
    601  * release default address used by given hub
    602  *
    603  * Also unsets hub->is_default_address_used. Convenience wrapper function.
    604  * @note hub->connection MUST be open for communication
    605  * @param hub hub representation
    606  * @return error code
    607  */
    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 representation
    622  * @param port port number, starting from 1
    623  * @param speed transfer speed of attached device, one of low, full or high
    624  * @return error code
    625  */
    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 more
    629         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 address
    640         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 port
    650         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, 0
    655                 );
    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 reset
    666  *
    667  * Set device`s address and start it`s driver.
    668  * @param hub hub representation
    669  * @param port port number, starting from 1
    670  * @param speed transfer speed of attached device, one of low, full or high
    671  */
    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 device
    686         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->connection
    691                 );
    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                 speed
    701                 );
    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 removed
    760  *
    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 device
    763  * from it`s device tree.
    764  * @param hub hub representation
    765  * @param port port number, starting from 1
    766  */
    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 in
    776          * devide manager
    777          */
    778 
    779         //close address
    780         if (hub->attached_devs[port].address != 0) {
    781                 /*uncomment this code to use it when DDF allows device removal
    782                 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 address
    798                 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 representation
    808  * @param port port number, starting from 1
    809  */
    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 sollution
    813         /// get affected ports
    814         /// power them off
    815         /// wait until there over-current is cleared
    816         /// power them on
    817 
    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 port
    838  *
    839  * Accepts connection, over current and port reset change.
    840  * @param hub hub representation
    841  * @param port port number, starting from 1
    842  */
    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 change
    847         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 0
    857 
    858         opResult = usb_pipe_control_read(
    859                 pipe,
    860                 &request, sizeof (usb_device_request_setup_packet_t),
    861                 &status, 4, &rcvd_size
    862                 );
    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/disconnected
    872         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 current
    883         if (usb_port_overcurrent_change(&status)) {
    884                 //check if it was not auto-resolved
    885                 usb_log_debug("overcurrent change on port\n");
    886                 usb_hub_port_over_current(hub, port, status);
    887         }
    888         //port reset
    889         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 change
    914  *
    915  * This means either to power off the hub or power it on.
    916  * @param hub_info hub instance
    917  * @param status hub status bitmask
    918  * @return error code
    919  */
    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 change
    944  *
    945  * If the power has been lost, reestablish it.
    946  * If it was reestablished, re-power all ports.
    947  * @param hub_info hub instance
    948  * @param status hub status bitmask
    949  * @return error code
    950  */
    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 hub
    957                 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 ports
    964                 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 interrupts
    980  *
    981  * The change can be either in the over-current condition or
    982  * local-power lost condition.
    983  * @param hub_info hub instance
    984  */
    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 0
    996 
    997         opResult = usb_pipe_control_read(
    998                 pipe,
    999                 &request, sizeof (usb_device_request_setup_packet_t),
    1000                 &status, 4, &rcvd_size
    1001                 );
    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 reset
    1011         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 hub
    1021  *
    1022  * @param hub_info hub instance
    1023  * @param port port number, counting from 1
    1024  * @return error code
    1025  */
    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", port
    1031                 );
    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 0
    1039 
    1040         opResult = usb_pipe_control_read(
    1041                 hub_info->control_pipe,
    1042                 &request, sizeof (usb_device_request_setup_packet_t),
    1043                 &status, 4, &rcvd_size
    1044                 );
    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 
    10641062
    10651063/**
Note: See TracChangeset for help on using the changeset viewer.