Ignore:
File:
1 edited

Legend:

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

    ra0487a2 rb77931d  
    4646/** Data needed for polling. */
    4747typedef struct {
    48         /** Parameters for automated polling. */
    49         usb_device_auto_polling_t auto_polling;
    50 
    51         /** USB device to poll. */
     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
    5256        usb_device_t *dev;
    53         /** Device pipe to use for polling. */
    5457        size_t pipe_index;
    55         /** Size of the recieved data. */
    5658        size_t request_size;
    57         /** Data buffer. */
    5859        uint8_t *buffer;
     60        void *custom_arg;
    5961} polling_data_t;
    6062
     
    6769static int polling_fibril(void *arg)
    6870{
    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;
     71        polling_data_t *polling_data = (polling_data_t *) arg;
     72        assert(polling_data);
    7373
    7474        usb_pipe_t *pipe
    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];
     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];
    8080                usb_log_debug("Poll%p: started polling of `%s' - " \
    8181                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    82                     data, data->dev->ddf_dev->name,
     82                    polling_data,
     83                    polling_data->dev->ddf_dev->name,
    8384                    (int) mapping->interface->interface_number,
    8485                    usb_str_class(mapping->interface->interface_class),
    8586                    (int) mapping->interface->interface_subclass,
    8687                    (int) mapping->interface->interface_protocol,
    87                     data->request_size, pipe->max_packet_size);
    88         }
    89 
    90         usb_pipe_start_long_transfer(pipe);
     88                    polling_data->request_size, pipe->max_packet_size);
     89        }
     90
    9191        size_t failed_attempts = 0;
    92         while (failed_attempts <= params->max_failures) {
     92        while (failed_attempts <= polling_data->max_failures) {
     93                int rc;
     94
    9395                size_t actual_size;
    94                 const int rc = usb_pipe_read(pipe, data->buffer,
    95                     data->request_size, &actual_size);
    96 
    97                 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) {
    98100                        if (rc == EOK) {
    99101                                usb_log_debug(
    100102                                    "Poll%p: received: '%s' (%zuB).\n",
    101                                     data,
    102                                     usb_debug_str_buffer(data->buffer,
     103                                    polling_data,
     104                                    usb_debug_str_buffer(polling_data->buffer,
    103105                                        actual_size, 16),
    104106                                    actual_size);
     
    106108                                usb_log_debug(
    107109                                    "Poll%p: polling failed: %s.\n",
    108                                     data, str_error(rc));
     110                                    polling_data, str_error(rc));
    109111                        }
    110112                }
    111113
    112114                /* If the pipe stalled, we can try to reset the stall. */
    113                 if ((rc == ESTALL) && (params->auto_clear_halt)) {
     115                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
    114116                        /*
    115117                         * We ignore error here as this is usually a futile
     
    117119                         */
    118120                        usb_request_clear_endpoint_halt(
    119                             &data->dev->ctrl_pipe, pipe->endpoint_no);
     121                            &polling_data->dev->ctrl_pipe,
     122                            pipe->endpoint_no);
    120123                }
    121124
    122125                if (rc != EOK) {
    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;
     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                                }
    128134                        }
     135                        failed_attempts++;
    129136                        continue;
    130137                }
    131138
    132139                /* We have the data, execute the callback now. */
    133                 assert(params->on_data);
    134                 const bool carry_on = params->on_data(
    135                     data->dev, data->buffer, actual_size, params->arg);
     140                bool carry_on = polling_data->on_data(polling_data->dev,
     141                    polling_data->buffer, actual_size,
     142                    polling_data->custom_arg);
    136143
    137144                if (!carry_on) {
    138                         /* This is user requested abort, erases failures. */
    139145                        failed_attempts = 0;
    140146                        break;
     
    145151
    146152                /* Take a rest before next request. */
    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);
     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");
    162167                } else {
    163                         usb_log_debug("Polling of device `%s' terminated: "
    164                             "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                        );
    165172                }
    166173        }
    167174
    168175        /* Free the allocated memory. */
    169         free(data->buffer);
    170         free(data);
     176        free(polling_data->buffer);
     177        free(polling_data);
    171178
    172179        return EOK;
     
    195202    usb_polling_terminted_callback_t terminated_callback, void *arg)
    196203{
     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
    197215        const usb_device_auto_polling_t auto_polling = {
    198216                .debug = 1,
     
    203221                .on_polling_end = terminated_callback,
    204222                .on_error = NULL,
    205                 .arg = arg,
    206223        };
    207224
    208225        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
    209            request_size);
     226           request_size, arg);
    210227}
    211228
     
    229246int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    230247    const usb_device_auto_polling_t *polling,
    231     size_t request_size)
     248    size_t request_size, void *arg)
    232249{
    233         if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
     250        if (dev == NULL) {
    234251                return EBADMEM;
    235252        }
    236 
    237         if (pipe_index >= dev->pipes_count || request_size == 0) {
     253        if (pipe_index >= dev->pipes_count) {
    238254                return EINVAL;
    239255        }
     
    241257            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    242258                return EINVAL;
     259        }
     260        if ((polling == NULL) || (polling->on_data == NULL)) {
     261                return EBADMEM;
    243262        }
    244263
     
    257276        polling_data->dev = dev;
    258277        polling_data->pipe_index = pipe_index;
    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         }
     278        polling_data->custom_arg = arg;
     279
     280        polling_data->debug = polling->debug;
     281        polling_data->max_failures = polling->max_failures;
     282        if (polling->delay >= 0) {
     283                polling_data->delay = (useconds_t) polling->delay;
     284        } else {
     285                polling_data->delay = (useconds_t) dev->pipes[pipe_index]
     286                    .descriptor->poll_interval;
     287        }
     288        polling_data->auto_clear_halt = polling->auto_clear_halt;
     289
     290        polling_data->on_data = polling->on_data;
     291        polling_data->on_polling_end = polling->on_polling_end;
     292        polling_data->on_error = polling->on_error;
    268293
    269294        fid_t fibril = fibril_create(polling_fibril, polling_data);
Note: See TracChangeset for help on using the changeset viewer.