Ignore:
File:
1 edited

Legend:

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

    r9dbfd288 r160b75e  
    4646/** Data needed for polling. */
    4747typedef struct {
    48         usb_device_auto_polling_t auto_polling;
     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 *);
    4955
    5056        usb_device_t *dev;
     
    6369static int polling_fibril(void *arg)
    6470{
    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;
     71        polling_data_t *polling_data = (polling_data_t *) arg;
     72        assert(polling_data);
    6973
    7074        usb_pipe_t *pipe
    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];
     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];
    7680                usb_log_debug("Poll%p: started polling of `%s' - " \
    7781                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    78                     data, data->dev->ddf_dev->name,
     82                    polling_data,
     83                    polling_data->dev->ddf_dev->name,
    7984                    (int) mapping->interface->interface_number,
    8085                    usb_str_class(mapping->interface->interface_class),
    8186                    (int) mapping->interface->interface_subclass,
    8287                    (int) mapping->interface->interface_protocol,
    83                     data->request_size, pipe->max_packet_size);
    84         }
    85 
    86         usb_pipe_start_long_transfer(pipe);
     88                    polling_data->request_size, pipe->max_packet_size);
     89        }
     90
    8791        size_t failed_attempts = 0;
    88         while (failed_attempts <= params->max_failures) {
     92        while (failed_attempts <= polling_data->max_failures) {
     93                int rc;
     94
    8995                size_t actual_size;
    90                 const int rc = usb_pipe_read(pipe, data->buffer,
    91                     data->request_size, &actual_size);
    92 
    93                 if (params->debug > 1) {
     96                rc = usb_pipe_read(pipe, polling_data->buffer,
     97                    polling_data->request_size, &actual_size);
     98
     99                if (polling_data->debug > 1) {
    94100                        if (rc == EOK) {
    95101                                usb_log_debug(
    96102                                    "Poll%p: received: '%s' (%zuB).\n",
    97                                     data,
    98                                     usb_debug_str_buffer(data->buffer,
     103                                    polling_data,
     104                                    usb_debug_str_buffer(polling_data->buffer,
    99105                                        actual_size, 16),
    100106                                    actual_size);
     
    102108                                usb_log_debug(
    103109                                    "Poll%p: polling failed: %s.\n",
    104                                     data, str_error(rc));
     110                                    polling_data, str_error(rc));
    105111                        }
    106112                }
    107113
    108114                /* If the pipe stalled, we can try to reset the stall. */
    109                 if ((rc == ESTALL) && (params->auto_clear_halt)) {
     115                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
    110116                        /*
    111117                         * We ignore error here as this is usually a futile
     
    113119                         */
    114120                        usb_request_clear_endpoint_halt(
    115                             &data->dev->ctrl_pipe, pipe->endpoint_no);
     121                            &polling_data->dev->ctrl_pipe,
     122                            pipe->endpoint_no);
    116123                }
    117124
    118125                if (rc != EOK) {
    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;
     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                                }
    124134                        }
     135                        failed_attempts++;
    125136                        continue;
    126137                }
    127138
    128139                /* We have the data, execute the callback now. */
    129                 assert(params->on_data);
    130                 const bool carry_on = params->on_data(
    131                     data->dev, data->buffer, actual_size, data->custom_arg);
     140                bool carry_on = polling_data->on_data(polling_data->dev,
     141                    polling_data->buffer, actual_size,
     142                    polling_data->custom_arg);
    132143
    133144                if (!carry_on) {
    134                         /* This is user requested abort, erases failures. */
    135145                        failed_attempts = 0;
    136146                        break;
     
    141151
    142152                /* Take a rest before next request. */
    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);
     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");
    158167                } else {
    159                         usb_log_debug("Polling of device `%s' terminated: "
    160                             "driver request.\n", data->dev->ddf_dev->name);
     168                        usb_log_debug(
     169                            "Polling of device `%s' terminated by user.\n",
     170                            polling_data->dev->ddf_dev->name
     171                        );
    161172                }
    162173        }
    163174
    164175        /* Free the allocated memory. */
    165         free(data->buffer);
    166         free(data);
     176        free(polling_data->buffer);
     177        free(polling_data);
    167178
    168179        return EOK;
     
    191202    usb_polling_terminted_callback_t terminated_callback, void *arg)
    192203{
    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,
     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,
    204230           request_size, arg);
     231
     232        free(auto_polling);
     233
     234        return rc;
    205235}
    206236
     
    223253 */
    224254int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    225     const usb_device_auto_polling_t *polling,
     255    usb_device_auto_polling_t *polling,
    226256    size_t request_size, void *arg)
    227257{
    228         if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
     258        if (dev == NULL) {
    229259                return EBADMEM;
    230260        }
    231 
    232         if (pipe_index >= dev->pipes_count || request_size == 0) {
     261        if (pipe_index >= dev->pipes_count) {
    233262                return EINVAL;
    234263        }
    235         if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
    236             || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
     264        if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
     265            || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
    237266                return EINVAL;
     267        }
     268        if ((polling == NULL) || (polling->on_data == NULL)) {
     269                return EBADMEM;
    238270        }
    239271
     
    254286        polling_data->custom_arg = arg;
    255287
    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         }
     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;
    264301
    265302        fid_t fibril = fibril_create(polling_fibril, polling_data);
Note: See TracChangeset for help on using the changeset viewer.