Ignore:
File:
1 edited

Legend:

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

    r4291215 rb77931d  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
    3  * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
     28
    2929/** @addtogroup libusbdev
    3030 * @{
     
    3636#include <usb/dev/request.h>
    3737#include <usb/debug.h>
    38 #include <usb/dev.h>
     38#include <usb/dev/dp.h>
    3939#include <errno.h>
    4040#include <str_error.h>
     
    4646
    4747static driver_ops_t generic_driver_ops = {
    48         .dev_add = generic_device_add,
     48        .add_device = generic_device_add,
    4949        .dev_remove = generic_device_remove,
    5050        .dev_gone = generic_device_gone,
     
    5656static const usb_driver_t *driver = NULL;
    5757
     58
    5859/** Main routine of USB device driver.
    5960 *
     
    7475        return ddf_driver_main(&generic_driver);
    7576}
    76 /*----------------------------------------------------------------------------*/
     77
    7778/** Count number of pipes the driver expects.
    7879 *
     
    8485{
    8586        size_t count;
    86         for (count = 0; endpoints != NULL && endpoints[count] != NULL; ++count);
     87        for (count = 0; endpoints && endpoints[count] != NULL; ++count);
    8788        return count;
     89}
     90
     91/** Initialize endpoint pipes, excluding default control one.
     92 *
     93 * @param drv The device driver.
     94 * @param dev Device to be initialized.
     95 * @return Error code.
     96 */
     97static int initialize_other_pipes(const usb_endpoint_description_t **endpoints,
     98    usb_device_t *dev, int alternate_setting)
     99{
     100        assert(dev);
     101
     102        if (endpoints == NULL) {
     103                dev->pipes = NULL;
     104                dev->pipes_count = 0;
     105                return EOK;
     106        }
     107
     108        usb_endpoint_mapping_t *pipes;
     109        size_t pipes_count;
     110
     111        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
     112            dev->descriptors.configuration, dev->descriptors.configuration_size,
     113            dev->interface_no, alternate_setting, &pipes, &pipes_count);
     114
     115        if (rc != EOK) {
     116                return rc;
     117        }
     118
     119        dev->pipes = pipes;
     120        dev->pipes_count = pipes_count;
     121
     122        return EOK;
    88123}
    89124/*----------------------------------------------------------------------------*/
     
    101136        assert(driver->ops->device_add);
    102137
    103         /* Get place for driver data. */
    104138        usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));
    105139        if (dev == NULL) {
     
    108142                return ENOMEM;
    109143        }
    110 
    111         /* Initialize generic USB driver data. */
    112144        const char *err_msg = NULL;
    113145        int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);
     
    118150        }
    119151
    120         /* Start USB driver specific initialization. */
    121152        rc = driver->ops->device_add(dev);
    122153        if (rc != EOK)
     
    138169        if (driver->ops->device_rem == NULL)
    139170                return ENOTSUP;
    140         /* Just tell the driver to stop whatever it is doing */
    141         usb_device_t *usb_dev = gen_dev->driver_data;
    142         const int ret = driver->ops->device_rem(usb_dev);
    143         if (ret != EOK)
    144                 return ret;
    145         usb_device_deinit(usb_dev);
    146         return EOK;
     171        /* Just tell the driver to stop whatever it is doing, keep structures */
     172        return driver->ops->device_rem(gen_dev->driver_data);
    147173}
    148174/*----------------------------------------------------------------------------*/
     
    171197 *
    172198 * @param dev Device where to destroy the pipes.
    173  */
    174 static void destroy_current_pipes(usb_device_t *dev)
    175 {
    176         usb_device_destroy_pipes(dev->pipes, dev->pipes_count);
     199 * @return Error code.
     200 */
     201static int destroy_current_pipes(usb_device_t *dev)
     202{
     203        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     204            dev->pipes, dev->pipes_count);
     205        if (rc != EOK) {
     206                return rc;
     207        }
     208
    177209        dev->pipes = NULL;
    178210        dev->pipes_count = 0;
    179 }
    180 /*----------------------------------------------------------------------------*/
     211
     212        return EOK;
     213}
     214
    181215/** Change interface setting of a device.
    182216 * This function selects new alternate setting of an interface by issuing
     
    208242        }
    209243
     244        int rc;
     245
    210246        /* Destroy existing pipes. */
    211         destroy_current_pipes(dev);
     247        rc = destroy_current_pipes(dev);
     248        if (rc != EOK) {
     249                return rc;
     250        }
    212251
    213252        /* Change the interface itself. */
    214         int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
     253        rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
    215254            alternate_setting);
    216255        if (rc != EOK) {
     
    219258
    220259        /* Create new pipes. */
    221         rc = usb_device_create_pipes(&dev->wire, endpoints,
    222             dev->descriptors.configuration, dev->descriptors.configuration_size,
    223             dev->interface_no, (int)alternate_setting,
    224             &dev->pipes, &dev->pipes_count);
     260        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    225261
    226262        return rc;
     
    280316 * - registers endpoints with the host controller
    281317 *
     318 * @param[in] dev Generic DDF device backing the USB one.
    282319 * @param[in] wire Initialized backing connection to the host controller.
    283320 * @param[in] endpoints Endpoints description, NULL terminated.
     
    292329 * @return Error code.
    293330 */
    294 int usb_device_create_pipes(usb_device_connection_t *wire,
     331int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire,
    295332    const usb_endpoint_description_t **endpoints,
    296333    const uint8_t *config_descr, size_t config_descr_size,
     
    298335    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
    299336{
     337        assert(dev != NULL);
    300338        assert(wire != NULL);
     339        assert(endpoints != NULL);
    301340        assert(config_descr != NULL);
    302341        assert(config_descr_size > 0);
     
    320359        }
    321360
    322         /* Now initialize. */
     361        /* Now allocate and fully initialize. */
    323362        for (i = 0; i < pipe_count; i++) {
    324363                pipes[i].description = endpoints[i];
     
    331370            config_descr, config_descr_size, wire);
    332371        if (rc != EOK) {
    333                 free(pipes);
    334                 return rc;
    335         }
    336 
    337         /* Register created pipes. */
     372                goto rollback_free_only;
     373        }
     374
     375        /* Register the endpoints with HC. */
     376        usb_hc_connection_t hc_conn;
     377        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     378        if (rc != EOK) {
     379                goto rollback_free_only;
     380        }
     381
     382        rc = usb_hc_connection_open(&hc_conn);
     383        if (rc != EOK) {
     384                goto rollback_free_only;
     385        }
     386
    338387        for (i = 0; i < pipe_count; i++) {
    339388                if (pipes[i].present) {
    340389                        rc = usb_pipe_register(&pipes[i].pipe,
    341                             pipes[i].descriptor->poll_interval);
     390                            pipes[i].descriptor->poll_interval, &hc_conn);
    342391                        if (rc != EOK) {
    343392                                goto rollback_unregister_endpoints;
     
    345394                }
    346395        }
     396
     397        if (usb_hc_connection_close(&hc_conn) != EOK)
     398                usb_log_warning("%s: Failed to close connection.\n",
     399                    __FUNCTION__);
    347400
    348401        *pipes_ptr = pipes;
     
    362415        for (i = 0; i < pipe_count; i++) {
    363416                if (pipes[i].present) {
    364                         usb_pipe_unregister(&pipes[i].pipe);
     417                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    365418                }
    366419        }
    367420
     421        if (usb_hc_connection_close(&hc_conn) != EOK)
     422                usb_log_warning("usb_device_create_pipes(): "
     423                    "Failed to close connection.\n");
     424
     425        /*
     426         * Jump here if something went wrong before some actual communication
     427         * with HC. Then the only thing that needs to be done is to free
     428         * allocated memory.
     429         */
     430rollback_free_only:
    368431        free(pipes);
     432
    369433        return rc;
    370434}
     
    372436/** Destroy pipes previously created by usb_device_create_pipes.
    373437 *
     438 * @param[in] dev Generic DDF device backing the USB one.
    374439 * @param[in] pipes Endpoint mapping to be destroyed.
    375440 * @param[in] pipes_count Number of endpoints.
    376441 */
    377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count)
    378 {
     442int usb_device_destroy_pipes(const ddf_dev_t *dev,
     443    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     444{
     445        assert(dev != NULL);
     446
     447        if (pipes_count == 0) {
     448                assert(pipes == NULL);
     449                return EOK;
     450        }
     451        assert(pipes != NULL);
     452
     453        int rc;
     454
     455        /* Prepare connection to HC to allow endpoint unregistering. */
     456        usb_hc_connection_t hc_conn;
     457        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     458        if (rc != EOK) {
     459                return rc;
     460        }
     461        rc = usb_hc_connection_open(&hc_conn);
     462        if (rc != EOK) {
     463                return rc;
     464        }
     465
    379466        /* Destroy the pipes. */
    380         for (size_t i = 0; i < pipes_count; ++i) {
    381                 assert(pipes);
    382                 usb_log_debug2("Unregistering pipe %zu: %spresent.\n",
     467        size_t i;
     468        for (i = 0; i < pipes_count; i++) {
     469                usb_log_debug2("Unregistering pipe %zu (%spresent).\n",
    383470                    i, pipes[i].present ? "" : "not ");
    384471                if (pipes[i].present)
    385                         usb_pipe_unregister(&pipes[i].pipe);
    386         }
     472                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
     473        }
     474
     475        if (usb_hc_connection_close(&hc_conn) != EOK)
     476                usb_log_warning("usb_device_destroy_pipes(): "
     477                    "Failed to close connection.\n");
     478
    387479        free(pipes);
     480
     481        return EOK;
    388482}
    389483
     
    411505        usb_dev->pipes = NULL;
    412506
    413         /* Get assigned params */
    414         devman_handle_t hc_handle;
    415         usb_address_t address;
    416 
    417         int rc = usb_get_info_by_handle(ddf_dev->handle,
    418             &hc_handle, &address, &usb_dev->interface_no);
    419         if (rc != EOK) {
    420                 *errstr_ptr = "device parameters retrieval";
    421                 return rc;
    422         }
    423 
    424         /* Initialize hc connection. */
    425         usb_hc_connection_initialize(&usb_dev->hc_conn, hc_handle);
    426 
    427507        /* Initialize backing wire and control pipe. */
    428         rc = usb_device_connection_initialize(
    429             &usb_dev->wire, &usb_dev->hc_conn, address);
     508        int rc = usb_device_connection_initialize_from_device(
     509            &usb_dev->wire, ddf_dev);
    430510        if (rc != EOK) {
    431511                *errstr_ptr = "device connection initialization";
     
    435515        /* This pipe was registered by the hub driver,
    436516         * during device initialization. */
    437         rc = usb_pipe_initialize_default_control(
    438             &usb_dev->ctrl_pipe, &usb_dev->wire);
     517        rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
     518            &usb_dev->wire);
    439519        if (rc != EOK) {
    440520                *errstr_ptr = "default control pipe initialization";
     
    442522        }
    443523
    444         /* Open hc connection for pipe registration. */
    445         rc = usb_hc_connection_open(&usb_dev->hc_conn);
    446         if (rc != EOK) {
    447                 *errstr_ptr = "hc connection open";
    448                 return rc;
    449         }
     524        /* Get our interface. */
     525        usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
    450526
    451527        /* Retrieve standard descriptors. */
    452         rc = usb_device_retrieve_descriptors(
    453             &usb_dev->ctrl_pipe, &usb_dev->descriptors);
     528        rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
     529            &usb_dev->descriptors);
    454530        if (rc != EOK) {
    455531                *errstr_ptr = "descriptor retrieval";
    456                 usb_hc_connection_close(&usb_dev->hc_conn);
    457532                return rc;
    458533        }
     
    468543            (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
    469544
    470         /* Create and register other pipes than default control (EP 0) */
    471         rc = usb_device_create_pipes(&usb_dev->wire, endpoints,
    472             usb_dev->descriptors.configuration,
    473             usb_dev->descriptors.configuration_size,
    474             usb_dev->interface_no, (int)alternate_iface,
    475             &usb_dev->pipes, &usb_dev->pipes_count);
    476         if (rc != EOK) {
    477                 usb_hc_connection_close(&usb_dev->hc_conn);
     545        /* TODO Add comment here. */
     546        rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
     547        if (rc != EOK) {
    478548                /* Full configuration descriptor is allocated. */
    479549                usb_device_release_descriptors(&usb_dev->descriptors);
     
    484554        }
    485555
    486         usb_hc_connection_close(&usb_dev->hc_conn);
    487556        return EOK;
    488557}
     
    497566{
    498567        if (dev) {
    499                 /* Destroy existing pipes. */
     568                /* Ignore errors and hope for the best. */
    500569                destroy_current_pipes(dev);
    501                 /* Ignore errors and hope for the best. */
    502                 usb_hc_connection_deinitialize(&dev->hc_conn);
     570
    503571                usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
    504572                usb_device_release_descriptors(&dev->descriptors);
    505573                free(dev->driver_data);
    506                 dev->driver_data = NULL;
    507         }
    508 }
    509 
    510 /** Allocate driver specific data.
    511  * @param usb_dev usb_device structure.
    512  * @param size requested data size.
    513  * @return Pointer to the newly allocated space, NULL on failure.
    514  */
     574        }
     575}
     576
    515577void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size)
    516578{
Note: See TracChangeset for help on using the changeset viewer.