Ignore:
File:
1 edited

Legend:

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

    r1c258d1 r4ede178  
    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))
    4842
    4943/** Check that HC connection is alright.
     
    5852                } \
    5953        } 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 */
     62int 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 */
     77int 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}
    6085
    6186/** Ask host controller for free address assignment.
     
    210235        }
    211236
    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.)
     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.
    217258         */
    218259        usb_device_connection_t dev_conn;
     
    221262        if (rc != EOK) {
    222263                rc = ENOTCONN;
    223                 goto leave_release_free_address;
     264                goto leave_release_default_address;
    224265        }
    225266
     
    229270        if (rc != EOK) {
    230271                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) {
    249                 goto leave_release_default_address;
    250         }
    251 
     272                goto leave_release_default_address;
     273        }
     274
     275        /* Before sending any traffic, we need to register this
     276         * endpoint.
     277         */
     278        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
     279        if (rc != EOK) {
     280                rc = EREFUSED;
     281                goto leave_release_default_address;
     282        }
    252283        rc = usb_pipe_probe_default_control(&ctrl_pipe);
    253284        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) {
    254291                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.
     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.
    267306         */
    268307        unregister_control_endpoint_on_default_address(&hc_conn);
    269308
    270309        /*
    271          * Time to register the new endpoint.
    272          */
    273         rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    274         if (rc != EOK) {
    275                 goto leave_release_free_address;
    276         }
     310         * Once the address is changed, we can return the default address.
     311         */
     312        usb_hc_release_default_address(&hc_conn);
     313
    277314
    278315        /*
     
    289326        }
    290327
     328
     329
    291330        /*
    292331         * And now inform the host controller about the handle.
     
    320359         * Completely ignoring errors here.
    321360         */
     361
     362leave_stop_session:
     363        usb_pipe_end_session(&ctrl_pipe);
     364
     365leave_unregister_endpoint:
     366        usb_pipe_unregister(&ctrl_pipe, &hc_conn);
     367
    322368leave_release_default_address:
    323         usb_pipe_unregister(&ctrl_pipe, &hc_conn);
     369        usb_hc_release_default_address(&hc_conn);
    324370
    325371leave_release_free_address:
Note: See TracChangeset for help on using the changeset viewer.