Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 0146d41 in mainline


Ignore:
Timestamp:
2011-04-14T14:00:51Z (11 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master
Children:
2471aaf, e583fd4
Parents:
8d517c3 (diff), 12b8e03 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Enhance auto polling, auto unstall (#166, #190)

Location:
uspace
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/main.c

    r8d517c3 r0146d41  
    4242
    4343#include <usb/devdrv.h>
     44#include <usb/devpoll.h>
    4445
    4546#include "usbhid.h"
  • uspace/drv/usbhub/usbhub.c

    r8d517c3 r0146d41  
    4545#include <usb/request.h>
    4646#include <usb/classes/hub.h>
     47#include <usb/devpoll.h>
    4748#include <stdio.h>
    4849
  • uspace/drv/usbkbd/main.c

    r8d517c3 r0146d41  
    4242
    4343#include <usb/devdrv.h>
     44#include <usb/devpoll.h>
    4445
    4546#include "kbddev.h"
  • uspace/drv/usbmouse/main.c

    r8d517c3 r0146d41  
    3636#include "mouse.h"
    3737#include <usb/debug.h>
     38#include <usb/devpoll.h>
    3839#include <errno.h>
    3940#include <str_error.h>
  • uspace/lib/usb/include/usb/devdrv.h

    r8d517c3 r0146d41  
    162162    usb_endpoint_description_t **);
    163163
    164 typedef bool (*usb_polling_callback_t)(usb_device_t *,
    165     uint8_t *, size_t, void *);
    166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
    167 
    168 int usb_device_auto_poll(usb_device_t *, size_t,
    169     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
    170 
    171164int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
    172165int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
  • uspace/lib/usb/include/usb/pipes.h

    r8d517c3 r0146d41  
    9999        /** Number of active transfers over the pipe. */
    100100        int refcount;
     101
     102        /** Whether to automatically reset halt on the endpoint.
     103         * Valid only for control endpoint zero.
     104         */
     105        bool auto_reset_halt;
    101106} usb_pipe_t;
    102107
  • uspace/lib/usb/src/devpoll.c

    r8d517c3 r0146d41  
    3333 * USB device driver framework - automatic interrupt polling.
    3434 */
    35 #include <usb/devdrv.h>
     35#include <usb/devpoll.h>
    3636#include <usb/request.h>
    3737#include <usb/debug.h>
     38#include <usb/classes/classes.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     
    4546/** Data needed for polling. */
    4647typedef struct {
     48        int debug;
     49        size_t max_failures;
     50        useconds_t delay;
     51        bool auto_clear_halt;
     52        bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
     53        void (*on_polling_end)(usb_device_t *, bool, void *);
     54        bool (*on_error)(usb_device_t *, int, void *);
     55
    4756        usb_device_t *dev;
    4857        size_t pipe_index;
    49         usb_polling_callback_t callback;
    50         usb_polling_terminted_callback_t terminated_callback;
    5158        size_t request_size;
    5259        uint8_t *buffer;
     
    5461} polling_data_t;
    5562
     63
    5664/** Polling fibril.
    5765 *
     
    6775            = polling_data->dev->pipes[polling_data->pipe_index].pipe;
    6876       
    69         usb_log_debug("Pipe interface number: %d, protocol: %d, subclass: %d, max packet size: %d\n",
    70             polling_data->dev->pipes[polling_data->pipe_index].interface_no,
    71             polling_data->dev->pipes[polling_data->pipe_index].description->interface_protocol,
    72             polling_data->dev->pipes[polling_data->pipe_index].description->interface_subclass,
    73             pipe->max_packet_size);
     77        if (polling_data->debug > 0) {
     78                usb_endpoint_mapping_t *mapping
     79                    = &polling_data->dev->pipes[polling_data->pipe_index];
     80                usb_log_debug("Poll0x%x: started polling of `%s' - " \
     81                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
     82                    polling_data,
     83                    polling_data->dev->ddf_dev->name,
     84                    (int) mapping->interface->interface_number,
     85                    usb_str_class(mapping->interface->interface_class),
     86                    (int) mapping->interface->interface_subclass,
     87                    (int) mapping->interface->interface_protocol,
     88                    polling_data->request_size, pipe->max_packet_size);
     89        }
    7490
    7591        size_t failed_attempts = 0;
    76         while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     92        while (failed_attempts <= polling_data->max_failures) {
    7793                int rc;
    7894
     
    8197                    polling_data->request_size, &actual_size);
    8298
    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 //              }
     99                if (polling_data->debug > 1) {
     100                        if (rc == EOK) {
     101                                usb_log_debug(
     102                                    "Poll0x%x: received: '%s' (%zuB).\n",
     103                                    polling_data,
     104                                    usb_debug_str_buffer(polling_data->buffer,
     105                                        actual_size, 16),
     106                                    actual_size);
     107                        } else {
     108                                usb_log_debug(
     109                                    "Poll0x%x: polling failed: %s.\n",
     110                                    polling_data, str_error(rc));
     111                        }
     112                }
     113
     114                /* If the pipe stalled, we can try to reset the stall. */
     115                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     116                        /*
     117                         * We ignore error here as this is usually a futile
     118                         * attempt anyway.
     119                         */
     120                        usb_request_clear_endpoint_halt(
     121                            &polling_data->dev->ctrl_pipe,
     122                            pipe->endpoint_no);
     123                }
    90124
    91125                if (rc != EOK) {
     126                        if (polling_data->on_error != NULL) {
     127                                bool cont = polling_data->on_error(
     128                                    polling_data->dev, rc,
     129                                    polling_data->custom_arg);
     130                                if (!cont) {
     131                                        failed_attempts
     132                                            = polling_data->max_failures;
     133                                }
     134                        }
    92135                        failed_attempts++;
    93136                        continue;
     
    95138
    96139                /* We have the data, execute the callback now. */
    97                 bool carry_on = polling_data->callback(polling_data->dev,
     140                bool carry_on = polling_data->on_data(polling_data->dev,
    98141                    polling_data->buffer, actual_size,
    99142                    polling_data->custom_arg);
     
    106149                /* Reset as something might be only a temporary problem. */
    107150                failed_attempts = 0;
    108         }
    109 
    110         if (failed_attempts > 0) {
    111                 usb_log_error(
    112                     "Polling of device `%s' terminated: recurring failures.\n",
    113                     polling_data->dev->ddf_dev->name);
    114         }
    115 
    116         if (polling_data->terminated_callback != NULL) {
    117                 polling_data->terminated_callback(polling_data->dev,
     151
     152                /* Take a rest before next request. */
     153                async_usleep(polling_data->delay);
     154        }
     155
     156        if (polling_data->on_polling_end != NULL) {
     157                polling_data->on_polling_end(polling_data->dev,
    118158                    failed_attempts > 0, polling_data->custom_arg);
     159        }
     160
     161        if (polling_data->debug > 0) {
     162                if (failed_attempts > 0) {
     163                        usb_log_error(
     164                            "Polling of device `%s' terminated: %s.\n",
     165                            polling_data->dev->ddf_dev->name,
     166                            "recurring failures");
     167                } else {
     168                        usb_log_debug(
     169                            "Polling of device `%s' terminated by user.\n",
     170                            polling_data->dev->ddf_dev->name
     171                        );
     172                }
    119173        }
    120174
     
    159213        }
    160214
     215        usb_device_auto_polling_t *auto_polling
     216            = malloc(sizeof(usb_device_auto_polling_t));
     217        if (auto_polling == NULL) {
     218                return ENOMEM;
     219        }
     220
     221        auto_polling->debug = 1;
     222        auto_polling->auto_clear_halt = true;
     223        auto_polling->delay = 0;
     224        auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
     225        auto_polling->on_data = callback;
     226        auto_polling->on_polling_end = terminated_callback;
     227        auto_polling->on_error = NULL;
     228
     229        int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     230           request_size, arg);
     231
     232        free(auto_polling);
     233
     234        return rc;
     235}
     236
     237/** Start automatic device polling over interrupt in pipe.
     238 *
     239 * The polling settings is copied thus it is okay to destroy the structure
     240 * after this function returns.
     241 *
     242 * @warning There is no guarantee when the request to the device
     243 * will be sent for the first time (it is possible that this
     244 * first request would be executed prior to return from this function).
     245 *
     246 * @param dev Device to be periodically polled.
     247 * @param pipe_index Index of the endpoint pipe used for polling.
     248 * @param polling Polling settings.
     249 * @param request_size How many bytes to ask for in each request.
     250 * @param arg Custom argument (passed as is to the callbacks).
     251 * @return Error code.
     252 * @retval EOK New fibril polling the device was already started.
     253 */
     254int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     255    usb_device_auto_polling_t *polling,
     256    size_t request_size, void *arg)
     257{
     258        if (dev == NULL) {
     259                return EBADMEM;
     260        }
     261        if (pipe_index >= dev->pipes_count) {
     262                return EINVAL;
     263        }
     264        if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
     265            || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     266                return EINVAL;
     267        }
     268        if ((polling == NULL) || (polling->on_data == NULL)) {
     269                return EBADMEM;
     270        }
     271
    161272        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    162273        if (polling_data == NULL) {
     
    164275        }
    165276
    166         /* Allocate now to prevent immediate failure in the polling fibril. */
    167         polling_data->buffer = malloc(request_size);
     277        /* Fill-in the data. */
     278        polling_data->buffer = malloc(sizeof(request_size));
    168279        if (polling_data->buffer == NULL) {
    169280                free(polling_data);
    170281                return ENOMEM;
    171282        }
     283        polling_data->request_size = request_size;
    172284        polling_data->dev = dev;
    173285        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;
    177286        polling_data->custom_arg = arg;
     287
     288        polling_data->debug = polling->debug;
     289        polling_data->max_failures = polling->max_failures;
     290        if (polling->delay >= 0) {
     291                polling_data->delay = (useconds_t) polling->delay;
     292        } else {
     293                polling_data->delay = (useconds_t) dev->pipes[pipe_index]
     294                    .descriptor->poll_interval;
     295        }
     296        polling_data->auto_clear_halt = polling->auto_clear_halt;
     297
     298        polling_data->on_data = polling->on_data;
     299        polling_data->on_polling_end = polling->on_polling_end;
     300        polling_data->on_error = polling->on_error;
    178301
    179302        fid_t fibril = fibril_create(polling_fibril, polling_data);
     
    181304                free(polling_data->buffer);
    182305                free(polling_data);
    183                 /* FIXME: better error code. */
    184306                return ENOMEM;
    185307        }
    186308        fibril_add_ready(fibril);
    187309
    188         /* The allocated buffer etc. will be freed by the fibril. */
     310        /* Fibril launched. That fibril will free the allocated data. */
    189311
    190312        return EOK;
  • uspace/lib/usb/src/pipesinit.c

    r8d517c3 r0146d41  
    365365        pipe->direction = direction;
    366366        pipe->refcount = 0;
     367        pipe->auto_reset_halt = false;
    367368
    368369        return EOK;
     
    385386            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    386387            USB_DIRECTION_BOTH);
     388
     389        pipe->auto_reset_halt = true;
    387390
    388391        return rc;
  • uspace/lib/usb/src/pipesio.c

    r8d517c3 r0146d41  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include <usb/request.h>
    5152#include "pipepriv.h"
    5253
     
    307308}
    308309
     310/** Try to clear endpoint halt of default control pipe.
     311 *
     312 * @param pipe Pipe for control endpoint zero.
     313 */
     314static void clear_self_endpoint_halt(usb_pipe_t *pipe)
     315{
     316        assert(pipe != NULL);
     317
     318        if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     319                return;
     320        }
     321
     322
     323        /* Prevent indefinite recursion. */
     324        pipe->auto_reset_halt = false;
     325        usb_request_clear_endpoint_halt(pipe, 0);
     326        pipe->auto_reset_halt = true;
     327}
     328
    309329
    310330/** Request a control read transfer, no checking of input parameters.
     
    436456            setup_buffer, setup_buffer_size,
    437457            data_buffer, data_buffer_size, &act_size);
     458
     459        if (rc == ESTALL) {
     460                clear_self_endpoint_halt(pipe);
     461        }
    438462
    439463        pipe_drop_ref(pipe);
     
    563587            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
    564588
     589        if (rc == ESTALL) {
     590                clear_self_endpoint_halt(pipe);
     591        }
     592
    565593        pipe_drop_ref(pipe);
    566594
Note: See TracChangeset for help on using the changeset viewer.