Changeset 8989f48f in mainline


Ignore:
Timestamp:
2011-04-14T10:03:20Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5e168be1
Parents:
5e07e2b5
Message:

Generalized automatic device polling

Location:
uspace/lib/usb
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/include/usb/devpoll.h

    r5e07e2b5 r8989f48f  
    3737
    3838#include <usb/devdrv.h>
     39#include <time.h>
     40
     41typedef struct {
     42        /** Maximum number of consecutive errors before polling termination. */
     43        size_t max_failures;
     44        /** Delay between poll requests in milliseconds.
     45         * Set to negative value to use value from endpoint descriptor.
     46         */
     47        int delay;
     48        /** Whether to automatically try to clear the HALT feature after
     49         * the endpoint stalls.
     50         */
     51        bool auto_clear_halt;
     52        /** Callback when data arrives.
     53         *
     54         * @param dev Device that was polled.
     55         * @param data Data buffer (in USB endianness).
     56         * @param data_size Size of the @p data buffer in bytes.
     57         * @param arg Custom argument.
     58         * @return Whether to continue in polling.
     59         */
     60        bool (*on_data)(usb_device_t *dev, uint8_t *data, size_t data_size,
     61            void *arg);
     62        /** Callback when polling is terminated.
     63         *
     64         * @param dev Device where the polling was terminated.
     65         * @param due_to_errors Whether polling stopped due to several failures.
     66         * @param arg Custom argument.
     67         */
     68        void (*on_polling_end)(usb_device_t *dev, bool due_to_errors,
     69            void *arg);
     70        /** Callback when error occurs.
     71         *
     72         * @param dev Device where error occurred.
     73         * @param err_code Error code (as returned from usb_pipe_read).
     74         * @param arg Custom argument.
     75         * @return Whether to continue in polling.
     76         */
     77        bool (*on_error)(usb_device_t *dev, int err_code, void *arg);
     78} usb_device_auto_polling_t;
     79
     80int usb_device_auto_polling(usb_device_t *, size_t, usb_device_auto_polling_t *,
     81    size_t, void *);
    3982
    4083typedef bool (*usb_polling_callback_t)(usb_device_t *,
  • uspace/lib/usb/src/devpoll.c

    r5e07e2b5 r8989f48f  
    4545/** Data needed for polling. */
    4646typedef struct {
     47        size_t max_failures;
     48        useconds_t delay;
     49        bool auto_clear_halt;
     50        bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
     51        void (*on_polling_end)(usb_device_t *, bool, void *);
     52        bool (*on_error)(usb_device_t *, int, void *);
     53
    4754        usb_device_t *dev;
    4855        size_t pipe_index;
    49         usb_polling_callback_t callback;
    50         usb_polling_terminted_callback_t terminated_callback;
    5156        size_t request_size;
    5257        uint8_t *buffer;
    5358        void *custom_arg;
    5459} polling_data_t;
     60
    5561
    5662/** Polling fibril.
     
    7480
    7581        size_t failed_attempts = 0;
    76         while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     82        while (failed_attempts <= polling_data->max_failures) {
    7783                int rc;
    7884
     
    8187                    polling_data->request_size, &actual_size);
    8288
    83                
    84 //              if (rc == ESTALL) {
    85 //                      usb_log_debug("Seding clear feature...\n");
    86 //                      usb_request_clear_feature(pipe, USB_REQUEST_TYPE_STANDARD,
    87 //                        USB_REQUEST_RECIPIENT_ENDPOINT, 0, pipe->endpoint_no);
    88 //                      continue;
    89 //              }
     89                /* If the pipe stalled, we can try to reset the stall. */
     90                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     91                        /*
     92                         * We ignore error here as this is usually a futile
     93                         * attempt anyway.
     94                         */
     95                        usb_request_clear_endpoint_halt(
     96                            &polling_data->dev->ctrl_pipe,
     97                            pipe->endpoint_no);
     98                }
    9099
    91100                if (rc != EOK) {
     101                        if (polling_data->on_error != NULL) {
     102                                bool cont = polling_data->on_error(
     103                                    polling_data->dev, rc,
     104                                    polling_data->custom_arg);
     105                                if (!cont) {
     106                                        failed_attempts
     107                                            = polling_data->max_failures;
     108                                }
     109                        }
    92110                        failed_attempts++;
    93111                        continue;
     
    95113
    96114                /* We have the data, execute the callback now. */
    97                 bool carry_on = polling_data->callback(polling_data->dev,
     115                bool carry_on = polling_data->on_data(polling_data->dev,
    98116                    polling_data->buffer, actual_size,
    99117                    polling_data->custom_arg);
     
    106124                /* Reset as something might be only a temporary problem. */
    107125                failed_attempts = 0;
     126
     127                /* Take a rest before next request. */
     128                async_usleep(polling_data->delay);
    108129        }
    109130
     
    114135        }
    115136
    116         if (polling_data->terminated_callback != NULL) {
    117                 polling_data->terminated_callback(polling_data->dev,
     137        if (polling_data->on_polling_end != NULL) {
     138                polling_data->on_polling_end(polling_data->dev,
    118139                    failed_attempts > 0, polling_data->custom_arg);
    119140        }
     
    159180        }
    160181
     182        usb_device_auto_polling_t *auto_polling
     183            = malloc(sizeof(usb_device_auto_polling_t));
     184        if (auto_polling == NULL) {
     185                return ENOMEM;
     186        }
     187
     188        auto_polling->auto_clear_halt = true;
     189        auto_polling->delay = 0;
     190        auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
     191        auto_polling->on_data = callback;
     192        auto_polling->on_polling_end = terminated_callback;
     193        auto_polling->on_error = NULL;
     194
     195        int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     196           request_size, arg);
     197
     198        free(auto_polling);
     199
     200        return rc;
     201}
     202
     203/** Start automatic device polling over interrupt in pipe.
     204 *
     205 * The polling settings is copied thus it is okay to destroy the structure
     206 * after this function returns.
     207 *
     208 * @warning There is no guarantee when the request to the device
     209 * will be sent for the first time (it is possible that this
     210 * first request would be executed prior to return from this function).
     211 *
     212 * @param dev Device to be periodically polled.
     213 * @param pipe_index Index of the endpoint pipe used for polling.
     214 * @param polling Polling settings.
     215 * @param request_size How many bytes to ask for in each request.
     216 * @param arg Custom argument (passed as is to the callbacks).
     217 * @return Error code.
     218 * @retval EOK New fibril polling the device was already started.
     219 */
     220int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     221    usb_device_auto_polling_t *polling,
     222    size_t request_size, void *arg)
     223{
     224        if (dev == NULL) {
     225                return EBADMEM;
     226        }
     227        if (pipe_index >= dev->pipes_count) {
     228                return EINVAL;
     229        }
     230        if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
     231            || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     232                return EINVAL;
     233        }
     234        if ((polling == NULL) || (polling->on_data == NULL)) {
     235                return EBADMEM;
     236        }
     237
    161238        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    162239        if (polling_data == NULL) {
     
    164241        }
    165242
    166         /* Allocate now to prevent immediate failure in the polling fibril. */
    167         polling_data->buffer = malloc(request_size);
     243        /* Fill-in the data. */
     244        polling_data->buffer = malloc(sizeof(request_size));
    168245        if (polling_data->buffer == NULL) {
    169246                free(polling_data);
    170247                return ENOMEM;
    171248        }
     249        polling_data->request_size = request_size;
    172250        polling_data->dev = dev;
    173251        polling_data->pipe_index = pipe_index;
    174         polling_data->callback = callback;
    175         polling_data->terminated_callback = terminated_callback;
    176         polling_data->request_size = request_size;
    177252        polling_data->custom_arg = arg;
     253
     254        polling_data->max_failures = polling->max_failures;
     255        if (polling->delay >= 0) {
     256                polling_data->delay = (useconds_t) polling->delay;
     257        } else {
     258                polling_data->delay = (useconds_t) dev->pipes[pipe_index]
     259                    .descriptor->poll_interval;
     260        }
     261        polling_data->auto_clear_halt = polling->auto_clear_halt;
     262
     263        polling_data->on_data = polling->on_data;
     264        polling_data->on_polling_end = polling->on_polling_end;
     265        polling_data->on_error = polling->on_error;
    178266
    179267        fid_t fibril = fibril_create(polling_fibril, polling_data);
     
    181269                free(polling_data->buffer);
    182270                free(polling_data);
    183                 /* FIXME: better error code. */
    184271                return ENOMEM;
    185272        }
    186273        fibril_add_ready(fibril);
    187274
    188         /* The allocated buffer etc. will be freed by the fibril. */
     275        /* Fibril launched. That fibril will free the allocated data. */
    189276
    190277        return EOK;
Note: See TracChangeset for help on using the changeset viewer.