Ignore:
File:
1 edited

Legend:

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

    r160b75e r9dbfd288  
    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 *);
     48        usb_device_auto_polling_t auto_polling;
    5549
    5650        usb_device_t *dev;
     
    6963static int polling_fibril(void *arg)
    7064{
    71         polling_data_t *polling_data = (polling_data_t *) arg;
    72         assert(polling_data);
     65        assert(arg);
     66        const polling_data_t *data = arg;
     67        /* Helper to reduce typing. */
     68        const usb_device_auto_polling_t *params = &data->auto_polling;
    7369
    7470        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];
     71            = &data->dev->pipes[data->pipe_index].pipe;
     72
     73        if (params->debug > 0) {
     74                const usb_endpoint_mapping_t *mapping
     75                    = &data->dev->pipes[data->pipe_index];
    8076                usb_log_debug("Poll%p: started polling of `%s' - " \
    8177                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    82                     polling_data,
    83                     polling_data->dev->ddf_dev->name,
     78                    data, data->dev->ddf_dev->name,
    8479                    (int) mapping->interface->interface_number,
    8580                    usb_str_class(mapping->interface->interface_class),
    8681                    (int) mapping->interface->interface_subclass,
    8782                    (int) mapping->interface->interface_protocol,
    88                     polling_data->request_size, pipe->max_packet_size);
    89         }
    90 
     83                    data->request_size, pipe->max_packet_size);
     84        }
     85
     86        usb_pipe_start_long_transfer(pipe);
    9187        size_t failed_attempts = 0;
    92         while (failed_attempts <= polling_data->max_failures) {
    93                 int rc;
    94 
     88        while (failed_attempts <= params->max_failures) {
    9589                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) {
     90                const int rc = usb_pipe_read(pipe, data->buffer,
     91                    data->request_size, &actual_size);
     92
     93                if (params->debug > 1) {
    10094                        if (rc == EOK) {
    10195                                usb_log_debug(
    10296                                    "Poll%p: received: '%s' (%zuB).\n",
    103                                     polling_data,
    104                                     usb_debug_str_buffer(polling_data->buffer,
     97                                    data,
     98                                    usb_debug_str_buffer(data->buffer,
    10599                                        actual_size, 16),
    106100                                    actual_size);
     
    108102                                usb_log_debug(
    109103                                    "Poll%p: polling failed: %s.\n",
    110                                     polling_data, str_error(rc));
     104                                    data, str_error(rc));
    111105                        }
    112106                }
    113107
    114108                /* If the pipe stalled, we can try to reset the stall. */
    115                 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     109                if ((rc == ESTALL) && (params->auto_clear_halt)) {
    116110                        /*
    117111                         * We ignore error here as this is usually a futile
     
    119113                         */
    120114                        usb_request_clear_endpoint_halt(
    121                             &polling_data->dev->ctrl_pipe,
    122                             pipe->endpoint_no);
     115                            &data->dev->ctrl_pipe, pipe->endpoint_no);
    123116                }
    124117
    125118                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                                 }
     119                        ++failed_attempts;
     120                        const bool cont = (params->on_error == NULL) ? true :
     121                            params->on_error(data->dev, rc, data->custom_arg);
     122                        if (!cont) {
     123                                failed_attempts = params->max_failures;
    134124                        }
    135                         failed_attempts++;
    136125                        continue;
    137126                }
    138127
    139128                /* 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);
     129                assert(params->on_data);
     130                const bool carry_on = params->on_data(
     131                    data->dev, data->buffer, actual_size, data->custom_arg);
    143132
    144133                if (!carry_on) {
     134                        /* This is user requested abort, erases failures. */
    145135                        failed_attempts = 0;
    146136                        break;
     
    151141
    152142                /* 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");
     143                async_usleep(params->delay);
     144        }
     145
     146        usb_pipe_end_long_transfer(pipe);
     147
     148        const bool failed = failed_attempts > 0;
     149
     150        if (params->on_polling_end != NULL) {
     151                params->on_polling_end(data->dev, failed, data->custom_arg);
     152        }
     153
     154        if (params->debug > 0) {
     155                if (failed) {
     156                        usb_log_error("Polling of device `%s' terminated: "
     157                            "recurring failures.\n", data->dev->ddf_dev->name);
    167158                } else {
    168                         usb_log_debug(
    169                             "Polling of device `%s' terminated by user.\n",
    170                             polling_data->dev->ddf_dev->name
    171                         );
     159                        usb_log_debug("Polling of device `%s' terminated: "
     160                            "driver request.\n", data->dev->ddf_dev->name);
    172161                }
    173162        }
    174163
    175164        /* Free the allocated memory. */
    176         free(polling_data->buffer);
    177         free(polling_data);
     165        free(data->buffer);
     166        free(data);
    178167
    179168        return EOK;
     
    202191    usb_polling_terminted_callback_t terminated_callback, void *arg)
    203192{
    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,
     193        const usb_device_auto_polling_t auto_polling = {
     194                .debug = 1,
     195                .auto_clear_halt = true,
     196                .delay = 0,
     197                .max_failures = MAX_FAILED_ATTEMPTS,
     198                .on_data = callback,
     199                .on_polling_end = terminated_callback,
     200                .on_error = NULL,
     201        };
     202
     203        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
    230204           request_size, arg);
    231 
    232         free(auto_polling);
    233 
    234         return rc;
    235205}
    236206
     
    253223 */
    254224int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    255     usb_device_auto_polling_t *polling,
     225    const usb_device_auto_polling_t *polling,
    256226    size_t request_size, void *arg)
    257227{
    258         if (dev == NULL) {
     228        if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
    259229                return EBADMEM;
    260230        }
    261         if (pipe_index >= dev->pipes_count) {
     231
     232        if (pipe_index >= dev->pipes_count || request_size == 0) {
    262233                return EINVAL;
    263234        }
    264         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    265             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     235        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     236            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    266237                return EINVAL;
    267         }
    268         if ((polling == NULL) || (polling->on_data == NULL)) {
    269                 return EBADMEM;
    270238        }
    271239
     
    286254        polling_data->custom_arg = arg;
    287255
    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;
     256        /* Copy provided settings. */
     257        polling_data->auto_polling = *polling;
     258
     259        /* Negative value means use descriptor provided value. */
     260        if (polling->delay < 0) {
     261                polling_data->auto_polling.delay =
     262                    (int) dev->pipes[pipe_index].descriptor->poll_interval;
     263        }
    301264
    302265        fid_t fibril = fibril_create(polling_fibril, polling_data);
Note: See TracChangeset for help on using the changeset viewer.