Ignore:
File:
1 edited

Legend:

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

    rb77931d r70452dd4  
    4141#include <assert.h>
    4242
    43 static int generic_device_add(ddf_dev_t *);
    44 static int generic_device_remove(ddf_dev_t *);
    45 static int generic_device_gone(ddf_dev_t *);
     43static int generic_add_device(ddf_dev_t *);
    4644
    4745static driver_ops_t generic_driver_ops = {
    48         .add_device = generic_device_add,
    49         .dev_remove = generic_device_remove,
    50         .dev_gone = generic_device_gone,
     46        .add_device = generic_add_device
    5147};
    5248static driver_t generic_driver = {
     
    5450};
    5551
    56 static const usb_driver_t *driver = NULL;
     52static usb_driver_t *driver = NULL;
    5753
    5854
     
    6460 * @return Task exit status.
    6561 */
    66 int usb_driver_main(const usb_driver_t *drv)
     62int usb_driver_main(usb_driver_t *drv)
    6763{
    6864        assert(drv != NULL);
     
    8177 * @return Number of pipes (excluding default control pipe).
    8278 */
    83 static inline size_t count_other_pipes(
    84     const usb_endpoint_description_t **endpoints)
    85 {
    86         size_t count;
    87         for (count = 0; endpoints && endpoints[count] != NULL; ++count);
     79static size_t count_other_pipes(usb_endpoint_description_t **endpoints)
     80{
     81        size_t count = 0;
     82        if (endpoints == NULL) {
     83                return 0;
     84        }
     85
     86        while (endpoints[count] != NULL) {
     87                count++;
     88        }
     89
    8890        return count;
    8991}
     
    9597 * @return Error code.
    9698 */
    97 static int initialize_other_pipes(const usb_endpoint_description_t **endpoints,
     99static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
    98100    usb_device_t *dev, int alternate_setting)
    99101{
    100         assert(dev);
    101 
    102102        if (endpoints == NULL) {
    103103                dev->pipes = NULL;
     
    111111        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
    112112            dev->descriptors.configuration, dev->descriptors.configuration_size,
    113             dev->interface_no, alternate_setting, &pipes, &pipes_count);
     113            dev->interface_no, alternate_setting,
     114            &pipes, &pipes_count);
    114115
    115116        if (rc != EOK) {
     
    122123        return EOK;
    123124}
    124 /*----------------------------------------------------------------------------*/
    125 /** Callback when a new device is supposed to be controlled by this driver.
    126  *
    127  * This callback is a wrapper for USB specific version of @c device_add.
     125
     126/** Callback when new device is supposed to be controlled by this driver.
     127 *
     128 * This callback is a wrapper for USB specific version of @c add_device.
    128129 *
    129130 * @param gen_dev Device structure as prepared by DDF.
    130131 * @return Error code.
    131132 */
    132 int generic_device_add(ddf_dev_t *gen_dev)
     133int generic_add_device(ddf_dev_t *gen_dev)
    133134{
    134135        assert(driver);
    135136        assert(driver->ops);
    136         assert(driver->ops->device_add);
    137 
    138         usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));
    139         if (dev == NULL) {
    140                 usb_log_error("USB device `%s' structure allocation failed.\n",
    141                     gen_dev->name);
    142                 return ENOMEM;
    143         }
     137        assert(driver->ops->add_device);
     138
     139        int rc;
     140
     141        usb_device_t *dev = NULL;
    144142        const char *err_msg = NULL;
    145         int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);
    146         if (rc != EOK) {
    147                 usb_log_error("USB device `%s' init failed (%s): %s.\n",
     143        rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
     144        if (rc != EOK) {
     145                usb_log_error("USB device `%s' creation failed (%s): %s.\n",
    148146                    gen_dev->name, err_msg, str_error(rc));
    149147                return rc;
    150148        }
    151149
    152         rc = driver->ops->device_add(dev);
    153         if (rc != EOK)
    154                 usb_device_deinit(dev);
    155         return rc;
    156 }
    157 /*----------------------------------------------------------------------------*/
    158 /** Callback when a device is supposed to be removed from the system.
    159  *
    160  * This callback is a wrapper for USB specific version of @c device_remove.
    161  *
    162  * @param gen_dev Device structure as prepared by DDF.
    163  * @return Error code.
    164  */
    165 int generic_device_remove(ddf_dev_t *gen_dev)
    166 {
    167         assert(driver);
    168         assert(driver->ops);
    169         if (driver->ops->device_rem == NULL)
    170                 return ENOTSUP;
    171         /* Just tell the driver to stop whatever it is doing, keep structures */
    172         return driver->ops->device_rem(gen_dev->driver_data);
    173 }
    174 /*----------------------------------------------------------------------------*/
    175 /** Callback when a device was removed from the system.
    176  *
    177  * This callback is a wrapper for USB specific version of @c device_gone.
    178  *
    179  * @param gen_dev Device structure as prepared by DDF.
    180  * @return Error code.
    181  */
    182 int generic_device_gone(ddf_dev_t *gen_dev)
    183 {
    184         assert(driver);
    185         assert(driver->ops);
    186         if (driver->ops->device_gone == NULL)
    187                 return ENOTSUP;
    188         usb_device_t *usb_dev = gen_dev->driver_data;
    189         const int ret = driver->ops->device_gone(usb_dev);
    190         if (ret == EOK)
    191                 usb_device_deinit(usb_dev);
    192 
    193         return ret;
    194 }
    195 /*----------------------------------------------------------------------------*/
     150        return driver->ops->add_device(dev);
     151}
     152
    196153/** Destroy existing pipes of a USB device.
    197154 *
     
    236193 */
    237194int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,
    238     const usb_endpoint_description_t **endpoints)
     195    usb_endpoint_description_t **endpoints)
    239196{
    240197        if (dev->interface_no < 0) {
     
    296253
    297254        return rc;
    298 }
    299 
    300 /** Cleanup structure initialized via usb_device_retrieve_descriptors.
    301  *
    302  * @param[in] descriptors Where to store the descriptors.
    303  */
    304 void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
    305 {
    306         assert(descriptors);
    307         free(descriptors->configuration);
    308         descriptors->configuration = NULL;
    309255}
    310256
     
    326272 *      (not NULL terminated).
    327273 * @param[out] pipes_count_ptr Where to store number of pipes
    328  *      (set to NULL if you wish to ignore the count).
    329  * @return Error code.
    330  */
    331 int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire,
    332     const usb_endpoint_description_t **endpoints,
    333     const uint8_t *config_descr, size_t config_descr_size,
     274 *      (set to if you wish to ignore the count).
     275 * @return Error code.
     276 */
     277int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
     278    usb_endpoint_description_t **endpoints,
     279    uint8_t *config_descr, size_t config_descr_size,
    334280    int interface_no, int interface_setting,
    335281    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
     
    345291        int rc;
    346292
    347         const size_t pipe_count = count_other_pipes(endpoints);
     293        size_t pipe_count = count_other_pipes(endpoints);
    348294        if (pipe_count == 0) {
    349                 if (pipes_count_ptr)
    350                         *pipes_count_ptr = pipe_count;
    351295                *pipes_ptr = NULL;
    352296                return EOK;
     
    354298
    355299        usb_endpoint_mapping_t *pipes
    356             = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
     300            = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    357301        if (pipes == NULL) {
    358302                return ENOMEM;
    359303        }
    360304
     305        /* Initialize to NULL to allow smooth rollback. */
     306        for (i = 0; i < pipe_count; i++) {
     307                pipes[i].pipe = NULL;
     308        }
     309
    361310        /* Now allocate and fully initialize. */
    362311        for (i = 0; i < pipe_count; i++) {
     312                pipes[i].pipe = malloc(sizeof(usb_pipe_t));
     313                if (pipes[i].pipe == NULL) {
     314                        rc = ENOMEM;
     315                        goto rollback_free_only;
     316                }
    363317                pipes[i].description = endpoints[i];
    364318                pipes[i].interface_no = interface_no;
     
    387341        for (i = 0; i < pipe_count; i++) {
    388342                if (pipes[i].present) {
    389                         rc = usb_pipe_register(&pipes[i].pipe,
     343                        rc = usb_pipe_register(pipes[i].pipe,
    390344                            pipes[i].descriptor->poll_interval, &hc_conn);
    391345                        if (rc != EOK) {
     
    395349        }
    396350
    397         if (usb_hc_connection_close(&hc_conn) != EOK)
    398                 usb_log_warning("%s: Failed to close connection.\n",
    399                     __FUNCTION__);
     351        usb_hc_connection_close(&hc_conn);
    400352
    401353        *pipes_ptr = pipes;
     
    415367        for (i = 0; i < pipe_count; i++) {
    416368                if (pipes[i].present) {
    417                         usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
     369                        usb_pipe_unregister(pipes[i].pipe, &hc_conn);
    418370                }
    419371        }
    420372
    421         if (usb_hc_connection_close(&hc_conn) != EOK)
    422                 usb_log_warning("usb_device_create_pipes(): "
    423                     "Failed to close connection.\n");
     373        usb_hc_connection_close(&hc_conn);
    424374
    425375        /*
     
    429379         */
    430380rollback_free_only:
     381        for (i = 0; i < pipe_count; i++) {
     382                if (pipes[i].pipe != NULL) {
     383                        free(pipes[i].pipe);
     384                }
     385        }
    431386        free(pipes);
    432387
     
    440395 * @param[in] pipes_count Number of endpoints.
    441396 */
    442 int usb_device_destroy_pipes(const ddf_dev_t *dev,
     397int usb_device_destroy_pipes(ddf_dev_t *dev,
    443398    usb_endpoint_mapping_t *pipes, size_t pipes_count)
    444399{
    445400        assert(dev != NULL);
     401        assert(((pipes != NULL) && (pipes_count > 0))
     402            || ((pipes == NULL) && (pipes_count == 0)));
    446403
    447404        if (pipes_count == 0) {
    448                 assert(pipes == NULL);
    449405                return EOK;
    450406        }
    451         assert(pipes != NULL);
    452407
    453408        int rc;
     
    467422        size_t i;
    468423        for (i = 0; i < pipes_count; i++) {
    469                 usb_log_debug2("Unregistering pipe %zu (%spresent).\n",
    470                     i, pipes[i].present ? "" : "not ");
    471                 if (pipes[i].present)
    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");
     424                usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     425                free(pipes[i].pipe);
     426        }
     427
     428        usb_hc_connection_close(&hc_conn);
    478429
    479430        free(pipes);
     
    482433}
    483434
    484 /** Initialize new instance of USB device.
    485  *
    486  * @param[in] usb_dev Pointer to the new device.
     435/** Initialize control pipe in a device.
     436 *
     437 * @param dev USB device in question.
     438 * @param errmsg Where to store error context.
     439 * @return
     440 */
     441static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
     442{
     443        int rc;
     444
     445        rc = usb_device_connection_initialize_from_device(&dev->wire,
     446            dev->ddf_dev);
     447        if (rc != EOK) {
     448                *errmsg = "device connection initialization";
     449                return rc;
     450        }
     451
     452        rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
     453            &dev->wire);
     454        if (rc != EOK) {
     455                *errmsg = "default control pipe initialization";
     456                return rc;
     457        }
     458
     459        return EOK;
     460}
     461
     462
     463/** Create new instance of USB device.
     464 *
    487465 * @param[in] ddf_dev Generic DDF device backing the USB one.
    488466 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     467 * @param[out] dev_ptr Where to store pointer to the new device.
    489468 * @param[out] errstr_ptr Where to store description of context
    490469 *      (in case error occurs).
    491470 * @return Error code.
    492471 */
    493 int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev,
    494     const usb_endpoint_description_t **endpoints, const char **errstr_ptr)
    495 {
    496         assert(usb_dev != NULL);
     472int usb_device_create(ddf_dev_t *ddf_dev,
     473    usb_endpoint_description_t **endpoints,
     474    usb_device_t **dev_ptr, const char **errstr_ptr)
     475{
     476        assert(dev_ptr != NULL);
    497477        assert(ddf_dev != NULL);
    498478
     479        int rc;
     480
     481        usb_device_t *dev = malloc(sizeof(usb_device_t));
     482        if (dev == NULL) {
     483                *errstr_ptr = "structure allocation";
     484                return ENOMEM;
     485        }
     486
     487        // FIXME: proper deallocation in case of errors
     488
     489        dev->ddf_dev = ddf_dev;
     490        dev->driver_data = NULL;
     491        dev->descriptors.configuration = NULL;
     492        dev->alternate_interfaces = NULL;
     493
     494        dev->pipes_count = 0;
     495        dev->pipes = NULL;
     496
     497        /* Initialize backing wire and control pipe. */
     498        rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
     499        if (rc != EOK) {
     500                return rc;
     501        }
     502
     503        /* Get our interface. */
     504        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     505
     506        /* Retrieve standard descriptors. */
     507        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     508            &dev->descriptors);
     509        if (rc != EOK) {
     510                *errstr_ptr = "descriptor retrieval";
     511                return rc;
     512        }
     513
     514        /* Create alternate interfaces. */
     515        rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
     516            dev->descriptors.configuration_size, dev->interface_no,
     517            &dev->alternate_interfaces);
     518        if (rc != EOK) {
     519                /* We will try to silently ignore this. */
     520                dev->alternate_interfaces = NULL;
     521        }
     522
     523        rc = initialize_other_pipes(endpoints, dev, 0);
     524        if (rc != EOK) {
     525                *errstr_ptr = "pipes initialization";
     526                return rc;
     527        }
     528
    499529        *errstr_ptr = NULL;
    500 
    501         usb_dev->ddf_dev = ddf_dev;
    502         usb_dev->driver_data = NULL;
    503         usb_dev->descriptors.configuration = NULL;
    504         usb_dev->pipes_count = 0;
    505         usb_dev->pipes = NULL;
    506 
    507         /* Initialize backing wire and control pipe. */
    508         int rc = usb_device_connection_initialize_from_device(
    509             &usb_dev->wire, ddf_dev);
    510         if (rc != EOK) {
    511                 *errstr_ptr = "device connection initialization";
    512                 return rc;
    513         }
    514 
    515         /* This pipe was registered by the hub driver,
    516          * during device initialization. */
    517         rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
    518             &usb_dev->wire);
    519         if (rc != EOK) {
    520                 *errstr_ptr = "default control pipe initialization";
    521                 return rc;
    522         }
    523 
    524         /* Get our interface. */
    525         usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
    526 
    527         /* Retrieve standard descriptors. */
    528         rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
    529             &usb_dev->descriptors);
    530         if (rc != EOK) {
    531                 *errstr_ptr = "descriptor retrieval";
    532                 return rc;
    533         }
    534 
    535         /* Create alternate interfaces. We will silently ignore failure.
    536          * We might either control one interface or an entire device,
    537          * it makes no sense to speak about alternate interfaces when
    538          * controlling a device. */
    539         rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
    540             usb_dev->descriptors.configuration,
    541             usb_dev->descriptors.configuration_size, usb_dev->interface_no);
    542         const int alternate_iface =
    543             (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
    544 
    545         /* TODO Add comment here. */
    546         rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
    547         if (rc != EOK) {
    548                 /* Full configuration descriptor is allocated. */
    549                 usb_device_release_descriptors(&usb_dev->descriptors);
    550                 /* Alternate interfaces may be allocated */
    551                 usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
    552                 *errstr_ptr = "pipes initialization";
    553                 return rc;
    554         }
     530        *dev_ptr = dev;
    555531
    556532        return EOK;
    557533}
    558534
    559 /** Clean instance of a USB device.
    560  *
    561  * @param dev Device to be de-initialized.
    562  *
    563  * Does not free/destroy supplied pointer.
    564  */
    565 void usb_device_deinit(usb_device_t *dev)
    566 {
    567         if (dev) {
    568                 /* Ignore errors and hope for the best. */
    569                 destroy_current_pipes(dev);
    570 
    571                 usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
    572                 usb_device_release_descriptors(&dev->descriptors);
    573                 free(dev->driver_data);
    574         }
    575 }
    576 
    577 void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size)
    578 {
    579         assert(usb_dev);
    580         assert(usb_dev->driver_data == NULL);
    581         return usb_dev->driver_data = calloc(1, size);
    582 
     535/** Destroy instance of a USB device.
     536 *
     537 * @param dev Device to be destroyed.
     538 */
     539void usb_device_destroy(usb_device_t *dev)
     540{
     541        if (dev == NULL) {
     542                return;
     543        }
     544
     545        /* Ignore errors and hope for the best. */
     546        usb_device_destroy_pipes(dev->ddf_dev, dev->pipes, dev->pipes_count);
     547        if (dev->descriptors.configuration != NULL) {
     548                free(dev->descriptors.configuration);
     549        }
     550
     551        if (dev->alternate_interfaces != NULL) {
     552                if (dev->alternate_interfaces->alternatives != NULL) {
     553                        free(dev->alternate_interfaces->alternatives);
     554                }
     555                free(dev->alternate_interfaces);
     556        }
     557
     558        free(dev);
    583559}
    584560
Note: See TracChangeset for help on using the changeset viewer.