Ignore:
File:
1 edited

Legend:

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

    r70452dd4 r0c0f823b  
    4141#include <assert.h>
    4242
    43 static int generic_add_device(ddf_dev_t *);
     43static int generic_device_add(ddf_dev_t *);
     44static int generic_device_remove(ddf_dev_t *);
     45static int generic_device_gone(ddf_dev_t *);
    4446
    4547static driver_ops_t generic_driver_ops = {
    46         .add_device = generic_add_device
     48        .dev_add = generic_device_add,
     49        .dev_remove = generic_device_remove,
     50        .dev_gone = generic_device_gone,
    4751};
    4852static driver_t generic_driver = {
     
    5054};
    5155
    52 static usb_driver_t *driver = NULL;
     56static const usb_driver_t *driver = NULL;
    5357
    5458
     
    6064 * @return Task exit status.
    6165 */
    62 int usb_driver_main(usb_driver_t *drv)
     66int usb_driver_main(const usb_driver_t *drv)
    6367{
    6468        assert(drv != NULL);
     
    7781 * @return Number of pipes (excluding default control pipe).
    7882 */
    79 static 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 
     83static 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);
    9088        return count;
    9189}
     
    9795 * @return Error code.
    9896 */
    99 static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
     97static int initialize_other_pipes(const usb_endpoint_description_t **endpoints,
    10098    usb_device_t *dev, int alternate_setting)
    10199{
     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,
    114             &pipes, &pipes_count);
     113            dev->interface_no, alternate_setting, &pipes, &pipes_count);
    115114
    116115        if (rc != EOK) {
     
    123122        return EOK;
    124123}
    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.
     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.
    129128 *
    130129 * @param gen_dev Device structure as prepared by DDF.
    131130 * @return Error code.
    132131 */
    133 int generic_add_device(ddf_dev_t *gen_dev)
     132int generic_device_add(ddf_dev_t *gen_dev)
    134133{
    135134        assert(driver);
    136135        assert(driver->ops);
    137         assert(driver->ops->add_device);
    138 
    139         int rc;
    140 
    141         usb_device_t *dev = NULL;
     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        }
    142144        const char *err_msg = NULL;
    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",
     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",
    146148                    gen_dev->name, err_msg, str_error(rc));
    147149                return rc;
    148150        }
    149151
    150         return driver->ops->add_device(dev);
    151 }
    152 
     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 */
     165int 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 */
     182int 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/*----------------------------------------------------------------------------*/
    153196/** Destroy existing pipes of a USB device.
    154197 *
     
    193236 */
    194237int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,
    195     usb_endpoint_description_t **endpoints)
     238    const usb_endpoint_description_t **endpoints)
    196239{
    197240        if (dev->interface_no < 0) {
     
    253296
    254297        return rc;
     298}
     299
     300/** Cleanup structure initialized via usb_device_retrieve_descriptors.
     301 *
     302 * @param[in] descriptors Where to store the descriptors.
     303 */
     304void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
     305{
     306        assert(descriptors);
     307        free(descriptors->configuration);
     308        descriptors->configuration = NULL;
    255309}
    256310
     
    272326 *      (not NULL terminated).
    273327 * @param[out] pipes_count_ptr Where to store number of pipes
    274  *      (set to if you wish to ignore the count).
    275  * @return Error code.
    276  */
    277 int 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,
     328 *      (set to NULL if you wish to ignore the count).
     329 * @return Error code.
     330 */
     331int 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,
    280334    int interface_no, int interface_setting,
    281335    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
     
    291345        int rc;
    292346
    293         size_t pipe_count = count_other_pipes(endpoints);
     347        const size_t pipe_count = count_other_pipes(endpoints);
    294348        if (pipe_count == 0) {
     349                if (pipes_count_ptr)
     350                        *pipes_count_ptr = pipe_count;
    295351                *pipes_ptr = NULL;
    296352                return EOK;
     
    298354
    299355        usb_endpoint_mapping_t *pipes
    300             = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
     356            = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
    301357        if (pipes == NULL) {
    302358                return ENOMEM;
    303359        }
    304360
    305         /* Initialize to NULL to allow smooth rollback. */
    306         for (i = 0; i < pipe_count; i++) {
    307                 pipes[i].pipe = NULL;
    308         }
    309 
    310361        /* Now allocate and fully initialize. */
    311362        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                 }
    317363                pipes[i].description = endpoints[i];
    318364                pipes[i].interface_no = interface_no;
     
    341387        for (i = 0; i < pipe_count; i++) {
    342388                if (pipes[i].present) {
    343                         rc = usb_pipe_register(pipes[i].pipe,
     389                        rc = usb_pipe_register(&pipes[i].pipe,
    344390                            pipes[i].descriptor->poll_interval, &hc_conn);
    345391                        if (rc != EOK) {
     
    349395        }
    350396
    351         usb_hc_connection_close(&hc_conn);
     397        if (usb_hc_connection_close(&hc_conn) != EOK)
     398                usb_log_warning("%s: Failed to close connection.\n",
     399                    __FUNCTION__);
    352400
    353401        *pipes_ptr = pipes;
     
    367415        for (i = 0; i < pipe_count; i++) {
    368416                if (pipes[i].present) {
    369                         usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     417                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    370418                }
    371419        }
    372420
    373         usb_hc_connection_close(&hc_conn);
     421        if (usb_hc_connection_close(&hc_conn) != EOK)
     422                usb_log_warning("usb_device_create_pipes(): "
     423                    "Failed to close connection.\n");
    374424
    375425        /*
     
    379429         */
    380430rollback_free_only:
    381         for (i = 0; i < pipe_count; i++) {
    382                 if (pipes[i].pipe != NULL) {
    383                         free(pipes[i].pipe);
    384                 }
    385         }
    386431        free(pipes);
    387432
     
    395440 * @param[in] pipes_count Number of endpoints.
    396441 */
    397 int usb_device_destroy_pipes(ddf_dev_t *dev,
     442int usb_device_destroy_pipes(const ddf_dev_t *dev,
    398443    usb_endpoint_mapping_t *pipes, size_t pipes_count)
    399444{
    400445        assert(dev != NULL);
    401         assert(((pipes != NULL) && (pipes_count > 0))
    402             || ((pipes == NULL) && (pipes_count == 0)));
    403446
    404447        if (pipes_count == 0) {
     448                assert(pipes == NULL);
    405449                return EOK;
    406450        }
     451        assert(pipes != NULL);
    407452
    408453        int rc;
     
    422467        size_t i;
    423468        for (i = 0; i < pipes_count; i++) {
    424                 usb_pipe_unregister(pipes[i].pipe, &hc_conn);
    425                 free(pipes[i].pipe);
    426         }
    427 
    428         usb_hc_connection_close(&hc_conn);
     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");
    429478
    430479        free(pipes);
     
    433482}
    434483
    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  */
    441 static 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  *
     484/** Initialize new instance of USB device.
     485 *
     486 * @param[in] usb_dev Pointer to the new device.
    465487 * @param[in] ddf_dev Generic DDF device backing the USB one.
    466488 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
    467  * @param[out] dev_ptr Where to store pointer to the new device.
    468489 * @param[out] errstr_ptr Where to store description of context
    469490 *      (in case error occurs).
    470491 * @return Error code.
    471492 */
    472 int 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);
     493int 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);
    477497        assert(ddf_dev != NULL);
    478498
    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;
     499        *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;
    496506
    497507        /* Initialize backing wire and control pipe. */
    498         rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
    499         if (rc != EOK) {
     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";
    500521                return rc;
    501522        }
    502523
    503524        /* Get our interface. */
    504         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     525        usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
    505526
    506527        /* Retrieve standard descriptors. */
    507         rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
    508             &dev->descriptors);
     528        rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
     529            &usb_dev->descriptors);
    509530        if (rc != EOK) {
    510531                *errstr_ptr = "descriptor retrieval";
     
    512533        }
    513534
    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) {
     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);
    525552                *errstr_ptr = "pipes initialization";
    526553                return rc;
    527554        }
    528555
    529         *errstr_ptr = NULL;
    530         *dev_ptr = dev;
    531 
    532556        return EOK;
    533557}
    534558
    535 /** Destroy instance of a USB device.
    536  *
    537  * @param dev Device to be destroyed.
    538  */
    539 void 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);
     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 */
     565void 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
     577void * 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
    559583}
    560584
Note: See TracChangeset for help on using the changeset viewer.