Ignore:
File:
1 edited

Legend:

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

    rb77931d ra0487a2  
    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 
    215197        const usb_device_auto_polling_t auto_polling = {
    216198                .debug = 1,
     
    221203                .on_polling_end = terminated_callback,
    222204                .on_error = NULL,
     205                .arg = arg,
    223206        };
    224207
    225208        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
    226            request_size, arg);
     209           request_size);
    227210}
    228211
     
    246229int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    247230    const usb_device_auto_polling_t *polling,
    248     size_t request_size, void *arg)
     231    size_t request_size)
    249232{
    250         if (dev == NULL) {
     233        if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
    251234                return EBADMEM;
    252235        }
    253         if (pipe_index >= dev->pipes_count) {
     236
     237        if (pipe_index >= dev->pipes_count || request_size == 0) {
    254238                return EINVAL;
    255239        }
     
    257241            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    258242                return EINVAL;
    259         }
    260         if ((polling == NULL) || (polling->on_data == NULL)) {
    261                 return EBADMEM;
    262243        }
    263244
     
    276257        polling_data->dev = dev;
    277258        polling_data->pipe_index = pipe_index;
    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;
     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        }
    293268
    294269        fid_t fibril = fibril_create(polling_fibril, polling_data);
Note: See TracChangeset for help on using the changeset viewer.