Changeset df6ded8 in mainline for uspace/lib/usbdev/src


Ignore:
Timestamp:
2018-02-28T16:37:50Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b20da0
Parents:
f5e5f73 (diff), b2dca8de (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.
git-author:
Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
git-committer:
Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
Message:

Merge github.com:helenos-xhci-team/helenos

This commit merges support for USB 3 and generally refactors, fixes,
extends and cleans up the existing USB framework.

Notable additions and features:

  • new host controller driver has been implemented to control various xHC models (among others, NEC Renesas uPD720200)
  • isochronous data transfer mode
  • support for explicit USB device removal
  • USB tablet driver
Location:
uspace/lib/usbdev/src
Files:
7 edited

Legend:

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

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek, Michal Staruch
    45 * All rights reserved.
    56 *
     
    4849#include <devman.h>
    4950#include <errno.h>
     51#include <str_error.h>
    5052#include <stdlib.h>
    5153
     
    5658        /** Connection to device on USB bus */
    5759        usb_dev_session_t *bus_session;
    58        
     60
    5961        /** devman handle */
    6062        devman_handle_t handle;
    61        
     63
    6264        /** The default control pipe. */
    6365        usb_pipe_t ctrl_pipe;
    64        
     66
    6567        /** Other endpoint pipes.
    6668         *
     
    6971         */
    7072        usb_endpoint_mapping_t *pipes;
    71        
     73
    7274        /** Number of other endpoint pipes. */
    7375        size_t pipes_count;
    74        
     76
     77        /** USB address of this device */
     78        usb_address_t address;
     79
     80        /** Depth in the USB hub hiearchy */
     81        unsigned depth;
     82
     83        /** USB speed of this device */
     84        usb_speed_t speed;
     85
    7586        /** Current interface.
    7687         *
     
    7990         */
    8091        int interface_no;
    81        
     92
    8293        /** Alternative interfaces. */
    8394        usb_alternate_interfaces_t alternate_interfaces;
    84        
     95
    8596        /** Some useful descriptors for USB device. */
    8697        usb_device_descriptors_t descriptors;
    87        
     98
    8899        /** Generic DDF device backing this one. DO NOT TOUCH! */
    89100        ddf_dev_t *ddf_dev;
    90        
     101
    91102        /** Custom driver data.
    92103         *
     
    146157                return rc;
    147158        }
    148        
     159
    149160        /* Change current alternative */
    150161        usb_dev->alternate_interfaces.current = alternate_setting;
     
    255266
    256267        /* Register created pipes. */
     268        unsigned pipes_registered = 0;
    257269        for (size_t i = 0; i < pipe_count; i++) {
    258270                if (pipes[i].present) {
    259                         rc = usb_pipe_register(&pipes[i].pipe,
    260                             pipes[i].descriptor->poll_interval);
     271                        rc = usb_pipe_register(&pipes[i].pipe, pipes[i].descriptor, pipes[i].companion_descriptor);
    261272                        if (rc != EOK) {
    262273                                goto rollback_unregister_endpoints;
    263274                        }
    264275                }
     276                pipes_registered++;
    265277        }
    266278
     
    277289         */
    278290rollback_unregister_endpoints:
    279         for (size_t i = 0; i < pipe_count; i++) {
     291        for (size_t i = 0; i < pipes_registered; i++) {
    280292                if (pipes[i].present) {
    281293                        usb_pipe_unregister(&pipes[i].pipe);
     
    296308        assert(usb_dev);
    297309        assert(usb_dev->pipes || usb_dev->pipes_count == 0);
    298        
     310
    299311        /* Destroy the pipes. */
     312        int rc;
    300313        for (size_t i = 0; i < usb_dev->pipes_count; ++i) {
    301                 usb_log_debug2("Unregistering pipe %zu: %spresent.\n",
     314                usb_log_debug2("Unregistering pipe %zu: %spresent.",
    302315                    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        
     316
     317                rc = usb_device_unmap_ep(usb_dev->pipes + i);
     318                if (rc != EOK && rc != ENOENT)
     319                        usb_log_warning("Unregistering pipe %zu failed: %s", i, str_error(rc));
     320        }
     321
    307322        free(usb_dev->pipes);
    308323        usb_dev->pipes = NULL;
     
    327342}
    328343
    329 usb_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 
    340 int usb_device_get_iface_number(usb_device_t *usb_dev)
     344int usb_device_unmap_ep(usb_endpoint_mapping_t *epm)
     345{
     346        assert(epm);
     347
     348        if (!epm->present)
     349                return ENOENT;
     350
     351        const int rc = usb_pipe_unregister(&epm->pipe);
     352        if (rc != EOK)
     353                return rc;
     354
     355        epm->present = false;
     356        return EOK;
     357}
     358
     359usb_address_t usb_device_get_address(const usb_device_t *usb_dev)
     360{
     361        assert(usb_dev);
     362        return usb_dev->depth;
     363}
     364
     365unsigned usb_device_get_depth(const usb_device_t *usb_dev)
     366{
     367        assert(usb_dev);
     368        return usb_dev->depth;
     369}
     370
     371usb_speed_t usb_device_get_speed(const usb_device_t *usb_dev)
     372{
     373        assert(usb_dev);
     374        return usb_dev->speed;
     375}
     376
     377int usb_device_get_iface_number(const usb_device_t *usb_dev)
    341378{
    342379        assert(usb_dev);
     
    344381}
    345382
    346 devman_handle_t usb_device_get_devman_handle(usb_device_t *usb_dev)
     383devman_handle_t usb_device_get_devman_handle(const usb_device_t *usb_dev)
    347384{
    348385        assert(usb_dev);
     
    394431 */
    395432static errno_t 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)
     433    const usb_endpoint_description_t **endpoints, const char **errstr_ptr)
    398434{
    399435        assert(usb_dev != NULL);
     
    403439
    404440        usb_dev->ddf_dev = ddf_dev;
    405         usb_dev->handle = handle;
    406         usb_dev->interface_no = interface_no;
    407441        usb_dev->driver_data = NULL;
    408442        usb_dev->descriptors.full_config = NULL;
     
    411445        usb_dev->pipes = NULL;
    412446
    413         usb_dev->bus_session = usb_dev_connect(handle);
     447        usb_dev->bus_session = usb_dev_connect(usb_dev->handle);
    414448
    415449        if (!usb_dev->bus_session) {
     
    420454        /* This pipe was registered by the hub driver,
    421455         * during device initialization. */
    422         errno_t rc = usb_pipe_initialize_default_control(
    423             &usb_dev->ctrl_pipe, usb_dev->bus_session);
     456        errno_t rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe, usb_dev->bus_session);
    424457        if (rc != EOK) {
    425458                usb_dev_disconnect(usb_dev->bus_session);
     
    440473         * it makes no sense to speak about alternate interfaces when
    441474         * controlling a device. */
    442         rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
     475        usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
    443476            usb_dev->descriptors.full_config,
    444477            usb_dev->descriptors.full_config_size, usb_dev->interface_no);
     
    457490}
    458491
    459 static errno_t 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        
     492static errno_t usb_device_get_info(async_sess_t *sess, usb_device_t *dev)
     493{
     494        assert(dev);
     495
    465496        async_exch_t *exch = async_exchange_begin(sess);
    466497        if (!exch)
    467498                return EPARTY;
    468        
    469         errno_t ret = usb_get_my_device_handle(exch, handle);
     499
     500        usb_device_desc_t dev_desc;
     501        const errno_t ret = usb_get_my_description(exch, &dev_desc);
     502
    470503        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        
     504                dev->address = dev_desc.address;
     505                dev->depth = dev_desc.depth;
     506                dev->speed = dev_desc.speed;
     507                dev->handle = dev_desc.handle;
     508                dev->interface_no = dev_desc.iface;
     509        }
     510
    478511        async_exchange_end(exch);
    479512        return ret;
     
    485518        assert(ddf_dev);
    486519        assert(err);
    487 
    488         devman_handle_t h = 0;
    489         int iface_no = -1;
    490520
    491521        async_sess_t *sess = ddf_dev_parent_sess_get(ddf_dev);
    492522        if (sess == NULL)
    493523                return ENOMEM;
    494         const errno_t ret = usb_device_get_info(sess, &h, &iface_no);
    495         if (ret != EOK)
    496                 return ret;
    497524
    498525        usb_device_t *usb_dev =
     
    502529                return ENOMEM;
    503530        }
    504        
    505         return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no);
     531
     532        const errno_t ret = usb_device_get_info(sess, usb_dev);
     533        if (ret != EOK)
     534                return ret;
     535
     536        return usb_device_init(usb_dev, ddf_dev, desc, err);
    506537}
    507538
     
    517548usb_device_t * usb_device_create(devman_handle_t handle)
    518549{
    519         devman_handle_t h = 0;
    520         int iface_no = -1;
    521 
    522         async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);
    523         errno_t ret = usb_device_get_info(sess, &h, &iface_no);
    524         if (sess)
    525                 async_hangup(sess);
    526         if (ret != EOK)
    527                 return NULL;
    528 
    529550        usb_device_t *usb_dev = malloc(sizeof(usb_device_t));
    530551        if (!usb_dev)
    531552                return NULL;
    532553
     554        async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING);
     555        errno_t ret = usb_device_get_info(sess, usb_dev);
     556        if (sess)
     557                async_hangup(sess);
     558        if (ret != EOK) {
     559                free(usb_dev);
     560                return NULL;
     561        }
     562
    533563        const char* dummy = NULL;
    534         ret = usb_device_init(usb_dev, NULL, NULL, &dummy, handle, iface_no);
     564        ret = usb_device_init(usb_dev, NULL, NULL, &dummy);
    535565        if (ret != EOK) {
    536566                free(usb_dev);
  • uspace/lib/usbdev/src/devpoll.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2017 Petr Manek
    34 * All rights reserved.
    45 *
     
    4748#include <errno.h>
    4849#include <fibril.h>
     50#include <fibril_synch.h>
    4951#include <stdbool.h>
    5052#include <stdlib.h>
     
    5355#include <stdint.h>
    5456
    55 /** Maximum number of failed consecutive requests before announcing failure. */
    56 #define MAX_FAILED_ATTEMPTS 3
    57 
    58 /** Data needed for polling. */
    59 typedef struct {
    60         /** Parameters for automated polling. */
    61         usb_device_auto_polling_t auto_polling;
    62 
    63         /** USB device to poll. */
    64         usb_device_t *dev;
    65         /** Device enpoint mapping to use for polling. */
    66         usb_endpoint_mapping_t *polling_mapping;
    67         /** Size of the recieved data. */
    68         size_t request_size;
    69         /** Data buffer. */
    70         uint8_t *buffer;
    71 } polling_data_t;
     57
     58/** Initialize the polling data structure, its internals and configuration
     59 *  with default values.
     60 *
     61 * @param polling Valid polling data structure.
     62 * @return Error code.
     63 * @retval EOK Polling data structure is ready to be used.
     64 */
     65int usb_polling_init(usb_polling_t *polling)
     66{
     67        if (!polling)
     68                return EBADMEM;
     69
     70        /* Zero out everything */
     71        memset(polling, 0, sizeof(usb_polling_t));
     72
     73        /* Internal initializers. */
     74        fibril_mutex_initialize(&polling->guard);
     75        fibril_condvar_initialize(&polling->cv);
     76
     77        /* Default configuration. */
     78        polling->auto_clear_halt = true;
     79        polling->delay = -1;
     80        polling->max_failures = 3;
     81
     82        return EOK;
     83}
     84
     85
     86/** Destroy the polling data structure.
     87 *  This function does nothing but a safety check whether the polling
     88 *  was joined successfully.
     89 *
     90 * @param polling Polling data structure.
     91 */
     92void usb_polling_fini(usb_polling_t *polling)
     93{
     94        /* Nothing done at the moment. */
     95        assert(polling);
     96        assert(!polling->running);
     97}
    7298
    7399
    74100/** Polling fibril.
    75101 *
    76  * @param arg Pointer to polling_data_t.
     102 * @param arg Pointer to usb_polling_t.
    77103 * @return Always EOK.
    78104 */
     
    80106{
    81107        assert(arg);
    82         polling_data_t *data = arg;
    83         /* Helper to reduce typing. */
    84         const usb_device_auto_polling_t *params = &data->auto_polling;
    85 
    86         usb_pipe_t *pipe = &data->polling_mapping->pipe;
    87 
    88         if (params->debug > 0) {
     108        usb_polling_t *polling = arg;
     109
     110        fibril_mutex_lock(&polling->guard);
     111        polling->running = true;
     112        fibril_mutex_unlock(&polling->guard);
     113
     114        usb_pipe_t *pipe = &polling->ep_mapping->pipe;
     115
     116        if (polling->debug > 0) {
    89117                const usb_endpoint_mapping_t *mapping =
    90                     data->polling_mapping;
     118                    polling->ep_mapping;
    91119                usb_log_debug("Poll (%p): started polling of `%s' - " \
    92120                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    93                     data, usb_device_get_name(data->dev),
     121                    polling, usb_device_get_name(polling->device),
    94122                    (int) mapping->interface->interface_number,
    95123                    usb_str_class(mapping->interface->interface_class),
    96124                    (int) mapping->interface->interface_subclass,
    97125                    (int) mapping->interface->interface_protocol,
    98                     data->request_size, pipe->max_packet_size);
     126                    polling->request_size, pipe->desc.max_transfer_size);
    99127        }
    100128
    101129        size_t failed_attempts = 0;
    102         while (failed_attempts <= params->max_failures) {
     130        while (failed_attempts <= polling->max_failures) {
    103131                size_t actual_size;
    104                 const errno_t rc = usb_pipe_read(pipe, data->buffer,
    105                     data->request_size, &actual_size);
     132                const errno_t rc = usb_pipe_read(pipe, polling->buffer,
     133                    polling->request_size, &actual_size);
    106134
    107135                if (rc == EOK) {
    108                         if (params->debug > 1) {
     136                        if (polling->debug > 1) {
    109137                                usb_log_debug(
    110138                                    "Poll%p: received: '%s' (%zuB).\n",
    111                                     data,
    112                                     usb_debug_str_buffer(data->buffer,
     139                                    polling,
     140                                    usb_debug_str_buffer(polling->buffer,
    113141                                        actual_size, 16),
    114142                                    actual_size);
     
    117145                                usb_log_debug(
    118146                                    "Poll%p: polling failed: %s.\n",
    119                                     data, str_error(rc));
     147                                    polling, str_error(rc));
    120148                }
    121149
    122150                /* If the pipe stalled, we can try to reset the stall. */
    123                 if ((rc == ESTALL) && (params->auto_clear_halt)) {
     151                if (rc == ESTALL && polling->auto_clear_halt) {
    124152                        /*
    125153                         * We ignore error here as this is usually a futile
    126154                         * attempt anyway.
    127155                         */
    128                         usb_request_clear_endpoint_halt(
    129                             usb_device_get_default_pipe(data->dev),
    130                             pipe->endpoint_no);
     156                        usb_pipe_clear_halt(
     157                            usb_device_get_default_pipe(polling->device), pipe);
    131158                }
    132159
    133160                if (rc != EOK) {
    134161                        ++failed_attempts;
    135                         const bool cont = (params->on_error == NULL) ? true :
    136                             params->on_error(data->dev, rc, params->arg);
    137                         if (!cont) {
    138                                 failed_attempts = params->max_failures;
     162                        const bool carry_on = !polling->on_error ? true :
     163                            polling->on_error(polling->device, rc, polling->arg);
     164
     165                        if (!carry_on || polling->joining) {
     166                                /* This is user requested abort, erases failures. */
     167                                failed_attempts = 0;
     168                                break;
    139169                        }
    140170                        continue;
     
    142172
    143173                /* We have the data, execute the callback now. */
    144                 assert(params->on_data);
    145                 const bool carry_on = params->on_data(
    146                     data->dev, data->buffer, actual_size, params->arg);
     174                assert(polling->on_data);
     175                const bool carry_on = polling->on_data(polling->device,
     176                    polling->buffer, actual_size, polling->arg);
    147177
    148178                if (!carry_on) {
     
    156186
    157187                /* Take a rest before next request. */
    158                
     188
    159189                // FIXME TODO: This is broken, the time is in ms not us.
    160190                // but first we need to fix drivers to actually stop using this,
    161191                // since polling delay should be implemented in HC schedule
    162                 async_usleep(params->delay);
     192                async_usleep(polling->delay);
    163193        }
    164194
    165195        const bool failed = failed_attempts > 0;
    166196
    167         if (params->on_polling_end != NULL) {
    168                 params->on_polling_end(data->dev, failed, params->arg);
    169         }
    170 
    171         if (params->debug > 0) {
     197        if (polling->on_polling_end)
     198                polling->on_polling_end(polling->device, failed, polling->arg);
     199
     200        if (polling->debug > 0) {
    172201                if (failed) {
    173202                        usb_log_error("Polling of device `%s' terminated: "
    174203                            "recurring failures.\n",
    175                             usb_device_get_name(data->dev));
     204                            usb_device_get_name(polling->device));
    176205                } else {
    177206                        usb_log_debug("Polling of device `%s' terminated: "
    178207                            "driver request.\n",
    179                             usb_device_get_name(data->dev));
     208                            usb_device_get_name(polling->device));
    180209                }
    181210        }
    182211
    183         /* Free the allocated memory. */
    184         free(data->buffer);
    185         free(data);
    186 
     212        fibril_mutex_lock(&polling->guard);
     213        polling->running = false;
     214        fibril_mutex_unlock(&polling->guard);
     215
     216        /* Notify joiners, if any. */
     217        fibril_condvar_broadcast(&polling->cv);
    187218        return EOK;
    188219}
     
    198229 * first request would be executed prior to return from this function).
    199230 *
    200  * @param dev Device to be periodically polled.
    201  * @param epm Endpoint mapping to use.
    202  * @param polling Polling settings.
    203  * @param request_size How many bytes to ask for in each request.
    204  * @param arg Custom argument (passed as is to the callbacks).
     231 * @param polling Polling data structure.
    205232 * @return Error code.
    206233 * @retval EOK New fibril polling the device was already started.
    207234 */
    208 static errno_t usb_device_auto_polling_internal(usb_device_t *dev,
    209     usb_endpoint_mapping_t *epm, const usb_device_auto_polling_t *polling,
    210     size_t request_size)
    211 {
    212         if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
     235errno_t usb_polling_start(usb_polling_t *polling)
     236{
     237        if (!polling || !polling->device || !polling->ep_mapping || !polling->on_data)
    213238                return EBADMEM;
    214         }
    215 
    216         if (request_size == 0)
     239
     240        if (!polling->request_size)
    217241                return EINVAL;
    218        
    219         if (!epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) ||
    220             (epm->pipe.direction != USB_DIRECTION_IN))
     242
     243        if (!polling->ep_mapping || (polling->ep_mapping->pipe.desc.transfer_type != USB_TRANSFER_INTERRUPT)
     244            || (polling->ep_mapping->pipe.desc.direction != USB_DIRECTION_IN))
    221245                return EINVAL;
    222        
    223 
    224         polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    225         if (polling_data == NULL) {
     246
     247        /* Negative value means use descriptor provided value. */
     248        if (polling->delay < 0)
     249                polling->delay = polling->ep_mapping->descriptor->poll_interval;
     250
     251        polling->fibril = fibril_create(polling_fibril, polling);
     252        if (!polling->fibril)
    226253                return ENOMEM;
    227         }
    228 
    229         /* Fill-in the data. */
    230         polling_data->buffer = malloc(sizeof(request_size));
    231         if (polling_data->buffer == NULL) {
    232                 free(polling_data);
    233                 return ENOMEM;
    234         }
    235         polling_data->request_size = request_size;
    236         polling_data->dev = dev;
    237         polling_data->polling_mapping = epm;
    238 
    239         /* Copy provided settings. */
    240         polling_data->auto_polling = *polling;
    241 
    242         /* Negative value means use descriptor provided value. */
    243         if (polling->delay < 0) {
    244                 polling_data->auto_polling.delay =
    245                     epm->descriptor->poll_interval;
    246         }
    247 
    248         fid_t fibril = fibril_create(polling_fibril, polling_data);
    249         if (fibril == 0) {
    250                 free(polling_data->buffer);
    251                 free(polling_data);
    252                 return ENOMEM;
    253         }
    254         fibril_add_ready(fibril);
     254
     255        fibril_add_ready(polling->fibril);
    255256
    256257        /* Fibril launched. That fibril will free the allocated data. */
    257 
    258258        return EOK;
    259259}
    260 /** Start automatic device polling over interrupt in pipe.
    261  *
    262  * The polling settings is copied thus it is okay to destroy the structure
    263  * after this function returns.
    264  *
    265  * @warning There is no guarantee when the request to the device
    266  * will be sent for the first time (it is possible that this
    267  * first request would be executed prior to return from this function).
    268  *
    269  * @param dev Device to be periodically polled.
    270  * @param pipe_index Index of the endpoint pipe used for polling.
    271  * @param polling Polling settings.
    272  * @param req_size How many bytes to ask for in each request.
    273  * @param arg Custom argument (passed as is to the callbacks).
    274  * @return Error code.
    275  * @retval EOK New fibril polling the device was already started.
    276  */
    277 errno_t usb_device_auto_polling(usb_device_t *usb_dev, usb_endpoint_t ep,
    278     const usb_device_auto_polling_t *polling, size_t req_size)
    279 {
    280         usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(usb_dev, ep);
    281         return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size);
    282 }
    283 
    284 /** Start automatic device polling over interrupt in pipe.
    285  *
    286  * @warning It is up to the callback to produce delays between individual
    287  * requests.
    288  *
    289  * @warning There is no guarantee when the request to the device
    290  * will be sent for the first time (it is possible that this
    291  * first request would be executed prior to return from this function).
    292  *
    293  * @param dev Device to be periodically polled.
    294  * @param ep Endpoint  used for polling.
    295  * @param callback Callback when data are available.
    296  * @param request_size How many bytes to ask for in each request.
    297  * @param delay NUmber of ms to wait between queries, -1 to use descriptor val.
    298  * @param terminated_callback Callback when polling is terminated.
    299  * @param arg Custom argument (passed as is to the callbacks).
    300  * @return Error code.
    301  * @retval EOK New fibril polling the device was already started.
    302  */
    303 errno_t usb_device_auto_poll(usb_device_t *dev, usb_endpoint_t ep,
    304     usb_polling_callback_t callback, size_t request_size, int delay,
    305     usb_polling_terminted_callback_t terminated_callback, void *arg)
    306 {
    307         const usb_device_auto_polling_t auto_polling = {
    308                 .debug = 1,
    309                 .auto_clear_halt = true,
    310                 .delay = delay,
    311                 .max_failures = MAX_FAILED_ATTEMPTS,
    312                 .on_data = callback,
    313                 .on_polling_end = terminated_callback,
    314                 .on_error = NULL,
    315                 .arg = arg,
    316         };
    317 
    318         usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(dev, ep);
    319         return usb_device_auto_polling_internal(
    320             dev, epm, &auto_polling, request_size);
    321 }
    322 
    323 errno_t usb_device_auto_polling_desc(usb_device_t *usb_dev,
    324     const usb_endpoint_description_t *desc,
    325     const usb_device_auto_polling_t *polling, size_t req_size)
    326 {
    327         usb_endpoint_mapping_t *epm =
    328             usb_device_get_mapped_ep_desc(usb_dev, desc);
    329         return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size);
    330 }
    331 
    332 errno_t usb_device_auto_poll_desc(usb_device_t * usb_dev,
    333     const usb_endpoint_description_t *desc, usb_polling_callback_t callback,
    334     size_t req_size, int delay,
    335     usb_polling_terminted_callback_t terminated_callback, void *arg)
    336 {
    337         const usb_device_auto_polling_t auto_polling = {
    338                 .debug = 1,
    339                 .auto_clear_halt = true,
    340                 .delay = delay,
    341                 .max_failures = MAX_FAILED_ATTEMPTS,
    342                 .on_data = callback,
    343                 .on_polling_end = terminated_callback,
    344                 .on_error = NULL,
    345                 .arg = arg,
    346         };
    347 
    348         usb_endpoint_mapping_t *epm =
    349             usb_device_get_mapped_ep_desc(usb_dev, desc);
    350         return usb_device_auto_polling_internal(
    351             usb_dev, epm, &auto_polling, req_size);
     260
     261/** Close the polling pipe permanently and synchronously wait
     262 *  until the automatic polling fibril terminates.
     263 *
     264 *  It is safe to deallocate the polling data structure (and its
     265 *  data buffer) only after a successful call to this function.
     266 *
     267 *  @warning Call to this function will trigger execution of the
     268 *  on_error() callback with EINTR error code.
     269 *
     270 *  @parram polling Polling data structure.
     271 *  @return Error code.
     272 *  @retval EOK Polling fibril has been successfully terminated.
     273 */
     274errno_t usb_polling_join(usb_polling_t *polling)
     275{
     276        errno_t rc;
     277        if (!polling)
     278                return EBADMEM;
     279
     280        /* Check if the fibril already terminated. */
     281        if (!polling->running)
     282                return EOK;
     283
     284        /* Set the flag */
     285        polling->joining = true;
     286
     287        /* Unregister the pipe. */
     288        rc = usb_device_unmap_ep(polling->ep_mapping);
     289        if (rc != EOK && rc != ENOENT && rc != EHANGUP)
     290                return rc;
     291
     292        /* Wait for the fibril to terminate. */
     293        fibril_mutex_lock(&polling->guard);
     294        while (polling->running)
     295                fibril_condvar_wait(&polling->cv, &polling->guard);
     296        fibril_mutex_unlock(&polling->guard);
     297
     298        return EOK;
    352299}
    353300
  • uspace/lib/usbdev/src/dp.c

    rf5e5f73 rdf6ded8  
    6262        NESTING(CONFIGURATION, INTERFACE),
    6363        NESTING(INTERFACE, ENDPOINT),
     64        NESTING(ENDPOINT, SSPEED_EP_COMPANION),
    6465        NESTING(INTERFACE, HUB),
    6566        NESTING(INTERFACE, HID),
     
    126127 * @retval -1 Invalid input.
    127128 */
    128 static int get_descriptor_type(const usb_dp_parser_data_t *data, const uint8_t *start)
     129static int get_descriptor_type(const usb_dp_parser_data_t *data,
     130    const uint8_t *start)
    129131{
    130132        if (start == NULL) {
     
    257259        int parent_type = get_descriptor_type(data, parent);
    258260        int possible_sibling_type = get_descriptor_type(data, possible_sibling);
    259         if (is_nested_descriptor_type(parser, possible_sibling_type, parent_type)) {
     261        if (is_nested_descriptor_type(parser,
     262                    possible_sibling_type, parent_type)) {
    260263                return possible_sibling;
    261264        } else {
  • uspace/lib/usbdev/src/driver.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Vojtech Horky
    33 * Copyright (c) 2013 Jan Vesely
     4 * Copyright (c) 2018 Petr Manek
    45 * All rights reserved.
    56 *
     
    6263        errno_t rc = usb_device_create_ddf(gen_dev, driver->endpoints, &err_msg);
    6364        if (rc != EOK) {
    64                 usb_log_error("USB device `%s' init failed (%s): %s.\n",
     65                usb_log_error("USB device `%s' init failed (%s): %s.",
    6566                    ddf_dev_get_name(gen_dev), err_msg, str_error(rc));
    6667                return rc;
     
    8586        assert(driver);
    8687        assert(driver->ops);
    87         if (driver->ops->device_rem == NULL)
     88        if (driver->ops->device_remove == NULL)
    8889                return ENOTSUP;
     90
    8991        /* Just tell the driver to stop whatever it is doing */
    9092        usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);
    91         const errno_t ret = driver->ops->device_rem(usb_dev);
     93        const errno_t ret = driver->ops->device_remove(usb_dev);
    9294        if (ret != EOK)
    9395                return ret;
     96
    9497        usb_device_destroy_ddf(gen_dev);
    9598        return EOK;
     
    117120}
    118121
     122/** Callback when the driver is asked to online a specific function.
     123 *
     124 * This callback is a wrapper for USB specific version of @c fun_online.
     125 *
     126 * @param gen_dev Device function structure as prepared by DDF.
     127 * @return Error code.
     128 */
     129static int generic_function_online(ddf_fun_t *fun)
     130{
     131        assert(driver);
     132        assert(driver->ops);
     133        if (driver->ops->function_online == NULL)
     134                return ENOTSUP;
     135        return driver->ops->function_online(fun);
     136}
     137
     138/** Callback when the driver is asked to offline a specific function.
     139 *
     140 * This callback is a wrapper for USB specific version of @c fun_offline.
     141 *
     142 * @param gen_dev Device function structure as prepared by DDF.
     143 * @return Error code.
     144 */
     145static int generic_function_offline(ddf_fun_t *fun)
     146{
     147        assert(driver);
     148        assert(driver->ops);
     149        if (driver->ops->function_offline == NULL)
     150                return ENOTSUP;
     151        return driver->ops->function_offline(fun);
     152}
     153
    119154static driver_ops_t generic_driver_ops = {
    120155        .dev_add = generic_device_add,
    121156        .dev_remove = generic_device_remove,
    122157        .dev_gone = generic_device_gone,
     158        .fun_online = generic_function_online,
     159        .fun_offline = generic_function_offline,
    123160};
    124161static driver_t generic_driver = {
  • uspace/lib/usbdev/src/pipes.c

    rf5e5f73 rdf6ded8  
    22 * Copyright (c) 2011 Vojtech Horky
    33 * Copyright (c) 2011 Jan Vesely
     4 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch
    45 * All rights reserved.
    56 *
     
    3637#include <usb/dev/request.h>
    3738#include <usb/usb.h>
    38 #include <usb_iface.h>
     39#include <usb/dma_buffer.h>
    3940
    4041#include <assert.h>
     42#include <bitops.h>
    4143#include <async.h>
     44#include <as.h>
    4245#include <errno.h>
    4346#include <mem.h>
     
    5154        assert(pipe != NULL);
    5255
    53         if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     56        if (!pipe->auto_reset_halt || (pipe->desc.endpoint_no != 0)) {
    5457                return;
    5558        }
     
    5760        /* Prevent infinite recursion. */
    5861        pipe->auto_reset_halt = false;
    59         usb_request_clear_endpoint_halt(pipe, 0);
     62        usb_pipe_clear_halt(pipe, pipe);
    6063        pipe->auto_reset_halt = true;
     64}
     65
     66/* Helper structure to avoid passing loads of arguments through */
     67typedef struct {
     68        usb_pipe_t *pipe;
     69        usb_direction_t dir;
     70        bool is_control;        // Only for checking purposes
     71
     72        usbhc_iface_transfer_request_t req;
     73
     74        size_t transferred_size;
     75} transfer_t;
     76
     77/**
     78 * Issue a transfer in a separate exchange.
     79 */
     80static errno_t transfer_common(transfer_t *t)
     81{
     82        if (!t->pipe)
     83                return EBADMEM;
     84
     85        /* Only control writes make sense without buffer */
     86        if ((t->dir != USB_DIRECTION_OUT || !t->is_control) && t->req.size == 0)
     87                return EINVAL;
     88
     89        /* Nonzero size requires buffer */
     90        if (!dma_buffer_is_set(&t->req.buffer) && t->req.size != 0)
     91                return EINVAL;
     92
     93        /* Check expected direction */
     94        if (t->pipe->desc.direction != USB_DIRECTION_BOTH &&
     95            t->pipe->desc.direction != t->dir)
     96                return EBADF;
     97
     98        /* Check expected transfer type */
     99        if ((t->pipe->desc.transfer_type == USB_TRANSFER_CONTROL) != t->is_control)
     100                return EBADF;
     101
     102        async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
     103        if (!exch)
     104                return ENOMEM;
     105
     106        t->req.dir = t->dir;
     107        t->req.endpoint = t->pipe->desc.endpoint_no;
     108
     109        const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size);
     110
     111        async_exchange_end(exch);
     112
     113        if (rc == ESTALL)
     114                clear_self_endpoint_halt(t->pipe);
     115
     116        return rc;
     117}
     118
     119/**
     120 * Setup the transfer request inside transfer according to dma buffer provided.
     121 *
     122 * TODO: The buffer could have been allocated as a more strict one. Currently,
     123 * we assume that the policy is just the requested one.
     124 */
     125static void setup_dma_buffer(transfer_t *t, void *base, void *ptr, size_t size)
     126{
     127        t->req.buffer.virt = base;
     128        t->req.buffer.policy = t->pipe->desc.transfer_buffer_policy;
     129        t->req.offset = ptr - base;
     130        t->req.size = size;
     131}
     132
     133/**
     134 * Compatibility wrapper for reads/writes without preallocated buffer.
     135 */
     136static errno_t transfer_wrap_dma(transfer_t *t, void *buf, size_t size)
     137{
     138        if (size == 0) {
     139                setup_dma_buffer(t, NULL, NULL, 0);
     140                return transfer_common(t);
     141        }
     142
     143        void *dma_buf = usb_pipe_alloc_buffer(t->pipe, size);
     144        setup_dma_buffer(t, dma_buf, dma_buf, size);
     145
     146        if (t->dir == USB_DIRECTION_OUT)
     147                memcpy(dma_buf, buf, size);
     148
     149        const errno_t err = transfer_common(t);
     150
     151        if (!err && t->dir == USB_DIRECTION_IN)
     152                memcpy(buf, dma_buf, t->transferred_size);
     153
     154        usb_pipe_free_buffer(t->pipe, dma_buf);
     155        return err;
     156}
     157
     158static errno_t prepare_control(transfer_t *t, const void *setup, size_t setup_size)
     159{
     160        if ((setup == NULL) || (setup_size != 8))
     161                return EINVAL;
     162       
     163        memcpy(&t->req.setup, setup, 8);
     164        return EOK;
    61165}
    62166
     
    70174 * @param[out] data_buffer Buffer for incoming data.
    71175 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    72  * @param[out] data_transfered_size Number of bytes that were actually
    73  *                                  transfered during the DATA stage.
     176 * @param[out] data_transferred_size Number of bytes that were actually
     177 *                                  transferred during the DATA stage.
    74178 * @return Error code.
    75179 */
    76180errno_t usb_pipe_control_read(usb_pipe_t *pipe,
    77181    const void *setup_buffer, size_t setup_buffer_size,
    78     void *buffer, size_t buffer_size, size_t *transfered_size)
    79 {
    80         assert(pipe);
    81 
    82         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    83                 return EINVAL;
    84         }
    85 
    86         if ((buffer == NULL) || (buffer_size == 0)) {
    87                 return EINVAL;
    88         }
    89 
    90         if ((pipe->direction != USB_DIRECTION_BOTH)
    91             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    92                 return EBADF;
    93         }
    94 
    95         uint64_t setup_packet;
    96         memcpy(&setup_packet, setup_buffer, 8);
    97 
    98         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    99         size_t act_size = 0;
    100         const errno_t rc = usb_read(exch, pipe->endpoint_no, setup_packet, buffer,
    101             buffer_size, &act_size);
    102         async_exchange_end(exch);
    103 
    104         if (rc == ESTALL) {
    105                 clear_self_endpoint_halt(pipe);
    106         }
    107 
    108         if (rc == EOK && transfered_size != NULL) {
    109                 *transfered_size = act_size;
    110         }
    111 
    112         return rc;
     182    void *buffer, size_t buffer_size, size_t *transferred_size)
     183{
     184        errno_t err;
     185        transfer_t transfer = {
     186                .pipe = pipe,
     187                .dir = USB_DIRECTION_IN,
     188                .is_control = true,
     189        };
     190
     191        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
     192                return err;
     193
     194        if ((err = transfer_wrap_dma(&transfer, buffer, buffer_size)))
     195                return err;
     196
     197        if (transferred_size)
     198                *transferred_size = transfer.transferred_size;
     199
     200        return EOK;
    113201}
    114202
     
    129217{
    130218        assert(pipe);
    131 
    132         if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    133                 return EINVAL;
    134         }
    135 
    136         if ((buffer == NULL) && (buffer_size > 0)) {
    137                 return EINVAL;
    138         }
    139 
    140         if ((buffer != NULL) && (buffer_size == 0)) {
    141                 return EINVAL;
    142         }
    143 
    144         if ((pipe->direction != USB_DIRECTION_BOTH)
    145             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    146                 return EBADF;
    147         }
    148 
    149         uint64_t setup_packet;
    150         memcpy(&setup_packet, setup_buffer, 8);
    151 
    152         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    153         const errno_t rc = usb_write(exch,
    154             pipe->endpoint_no, setup_packet, buffer, buffer_size);
    155         async_exchange_end(exch);
    156 
    157         if (rc == ESTALL) {
    158                 clear_self_endpoint_halt(pipe);
    159         }
    160 
    161         return rc;
     219        errno_t err;
     220        transfer_t transfer = {
     221                .pipe = pipe,
     222                .dir = USB_DIRECTION_OUT,
     223                .is_control = true,
     224        };
     225
     226        if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
     227                return err;
     228
     229        return transfer_wrap_dma(&transfer, (void *) buffer, buffer_size);
     230}
     231
     232/**
     233 * Allocate a buffer for data transmission, that satisfies the constraints
     234 * imposed by the host controller.
     235 *
     236 * @param[in] pipe Pipe for which the buffer is allocated
     237 * @param[in] size Size of the required buffer
     238 */
     239void *usb_pipe_alloc_buffer(usb_pipe_t *pipe, size_t size)
     240{
     241        dma_buffer_t buf;
     242        if (dma_buffer_alloc_policy(&buf, size, pipe->desc.transfer_buffer_policy))
     243                return NULL;
     244
     245        return buf.virt;
     246}
     247
     248void usb_pipe_free_buffer(usb_pipe_t *pipe, void *buffer)
     249{
     250        dma_buffer_t buf;
     251        buf.virt = buffer;
     252        dma_buffer_free(&buf);
    162253}
    163254
     
    167258 * @param[out] buffer Buffer where to store the data.
    168259 * @param[in] size Size of the buffer (in bytes).
    169  * @param[out] size_transfered Number of bytes that were actually transfered.
     260 * @param[out] size_transferred Number of bytes that were actually transferred.
    170261 * @return Error code.
    171262 */
    172263errno_t usb_pipe_read(usb_pipe_t *pipe,
    173     void *buffer, size_t size, size_t *size_transfered)
    174 {
    175         assert(pipe);
    176 
    177         if (buffer == NULL) {
    178                 return EINVAL;
    179         }
    180 
    181         if (size == 0) {
    182                 return EINVAL;
    183         }
    184 
    185         if (pipe->direction != USB_DIRECTION_IN) {
    186                 return EBADF;
    187         }
    188 
    189         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    190                 return EBADF;
    191         }
    192 
    193         /* Isochronous transfer are not supported (yet) */
    194         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    195             pipe->transfer_type != USB_TRANSFER_BULK)
    196             return ENOTSUP;
    197 
    198         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    199         size_t act_size = 0;
    200         const errno_t rc =
    201             usb_read(exch, pipe->endpoint_no, 0, buffer, size, &act_size);
    202         async_exchange_end(exch);
    203 
    204         if (rc == EOK && size_transfered != NULL) {
    205                 *size_transfered = act_size;
    206         }
    207 
    208         return rc;
     264    void *buffer, size_t size, size_t *size_transferred)
     265{
     266        assert(pipe);
     267        errno_t err;
     268        transfer_t transfer = {
     269                .pipe = pipe,
     270                .dir = USB_DIRECTION_IN,
     271        };
     272
     273        if ((err = transfer_wrap_dma(&transfer, buffer, size)))
     274                return err;
     275
     276        if (size_transferred)
     277                *size_transferred = transfer.transferred_size;
     278
     279        return EOK;
    209280}
    210281
     
    219290{
    220291        assert(pipe);
    221 
    222         if (buffer == NULL || size == 0) {
    223                 return EINVAL;
    224         }
    225 
    226         if (pipe->direction != USB_DIRECTION_OUT) {
    227                 return EBADF;
    228         }
    229 
    230         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    231                 return EBADF;
    232         }
    233 
    234         /* Isochronous transfer are not supported (yet) */
    235         if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    236             pipe->transfer_type != USB_TRANSFER_BULK)
    237             return ENOTSUP;
    238 
    239         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    240         const errno_t rc = usb_write(exch, pipe->endpoint_no, 0, buffer, size);
    241         async_exchange_end(exch);
    242         return rc;
     292        transfer_t transfer = {
     293                .pipe = pipe,
     294                .dir = USB_DIRECTION_OUT,
     295        };
     296
     297        return transfer_wrap_dma(&transfer, (void *) buffer, size);
     298}
     299
     300/**
     301 * Request a read (in) transfer on an endpoint pipe, declaring that buffer
     302 * is pointing to a memory area previously allocated by usb_pipe_alloc_buffer.
     303 *
     304 * @param[in] pipe Pipe used for the transfer.
     305 * @param[in] buffer Buffer, previously allocated with usb_pipe_alloc_buffer.
     306 * @param[in] size Size of the buffer (in bytes).
     307 * @param[out] size_transferred Number of bytes that were actually transferred.
     308 * @return Error code.
     309 */
     310errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size,
     311    size_t *size_transferred)
     312{
     313        assert(pipe);
     314        errno_t err;
     315        transfer_t transfer = {
     316                .pipe = pipe,
     317                .dir = USB_DIRECTION_IN,
     318        };
     319
     320        setup_dma_buffer(&transfer, base, ptr, size);
     321
     322        if ((err = transfer_common(&transfer)))
     323                return err;
     324
     325        if (size_transferred)
     326                *size_transferred = transfer.transferred_size;
     327
     328        return EOK;
     329}
     330
     331/**
     332 * Request a write (out) transfer on an endpoint pipe, declaring that buffer
     333 * is pointing to a memory area previously allocated by usb_pipe_alloc_buffer.
     334 *
     335 * @param[in] pipe Pipe used for the transfer.
     336 * @param[in] buffer Buffer, previously allocated with usb_pipe_alloc_buffer.
     337 * @param[in] size Size of the buffer (in bytes).
     338 * @return Error code.
     339 */
     340errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size)
     341{
     342        assert(pipe);
     343        transfer_t transfer = {
     344                .pipe = pipe,
     345                .dir = USB_DIRECTION_OUT,
     346        };
     347
     348        setup_dma_buffer(&transfer, base, ptr, size);
     349
     350        return transfer_common(&transfer);
    243351}
    244352
     
    246354 *
    247355 * @param pipe Endpoint pipe to be initialized.
    248  * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
    249  * @param transfer_type Transfer type (e.g. interrupt or bulk).
    250  * @param max_packet_size Maximum packet size in bytes.
    251  * @param direction Endpoint direction (in/out).
    252  * @return Error code.
    253  */
    254 errno_t usb_pipe_initialize(usb_pipe_t *pipe, usb_endpoint_t endpoint_no,
    255     usb_transfer_type_t transfer_type, size_t max_packet_size,
    256     usb_direction_t direction, unsigned packets, usb_dev_session_t *bus_session)
    257 {
    258         assert(pipe);
    259 
    260         pipe->endpoint_no = endpoint_no;
    261         pipe->transfer_type = transfer_type;
    262         pipe->packets = packets;
    263         pipe->max_packet_size = max_packet_size;
    264         pipe->direction = direction;
     356 * @param bus_session Endpoint pipe to be initialized.
     357 * @return Error code.
     358 */
     359errno_t usb_pipe_initialize(usb_pipe_t *pipe, usb_dev_session_t *bus_session)
     360{
     361        assert(pipe);
     362
    265363        pipe->auto_reset_halt = false;
    266364        pipe->bus_session = bus_session;
     
    269367}
    270368
    271 /** Initialize USB endpoint pipe as the default zero control pipe.
     369static const usb_pipe_desc_t default_control_pipe = {
     370        .endpoint_no = 0,
     371        .transfer_type = USB_TRANSFER_CONTROL,
     372        .direction = USB_DIRECTION_BOTH,
     373        .max_transfer_size = CTRL_PIPE_MIN_PACKET_SIZE,
     374        .transfer_buffer_policy = DMA_POLICY_STRICT,
     375};
     376
     377/** Initialize USB default control pipe.
     378 *
     379 * This one is special because it must not be registered, it is registered
     380 * automatically.
    272381 *
    273382 * @param pipe Endpoint pipe to be initialized.
     383 * @param bus_session Endpoint pipe to be initialized.
    274384 * @return Error code.
    275385 */
     
    277387    usb_dev_session_t *bus_session)
    278388{
    279         assert(pipe);
    280 
    281         const errno_t rc = usb_pipe_initialize(pipe, 0, USB_TRANSFER_CONTROL,
    282             CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH, 1, bus_session);
    283 
     389        const errno_t ret = usb_pipe_initialize(pipe, bus_session);
     390        if (ret)
     391                return ret;
     392
     393        pipe->desc = default_control_pipe;
    284394        pipe->auto_reset_halt = true;
    285395
    286         return rc;
     396        return EOK;
    287397}
    288398
     
    290400 *
    291401 * @param pipe Pipe to be registered.
    292  * @param interval Polling interval.
    293  * @return Error code.
    294  */
    295 errno_t usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
     402 * @param ep_desc Matched endpoint descriptor
     403 * @param comp_desc Matched superspeed companion descriptro, if any
     404 * @return Error code.
     405 */
     406errno_t usb_pipe_register(usb_pipe_t *pipe,
     407    const usb_standard_endpoint_descriptor_t *ep_desc,
     408    const usb_superspeed_endpoint_companion_descriptor_t *comp_desc)
     409{
     410        assert(pipe);
     411        assert(pipe->bus_session);
     412        assert(ep_desc);
     413
     414        async_exch_t *exch = async_exchange_begin(pipe->bus_session);
     415        if (!exch)
     416                return ENOMEM;
     417
     418        usb_endpoint_descriptors_t descriptors = { 0 };
     419
     420#define COPY(field) descriptors.endpoint.field = ep_desc->field
     421        COPY(endpoint_address);
     422        COPY(attributes);
     423        COPY(max_packet_size);
     424        COPY(poll_interval);
     425#undef COPY
     426
     427#define COPY(field) descriptors.companion.field = comp_desc->field
     428        if (comp_desc) {
     429                COPY(max_burst);
     430                COPY(attributes);
     431                COPY(bytes_per_interval);
     432        }
     433#undef COPY
     434
     435        const errno_t ret = usbhc_register_endpoint(exch,
     436            &pipe->desc, &descriptors);
     437        async_exchange_end(exch);
     438        return ret;
     439}
     440
     441/** Revert endpoint registration with the host controller.
     442 *
     443 * @param pipe Pipe to be unregistered.
     444 * @return Error code.
     445 */
     446errno_t usb_pipe_unregister(usb_pipe_t *pipe)
    296447{
    297448        assert(pipe);
     
    300451        if (!exch)
    301452                return ENOMEM;
    302         const errno_t ret = usb_register_endpoint(exch, pipe->endpoint_no,
    303             pipe->transfer_type, pipe->direction, pipe->max_packet_size,
    304             pipe->packets, interval);
     453
     454        const errno_t ret = usbhc_unregister_endpoint(exch, &pipe->desc);
     455
    305456        async_exchange_end(exch);
    306457        return ret;
    307458}
    308459
    309 /** Revert endpoint registration with the host controller.
    310  *
    311  * @param pipe Pipe to be unregistered.
    312  * @return Error code.
    313  */
    314 errno_t usb_pipe_unregister(usb_pipe_t *pipe)
    315 {
    316         assert(pipe);
    317         assert(pipe->bus_session);
    318         async_exch_t *exch = async_exchange_begin(pipe->bus_session);
    319         if (!exch)
    320                 return ENOMEM;
    321         const errno_t ret = usb_unregister_endpoint(exch, pipe->endpoint_no,
    322             pipe->direction);
    323         async_exchange_end(exch);
    324         return ret;
    325 }
    326 
    327460/**
    328461 * @}
  • uspace/lib/usbdev/src/pipesinit.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch
    34 * All rights reserved.
    45 *
     
    3839#include <usb/dev/request.h>
    3940#include <usb/usb.h>
     41#include <usb/debug.h>
    4042#include <usb/descriptor.h>
    4143
     
    5961        NESTING(INTERFACE, HID),
    6062        NESTING(HID, HID_REPORT),
     63        NESTING(ENDPOINT, SSPEED_EP_COMPANION),
    6164        LAST_NESTING
    6265};
     
    7073{
    7174        return descriptor[1] == USB_DESCTYPE_ENDPOINT;
     75}
     76
     77/** Tells whether given descriptor is of superspeed companion type.
     78 *
     79 * @param descriptor Descriptor in question.
     80 * @return Whether the given descriptor is superspeed companion descriptor.
     81 */
     82static inline bool is_superspeed_companion_descriptor(const uint8_t *descriptor)
     83{
     84        return descriptor[1] == USB_DESCTYPE_SSPEED_EP_COMPANION;
    7285}
    7386
     
    134147                if (interface_number_fits
    135148                    && interface_setting_fits
    136                     && endpoint_descriptions_fits) {
     149                    && endpoint_descriptions_fits
     150                    && !mapping->present) {
    137151                        return mapping;
    138152                }
     
    141155                mapping_count--;
    142156        }
     157
    143158        return NULL;
    144159}
     
    150165 * @param interface Interface descriptor under which belongs the @p endpoint.
    151166 * @param endpoint Endpoint descriptor.
     167 * @param companion Superspeed companion descriptor.
    152168 * @return Error code.
    153169 */
     
    156172    usb_standard_interface_descriptor_t *interface,
    157173    usb_standard_endpoint_descriptor_t *endpoint_desc,
     174    usb_superspeed_endpoint_companion_descriptor_t *companion_desc,
    158175    usb_dev_session_t *bus_session)
    159176{
     
    162179         * Get endpoint characteristics.
    163180         */
    164 
    165         /* Actual endpoint number is in bits 0..3 */
    166         const usb_endpoint_t ep_no = endpoint_desc->endpoint_address & 0x0F;
    167 
    168181        const usb_endpoint_description_t description = {
    169                 /* Endpoint direction is set by bit 7 */
    170                 .direction = (endpoint_desc->endpoint_address & 128)
    171                     ? USB_DIRECTION_IN : USB_DIRECTION_OUT,
    172                 /* Transfer type is in bits 0..2 and
    173                  * the enum values corresponds 1:1 */
    174                 .transfer_type = endpoint_desc->attributes & 3,
     182                .transfer_type = USB_ED_GET_TRANSFER_TYPE(*endpoint_desc),
     183                .direction = USB_ED_GET_DIR(*endpoint_desc),
    175184
    176185                /* Get interface characteristics. */
     
    194203        }
    195204
    196         errno_t rc = usb_pipe_initialize(&ep_mapping->pipe,
    197             ep_no, description.transfer_type,
    198             ED_MPS_PACKET_SIZE_GET(
    199                 uint16_usb2host(endpoint_desc->max_packet_size)),
    200             description.direction,
    201             ED_MPS_TRANS_OPPORTUNITIES_GET(
    202                 uint16_usb2host(endpoint_desc->max_packet_size)), bus_session);
    203         if (rc != EOK) {
    204                 return rc;
    205         }
     205        errno_t err = usb_pipe_initialize(&ep_mapping->pipe, bus_session);
     206        if (err)
     207                return err;
    206208
    207209        ep_mapping->present = true;
    208210        ep_mapping->descriptor = endpoint_desc;
     211        ep_mapping->companion_descriptor = companion_desc;
    209212        ep_mapping->interface = interface;
    210213
     
    235238        do {
    236239                if (is_endpoint_descriptor(descriptor)) {
     240                        /* Check if companion descriptor is present too, it should immediatelly follow. */
     241                        const uint8_t *companion_desc = usb_dp_get_nested_descriptor(parser,
     242                                parser_data, descriptor);
     243                        if (companion_desc && !is_superspeed_companion_descriptor(companion_desc)) {
     244                                /* Not what we wanted, don't pass it further. */
     245                                companion_desc = NULL;
     246                        }
     247
    237248                        (void) process_endpoint(mapping, mapping_count,
    238249                            (usb_standard_interface_descriptor_t *)
     
    240251                            (usb_standard_endpoint_descriptor_t *)
    241252                                descriptor,
     253                            (usb_superspeed_endpoint_companion_descriptor_t *)
     254                                companion_desc,
    242255                            bus_session);
    243256                }
     
    288301        if (config_descriptor == NULL)
    289302                return EBADMEM;
    290        
     303
    291304        if (config_descriptor_size <
    292305            sizeof(usb_standard_configuration_descriptor_t)) {
     
    328341}
    329342
    330 /** Probe default control pipe for max packet size.
    331  *
    332  * The function tries to get the correct value of max packet size several
    333  * time before giving up.
    334  *
    335  * The session on the pipe shall not be started.
    336  *
    337  * @param pipe Default control pipe.
    338  * @return Error code.
    339  */
    340 errno_t usb_pipe_probe_default_control(usb_pipe_t *pipe)
    341 {
    342         assert(pipe);
    343         static_assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
    344 
    345         if ((pipe->direction != USB_DIRECTION_BOTH) ||
    346             (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
    347             (pipe->endpoint_no != 0)) {
    348                 return EINVAL;
    349         }
    350 
    351         uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
    352         size_t transferred_size;
    353         errno_t rc;
    354         for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) {
    355                 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
    356                     USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
    357                     0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
    358                     &transferred_size);
    359                 if (rc == EOK) {
    360                         if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
    361                                 rc = ELIMIT;
    362                                 continue;
    363                         }
    364                         break;
    365                 }
    366         }
    367         if (rc != EOK) {
    368                 return rc;
    369         }
    370 
    371         pipe->max_packet_size
    372             = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
    373 
    374         return EOK;
    375 }
    376 
    377343/**
    378344 * @}
  • uspace/lib/usbdev/src/request.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Vojtech Horky
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    118119 * @param data_size        Size of the @p data buffer
    119120 *                         (in native endianness).
    120  * @param actual_data_size Actual size of transfered data
     121 * @param actual_data_size Actual size of transferred data
    121122 *                         (in native endianness).
    122123 *
     
    183184
    184185        uint16_t status_usb_endianess;
    185         size_t data_transfered_size;
     186        size_t data_transferred_size;
    186187        errno_t rc = usb_control_request_get(pipe, USB_REQUEST_TYPE_STANDARD,
    187188            recipient, USB_DEVREQ_GET_STATUS, 0, uint16_host2usb(index),
    188             &status_usb_endianess, 2, &data_transfered_size);
    189         if (rc != EOK) {
    190                 return rc;
    191         }
    192         if (data_transfered_size != 2) {
     189            &status_usb_endianess, 2, &data_transferred_size);
     190        if (rc != EOK) {
     191                return rc;
     192        }
     193        if (data_transferred_size != 2) {
    193194                return ELIMIT;
    194195        }
     
    314315         */
    315316        uint8_t tmp_buffer;
    316         size_t bytes_transfered;
     317        size_t bytes_transferred;
    317318        rc = usb_request_get_descriptor(pipe, request_type, recipient,
    318319            descriptor_type, descriptor_index, language,
    319             &tmp_buffer, sizeof(tmp_buffer), &bytes_transfered);
    320         if (rc != EOK) {
    321                 return rc;
    322         }
    323         if (bytes_transfered != 1) {
     320            &tmp_buffer, sizeof(tmp_buffer), &bytes_transferred);
     321        if (rc != EOK) {
     322                return rc;
     323        }
     324        if (bytes_transferred != 1) {
    324325                return ELIMIT;
    325326        }
     
    340341        rc = usb_request_get_descriptor(pipe, request_type, recipient,
    341342            descriptor_type, descriptor_index, language,
    342             buffer, size, &bytes_transfered);
     343            buffer, size, &bytes_transferred);
    343344        if (rc != EOK) {
    344345                free(buffer);
    345346                return rc;
    346347        }
    347         if (bytes_transfered != size) {
     348        if (bytes_transferred != size) {
    348349                free(buffer);
    349350                return ELIMIT;
     
    824825 * @return Error code.
    825826 */
    826 errno_t usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
     827static errno_t usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
    827828{
    828829        return usb_request_clear_feature(pipe,
     
    843844                return EINVAL;
    844845        }
    845         return usb_request_clear_endpoint_halt(ctrl_pipe,
    846             target_pipe->endpoint_no);
     846
     847        uint16_t index = target_pipe->desc.endpoint_no;
     848        index |= (target_pipe->desc.direction == USB_DIRECTION_IN) << 7;
     849        return usb_request_clear_endpoint_halt(ctrl_pipe, index);
    847850}
    848851
     
    858861{
    859862        uint16_t status_tmp;
    860         uint16_t pipe_index = (uint16_t) pipe->endpoint_no;
     863        uint16_t pipe_index = (uint16_t) pipe->desc.endpoint_no;
    861864        errno_t rc = usb_request_get_status(ctrl_pipe,
    862865            USB_REQUEST_RECIPIENT_ENDPOINT, uint16_host2usb(pipe_index),
Note: See TracChangeset for help on using the changeset viewer.