Changeset 00aece0 in mainline for uspace/lib/usbdev/src/devpoll.c


Ignore:
Timestamp:
2012-02-18T16:47:38Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4449c6c
Parents:
bd5f3b7 (diff), f943dd3 (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:

Merge mainline changes.

File:
1 edited

Legend:

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

    rbd5f3b7 r00aece0  
    4646/** Data needed for polling. */
    4747typedef 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 
     48        /** Parameters for automated polling. */
     49        usb_device_auto_polling_t auto_polling;
     50
     51        /** USB device to poll. */
    5652        usb_device_t *dev;
     53        /** Device pipe to use for polling. */
    5754        size_t pipe_index;
     55        /** Size of the recieved data. */
    5856        size_t request_size;
     57        /** Data buffer. */
    5958        uint8_t *buffer;
    60         void *custom_arg;
    6159} polling_data_t;
    6260
     
    6967static int polling_fibril(void *arg)
    7068{
    71         polling_data_t *polling_data = (polling_data_t *) arg;
    72         assert(polling_data);
     69        assert(arg);
     70        const polling_data_t *data = arg;
     71        /* Helper to reduce typing. */
     72        const usb_device_auto_polling_t *params = &data->auto_polling;
    7373
    7474        usb_pipe_t *pipe
    75             = polling_data->dev->pipes[polling_data->pipe_index].pipe;
    76        
    77         if (polling_data->debug > 0) {
    78                 usb_endpoint_mapping_t *mapping
    79                     = &polling_data->dev->pipes[polling_data->pipe_index];
     75            = &data->dev->pipes[data->pipe_index].pipe;
     76
     77        if (params->debug > 0) {
     78                const usb_endpoint_mapping_t *mapping
     79                    = &data->dev->pipes[data->pipe_index];
    8080                usb_log_debug("Poll%p: started polling of `%s' - " \
    8181                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    82                     polling_data,
    83                     polling_data->dev->ddf_dev->name,
     82                    data, data->dev->ddf_dev->name,
    8483                    (int) mapping->interface->interface_number,
    8584                    usb_str_class(mapping->interface->interface_class),
    8685                    (int) mapping->interface->interface_subclass,
    8786                    (int) mapping->interface->interface_protocol,
    88                     polling_data->request_size, pipe->max_packet_size);
    89         }
    90 
     87                    data->request_size, pipe->max_packet_size);
     88        }
     89
     90        usb_pipe_start_long_transfer(pipe);
    9191        size_t failed_attempts = 0;
    92         while (failed_attempts <= polling_data->max_failures) {
    93                 int rc;
    94 
     92        while (failed_attempts <= params->max_failures) {
    9593                size_t actual_size;
    96                 rc = usb_pipe_read(pipe, polling_data->buffer,
    97                     polling_data->request_size, &actual_size);
    98 
    99                 if (polling_data->debug > 1) {
     94                const int rc = usb_pipe_read(pipe, data->buffer,
     95                    data->request_size, &actual_size);
     96
     97                if (params->debug > 1) {
    10098                        if (rc == EOK) {
    10199                                usb_log_debug(
    102100                                    "Poll%p: received: '%s' (%zuB).\n",
    103                                     polling_data,
    104                                     usb_debug_str_buffer(polling_data->buffer,
     101                                    data,
     102                                    usb_debug_str_buffer(data->buffer,
    105103                                        actual_size, 16),
    106104                                    actual_size);
     
    108106                                usb_log_debug(
    109107                                    "Poll%p: polling failed: %s.\n",
    110                                     polling_data, str_error(rc));
     108                                    data, str_error(rc));
    111109                        }
    112110                }
    113111
    114112                /* If the pipe stalled, we can try to reset the stall. */
    115                 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     113                if ((rc == ESTALL) && (params->auto_clear_halt)) {
    116114                        /*
    117115                         * We ignore error here as this is usually a futile
     
    119117                         */
    120118                        usb_request_clear_endpoint_halt(
    121                             &polling_data->dev->ctrl_pipe,
    122                             pipe->endpoint_no);
     119                            &data->dev->ctrl_pipe, pipe->endpoint_no);
    123120                }
    124121
    125122                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                                 }
     123                        ++failed_attempts;
     124                        const bool cont = (params->on_error == NULL) ? true :
     125                            params->on_error(data->dev, rc, params->arg);
     126                        if (!cont) {
     127                                failed_attempts = params->max_failures;
    134128                        }
    135                         failed_attempts++;
    136129                        continue;
    137130                }
    138131
    139132                /* We have the data, execute the callback now. */
    140                 bool carry_on = polling_data->on_data(polling_data->dev,
    141                     polling_data->buffer, actual_size,
    142                     polling_data->custom_arg);
     133                assert(params->on_data);
     134                const bool carry_on = params->on_data(
     135                    data->dev, data->buffer, actual_size, params->arg);
    143136
    144137                if (!carry_on) {
     138                        /* This is user requested abort, erases failures. */
    145139                        failed_attempts = 0;
    146140                        break;
     
    151145
    152146                /* 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,
    158                     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");
     147                async_usleep(params->delay);
     148        }
     149
     150        usb_pipe_end_long_transfer(pipe);
     151
     152        const bool failed = failed_attempts > 0;
     153
     154        if (params->on_polling_end != NULL) {
     155                params->on_polling_end(data->dev, failed, params->arg);
     156        }
     157
     158        if (params->debug > 0) {
     159                if (failed) {
     160                        usb_log_error("Polling of device `%s' terminated: "
     161                            "recurring failures.\n", data->dev->ddf_dev->name);
    167162                } else {
    168                         usb_log_debug(
    169                             "Polling of device `%s' terminated by user.\n",
    170                             polling_data->dev->ddf_dev->name
    171                         );
     163                        usb_log_debug("Polling of device `%s' terminated: "
     164                            "driver request.\n", data->dev->ddf_dev->name);
    172165                }
    173166        }
    174167
    175168        /* Free the allocated memory. */
    176         free(polling_data->buffer);
    177         free(polling_data);
     169        free(data->buffer);
     170        free(data);
    178171
    179172        return EOK;
     
    202195    usb_polling_terminted_callback_t terminated_callback, void *arg)
    203196{
    204         if ((dev == NULL) || (callback == NULL)) {
    205                 return EBADMEM;
    206         }
    207         if (request_size == 0) {
    208                 return EINVAL;
    209         }
    210         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    211             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
    212                 return EINVAL;
    213         }
    214 
    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;
     197        const usb_device_auto_polling_t auto_polling = {
     198                .debug = 1,
     199                .auto_clear_halt = true,
     200                .delay = 0,
     201                .max_failures = MAX_FAILED_ATTEMPTS,
     202                .on_data = callback,
     203                .on_polling_end = terminated_callback,
     204                .on_error = NULL,
     205                .arg = arg,
     206        };
     207
     208        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
     209           request_size);
    235210}
    236211
     
    253228 */
    254229int 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)
     230    const usb_device_auto_polling_t *polling,
     231    size_t request_size)
    257232{
    258         if (dev == NULL) {
     233        if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
    259234                return EBADMEM;
    260235        }
    261         if (pipe_index >= dev->pipes_count) {
     236
     237        if (pipe_index >= dev->pipes_count || request_size == 0) {
    262238                return EINVAL;
    263239        }
    264         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    265             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     240        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     241            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    266242                return EINVAL;
    267         }
    268         if ((polling == NULL) || (polling->on_data == NULL)) {
    269                 return EBADMEM;
    270243        }
    271244
     
    284257        polling_data->dev = dev;
    285258        polling_data->pipe_index = pipe_index;
    286         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;
     259
     260        /* Copy provided settings. */
     261        polling_data->auto_polling = *polling;
     262
     263        /* Negative value means use descriptor provided value. */
     264        if (polling->delay < 0) {
     265                polling_data->auto_polling.delay =
     266                    (int) dev->pipes[pipe_index].descriptor->poll_interval;
     267        }
    301268
    302269        fid_t fibril = fibril_create(polling_fibril, polling_data);
Note: See TracChangeset for help on using the changeset viewer.