Ignore:
File:
1 edited

Legend:

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

    r9d58539 rb803845  
    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 *
     
    6364 * @return Task exit status.
    6465 */
    65 int usb_driver_main(const usb_driver_t *drv)
     66int usb_driver_main(usb_driver_t *drv)
    6667{
    6768        assert(drv != NULL);
     
    7475        return ddf_driver_main(&generic_driver);
    7576}
    76 /*----------------------------------------------------------------------------*/
     77
    7778/** Count number of pipes the driver expects.
    7879 *
     
    8081 * @return Number of pipes (excluding default control pipe).
    8182 */
    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);
     83static size_t count_other_pipes(const usb_endpoint_description_t **endpoints)
     84{
     85        size_t count = 0;
     86        if (endpoints == NULL) {
     87                return 0;
     88        }
     89
     90        while (endpoints[count] != NULL) {
     91                count++;
     92        }
     93
    8794        return count;
     95}
     96
     97/** Initialize endpoint pipes, excluding default control one.
     98 *
     99 * @param drv The device driver.
     100 * @param dev Device to be initialized.
     101 * @return Error code.
     102 */
     103static int initialize_other_pipes(const usb_endpoint_description_t **endpoints,
     104    usb_device_t *dev, int alternate_setting)
     105{
     106        if (endpoints == NULL) {
     107                dev->pipes = NULL;
     108                dev->pipes_count = 0;
     109                return EOK;
     110        }
     111
     112        usb_endpoint_mapping_t *pipes;
     113        size_t pipes_count;
     114
     115        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
     116            dev->descriptors.configuration, dev->descriptors.configuration_size,
     117            dev->interface_no, alternate_setting, &pipes, &pipes_count);
     118
     119        if (rc != EOK) {
     120                return rc;
     121        }
     122
     123        dev->pipes = pipes;
     124        dev->pipes_count = pipes_count;
     125
     126        return EOK;
    88127}
    89128/*----------------------------------------------------------------------------*/
     
    101140        assert(driver->ops->device_add);
    102141
    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. */
     142        int rc;
     143
     144        usb_device_t *dev = NULL;
    112145        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",
     146        rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
     147        if (rc != EOK) {
     148                usb_log_error("USB device `%s' creation failed (%s): %s.\n",
    116149                    gen_dev->name, err_msg, str_error(rc));
    117150                return rc;
    118151        }
    119 
    120         /* Start USB driver specific initialization. */
     152        gen_dev->driver_data = dev;
     153
    121154        rc = driver->ops->device_add(dev);
    122155        if (rc != EOK)
     
    138171        if (driver->ops->device_rem == NULL)
    139172                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;
     173        /* Just tell the driver to stop whatever it is doing, keep structures */
     174        return driver->ops->device_rem(gen_dev->driver_data);
    147175}
    148176/*----------------------------------------------------------------------------*/
     
    171199 *
    172200 * @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);
     201 * @return Error code.
     202 */
     203static int destroy_current_pipes(usb_device_t *dev)
     204{
     205        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     206            dev->pipes, dev->pipes_count);
     207        if (rc != EOK) {
     208                return rc;
     209        }
     210
    177211        dev->pipes = NULL;
    178212        dev->pipes_count = 0;
    179 }
    180 /*----------------------------------------------------------------------------*/
     213
     214        return EOK;
     215}
     216
    181217/** Change interface setting of a device.
    182218 * This function selects new alternate setting of an interface by issuing
     
    208244        }
    209245
     246        int rc;
     247
    210248        /* Destroy existing pipes. */
    211         destroy_current_pipes(dev);
     249        rc = destroy_current_pipes(dev);
     250        if (rc != EOK) {
     251                return rc;
     252        }
    212253
    213254        /* Change the interface itself. */
    214         int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
     255        rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
    215256            alternate_setting);
    216257        if (rc != EOK) {
     
    219260
    220261        /* 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);
     262        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    225263
    226264        return rc;
     
    262300}
    263301
    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 
    275302/** Create pipes for a device.
    276303 *
     
    280307 * - registers endpoints with the host controller
    281308 *
     309 * @param[in] dev Generic DDF device backing the USB one.
    282310 * @param[in] wire Initialized backing connection to the host controller.
    283311 * @param[in] endpoints Endpoints description, NULL terminated.
     
    289317 *      (not NULL terminated).
    290318 * @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,
     319 *      (set to if you wish to ignore the count).
     320 * @return Error code.
     321 */
     322int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire,
    295323    const usb_endpoint_description_t **endpoints,
    296324    const uint8_t *config_descr, size_t config_descr_size,
     
    298326    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
    299327{
     328        assert(dev != NULL);
    300329        assert(wire != NULL);
     330        assert(endpoints != NULL);
    301331        assert(config_descr != NULL);
    302332        assert(config_descr_size > 0);
     
    308338        const size_t pipe_count = count_other_pipes(endpoints);
    309339        if (pipe_count == 0) {
    310                 if (pipes_count_ptr)
    311                         *pipes_count_ptr = pipe_count;
     340                *pipes_count_ptr = pipe_count;
    312341                *pipes_ptr = NULL;
    313342                return EOK;
     
    315344
    316345        usb_endpoint_mapping_t *pipes
    317             = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
     346            = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    318347        if (pipes == NULL) {
    319348                return ENOMEM;
    320349        }
    321350
    322         /* Now initialize. */
     351        /* Initialize to NULL to allow smooth rollback. */
    323352        for (i = 0; i < pipe_count; i++) {
     353                pipes[i].pipe = NULL;
     354        }
     355
     356        /* Now allocate and fully initialize. */
     357        for (i = 0; i < pipe_count; i++) {
     358                pipes[i].pipe = malloc(sizeof(usb_pipe_t));
     359                if (pipes[i].pipe == NULL) {
     360                        rc = ENOMEM;
     361                        goto rollback_free_only;
     362                }
    324363                pipes[i].description = endpoints[i];
    325364                pipes[i].interface_no = interface_no;
     
    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) {
    340                         rc = usb_pipe_register(&pipes[i].pipe,
    341                             pipes[i].descriptor->poll_interval);
     389                        rc = usb_pipe_register(pipes[i].pipe,
     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("usb_device_create_pipes(): "
     399                    "Failed to close connection.\n");
    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:
     431        for (i = 0; i < pipe_count; i++) {
     432                if (pipes[i].pipe != NULL) {
     433                        free(pipes[i].pipe);
     434                }
     435        }
    368436        free(pipes);
     437
    369438        return rc;
    370439}
     
    372441/** Destroy pipes previously created by usb_device_create_pipes.
    373442 *
     443 * @param[in] dev Generic DDF device backing the USB one.
    374444 * @param[in] pipes Endpoint mapping to be destroyed.
    375445 * @param[in] pipes_count Number of endpoints.
    376446 */
    377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count)
    378 {
     447int usb_device_destroy_pipes(const ddf_dev_t *dev,
     448    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     449{
     450        assert(dev != NULL);
     451
     452        if (pipes_count == 0) {
     453                assert(pipes == NULL);
     454                return EOK;
     455        }
     456        assert(pipes != NULL);
     457
     458        int rc;
     459
     460        /* Prepare connection to HC to allow endpoint unregistering. */
     461        usb_hc_connection_t hc_conn;
     462        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     463        if (rc != EOK) {
     464                return rc;
     465        }
     466        rc = usb_hc_connection_open(&hc_conn);
     467        if (rc != EOK) {
     468                return rc;
     469        }
     470
    379471        /* 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",
     472        size_t i;
     473        for (i = 0; i < pipes_count; i++) {
     474                usb_log_debug2("Unregistering pipe %zu (%spresent).\n",
    383475                    i, pipes[i].present ? "" : "not ");
    384476                if (pipes[i].present)
    385                         usb_pipe_unregister(&pipes[i].pipe);
    386         }
     477                        usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     478                free(pipes[i].pipe);
     479        }
     480
     481        if (usb_hc_connection_close(&hc_conn) != EOK)
     482                usb_log_warning("usb_device_destroy_pipes(): "
     483                    "Failed to close connection.\n");
     484
    387485        free(pipes);
    388 }
    389 
    390 /** Initialize new instance of USB device.
    391  *
    392  * @param[in] usb_dev Pointer to the new device.
     486
     487        return EOK;
     488}
     489
     490/** Initialize control pipe in a device.
     491 *
     492 * @param dev USB device in question.
     493 * @param errmsg Where to store error context.
     494 * @return
     495 */
     496static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
     497{
     498        int rc;
     499
     500        rc = usb_device_connection_initialize_from_device(&dev->wire,
     501            dev->ddf_dev);
     502        if (rc != EOK) {
     503                *errmsg = "device connection initialization";
     504                return rc;
     505        }
     506
     507        rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
     508            &dev->wire);
     509        if (rc != EOK) {
     510                *errmsg = "default control pipe initialization";
     511                return rc;
     512        }
     513
     514        return EOK;
     515}
     516
     517
     518/** Create new instance of USB device.
     519 *
    393520 * @param[in] ddf_dev Generic DDF device backing the USB one.
    394521 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     522 * @param[out] dev_ptr Where to store pointer to the new device.
    395523 * @param[out] errstr_ptr Where to store description of context
    396524 *      (in case error occurs).
    397525 * @return Error code.
    398526 */
    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);
     527int usb_device_create(ddf_dev_t *ddf_dev,
     528    const usb_endpoint_description_t **endpoints,
     529    usb_device_t **dev_ptr, const char **errstr_ptr)
     530{
     531        assert(dev_ptr != NULL);
    403532        assert(ddf_dev != NULL);
    404533
     534        int rc;
     535
     536        usb_device_t *dev = malloc(sizeof(usb_device_t));
     537        if (dev == NULL) {
     538                *errstr_ptr = "structure allocation";
     539                return ENOMEM;
     540        }
     541
     542        // FIXME: proper deallocation in case of errors
     543
     544        dev->ddf_dev = ddf_dev;
     545        dev->driver_data = NULL;
     546        dev->descriptors.configuration = NULL;
     547        dev->alternate_interfaces = NULL;
     548
     549        dev->pipes_count = 0;
     550        dev->pipes = NULL;
     551
     552        /* Initialize backing wire and control pipe. */
     553        rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
     554        if (rc != EOK) {
     555                return rc;
     556        }
     557
     558        /* Get our interface. */
     559        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     560
     561        /* Retrieve standard descriptors. */
     562        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     563            &dev->descriptors);
     564        if (rc != EOK) {
     565                *errstr_ptr = "descriptor retrieval";
     566                return rc;
     567        }
     568
     569        /* Create alternate interfaces. */
     570        rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
     571            dev->descriptors.configuration_size, dev->interface_no,
     572            &dev->alternate_interfaces);
     573        if (rc != EOK) {
     574                /* We will try to silently ignore this. */
     575                dev->alternate_interfaces = NULL;
     576        }
     577
     578        rc = initialize_other_pipes(endpoints, dev, 0);
     579        if (rc != EOK) {
     580                *errstr_ptr = "pipes initialization";
     581                return rc;
     582        }
     583
    405584        *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);
     585        *dev_ptr = dev;
     586
    487587        return EOK;
    488588}
    489589
    490 /** Clean instance of a USB device.
     590/** Destroy instance of a USB device.
    491591 *
    492592 * @param dev Device to be de-initialized.
     
    496596void usb_device_deinit(usb_device_t *dev)
    497597{
    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  */
     598        if (dev == NULL) {
     599                return;
     600        }
     601
     602        /* Ignore errors and hope for the best. */
     603        destroy_current_pipes(dev);
     604
     605        if (dev->alternate_interfaces != NULL) {
     606                free(dev->alternate_interfaces->alternatives);
     607        }
     608        free(dev->alternate_interfaces);
     609        free(dev->descriptors.configuration);
     610        free(dev->driver_data);
     611}
     612
    515613void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size)
    516614{
Note: See TracChangeset for help on using the changeset viewer.