Ignore:
File:
1 edited

Legend:

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

    r6e3c005 r7711296  
    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        if (!exch)
     81                return (usb_address_t)ENOMEM;
     82
     83        usb_address_t address = preferred;
     84        const int ret = usbhc_request_address(exch, &address, strict, speed);
     85
     86        async_exchange_end(exch);
     87        return ret == EOK ? address : ret;
     88}
    5089
    5190/** Inform host controller about new device.
     
    5594 * @return Error code.
    5695 */
    57 int usb_hub_register_device(usb_hc_connection_t *connection,
     96int usb_hc_register_device(usb_hc_connection_t *connection,
    5897    const usb_hub_attached_device_t *attached_device)
    5998{
    60         assert(connection);
     99        CHECK_CONNECTION(connection);
    61100        if (attached_device == NULL || attached_device->fun == NULL)
    62                 return EBADMEM;
    63         return usb_hc_bind_address(connection,
     101                return EINVAL;
     102
     103        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     104        if (!exch)
     105                return ENOMEM;
     106        const int ret = usbhc_bind_address(exch,
    64107            attached_device->address, attached_device->fun->handle);
     108        async_exchange_end(exch);
     109
     110        return ret;
     111}
     112
     113/** Inform host controller about device removal.
     114 *
     115 * @param connection Opened connection to host controller.
     116 * @param address Address of the device that is being removed.
     117 * @return Error code.
     118 */
     119int usb_hc_unregister_device(usb_hc_connection_t *connection,
     120    usb_address_t address)
     121{
     122        CHECK_CONNECTION(connection);
     123
     124        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
     125        if (!exch)
     126                return ENOMEM;
     127        const int ret = usbhc_release_address(exch, address);
     128        async_exchange_end(exch);
     129
     130        return ret;
    65131}
    66132
     
    79145 * @return Error code.
    80146 */
    81 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address)
     147static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
     148    usb_hc_connection_t *hc_conn)
    82149{
    83150        if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
     
    85152        }
    86153        assert(pipe);
     154        assert(hc_conn);
    87155        assert(pipe->wire != NULL);
    88156
     
    98166
    99167        /* TODO: prevent others from accessing the wire now. */
    100         if (usb_pipe_unregister(pipe) != EOK) {
     168        if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
    101169                usb_log_warning(
    102170                    "Failed to unregister the old pipe on address change.\n");
    103171        }
    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 
    108172        /* The address is already changed so set it in the wire */
    109173        pipe->wire->address = new_address;
    110         rc = usb_pipe_register(pipe, 0);
     174        rc = usb_pipe_register(pipe, 0, hc_conn);
    111175        if (rc != EOK)
    112176                return EADDRNOTAVAIL;
     
    156220 */
    157221int usb_hc_new_device_wrapper(ddf_dev_t *parent,
    158     usb_hc_connection_t *hc_conn, usb_speed_t dev_speed,
     222    usb_hc_connection_t *connection, usb_speed_t dev_speed,
    159223    int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
    160224    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    161225{
    162         if (new_fun == NULL || hc_conn == NULL)
     226        if (new_fun == NULL || connection == NULL)
    163227                return EINVAL;
     228
     229        // TODO: Why not use provided connection?
     230        usb_hc_connection_t hc_conn;
     231        usb_hc_connection_initialize(&hc_conn, connection->hc_handle);
    164232
    165233        int rc;
     
    171239        }
    172240
    173         /* We are gona do a lot of communication better open it in advance. */
    174         rc = usb_hc_connection_open(hc_conn);
     241        rc = usb_hc_connection_open(&hc_conn);
    175242        if (rc != EOK) {
    176243                return rc;
    177244        }
    178245
    179         /* Request a new address. */
     246        /*
     247         * Request new address.
     248         */
    180249        usb_address_t dev_addr =
    181             usb_hc_request_address(hc_conn, 0, false, dev_speed);
     250            usb_hc_request_address(&hc_conn, 0, false, dev_speed);
    182251        if (dev_addr < 0) {
    183252                rc = EADDRNOTAVAIL;
     
    185254        }
    186255
    187         /* Initialize connection to device. */
     256        /*
     257         * We will not register control pipe on default address.
     258         * The registration might fail. That means that someone else already
     259         * registered that endpoint. We will simply wait and try again.
     260         * (Someone else already wants to add a new device.)
     261         */
    188262        usb_device_connection_t dev_conn;
    189         rc = usb_device_connection_initialize(
    190             &dev_conn, hc_conn, USB_ADDRESS_DEFAULT);
     263        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
     264            &hc_conn);
    191265        if (rc != EOK) {
    192266                rc = ENOTCONN;
     
    194268        }
    195269
    196         /* Initialize control pipe on default address. Don't register yet. */
    197270        usb_pipe_t ctrl_pipe;
    198271        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
     
    202275        }
    203276
    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          */
    210277        do {
    211                 rc = usb_hc_request_address(hc_conn, USB_ADDRESS_DEFAULT,
     278                rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
    212279                    true, dev_speed);
    213280                if (rc == ENOENT) {
    214281                        /* Do not overheat the CPU ;-). */
    215                         async_usleep(DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC);
     282                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    216283                }
    217284        } while (rc == ENOENT);
     
    220287        }
    221288
    222         /* Register control pipe on default address. 0 means no interval. */
    223         rc = usb_pipe_register(&ctrl_pipe, 0);
     289        /* Register control pipe on default address. */
     290        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    224291        if (rc != EOK) {
    225292                rc = ENOTCONN;
     
    228295
    229296        struct timeval end_time;
     297
    230298        rc = gettimeofday(&end_time, NULL);
    231299        if (rc != EOK) {
     
    262330        }
    263331
    264         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     332        rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
    265333        if (rc != EOK) {
    266334                rc = ESTALL;
     
    268336        }
    269337
     338        /* Address changed. We can release the default, thus
     339         * allowing other to access the default address. */
     340        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    270341
    271342        /* Register the device with devman. */
     
    285356
    286357        /* Inform the host controller about the handle. */
    287         rc = usb_hub_register_device(hc_conn, &new_device);
     358        rc = usb_hc_register_device(&hc_conn, &new_device);
    288359        if (rc != EOK) {
    289360                /* We know nothing about that data. */
     
    310381         */
    311382leave_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__);
     383        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    315384
    316385leave_release_free_address:
    317386        /* This might be either 0:0 or dev_addr:0 */
    318         if (usb_pipe_unregister(&ctrl_pipe) != EOK)
     387        if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
    319388                usb_log_warning("%s: Failed to unregister default pipe.\n",
    320389                    __FUNCTION__);
    321390
    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);
     391        if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
     392                usb_log_warning("%s: Failed to unregister device.\n",
     393                    __FUNCTION__);
    325394
    326395close_connection:
    327         if (usb_hc_connection_close(hc_conn) != EOK)
     396        if (usb_hc_connection_close(&hc_conn) != EOK)
    328397                usb_log_warning("%s: Failed to close hc connection.\n",
    329398                    __FUNCTION__);
Note: See TracChangeset for help on using the changeset viewer.