Ignore:
File:
1 edited

Legend:

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

    r33b8d024 r5a6cc679  
    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
Note: See TracChangeset for help on using the changeset viewer.