Ignore:
File:
1 edited

Legend:

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

    r6e3c005 r2179cf95  
    3838#include <usb/dev/recognise.h>
    3939#include <usb/debug.h>
     40#include <usbhc_iface.h>
    4041#include <errno.h>
    4142#include <assert.h>
     
    4445#include <async.h>
    4546
    46 /** How much time to wait between attempts to get the default address.
     47/** How much time to wait between attempts to register endpoint 0:0.
    4748 * The value is based on typical value for port reset + some overhead.
    4849 */
    49 #define DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
     50#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
     51
     52/** Check that HC connection is alright.
     53 *
     54 * @param conn Connection to be checked.
     55 */
     56#define CHECK_CONNECTION(conn) \
     57        do { \
     58                assert((conn)); \
     59                if (!usb_hc_connection_is_opened((conn))) { \
     60                        usb_log_error("Connection not open.\n"); \
     61                        return ENOTCONN; \
     62                } \
     63        } while (false)
     64
     65/** Ask host controller for free address assignment.
     66 *
     67 * @param connection Opened connection to host controller.
     68 * @param preferred Preferred SUB address.
     69 * @param strict Fail if the preferred address is not avialable.
     70 * @param speed Speed of the new device (device that will be assigned
     71 *    the returned address).
     72 * @return Assigned USB address or negative error code.
     73 */
     74usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
     75    usb_address_t preferred, bool strict, usb_speed_t speed)
     76{
     77        CHECK_CONNECTION(connection);
     78       
     79        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     80       
     81        sysarg_t address;
     82        int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     83            IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address);
     84       
     85        async_exchange_end(exch);
     86       
     87        if (rc != EOK)
     88                return (usb_address_t) rc;
     89       
     90        return (usb_address_t) address;
     91}
    5092
    5193/** Inform host controller about new device.
     
    5597 * @return Error code.
    5698 */
    57 int usb_hub_register_device(usb_hc_connection_t *connection,
     99int usb_hc_register_device(usb_hc_connection_t * connection,
    58100    const usb_hub_attached_device_t *attached_device)
    59101{
    60         assert(connection);
    61         if (attached_device == NULL || attached_device->fun == NULL)
     102        CHECK_CONNECTION(connection);
     103       
     104        if (attached_device == NULL)
    62105                return EBADMEM;
    63         return usb_hc_bind_address(connection,
     106       
     107        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     108        int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     109            IPC_M_USBHC_BIND_ADDRESS,
    64110            attached_device->address, attached_device->fun->handle);
     111        async_exchange_end(exch);
     112       
     113        return rc;
     114}
     115
     116/** Inform host controller about device removal.
     117 *
     118 * @param connection Opened connection to host controller.
     119 * @param address Address of the device that is being removed.
     120 * @return Error code.
     121 */
     122int usb_hc_unregister_device(usb_hc_connection_t *connection,
     123    usb_address_t address)
     124{
     125        CHECK_CONNECTION(connection);
     126       
     127        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     128        int rc = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     129            IPC_M_USBHC_RELEASE_ADDRESS, address);
     130        async_exchange_end(exch);
     131       
     132        return rc;
    65133}
    66134
     
    79147 * @return Error code.
    80148 */
    81 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address)
     149static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
     150    usb_hc_connection_t *hc_conn)
    82151{
    83152        if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
     
    85154        }
    86155        assert(pipe);
     156        assert(hc_conn);
    87157        assert(pipe->wire != NULL);
    88158
     
    98168
    99169        /* TODO: prevent others from accessing the wire now. */
    100         if (usb_pipe_unregister(pipe) != EOK) {
     170        if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
    101171                usb_log_warning(
    102172                    "Failed to unregister the old pipe on address change.\n");
    103173        }
    104         /* Address changed. We can release the old one, thus
    105          * allowing other to us it. */
    106         usb_hc_release_address(pipe->wire->hc_connection, pipe->wire->address);
    107 
    108174        /* The address is already changed so set it in the wire */
    109175        pipe->wire->address = new_address;
    110         rc = usb_pipe_register(pipe, 0);
     176        rc = usb_pipe_register(pipe, 0, hc_conn);
    111177        if (rc != EOK)
    112178                return EADDRNOTAVAIL;
     
    155221 *      request or requests for descriptors when creating match ids).
    156222 */
    157 int usb_hc_new_device_wrapper(ddf_dev_t *parent,
    158     usb_hc_connection_t *hc_conn, usb_speed_t dev_speed,
     223int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,
     224    usb_speed_t dev_speed,
    159225    int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
    160226    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    161227{
    162         if (new_fun == NULL || hc_conn == NULL)
     228        if (new_fun == NULL || connection == NULL)
    163229                return EINVAL;
     230
     231        // FIXME: this is awful, we are accessing directly the structure.
     232        // TODO: Why not use provided connection?
     233        usb_hc_connection_t hc_conn = {
     234                .hc_handle = connection->hc_handle,
     235                .hc_sess = NULL
     236        };
    164237
    165238        int rc;
     
    171244        }
    172245
    173         /* We are gona do a lot of communication better open it in advance. */
    174         rc = usb_hc_connection_open(hc_conn);
     246        rc = usb_hc_connection_open(&hc_conn);
    175247        if (rc != EOK) {
    176248                return rc;
    177249        }
    178250
    179         /* Request a new address. */
     251        /*
     252         * Request new address.
     253         */
    180254        usb_address_t dev_addr =
    181             usb_hc_request_address(hc_conn, 0, false, dev_speed);
     255            usb_hc_request_address(&hc_conn, 0, false, dev_speed);
    182256        if (dev_addr < 0) {
    183257                rc = EADDRNOTAVAIL;
     
    185259        }
    186260
    187         /* Initialize connection to device. */
     261        /*
     262         * We will not register control pipe on default address.
     263         * The registration might fail. That means that someone else already
     264         * registered that endpoint. We will simply wait and try again.
     265         * (Someone else already wants to add a new device.)
     266         */
    188267        usb_device_connection_t dev_conn;
    189         rc = usb_device_connection_initialize(
    190             &dev_conn, hc_conn, USB_ADDRESS_DEFAULT);
     268        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
     269            &hc_conn);
    191270        if (rc != EOK) {
    192271                rc = ENOTCONN;
     
    194273        }
    195274
    196         /* Initialize control pipe on default address. Don't register yet. */
    197275        usb_pipe_t ctrl_pipe;
    198276        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
     
    202280        }
    203281
    204         /*
    205          * The default address request might fail.
    206          * That means that someone else is already using that address.
    207          * We will simply wait and try again.
    208          * (Someone else already wants to add a new device.)
    209          */
    210282        do {
    211                 rc = usb_hc_request_address(hc_conn, USB_ADDRESS_DEFAULT,
     283                rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
    212284                    true, dev_speed);
    213285                if (rc == ENOENT) {
    214286                        /* Do not overheat the CPU ;-). */
    215                         async_usleep(DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC);
     287                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    216288                }
    217289        } while (rc == ENOENT);
     
    220292        }
    221293
    222         /* Register control pipe on default address. 0 means no interval. */
    223         rc = usb_pipe_register(&ctrl_pipe, 0);
     294        /* Register control pipe on default address. */
     295        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    224296        if (rc != EOK) {
    225297                rc = ENOTCONN;
     
    228300
    229301        struct timeval end_time;
     302
    230303        rc = gettimeofday(&end_time, NULL);
    231304        if (rc != EOK) {
     
    262335        }
    263336
    264         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     337        rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
    265338        if (rc != EOK) {
    266339                rc = ESTALL;
     
    268341        }
    269342
     343        /* Address changed. We can release the default, thus
     344         * allowing other to access the default address. */
     345        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    270346
    271347        /* Register the device with devman. */
     
    285361
    286362        /* Inform the host controller about the handle. */
    287         rc = usb_hub_register_device(hc_conn, &new_device);
     363        rc = usb_hc_register_device(&hc_conn, &new_device);
    288364        if (rc != EOK) {
    289365                /* We know nothing about that data. */
     
    310386         */
    311387leave_release_default_address:
    312         if (usb_hc_release_address(hc_conn, USB_ADDRESS_DEFAULT) != EOK)
    313                 usb_log_warning("%s: Failed to release defaut address.\n",
    314                     __FUNCTION__);
     388        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    315389
    316390leave_release_free_address:
    317391        /* This might be either 0:0 or dev_addr:0 */
    318         if (usb_pipe_unregister(&ctrl_pipe) != EOK)
     392        if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
    319393                usb_log_warning("%s: Failed to unregister default pipe.\n",
    320394                    __FUNCTION__);
    321395
    322         if (usb_hc_release_address(hc_conn, dev_addr) != EOK)
    323                 usb_log_warning("%s: Failed to release address: %d.\n",
    324                     __FUNCTION__, dev_addr);
     396        if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
     397                usb_log_warning("%s: Failed to unregister device.\n",
     398                    __FUNCTION__);
    325399
    326400close_connection:
    327         if (usb_hc_connection_close(hc_conn) != EOK)
     401        if (usb_hc_connection_close(&hc_conn) != EOK)
    328402                usb_log_warning("%s: Failed to close hc connection.\n",
    329403                    __FUNCTION__);
Note: See TracChangeset for help on using the changeset viewer.