Changeset b4b534ac in mainline for uspace/lib/usbdev/src/devdrv.c


Ignore:
Timestamp:
2016-07-22T08:24:47Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f76d2c2
Parents:
5b18137 (diff), 8351f9a4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~jan.vesely/helenos/usb

File:
1 edited

Legend:

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

    r5b18137 rb4b534ac  
    3333 * USB device driver framework.
    3434 */
    35 #include <usb/dev/driver.h>
     35
     36#include <usb_iface.h>
     37#include <usb/dev/alternate_ifaces.h>
     38#include <usb/dev/device.h>
     39#include <usb/dev/pipes.h>
    3640#include <usb/dev/request.h>
    3741#include <usb/debug.h>
    38 #include <usb/dev.h>
     42#include <usb/descriptor.h>
     43#include <usb/usb.h>
     44
     45#include <assert.h>
     46#include <async.h>
     47#include <devman.h>
    3948#include <errno.h>
    40 #include <str_error.h>
    41 #include <assert.h>
    42 
    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 *);
    46 
    47 static driver_ops_t generic_driver_ops = {
    48         .dev_add = generic_device_add,
    49         .dev_remove = generic_device_remove,
    50         .dev_gone = generic_device_gone,
    51 };
    52 static driver_t generic_driver = {
    53         .driver_ops = &generic_driver_ops
    54 };
    55 
    56 static const usb_driver_t *driver = NULL;
    57 
    58 /** Main routine of USB device driver.
    59  *
    60  * Under normal conditions, this function never returns.
    61  *
    62  * @param drv USB device driver structure.
    63  * @return Task exit status.
    64  */
    65 int usb_driver_main(const usb_driver_t *drv)
    66 {
    67         assert(drv != NULL);
    68 
    69         /* Prepare the generic driver. */
    70         generic_driver.name = drv->name;
    71 
    72         driver = drv;
    73 
    74         return ddf_driver_main(&generic_driver);
    75 }
     49#include <stdlib.h>
     50
     51#include <ddf/driver.h>
     52
     53/** USB device structure. */
     54typedef struct usb_device {
     55        /** Connection to device on USB bus */
     56        usb_dev_session_t *bus_session;
     57        /** devman handle */
     58        devman_handle_t handle;
     59        /** The default control pipe. */
     60        usb_pipe_t ctrl_pipe;
     61
     62        /** Other endpoint pipes.
     63         * This is an array of other endpoint pipes in the same order as
     64         * in usb_driver_t.
     65         */
     66        usb_endpoint_mapping_t *pipes;
     67        /** Number of other endpoint pipes. */
     68        size_t pipes_count;
     69        /** Current interface.
     70         * Usually, drivers operate on single interface only.
     71         * This item contains the value of the interface or -1 for any.
     72         */
     73        int interface_no;
     74        /** Alternative interfaces. */
     75        usb_alternate_interfaces_t alternate_interfaces;
     76        /** Some useful descriptors for USB device. */
     77        usb_device_descriptors_t descriptors;
     78        /** Generic DDF device backing this one. DO NOT TOUCH! */
     79        ddf_dev_t *ddf_dev;
     80        /** Custom driver data.
     81         * Do not use the entry in generic device, that is already used
     82         * by the framework.
     83         */
     84        void *driver_data;
     85
     86} usb_device_t;
    7687
    7788/** Count number of pipes the driver expects.
     
    8091 * @return Number of pipes (excluding default control pipe).
    8192 */
    82 static inline size_t count_other_pipes(
    83     const usb_endpoint_description_t **endpoints)
     93static inline size_t count_pipes(const usb_endpoint_description_t **endpoints)
    8494{
    8595        size_t count;
    8696        for (count = 0; endpoints != NULL && endpoints[count] != NULL; ++count);
    8797        return count;
    88 }
    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.
    93  *
    94  * @param gen_dev Device structure as prepared by DDF.
    95  * @return Error code.
    96  */
    97 int generic_device_add(ddf_dev_t *gen_dev)
    98 {
    99         assert(driver);
    100         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                     ddf_dev_get_name(gen_dev));
    108                 return ENOMEM;
    109         }
    110 
    111         /* Initialize generic USB driver data. */
    112         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",
    116                     ddf_dev_get_name(gen_dev), err_msg, str_error(rc));
    117                 return rc;
    118         }
    119 
    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 = ddf_dev_data_get(gen_dev);
    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 = ddf_dev_data_get(gen_dev);
    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 
    170 /** Destroy existing pipes of a USB device.
    171  *
    172  * @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);
    177         dev->pipes = NULL;
    178         dev->pipes_count = 0;
    17998}
    18099
     
    201120 * @return Error code.
    202121 */
    203 int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,
    204     const usb_endpoint_description_t **endpoints)
    205 {
    206         if (dev->interface_no < 0) {
     122int usb_device_select_interface(usb_device_t *usb_dev,
     123    uint8_t alternate_setting, const usb_endpoint_description_t **endpoints)
     124{
     125        assert(usb_dev);
     126
     127        if (usb_dev->interface_no < 0) {
    207128                return EINVAL;
    208129        }
    209130
    210         /* Destroy existing pipes. */
    211         destroy_current_pipes(dev);
    212 
    213131        /* Change the interface itself. */
    214         int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
    215             alternate_setting);
     132        int rc = usb_request_set_interface(&usb_dev->ctrl_pipe,
     133            usb_dev->interface_no, alternate_setting);
    216134        if (rc != EOK) {
    217135                return rc;
    218136        }
    219137
     138        /* Change current alternative */
     139        usb_dev->alternate_interfaces.current = alternate_setting;
     140
     141        /* Destroy existing pipes. */
     142        usb_device_destroy_pipes(usb_dev);
     143
    220144        /* 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);
     145        rc = usb_device_create_pipes(usb_dev, endpoints);
    225146
    226147        return rc;
     
    233154 * @return Error code.
    234155 */
    235 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,
    236     usb_device_descriptors_t *descriptors)
    237 {
    238         assert(descriptors != NULL);
    239 
    240         descriptors->configuration = NULL;
    241 
    242         int rc;
    243 
    244         /* It is worth to start a long transfer. */
    245         usb_pipe_start_long_transfer(ctrl_pipe);
     156static int usb_device_retrieve_descriptors(usb_device_t *usb_dev)
     157{
     158        assert(usb_dev);
     159        assert(usb_dev->descriptors.full_config == NULL);
    246160
    247161        /* Get the device descriptor. */
    248         rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
     162        int rc = usb_request_get_device_descriptor(&usb_dev->ctrl_pipe,
     163            &usb_dev->descriptors.device);
    249164        if (rc != EOK) {
    250                 goto leave;
     165                return rc;
    251166        }
    252167
    253168        /* Get the full configuration descriptor. */
    254169        rc = usb_request_get_full_configuration_descriptor_alloc(
    255             ctrl_pipe, 0, (void **) &descriptors->configuration,
    256             &descriptors->configuration_size);
    257 
    258 leave:
    259         usb_pipe_end_long_transfer(ctrl_pipe);
     170            &usb_dev->ctrl_pipe, 0,
     171            &usb_dev->descriptors.full_config,
     172            &usb_dev->descriptors.full_config_size);
     173
    260174
    261175        return rc;
     
    266180 * @param[in] descriptors Where to store the descriptors.
    267181 */
    268 void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
    269 {
    270         assert(descriptors);
    271         free(descriptors->configuration);
    272         descriptors->configuration = NULL;
     182static void usb_device_release_descriptors(usb_device_t *usb_dev)
     183{
     184        assert(usb_dev);
     185        free(usb_dev->descriptors.full_config);
     186        usb_dev->descriptors.full_config = NULL;
     187        usb_dev->descriptors.full_config_size = 0;
    273188}
    274189
     
    280195 * - registers endpoints with the host controller
    281196 *
    282  * @param[in] wire Initialized backing connection to the host controller.
    283197 * @param[in] endpoints Endpoints description, NULL terminated.
    284198 * @param[in] config_descr Configuration descriptor of active configuration.
     
    292206 * @return Error code.
    293207 */
    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,
    297     int interface_no, int interface_setting,
    298     usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
    299 {
    300         assert(wire != NULL);
    301         assert(config_descr != NULL);
    302         assert(config_descr_size > 0);
    303         assert(pipes_ptr != NULL);
    304 
    305         size_t i;
    306         int rc;
    307 
    308         const size_t pipe_count = count_other_pipes(endpoints);
     208int usb_device_create_pipes(usb_device_t *usb_dev,
     209    const usb_endpoint_description_t **endpoints)
     210{
     211        assert(usb_dev);
     212        assert(usb_dev->descriptors.full_config);
     213        assert(usb_dev->pipes == NULL);
     214        assert(usb_dev->pipes_count == 0);
     215
     216        size_t pipe_count = count_pipes(endpoints);
    309217        if (pipe_count == 0) {
    310                 if (pipes_count_ptr)
    311                         *pipes_count_ptr = pipe_count;
    312                 *pipes_ptr = NULL;
    313218                return EOK;
    314219        }
    315220
    316         usb_endpoint_mapping_t *pipes
    317             = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
     221        usb_endpoint_mapping_t *pipes =
     222            calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
    318223        if (pipes == NULL) {
    319224                return ENOMEM;
     
    321226
    322227        /* Now initialize. */
    323         for (i = 0; i < pipe_count; i++) {
     228        for (size_t i = 0; i < pipe_count; i++) {
    324229                pipes[i].description = endpoints[i];
    325                 pipes[i].interface_no = interface_no;
    326                 pipes[i].interface_setting = interface_setting;
     230                pipes[i].interface_no = usb_dev->interface_no;
     231                pipes[i].interface_setting =
     232                    usb_dev->alternate_interfaces.current;
    327233        }
    328234
    329235        /* Find the mapping from configuration descriptor. */
    330         rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
    331             config_descr, config_descr_size, wire);
     236        int rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
     237            usb_dev->descriptors.full_config,
     238            usb_dev->descriptors.full_config_size,
     239            usb_dev->bus_session);
    332240        if (rc != EOK) {
    333241                free(pipes);
     
    336244
    337245        /* Register created pipes. */
    338         for (i = 0; i < pipe_count; i++) {
     246        for (size_t i = 0; i < pipe_count; i++) {
    339247                if (pipes[i].present) {
    340248                        rc = usb_pipe_register(&pipes[i].pipe,
     
    346254        }
    347255
    348         *pipes_ptr = pipes;
    349         if (pipes_count_ptr != NULL) {
    350                 *pipes_count_ptr = pipe_count;
    351         }
     256        usb_dev->pipes = pipes;
     257        usb_dev->pipes_count = pipe_count;
    352258
    353259        return EOK;
     
    360266         */
    361267rollback_unregister_endpoints:
    362         for (i = 0; i < pipe_count; i++) {
     268        for (size_t i = 0; i < pipe_count; i++) {
    363269                if (pipes[i].present) {
    364270                        usb_pipe_unregister(&pipes[i].pipe);
     
    372278/** Destroy pipes previously created by usb_device_create_pipes.
    373279 *
    374  * @param[in] pipes Endpoint mapping to be destroyed.
    375  * @param[in] pipes_count Number of endpoints.
    376  */
    377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count)
    378 {
     280 * @param[in] usb_dev USB device.
     281 */
     282void usb_device_destroy_pipes(usb_device_t *usb_dev)
     283{
     284        assert(usb_dev);
     285        assert(usb_dev->pipes || usb_dev->pipes_count == 0);
    379286        /* Destroy the pipes. */
    380         for (size_t i = 0; i < pipes_count; ++i) {
    381                 assert(pipes);
     287        for (size_t i = 0; i < usb_dev->pipes_count; ++i) {
    382288                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         }
    387         free(pipes);
     289                    i, usb_dev->pipes[i].present ? "" : "not ");
     290                if (usb_dev->pipes[i].present)
     291                        usb_pipe_unregister(&usb_dev->pipes[i].pipe);
     292        }
     293        free(usb_dev->pipes);
     294        usb_dev->pipes = NULL;
     295        usb_dev->pipes_count = 0;
     296}
     297
     298usb_pipe_t *usb_device_get_default_pipe(usb_device_t *usb_dev)
     299{
     300        assert(usb_dev);
     301        return &usb_dev->ctrl_pipe;
     302}
     303
     304usb_endpoint_mapping_t *usb_device_get_mapped_ep_desc(usb_device_t *usb_dev,
     305    const usb_endpoint_description_t *desc)
     306{
     307        assert(usb_dev);
     308        for (unsigned i = 0; i < usb_dev->pipes_count; ++i) {
     309                if (usb_dev->pipes[i].description == desc)
     310                        return &usb_dev->pipes[i];
     311        }
     312        return NULL;
     313}
     314
     315usb_endpoint_mapping_t * usb_device_get_mapped_ep(
     316    usb_device_t *usb_dev, usb_endpoint_t ep)
     317{
     318        assert(usb_dev);
     319        for (unsigned i = 0; i < usb_dev->pipes_count; ++i) {
     320                if (usb_dev->pipes[i].pipe.endpoint_no == ep)
     321                        return &usb_dev->pipes[i];
     322        }
     323        return NULL;
     324}
     325
     326int usb_device_get_iface_number(usb_device_t *usb_dev)
     327{
     328        assert(usb_dev);
     329        return usb_dev->interface_no;
     330}
     331
     332devman_handle_t usb_device_get_devman_handle(usb_device_t *usb_dev)
     333{
     334        assert(usb_dev);
     335        return usb_dev->handle;
     336}
     337
     338const usb_device_descriptors_t *usb_device_descriptors(usb_device_t *usb_dev)
     339{
     340        assert(usb_dev);
     341        return &usb_dev->descriptors;
     342}
     343
     344const usb_alternate_interfaces_t * usb_device_get_alternative_ifaces(
     345    usb_device_t *usb_dev)
     346{
     347        assert(usb_dev);
     348        return &usb_dev->alternate_interfaces;
     349}
     350
     351/** Clean instance of a USB device.
     352 *
     353 * @param dev Device to be de-initialized.
     354 *
     355 * Does not free/destroy supplied pointer.
     356 */
     357static void usb_device_fini(usb_device_t *usb_dev)
     358{
     359        if (usb_dev) {
     360                /* Destroy existing pipes. */
     361                usb_device_destroy_pipes(usb_dev);
     362                /* Ignore errors and hope for the best. */
     363                usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
     364                usb_device_release_descriptors(usb_dev);
     365                free(usb_dev->driver_data);
     366                usb_dev->driver_data = NULL;
     367                usb_dev_disconnect(usb_dev->bus_session);
     368                usb_dev->bus_session = NULL;
     369        }
    388370}
    389371
     
    397379 * @return Error code.
    398380 */
    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)
     381static int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev,
     382    const usb_endpoint_description_t **endpoints, const char **errstr_ptr,
     383    devman_handle_t handle, int interface_no)
    401384{
    402385        assert(usb_dev != NULL);
    403         assert(ddf_dev != NULL);
     386        assert(errstr_ptr);
    404387
    405388        *errstr_ptr = NULL;
    406389
    407390        usb_dev->ddf_dev = ddf_dev;
     391        usb_dev->handle = handle;
     392        usb_dev->interface_no = interface_no;
    408393        usb_dev->driver_data = NULL;
    409         usb_dev->descriptors.configuration = NULL;
     394        usb_dev->descriptors.full_config = NULL;
     395        usb_dev->descriptors.full_config_size = 0;
    410396        usb_dev->pipes_count = 0;
    411397        usb_dev->pipes = NULL;
    412398
    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_get_handle(ddf_dev),
    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;
     399        usb_dev->bus_session = usb_dev_connect(handle);
     400
     401        if (!usb_dev->bus_session) {
     402                *errstr_ptr = "device bus session create";
     403                return ENOMEM;
    433404        }
    434405
    435406        /* This pipe was registered by the hub driver,
    436407         * during device initialization. */
    437         rc = usb_pipe_initialize_default_control(
    438             &usb_dev->ctrl_pipe, &usb_dev->wire);
     408        int rc = usb_pipe_initialize_default_control(
     409            &usb_dev->ctrl_pipe, usb_dev->bus_session);
    439410        if (rc != EOK) {
     411                usb_dev_disconnect(usb_dev->bus_session);
    440412                *errstr_ptr = "default control pipe initialization";
    441413                return rc;
    442414        }
    443415
    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 
    451416        /* Retrieve standard descriptors. */
    452         rc = usb_device_retrieve_descriptors(
    453             &usb_dev->ctrl_pipe, &usb_dev->descriptors);
     417        rc = usb_device_retrieve_descriptors(usb_dev);
    454418        if (rc != EOK) {
    455419                *errstr_ptr = "descriptor retrieval";
    456                 usb_hc_connection_close(&usb_dev->hc_conn);
     420                usb_dev_disconnect(usb_dev->bus_session);
    457421                return rc;
    458422        }
     
    463427         * controlling a device. */
    464428        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);
     429            usb_dev->descriptors.full_config,
     430            usb_dev->descriptors.full_config_size, usb_dev->interface_no);
     431
     432        if (endpoints) {
     433                /* Create and register other pipes than default control (EP 0)*/
     434                rc = usb_device_create_pipes(usb_dev, endpoints);
     435                if (rc != EOK) {
     436                        usb_device_fini(usb_dev);
     437                        *errstr_ptr = "pipes initialization";
     438                        return rc;
     439                }
     440        }
     441
    487442        return EOK;
    488443}
    489444
    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         }
     445static int usb_device_get_info(async_sess_t *sess, devman_handle_t *handle,
     446        int *iface_no)
     447{
     448        assert(handle);
     449        assert(iface_no);
     450        async_exch_t *exch = async_exchange_begin(sess);
     451        if (!exch)
     452                return EPARTY;
     453        int ret = usb_get_my_device_handle(exch, handle);
     454        if (ret == EOK) {
     455                ret = usb_get_my_interface(exch, iface_no);
     456                if (ret == ENOTSUP) {
     457                        *iface_no = -1;
     458                        ret = EOK;
     459                }
     460        }
     461        async_exchange_end(exch);
     462        return ret;
     463}
     464
     465int usb_device_create_ddf(ddf_dev_t *ddf_dev,
     466    const usb_endpoint_description_t **desc, const char **err)
     467{
     468        assert(ddf_dev);
     469        assert(err);
     470
     471        devman_handle_t h = 0;
     472        int iface_no = -1;
     473
     474        async_sess_t *sess = devman_parent_device_connect(
     475            ddf_dev_get_handle(ddf_dev), IPC_FLAG_BLOCKING);
     476        const int ret = usb_device_get_info(sess, &h, &iface_no);
     477        async_hangup(sess);
     478        if (ret != EOK)
     479                return ret;
     480
     481        usb_device_t *usb_dev =
     482            ddf_dev_data_alloc(ddf_dev, sizeof(usb_device_t));
     483        if (usb_dev == NULL) {
     484                *err = "DDF data alloc";
     485                return ENOMEM;
     486        }
     487       
     488        return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no);
     489}
     490
     491void usb_device_destroy_ddf(ddf_dev_t *ddf_dev)
     492{
     493        assert(ddf_dev);
     494        usb_device_t *usb_dev = ddf_dev_data_get(ddf_dev);
     495        assert(usb_dev);
     496        usb_device_fini(usb_dev);
     497        return;
     498}
     499
     500usb_device_t * usb_device_create(devman_handle_t handle)
     501{
     502        devman_handle_t h = 0;
     503        int iface_no = -1;
     504
     505        async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);
     506        int ret = usb_device_get_info(sess, &h, &iface_no);
     507        if (sess)
     508                async_hangup(sess);
     509        if (ret != EOK)
     510                return NULL;
     511
     512        usb_device_t *usb_dev = malloc(sizeof(usb_device_t));
     513        if (!usb_dev)
     514                return NULL;
     515
     516        const char* dummy = NULL;
     517        ret = usb_device_init(usb_dev, NULL, NULL, &dummy, handle, iface_no);
     518        if (ret != EOK) {
     519                free(usb_dev);
     520                usb_dev = NULL;
     521        }
     522        return usb_dev;
     523}
     524
     525void usb_device_destroy(usb_device_t *usb_dev)
     526{
     527        if (usb_dev) {
     528                usb_device_fini(usb_dev);
     529                free(usb_dev);
     530        }
     531}
     532
     533const char *usb_device_get_name(usb_device_t *usb_dev)
     534{
     535        assert(usb_dev);
     536        if (usb_dev->ddf_dev)
     537                return ddf_dev_get_name(usb_dev->ddf_dev);
     538        return NULL;
     539}
     540
     541ddf_fun_t *usb_device_ddf_fun_create(usb_device_t *usb_dev, fun_type_t ftype,
     542    const char* name)
     543{
     544        assert(usb_dev);
     545        if (usb_dev->ddf_dev)
     546                return ddf_fun_create(usb_dev->ddf_dev, ftype, name);
     547        return NULL;
     548}
     549
     550async_exch_t * usb_device_bus_exchange_begin(usb_device_t *usb_dev)
     551{
     552        assert(usb_dev);
     553        return async_exchange_begin(usb_dev->bus_session);
     554}
     555
     556void usb_device_bus_exchange_end(async_exch_t *exch)
     557{
     558        async_exchange_end(exch);
    508559}
    509560
     
    521572}
    522573
     574void * usb_device_data_get(usb_device_t *usb_dev)
     575{
     576        assert(usb_dev);
     577        return usb_dev->driver_data;
     578}
     579
    523580/**
    524581 * @}
Note: See TracChangeset for help on using the changeset viewer.