Ignore:
File:
1 edited

Legend:

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

    r4291215 r70452dd4  
    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>
    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         .dev_add = 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;
     53
    5754
    5855/** Main routine of USB device driver.
     
    6360 * @return Task exit status.
    6461 */
    65 int usb_driver_main(const usb_driver_t *drv)
     62int usb_driver_main(usb_driver_t *drv)
    6663{
    6764        assert(drv != NULL);
     
    7471        return ddf_driver_main(&generic_driver);
    7572}
    76 /*----------------------------------------------------------------------------*/
     73
    7774/** Count number of pipes the driver expects.
    7875 *
     
    8077 * @return Number of pipes (excluding default control pipe).
    8178 */
    82 static inline size_t count_other_pipes(
    83     const usb_endpoint_description_t **endpoints)
    84 {
    85         size_t count;
    86         for (count = 0; endpoints != NULL && 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
    8790        return count;
    8891}
    89 /*----------------------------------------------------------------------------*/
    90 /** Callback when a new device is supposed to be controlled by this driver.
    91  *
    92  * This callback is a wrapper for USB specific version of @c device_add.
     92
     93/** Initialize endpoint pipes, excluding default control one.
     94 *
     95 * @param drv The device driver.
     96 * @param dev Device to be initialized.
     97 * @return Error code.
     98 */
     99static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
     100    usb_device_t *dev, int alternate_setting)
     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,
     114            &pipes, &pipes_count);
     115
     116        if (rc != EOK) {
     117                return rc;
     118        }
     119
     120        dev->pipes = pipes;
     121        dev->pipes_count = pipes_count;
     122
     123        return EOK;
     124}
     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.
    93129 *
    94130 * @param gen_dev Device structure as prepared by DDF.
    95131 * @return Error code.
    96132 */
    97 int generic_device_add(ddf_dev_t *gen_dev)
     133int generic_add_device(ddf_dev_t *gen_dev)
    98134{
    99135        assert(driver);
    100136        assert(driver->ops);
    101         assert(driver->ops->device_add);
    102 
    103         /* Get place for driver data. */
    104         usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));
    105         if (dev == NULL) {
    106                 usb_log_error("USB device `%s' structure allocation failed.\n",
    107                     gen_dev->name);
    108                 return ENOMEM;
    109         }
    110 
    111         /* Initialize generic USB driver data. */
     137        assert(driver->ops->add_device);
     138
     139        int rc;
     140
     141        usb_device_t *dev = NULL;
    112142        const char *err_msg = NULL;
    113         int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);
    114         if (rc != EOK) {
    115                 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",
    116146                    gen_dev->name, err_msg, str_error(rc));
    117147                return rc;
    118148        }
    119149
    120         /* Start USB driver specific initialization. */
    121         rc = driver->ops->device_add(dev);
    122         if (rc != EOK)
    123                 usb_device_deinit(dev);
    124         return rc;
    125 }
    126 /*----------------------------------------------------------------------------*/
    127 /** Callback when a device is supposed to be removed from the system.
    128  *
    129  * This callback is a wrapper for USB specific version of @c device_remove.
    130  *
    131  * @param gen_dev Device structure as prepared by DDF.
    132  * @return Error code.
    133  */
    134 int generic_device_remove(ddf_dev_t *gen_dev)
    135 {
    136         assert(driver);
    137         assert(driver->ops);
    138         if (driver->ops->device_rem == NULL)
    139                 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;
    147 }
    148 /*----------------------------------------------------------------------------*/
    149 /** Callback when a device was removed from the system.
    150  *
    151  * This callback is a wrapper for USB specific version of @c device_gone.
    152  *
    153  * @param gen_dev Device structure as prepared by DDF.
    154  * @return Error code.
    155  */
    156 int generic_device_gone(ddf_dev_t *gen_dev)
    157 {
    158         assert(driver);
    159         assert(driver->ops);
    160         if (driver->ops->device_gone == NULL)
    161                 return ENOTSUP;
    162         usb_device_t *usb_dev = gen_dev->driver_data;
    163         const int ret = driver->ops->device_gone(usb_dev);
    164         if (ret == EOK)
    165                 usb_device_deinit(usb_dev);
    166 
    167         return ret;
    168 }
    169 /*----------------------------------------------------------------------------*/
     150        return driver->ops->add_device(dev);
     151}
     152
    170153/** Destroy existing pipes of a USB device.
    171154 *
    172155 * @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);
     156 * @return Error code.
     157 */
     158static int destroy_current_pipes(usb_device_t *dev)
     159{
     160        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     161            dev->pipes, dev->pipes_count);
     162        if (rc != EOK) {
     163                return rc;
     164        }
     165
    177166        dev->pipes = NULL;
    178167        dev->pipes_count = 0;
    179 }
    180 /*----------------------------------------------------------------------------*/
     168
     169        return EOK;
     170}
     171
    181172/** Change interface setting of a device.
    182173 * This function selects new alternate setting of an interface by issuing
     
    202193 */
    203194int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,
    204     const usb_endpoint_description_t **endpoints)
     195    usb_endpoint_description_t **endpoints)
    205196{
    206197        if (dev->interface_no < 0) {
     
    208199        }
    209200
     201        int rc;
     202
    210203        /* Destroy existing pipes. */
    211         destroy_current_pipes(dev);
     204        rc = destroy_current_pipes(dev);
     205        if (rc != EOK) {
     206                return rc;
     207        }
    212208
    213209        /* Change the interface itself. */
    214         int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
     210        rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
    215211            alternate_setting);
    216212        if (rc != EOK) {
     
    219215
    220216        /* 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);
     217        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    225218
    226219        return rc;
     
    262255}
    263256
    264 /** Cleanup structure initialized via usb_device_retrieve_descriptors.
    265  *
    266  * @param[in] descriptors Where to store the descriptors.
    267  */
    268 void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
    269 {
    270         assert(descriptors);
    271         free(descriptors->configuration);
    272         descriptors->configuration = NULL;
    273 }
    274 
    275257/** Create pipes for a device.
    276258 *
     
    280262 * - registers endpoints with the host controller
    281263 *
     264 * @param[in] dev Generic DDF device backing the USB one.
    282265 * @param[in] wire Initialized backing connection to the host controller.
    283266 * @param[in] endpoints Endpoints description, NULL terminated.
     
    289272 *      (not NULL terminated).
    290273 * @param[out] pipes_count_ptr Where to store number of pipes
    291  *      (set to NULL if you wish to ignore the count).
    292  * @return Error code.
    293  */
    294 int usb_device_create_pipes(usb_device_connection_t *wire,
    295     const usb_endpoint_description_t **endpoints,
    296     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,
    297280    int interface_no, int interface_setting,
    298281    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
    299282{
     283        assert(dev != NULL);
    300284        assert(wire != NULL);
     285        assert(endpoints != NULL);
    301286        assert(config_descr != NULL);
    302287        assert(config_descr_size > 0);
     
    306291        int rc;
    307292
    308         const size_t pipe_count = count_other_pipes(endpoints);
     293        size_t pipe_count = count_other_pipes(endpoints);
    309294        if (pipe_count == 0) {
    310                 if (pipes_count_ptr)
    311                         *pipes_count_ptr = pipe_count;
    312295                *pipes_ptr = NULL;
    313296                return EOK;
     
    315298
    316299        usb_endpoint_mapping_t *pipes
    317             = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
     300            = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    318301        if (pipes == NULL) {
    319302                return ENOMEM;
    320303        }
    321304
    322         /* Now initialize. */
     305        /* Initialize to NULL to allow smooth rollback. */
    323306        for (i = 0; i < pipe_count; i++) {
     307                pipes[i].pipe = NULL;
     308        }
     309
     310        /* Now allocate and fully initialize. */
     311        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                }
    324317                pipes[i].description = endpoints[i];
    325318                pipes[i].interface_no = interface_no;
     
    331324            config_descr, config_descr_size, wire);
    332325        if (rc != EOK) {
    333                 free(pipes);
    334                 return rc;
    335         }
    336 
    337         /* Register created pipes. */
     326                goto rollback_free_only;
     327        }
     328
     329        /* Register the endpoints with HC. */
     330        usb_hc_connection_t hc_conn;
     331        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     332        if (rc != EOK) {
     333                goto rollback_free_only;
     334        }
     335
     336        rc = usb_hc_connection_open(&hc_conn);
     337        if (rc != EOK) {
     338                goto rollback_free_only;
     339        }
     340
    338341        for (i = 0; i < pipe_count; i++) {
    339342                if (pipes[i].present) {
    340                         rc = usb_pipe_register(&pipes[i].pipe,
    341                             pipes[i].descriptor->poll_interval);
     343                        rc = usb_pipe_register(pipes[i].pipe,
     344                            pipes[i].descriptor->poll_interval, &hc_conn);
    342345                        if (rc != EOK) {
    343346                                goto rollback_unregister_endpoints;
     
    345348                }
    346349        }
     350
     351        usb_hc_connection_close(&hc_conn);
    347352
    348353        *pipes_ptr = pipes;
     
    362367        for (i = 0; i < pipe_count; i++) {
    363368                if (pipes[i].present) {
    364                         usb_pipe_unregister(&pipes[i].pipe);
     369                        usb_pipe_unregister(pipes[i].pipe, &hc_conn);
    365370                }
    366371        }
    367372
     373        usb_hc_connection_close(&hc_conn);
     374
     375        /*
     376         * Jump here if something went wrong before some actual communication
     377         * with HC. Then the only thing that needs to be done is to free
     378         * allocated memory.
     379         */
     380rollback_free_only:
     381        for (i = 0; i < pipe_count; i++) {
     382                if (pipes[i].pipe != NULL) {
     383                        free(pipes[i].pipe);
     384                }
     385        }
    368386        free(pipes);
     387
    369388        return rc;
    370389}
     
    372391/** Destroy pipes previously created by usb_device_create_pipes.
    373392 *
     393 * @param[in] dev Generic DDF device backing the USB one.
    374394 * @param[in] pipes Endpoint mapping to be destroyed.
    375395 * @param[in] pipes_count Number of endpoints.
    376396 */
    377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count)
    378 {
     397int usb_device_destroy_pipes(ddf_dev_t *dev,
     398    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     399{
     400        assert(dev != NULL);
     401        assert(((pipes != NULL) && (pipes_count > 0))
     402            || ((pipes == NULL) && (pipes_count == 0)));
     403
     404        if (pipes_count == 0) {
     405                return EOK;
     406        }
     407
     408        int rc;
     409
     410        /* Prepare connection to HC to allow endpoint unregistering. */
     411        usb_hc_connection_t hc_conn;
     412        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     413        if (rc != EOK) {
     414                return rc;
     415        }
     416        rc = usb_hc_connection_open(&hc_conn);
     417        if (rc != EOK) {
     418                return rc;
     419        }
     420
    379421        /* 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",
    383                     i, pipes[i].present ? "" : "not ");
    384                 if (pipes[i].present)
    385                         usb_pipe_unregister(&pipes[i].pipe);
    386         }
     422        size_t i;
     423        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);
     429
    387430        free(pipes);
    388 }
    389 
    390 /** Initialize new instance of USB device.
    391  *
    392  * @param[in] usb_dev Pointer to the new device.
     431
     432        return EOK;
     433}
     434
     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 *
    393465 * @param[in] ddf_dev Generic DDF device backing the USB one.
    394466 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     467 * @param[out] dev_ptr Where to store pointer to the new device.
    395468 * @param[out] errstr_ptr Where to store description of context
    396469 *      (in case error occurs).
    397470 * @return Error code.
    398471 */
    399 int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev,
    400     const usb_endpoint_description_t **endpoints, const char **errstr_ptr)
    401 {
    402         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);
    403477        assert(ddf_dev != NULL);
    404478
     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
    405529        *errstr_ptr = NULL;
    406 
    407         usb_dev->ddf_dev = ddf_dev;
    408         usb_dev->driver_data = NULL;
    409         usb_dev->descriptors.configuration = NULL;
    410         usb_dev->pipes_count = 0;
    411         usb_dev->pipes = NULL;
    412 
    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 
    427         /* Initialize backing wire and control pipe. */
    428         rc = usb_device_connection_initialize(
    429             &usb_dev->wire, &usb_dev->hc_conn, address);
    430         if (rc != EOK) {
    431                 *errstr_ptr = "device connection initialization";
    432                 return rc;
    433         }
    434 
    435         /* This pipe was registered by the hub driver,
    436          * during device initialization. */
    437         rc = usb_pipe_initialize_default_control(
    438             &usb_dev->ctrl_pipe, &usb_dev->wire);
    439         if (rc != EOK) {
    440                 *errstr_ptr = "default control pipe initialization";
    441                 return rc;
    442         }
    443 
    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         }
    450 
    451         /* Retrieve standard descriptors. */
    452         rc = usb_device_retrieve_descriptors(
    453             &usb_dev->ctrl_pipe, &usb_dev->descriptors);
    454         if (rc != EOK) {
    455                 *errstr_ptr = "descriptor retrieval";
    456                 usb_hc_connection_close(&usb_dev->hc_conn);
    457                 return rc;
    458         }
    459 
    460         /* Create alternate interfaces. We will silently ignore failure.
    461          * We might either control one interface or an entire device,
    462          * it makes no sense to speak about alternate interfaces when
    463          * controlling a device. */
    464         rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
    465             usb_dev->descriptors.configuration,
    466             usb_dev->descriptors.configuration_size, usb_dev->interface_no);
    467         const int alternate_iface =
    468             (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
    469 
    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);
    478                 /* Full configuration descriptor is allocated. */
    479                 usb_device_release_descriptors(&usb_dev->descriptors);
    480                 /* Alternate interfaces may be allocated */
    481                 usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
    482                 *errstr_ptr = "pipes initialization";
    483                 return rc;
    484         }
    485 
    486         usb_hc_connection_close(&usb_dev->hc_conn);
     530        *dev_ptr = dev;
     531
    487532        return EOK;
    488533}
    489534
    490 /** Clean instance of a USB device.
    491  *
    492  * @param dev Device to be de-initialized.
    493  *
    494  * Does not free/destroy supplied pointer.
    495  */
    496 void usb_device_deinit(usb_device_t *dev)
    497 {
    498         if (dev) {
    499                 /* Destroy existing pipes. */
    500                 destroy_current_pipes(dev);
    501                 /* Ignore errors and hope for the best. */
    502                 usb_hc_connection_deinitialize(&dev->hc_conn);
    503                 usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
    504                 usb_device_release_descriptors(&dev->descriptors);
    505                 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  */
    515 void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size)
    516 {
    517         assert(usb_dev);
    518         assert(usb_dev->driver_data == NULL);
    519         return usb_dev->driver_data = calloc(1, size);
    520 
     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);
    521559}
    522560
Note: See TracChangeset for help on using the changeset viewer.