Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/hub.c

    r4ede178 r1c258d1  
    4040#include <errno.h>
    4141#include <assert.h>
     42#include <usb/debug.h>
     43
     44/** How much time to wait between attempts to register endpoint 0:0.
     45 * The value is based on typical value for port reset + some overhead.
     46 */
     47#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
    4248
    4349/** Check that HC connection is alright.
     
    5258                } \
    5359        } while (false)
    54 
    55 
    56 /** Tell host controller to reserve default address.
    57  *
    58  * @param connection Opened connection to host controller.
    59  * @param speed Speed of the device that will respond on the default address.
    60  * @return Error code.
    61  */
    62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    63     usb_speed_t speed)
    64 {
    65         CHECK_CONNECTION(connection);
    66 
    67         return async_req_2_0(connection->hc_phone,
    68             DEV_IFACE_ID(USBHC_DEV_IFACE),
    69             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
    70 }
    71 
    72 /** Tell host controller to release default address.
    73  *
    74  * @param connection Opened connection to host controller.
    75  * @return Error code.
    76  */
    77 int usb_hc_release_default_address(usb_hc_connection_t *connection)
    78 {
    79         CHECK_CONNECTION(connection);
    80 
    81         return async_req_1_0(connection->hc_phone,
    82             DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    84 }
    8560
    8661/** Ask host controller for free address assignment.
     
    235210        }
    236211
    237 
    238         /*
    239          * Reserve the default address.
    240          */
    241         rc = usb_hc_reserve_default_address(&hc_conn, dev_speed);
    242         if (rc != EOK) {
    243                 rc = EBUSY;
    244                 goto leave_release_free_address;
    245         }
    246 
    247         /*
    248          * Enable the port (i.e. allow signaling through this port).
    249          */
    250         rc = enable_port(port_no, arg);
    251         if (rc != EOK) {
    252                 goto leave_release_default_address;
    253         }
    254 
    255         /*
    256          * Change the address from default to the free one.
    257          * We need to create a new control pipe for that.
     212        /*
     213         * We will not register control pipe on default address.
     214         * The registration might fail. That means that someone else already
     215         * registered that endpoint. We will simply wait and try again.
     216         * (Someone else already wants to add a new device.)
    258217         */
    259218        usb_device_connection_t dev_conn;
     
    262221        if (rc != EOK) {
    263222                rc = ENOTCONN;
    264                 goto leave_release_default_address;
     223                goto leave_release_free_address;
    265224        }
    266225
     
    270229        if (rc != EOK) {
    271230                rc = ENOTCONN;
     231                goto leave_release_free_address;
     232        }
     233
     234        do {
     235                rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
     236                    &hc_conn);
     237                if (rc != EOK) {
     238                        /* Do not overheat the CPU ;-). */
     239                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
     240                }
     241        } while (rc != EOK);
     242
     243        /*
     244         * Endpoint is registered. We can enable the port and change
     245         * device address.
     246         */
     247        rc = enable_port(port_no, arg);
     248        if (rc != EOK) {
    272249                goto leave_release_default_address;
    273250        }
    274251
    275         /* Before sending any traffic, we need to register this
    276          * endpoint.
     252        rc = usb_pipe_probe_default_control(&ctrl_pipe);
     253        if (rc != EOK) {
     254                rc = ESTALL;
     255                goto leave_release_default_address;
     256        }
     257
     258        rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     259        if (rc != EOK) {
     260                rc = ESTALL;
     261                goto leave_release_default_address;
     262        }
     263
     264        /*
     265         * Address changed. We can release the original endpoint, thus
     266         * allowing other to access the default address.
     267         */
     268        unregister_control_endpoint_on_default_address(&hc_conn);
     269
     270        /*
     271         * Time to register the new endpoint.
    277272         */
    278273        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    279274        if (rc != EOK) {
    280                 rc = EREFUSED;
    281                 goto leave_release_default_address;
    282         }
    283         rc = usb_pipe_probe_default_control(&ctrl_pipe);
    284         if (rc != EOK) {
    285                 rc = ENOTCONN;
    286                 goto leave_release_default_address;
    287         }
    288 
    289         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    290         if (rc != EOK) {
    291                 rc = ESTALL;
    292                 goto leave_stop_session;
    293         }
    294 
    295         /*
    296          * Register the control endpoint for the new device.
    297          */
    298         rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    299         if (rc != EOK) {
    300                 rc = EREFUSED;
    301                 goto leave_unregister_endpoint;
    302         }
    303 
    304         /*
    305          * Release the original endpoint.
    306          */
    307         unregister_control_endpoint_on_default_address(&hc_conn);
    308 
    309         /*
    310          * Once the address is changed, we can return the default address.
    311          */
    312         usb_hc_release_default_address(&hc_conn);
    313 
     275                goto leave_release_free_address;
     276        }
    314277
    315278        /*
     
    326289        }
    327290
    328 
    329 
    330291        /*
    331292         * And now inform the host controller about the handle.
     
    359320         * Completely ignoring errors here.
    360321         */
    361 
    362 leave_stop_session:
    363         usb_pipe_end_session(&ctrl_pipe);
    364 
    365 leave_unregister_endpoint:
     322leave_release_default_address:
    366323        usb_pipe_unregister(&ctrl_pipe, &hc_conn);
    367 
    368 leave_release_default_address:
    369         usb_hc_release_default_address(&hc_conn);
    370324
    371325leave_release_free_address:
Note: See TracChangeset for help on using the changeset viewer.