Ignore:
File:
1 edited

Legend:

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

    r58563585 r56fd7cf  
    3333 * USB device driver framework - automatic interrupt polling.
    3434 */
    35 
    36 #include <usb/dev/device.h>
    37 #include <usb/dev/pipes.h>
    3835#include <usb/dev/poll.h>
    3936#include <usb/dev/request.h>
     37#include <usb/debug.h>
    4038#include <usb/classes/classes.h>
    41 #include <usb/debug.h>
    42 #include <usb/descriptor.h>
    43 #include <usb/usb.h>
    44 
     39#include <errno.h>
     40#include <str_error.h>
    4541#include <assert.h>
    46 #include <async.h>
    47 #include <errno.h>
    48 #include <fibril.h>
    49 #include <stdbool.h>
    50 #include <stdlib.h>
    51 #include <str_error.h>
    52 #include <sys/types.h>
    5342
    5443/** Maximum number of failed consecutive requests before announcing failure. */
     
    6251        /** USB device to poll. */
    6352        usb_device_t *dev;
    64         /** Device enpoint mapping to use for polling. */
    65         usb_endpoint_mapping_t *polling_mapping;
     53        /** Device pipe to use for polling. */
     54        size_t pipe_index;
    6655        /** Size of the recieved data. */
    6756        size_t request_size;
     
    8372        const usb_device_auto_polling_t *params = &data->auto_polling;
    8473
    85         usb_pipe_t *pipe = &data->polling_mapping->pipe;
     74        usb_pipe_t *pipe
     75            = &data->dev->pipes[data->pipe_index].pipe;
    8676
    8777        if (params->debug > 0) {
    88                 const usb_endpoint_mapping_t *mapping =
    89                     data->polling_mapping;
    90                 usb_log_debug("Poll (%p): started polling of `%s' - " \
     78                const usb_endpoint_mapping_t *mapping
     79                    = &data->dev->pipes[data->pipe_index];
     80                usb_log_debug("Poll%p: started polling of `%s' - " \
    9181                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    92                     data, usb_device_get_name(data->dev),
     82                    data, ddf_dev_get_name(data->dev->ddf_dev),
    9383                    (int) mapping->interface->interface_number,
    9484                    usb_str_class(mapping->interface->interface_class),
     
    9888        }
    9989
     90        usb_pipe_start_long_transfer(pipe);
    10091        size_t failed_attempts = 0;
    10192        while (failed_attempts <= params->max_failures) {
     
    10495                    data->request_size, &actual_size);
    10596
    106                 if (rc == EOK) {
    107                         if (params->debug > 1) {
     97                if (params->debug > 1) {
     98                        if (rc == EOK) {
    10899                                usb_log_debug(
    109100                                    "Poll%p: received: '%s' (%zuB).\n",
     
    112103                                        actual_size, 16),
    113104                                    actual_size);
    114                         }
    115                 } else {
     105                        } else {
    116106                                usb_log_debug(
    117107                                    "Poll%p: polling failed: %s.\n",
    118108                                    data, str_error(rc));
     109                        }
    119110                }
    120111
     
    126117                         */
    127118                        usb_request_clear_endpoint_halt(
    128                             usb_device_get_default_pipe(data->dev),
    129                             pipe->endpoint_no);
     119                            &data->dev->ctrl_pipe, pipe->endpoint_no);
    130120                }
    131121
     
    155145
    156146                /* Take a rest before next request. */
    157                
    158                 // FIXME TODO: This is broken, the time is in ms not us.
    159                 // but first we need to fix drivers to actually stop using this,
    160                 // since polling delay should be implemented in HC schedule
    161147                async_usleep(params->delay);
    162148        }
     149
     150        usb_pipe_end_long_transfer(pipe);
    163151
    164152        const bool failed = failed_attempts > 0;
     
    171159                if (failed) {
    172160                        usb_log_error("Polling of device `%s' terminated: "
    173                             "recurring failures.\n",
    174                             usb_device_get_name(data->dev));
     161                            "recurring failures.\n", ddf_dev_get_name(
     162                            data->dev->ddf_dev));
    175163                } else {
    176164                        usb_log_debug("Polling of device `%s' terminated: "
    177                             "driver request.\n",
    178                             usb_device_get_name(data->dev));
     165                            "driver request.\n", ddf_dev_get_name(
     166                            data->dev->ddf_dev));
    179167                }
    180168        }
     
    187175}
    188176
    189 
    190177/** Start automatic device polling over interrupt in pipe.
    191178 *
    192  * The polling settings is copied thus it is okay to destroy the structure
    193  * after this function returns.
     179 * @warning It is up to the callback to produce delays between individual
     180 * requests.
    194181 *
    195182 * @warning There is no guarantee when the request to the device
     
    198185 *
    199186 * @param dev Device to be periodically polled.
    200  * @param epm Endpoint mapping to use.
    201  * @param polling Polling settings.
    202  * @param request_size How many bytes to ask for in each request.
    203  * @param arg Custom argument (passed as is to the callbacks).
    204  * @return Error code.
    205  * @retval EOK New fibril polling the device was already started.
    206  */
    207 static int usb_device_auto_polling_internal(usb_device_t *dev,
    208     usb_endpoint_mapping_t *epm, const usb_device_auto_polling_t *polling,
    209     size_t request_size)
    210 {
    211         if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
    212                 return EBADMEM;
    213         }
    214 
    215         if (request_size == 0)
    216                 return EINVAL;
    217        
    218         if (!epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) ||
    219             (epm->pipe.direction != USB_DIRECTION_IN))
    220                 return EINVAL;
    221        
    222 
    223         polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    224         if (polling_data == NULL) {
    225                 return ENOMEM;
    226         }
    227 
    228         /* Fill-in the data. */
    229         polling_data->buffer = malloc(sizeof(request_size));
    230         if (polling_data->buffer == NULL) {
    231                 free(polling_data);
    232                 return ENOMEM;
    233         }
    234         polling_data->request_size = request_size;
    235         polling_data->dev = dev;
    236         polling_data->polling_mapping = epm;
    237 
    238         /* Copy provided settings. */
    239         polling_data->auto_polling = *polling;
    240 
    241         /* Negative value means use descriptor provided value. */
    242         if (polling->delay < 0) {
    243                 polling_data->auto_polling.delay =
    244                     epm->descriptor->poll_interval;
    245         }
    246 
    247         fid_t fibril = fibril_create(polling_fibril, polling_data);
    248         if (fibril == 0) {
    249                 free(polling_data->buffer);
    250                 free(polling_data);
    251                 return ENOMEM;
    252         }
    253         fibril_add_ready(fibril);
    254 
    255         /* Fibril launched. That fibril will free the allocated data. */
    256 
    257         return EOK;
    258 }
    259 /** Start automatic device polling over interrupt in pipe.
    260  *
    261  * The polling settings is copied thus it is okay to destroy the structure
    262  * after this function returns.
    263  *
    264  * @warning There is no guarantee when the request to the device
    265  * will be sent for the first time (it is possible that this
    266  * first request would be executed prior to return from this function).
    267  *
    268  * @param dev Device to be periodically polled.
    269187 * @param pipe_index Index of the endpoint pipe used for polling.
    270  * @param polling Polling settings.
    271  * @param req_size How many bytes to ask for in each request.
    272  * @param arg Custom argument (passed as is to the callbacks).
    273  * @return Error code.
    274  * @retval EOK New fibril polling the device was already started.
    275  */
    276 int usb_device_auto_polling(usb_device_t *usb_dev, usb_endpoint_t ep,
    277     const usb_device_auto_polling_t *polling, size_t req_size)
    278 {
    279         usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(usb_dev, ep);
    280         return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size);
    281 }
    282 
    283 /** Start automatic device polling over interrupt in pipe.
    284  *
    285  * @warning It is up to the callback to produce delays between individual
    286  * requests.
    287  *
    288  * @warning There is no guarantee when the request to the device
    289  * will be sent for the first time (it is possible that this
    290  * first request would be executed prior to return from this function).
    291  *
    292  * @param dev Device to be periodically polled.
    293  * @param ep Endpoint  used for polling.
    294188 * @param callback Callback when data are available.
    295189 * @param request_size How many bytes to ask for in each request.
    296  * @param delay NUmber of ms to wait between queries, -1 to use descriptor val.
    297190 * @param terminated_callback Callback when polling is terminated.
    298191 * @param arg Custom argument (passed as is to the callbacks).
     
    300193 * @retval EOK New fibril polling the device was already started.
    301194 */
    302 int usb_device_auto_poll(usb_device_t *dev, usb_endpoint_t ep,
    303     usb_polling_callback_t callback, size_t request_size, int delay,
     195int usb_device_auto_poll(usb_device_t *dev, size_t pipe_index,
     196    usb_polling_callback_t callback, size_t request_size,
    304197    usb_polling_terminted_callback_t terminated_callback, void *arg)
    305198{
     
    307200                .debug = 1,
    308201                .auto_clear_halt = true,
    309                 .delay = delay,
     202                .delay = 0,
    310203                .max_failures = MAX_FAILED_ATTEMPTS,
    311204                .on_data = callback,
     
    315208        };
    316209
    317         usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(dev, ep);
    318         return usb_device_auto_polling_internal(
    319             dev, epm, &auto_polling, request_size);
     210        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
     211           request_size);
    320212}
    321213
    322 int usb_device_auto_polling_desc(usb_device_t *usb_dev,
    323     const usb_endpoint_description_t *desc,
    324     const usb_device_auto_polling_t *polling, size_t req_size)
     214/** Start automatic device polling over interrupt in pipe.
     215 *
     216 * The polling settings is copied thus it is okay to destroy the structure
     217 * after this function returns.
     218 *
     219 * @warning There is no guarantee when the request to the device
     220 * will be sent for the first time (it is possible that this
     221 * first request would be executed prior to return from this function).
     222 *
     223 * @param dev Device to be periodically polled.
     224 * @param pipe_index Index of the endpoint pipe used for polling.
     225 * @param polling Polling settings.
     226 * @param request_size How many bytes to ask for in each request.
     227 * @param arg Custom argument (passed as is to the callbacks).
     228 * @return Error code.
     229 * @retval EOK New fibril polling the device was already started.
     230 */
     231int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     232    const usb_device_auto_polling_t *polling,
     233    size_t request_size)
    325234{
    326         usb_endpoint_mapping_t *epm =
    327             usb_device_get_mapped_ep_desc(usb_dev, desc);
    328         return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size);
    329 }
    330 
    331 int usb_device_auto_poll_desc(usb_device_t * usb_dev,
    332     const usb_endpoint_description_t *desc, usb_polling_callback_t callback,
    333     size_t req_size, int delay,
    334     usb_polling_terminted_callback_t terminated_callback, void *arg)
    335 {
    336         const usb_device_auto_polling_t auto_polling = {
    337                 .debug = 1,
    338                 .auto_clear_halt = true,
    339                 .delay = delay,
    340                 .max_failures = MAX_FAILED_ATTEMPTS,
    341                 .on_data = callback,
    342                 .on_polling_end = terminated_callback,
    343                 .on_error = NULL,
    344                 .arg = arg,
    345         };
    346 
    347         usb_endpoint_mapping_t *epm =
    348             usb_device_get_mapped_ep_desc(usb_dev, desc);
    349         return usb_device_auto_polling_internal(
    350             usb_dev, epm, &auto_polling, req_size);
     235        if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
     236                return EBADMEM;
     237        }
     238
     239        if (pipe_index >= dev->pipes_count || request_size == 0) {
     240                return EINVAL;
     241        }
     242        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     243            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
     244                return EINVAL;
     245        }
     246
     247        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
     248        if (polling_data == NULL) {
     249                return ENOMEM;
     250        }
     251
     252        /* Fill-in the data. */
     253        polling_data->buffer = malloc(sizeof(request_size));
     254        if (polling_data->buffer == NULL) {
     255                free(polling_data);
     256                return ENOMEM;
     257        }
     258        polling_data->request_size = request_size;
     259        polling_data->dev = dev;
     260        polling_data->pipe_index = pipe_index;
     261
     262        /* Copy provided settings. */
     263        polling_data->auto_polling = *polling;
     264
     265        /* Negative value means use descriptor provided value. */
     266        if (polling->delay < 0) {
     267                polling_data->auto_polling.delay =
     268                    (int) dev->pipes[pipe_index].descriptor->poll_interval;
     269        }
     270
     271        fid_t fibril = fibril_create(polling_fibril, polling_data);
     272        if (fibril == 0) {
     273                free(polling_data->buffer);
     274                free(polling_data);
     275                return ENOMEM;
     276        }
     277        fibril_add_ready(fibril);
     278
     279        /* Fibril launched. That fibril will free the allocated data. */
     280
     281        return EOK;
    351282}
    352283
Note: See TracChangeset for help on using the changeset viewer.