Ignore:
File:
1 edited

Legend:

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

    r56fd7cf r58563585  
    2727 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2828 */
     29
    2930/** @addtogroup libusbdev
    3031 * @{
     
    3334 * USB device driver framework.
    3435 */
    35 #include <usb/dev/driver.h>
     36
     37#include <usb_iface.h>
     38#include <usb/dev/alternate_ifaces.h>
     39#include <usb/dev/device.h>
     40#include <usb/dev/pipes.h>
    3641#include <usb/dev/request.h>
    3742#include <usb/debug.h>
    38 #include <usb/dev.h>
     43#include <usb/descriptor.h>
     44#include <usb/usb.h>
     45
     46#include <assert.h>
     47#include <async.h>
     48#include <devman.h>
    3949#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 }
     50#include <stdlib.h>
     51
     52#include <ddf/driver.h>
     53
     54/** USB device structure. */
     55typedef struct usb_device {
     56        /** Connection to device on USB bus */
     57        usb_dev_session_t *bus_session;
     58       
     59        /** devman handle */
     60        devman_handle_t handle;
     61       
     62        /** The default control pipe. */
     63        usb_pipe_t ctrl_pipe;
     64       
     65        /** Other endpoint pipes.
     66         *
     67         * This is an array of other endpoint pipes in the same order as
     68         * in usb_driver_t.
     69         */
     70        usb_endpoint_mapping_t *pipes;
     71       
     72        /** Number of other endpoint pipes. */
     73        size_t pipes_count;
     74       
     75        /** Current interface.
     76         *
     77         * Usually, drivers operate on single interface only.
     78         * This item contains the value of the interface or -1 for any.
     79         */
     80        int interface_no;
     81       
     82        /** Alternative interfaces. */
     83        usb_alternate_interfaces_t alternate_interfaces;
     84       
     85        /** Some useful descriptors for USB device. */
     86        usb_device_descriptors_t descriptors;
     87       
     88        /** Generic DDF device backing this one. DO NOT TOUCH! */
     89        ddf_dev_t *ddf_dev;
     90       
     91        /** Custom driver data.
     92         *
     93         * Do not use the entry in generic device, that is already used
     94         * by the framework.
     95         */
     96        void *driver_data;
     97} usb_device_t;
    7698
    7799/** Count number of pipes the driver expects.
     
    80102 * @return Number of pipes (excluding default control pipe).
    81103 */
    82 static inline size_t count_other_pipes(
    83     const usb_endpoint_description_t **endpoints)
     104static inline size_t count_pipes(const usb_endpoint_description_t **endpoints)
    84105{
    85106        size_t count;
    86107        for (count = 0; endpoints != NULL && endpoints[count] != NULL; ++count);
    87108        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;
    179109}
    180110
     
    201131 * @return Error code.
    202132 */
    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) {
     133int usb_device_select_interface(usb_device_t *usb_dev,
     134    uint8_t alternate_setting, const usb_endpoint_description_t **endpoints)
     135{
     136        assert(usb_dev);
     137
     138        if (usb_dev->interface_no < 0) {
    207139                return EINVAL;
    208140        }
    209141
    210         /* Destroy existing pipes. */
    211         destroy_current_pipes(dev);
    212 
    213142        /* Change the interface itself. */
    214         int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
    215             alternate_setting);
     143        int rc = usb_request_set_interface(&usb_dev->ctrl_pipe,
     144            usb_dev->interface_no, alternate_setting);
    216145        if (rc != EOK) {
    217146                return rc;
    218147        }
     148       
     149        /* Change current alternative */
     150        usb_dev->alternate_interfaces.current = alternate_setting;
     151
     152        /* Destroy existing pipes. */
     153        usb_device_destroy_pipes(usb_dev);
    219154
    220155        /* 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);
     156        rc = usb_device_create_pipes(usb_dev, endpoints);
    225157
    226158        return rc;
     
    233165 * @return Error code.
    234166 */
    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);
     167static int usb_device_retrieve_descriptors(usb_device_t *usb_dev)
     168{
     169        assert(usb_dev);
     170        assert(usb_dev->descriptors.full_config == NULL);
    246171
    247172        /* Get the device descriptor. */
    248         rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
     173        int rc = usb_request_get_device_descriptor(&usb_dev->ctrl_pipe,
     174            &usb_dev->descriptors.device);
    249175        if (rc != EOK) {
    250                 goto leave;
     176                return rc;
    251177        }
    252178
    253179        /* Get the full configuration descriptor. */
    254180        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);
     181            &usb_dev->ctrl_pipe, 0,
     182            &usb_dev->descriptors.full_config,
     183            &usb_dev->descriptors.full_config_size);
     184
    260185
    261186        return rc;
     
    266191 * @param[in] descriptors Where to store the descriptors.
    267192 */
    268 void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
    269 {
    270         assert(descriptors);
    271         free(descriptors->configuration);
    272         descriptors->configuration = NULL;
     193static void usb_device_release_descriptors(usb_device_t *usb_dev)
     194{
     195        assert(usb_dev);
     196        free(usb_dev->descriptors.full_config);
     197        usb_dev->descriptors.full_config = NULL;
     198        usb_dev->descriptors.full_config_size = 0;
    273199}
    274200
     
    280206 * - registers endpoints with the host controller
    281207 *
    282  * @param[in] wire Initialized backing connection to the host controller.
    283208 * @param[in] endpoints Endpoints description, NULL terminated.
    284209 * @param[in] config_descr Configuration descriptor of active configuration.
     
    292217 * @return Error code.
    293218 */
    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);
     219int usb_device_create_pipes(usb_device_t *usb_dev,
     220    const usb_endpoint_description_t **endpoints)
     221{
     222        assert(usb_dev);
     223        assert(usb_dev->descriptors.full_config);
     224        assert(usb_dev->pipes == NULL);
     225        assert(usb_dev->pipes_count == 0);
     226
     227        size_t pipe_count = count_pipes(endpoints);
    309228        if (pipe_count == 0) {
    310                 if (pipes_count_ptr)
    311                         *pipes_count_ptr = pipe_count;
    312                 *pipes_ptr = NULL;
    313229                return EOK;
    314230        }
    315231
    316         usb_endpoint_mapping_t *pipes
    317             = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
     232        usb_endpoint_mapping_t *pipes =
     233            calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
    318234        if (pipes == NULL) {
    319235                return ENOMEM;
     
    321237
    322238        /* Now initialize. */
    323         for (i = 0; i < pipe_count; i++) {
     239        for (size_t i = 0; i < pipe_count; i++) {
    324240                pipes[i].description = endpoints[i];
    325                 pipes[i].interface_no = interface_no;
    326                 pipes[i].interface_setting = interface_setting;
     241                pipes[i].interface_no = usb_dev->interface_no;
     242                pipes[i].interface_setting =
     243                    usb_dev->alternate_interfaces.current;
    327244        }
    328245
    329246        /* Find the mapping from configuration descriptor. */
    330         rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
    331             config_descr, config_descr_size, wire);
     247        int rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
     248            usb_dev->descriptors.full_config,
     249            usb_dev->descriptors.full_config_size,
     250            usb_dev->bus_session);
    332251        if (rc != EOK) {
    333252                free(pipes);
     
    336255
    337256        /* Register created pipes. */
    338         for (i = 0; i < pipe_count; i++) {
     257        for (size_t i = 0; i < pipe_count; i++) {
    339258                if (pipes[i].present) {
    340259                        rc = usb_pipe_register(&pipes[i].pipe,
     
    346265        }
    347266
    348         *pipes_ptr = pipes;
    349         if (pipes_count_ptr != NULL) {
    350                 *pipes_count_ptr = pipe_count;
    351         }
     267        usb_dev->pipes = pipes;
     268        usb_dev->pipes_count = pipe_count;
    352269
    353270        return EOK;
     
    360277         */
    361278rollback_unregister_endpoints:
    362         for (i = 0; i < pipe_count; i++) {
     279        for (size_t i = 0; i < pipe_count; i++) {
    363280                if (pipes[i].present) {
    364281                        usb_pipe_unregister(&pipes[i].pipe);
     
    372289/** Destroy pipes previously created by usb_device_create_pipes.
    373290 *
    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 {
     291 * @param[in] usb_dev USB device.
     292 *
     293 */
     294void usb_device_destroy_pipes(usb_device_t *usb_dev)
     295{
     296        assert(usb_dev);
     297        assert(usb_dev->pipes || usb_dev->pipes_count == 0);
     298       
    379299        /* Destroy the pipes. */
    380         for (size_t i = 0; i < pipes_count; ++i) {
    381                 assert(pipes);
     300        for (size_t i = 0; i < usb_dev->pipes_count; ++i) {
    382301                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);
     302                    i, usb_dev->pipes[i].present ? "" : "not ");
     303                if (usb_dev->pipes[i].present)
     304                        usb_pipe_unregister(&usb_dev->pipes[i].pipe);
     305        }
     306       
     307        free(usb_dev->pipes);
     308        usb_dev->pipes = NULL;
     309        usb_dev->pipes_count = 0;
     310}
     311
     312usb_pipe_t *usb_device_get_default_pipe(usb_device_t *usb_dev)
     313{
     314        assert(usb_dev);
     315        return &usb_dev->ctrl_pipe;
     316}
     317
     318usb_endpoint_mapping_t *usb_device_get_mapped_ep_desc(usb_device_t *usb_dev,
     319    const usb_endpoint_description_t *desc)
     320{
     321        assert(usb_dev);
     322        for (unsigned i = 0; i < usb_dev->pipes_count; ++i) {
     323                if (usb_dev->pipes[i].description == desc)
     324                        return &usb_dev->pipes[i];
     325        }
     326        return NULL;
     327}
     328
     329usb_endpoint_mapping_t * usb_device_get_mapped_ep(
     330    usb_device_t *usb_dev, usb_endpoint_t ep)
     331{
     332        assert(usb_dev);
     333        for (unsigned i = 0; i < usb_dev->pipes_count; ++i) {
     334                if (usb_dev->pipes[i].pipe.endpoint_no == ep)
     335                        return &usb_dev->pipes[i];
     336        }
     337        return NULL;
     338}
     339
     340int usb_device_get_iface_number(usb_device_t *usb_dev)
     341{
     342        assert(usb_dev);
     343        return usb_dev->interface_no;
     344}
     345
     346devman_handle_t usb_device_get_devman_handle(usb_device_t *usb_dev)
     347{
     348        assert(usb_dev);
     349        return usb_dev->handle;
     350}
     351
     352const usb_device_descriptors_t *usb_device_descriptors(usb_device_t *usb_dev)
     353{
     354        assert(usb_dev);
     355        return &usb_dev->descriptors;
     356}
     357
     358const usb_alternate_interfaces_t * usb_device_get_alternative_ifaces(
     359    usb_device_t *usb_dev)
     360{
     361        assert(usb_dev);
     362        return &usb_dev->alternate_interfaces;
     363}
     364
     365/** Clean instance of a USB device.
     366 *
     367 * @param dev Device to be de-initialized.
     368 *
     369 * Does not free/destroy supplied pointer.
     370 */
     371static void usb_device_fini(usb_device_t *usb_dev)
     372{
     373        if (usb_dev) {
     374                /* Destroy existing pipes. */
     375                usb_device_destroy_pipes(usb_dev);
     376                /* Ignore errors and hope for the best. */
     377                usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
     378                usb_device_release_descriptors(usb_dev);
     379                free(usb_dev->driver_data);
     380                usb_dev->driver_data = NULL;
     381                usb_dev_disconnect(usb_dev->bus_session);
     382                usb_dev->bus_session = NULL;
     383        }
    388384}
    389385
     
    397393 * @return Error code.
    398394 */
    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)
     395static int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev,
     396    const usb_endpoint_description_t **endpoints, const char **errstr_ptr,
     397    devman_handle_t handle, int interface_no)
    401398{
    402399        assert(usb_dev != NULL);
    403         assert(ddf_dev != NULL);
     400        assert(errstr_ptr);
    404401
    405402        *errstr_ptr = NULL;
    406403
    407404        usb_dev->ddf_dev = ddf_dev;
     405        usb_dev->handle = handle;
     406        usb_dev->interface_no = interface_no;
    408407        usb_dev->driver_data = NULL;
    409         usb_dev->descriptors.configuration = NULL;
     408        usb_dev->descriptors.full_config = NULL;
     409        usb_dev->descriptors.full_config_size = 0;
    410410        usb_dev->pipes_count = 0;
    411411        usb_dev->pipes = NULL;
    412412
    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;
     413        usb_dev->bus_session = usb_dev_connect(handle);
     414
     415        if (!usb_dev->bus_session) {
     416                *errstr_ptr = "device bus session create";
     417                return ENOMEM;
    433418        }
    434419
    435420        /* This pipe was registered by the hub driver,
    436421         * during device initialization. */
    437         rc = usb_pipe_initialize_default_control(
    438             &usb_dev->ctrl_pipe, &usb_dev->wire);
     422        int rc = usb_pipe_initialize_default_control(
     423            &usb_dev->ctrl_pipe, usb_dev->bus_session);
    439424        if (rc != EOK) {
     425                usb_dev_disconnect(usb_dev->bus_session);
    440426                *errstr_ptr = "default control pipe initialization";
    441427                return rc;
    442428        }
    443429
    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 
    451430        /* Retrieve standard descriptors. */
    452         rc = usb_device_retrieve_descriptors(
    453             &usb_dev->ctrl_pipe, &usb_dev->descriptors);
     431        rc = usb_device_retrieve_descriptors(usb_dev);
    454432        if (rc != EOK) {
    455433                *errstr_ptr = "descriptor retrieval";
    456                 usb_hc_connection_close(&usb_dev->hc_conn);
     434                usb_dev_disconnect(usb_dev->bus_session);
    457435                return rc;
    458436        }
     
    463441         * controlling a device. */
    464442        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);
     443            usb_dev->descriptors.full_config,
     444            usb_dev->descriptors.full_config_size, usb_dev->interface_no);
     445
     446        if (endpoints) {
     447                /* Create and register other pipes than default control (EP 0)*/
     448                rc = usb_device_create_pipes(usb_dev, endpoints);
     449                if (rc != EOK) {
     450                        usb_device_fini(usb_dev);
     451                        *errstr_ptr = "pipes initialization";
     452                        return rc;
     453                }
     454        }
     455
    487456        return EOK;
    488457}
    489458
    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         }
     459static int usb_device_get_info(async_sess_t *sess, devman_handle_t *handle,
     460        int *iface_no)
     461{
     462        assert(handle);
     463        assert(iface_no);
     464       
     465        async_exch_t *exch = async_exchange_begin(sess);
     466        if (!exch)
     467                return EPARTY;
     468       
     469        int ret = usb_get_my_device_handle(exch, handle);
     470        if (ret == EOK) {
     471                ret = usb_get_my_interface(exch, iface_no);
     472                if (ret == ENOTSUP) {
     473                        *iface_no = -1;
     474                        ret = EOK;
     475                }
     476        }
     477       
     478        async_exchange_end(exch);
     479        return ret;
     480}
     481
     482int usb_device_create_ddf(ddf_dev_t *ddf_dev,
     483    const usb_endpoint_description_t **desc, const char **err)
     484{
     485        assert(ddf_dev);
     486        assert(err);
     487
     488        devman_handle_t h = 0;
     489        int iface_no = -1;
     490
     491        async_sess_t *sess = devman_parent_device_connect(
     492            ddf_dev_get_handle(ddf_dev), IPC_FLAG_BLOCKING);
     493        if (sess == NULL)
     494                return ENOMEM;
     495        const int ret = usb_device_get_info(sess, &h, &iface_no);
     496        async_hangup(sess);
     497        if (ret != EOK)
     498                return ret;
     499
     500        usb_device_t *usb_dev =
     501            ddf_dev_data_alloc(ddf_dev, sizeof(usb_device_t));
     502        if (usb_dev == NULL) {
     503                *err = "DDF data alloc";
     504                return ENOMEM;
     505        }
     506       
     507        return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no);
     508}
     509
     510void usb_device_destroy_ddf(ddf_dev_t *ddf_dev)
     511{
     512        assert(ddf_dev);
     513        usb_device_t *usb_dev = ddf_dev_data_get(ddf_dev);
     514        assert(usb_dev);
     515        usb_device_fini(usb_dev);
     516        return;
     517}
     518
     519usb_device_t * usb_device_create(devman_handle_t handle)
     520{
     521        devman_handle_t h = 0;
     522        int iface_no = -1;
     523
     524        async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);
     525        int ret = usb_device_get_info(sess, &h, &iface_no);
     526        if (sess)
     527                async_hangup(sess);
     528        if (ret != EOK)
     529                return NULL;
     530
     531        usb_device_t *usb_dev = malloc(sizeof(usb_device_t));
     532        if (!usb_dev)
     533                return NULL;
     534
     535        const char* dummy = NULL;
     536        ret = usb_device_init(usb_dev, NULL, NULL, &dummy, handle, iface_no);
     537        if (ret != EOK) {
     538                free(usb_dev);
     539                usb_dev = NULL;
     540        }
     541        return usb_dev;
     542}
     543
     544void usb_device_destroy(usb_device_t *usb_dev)
     545{
     546        if (usb_dev) {
     547                usb_device_fini(usb_dev);
     548                free(usb_dev);
     549        }
     550}
     551
     552const char *usb_device_get_name(usb_device_t *usb_dev)
     553{
     554        assert(usb_dev);
     555        if (usb_dev->ddf_dev)
     556                return ddf_dev_get_name(usb_dev->ddf_dev);
     557        return NULL;
     558}
     559
     560ddf_fun_t *usb_device_ddf_fun_create(usb_device_t *usb_dev, fun_type_t ftype,
     561    const char* name)
     562{
     563        assert(usb_dev);
     564        if (usb_dev->ddf_dev)
     565                return ddf_fun_create(usb_dev->ddf_dev, ftype, name);
     566        return NULL;
     567}
     568
     569async_exch_t * usb_device_bus_exchange_begin(usb_device_t *usb_dev)
     570{
     571        assert(usb_dev);
     572        return async_exchange_begin(usb_dev->bus_session);
     573}
     574
     575void usb_device_bus_exchange_end(async_exch_t *exch)
     576{
     577        async_exchange_end(exch);
    508578}
    509579
     
    521591}
    522592
     593void * usb_device_data_get(usb_device_t *usb_dev)
     594{
     595        assert(usb_dev);
     596        return usb_dev->driver_data;
     597}
     598
    523599/**
    524600 * @}
Note: See TracChangeset for help on using the changeset viewer.