diff options
author | Chris Dickens <christopher.a.dickens@gmail.com> | 2015-01-20 22:49:59 -0800 |
---|---|---|
committer | Chris Dickens <christopher.a.dickens@gmail.com> | 2015-01-20 22:49:59 -0800 |
commit | fec3f8c6de4683f7107d5b68dd887c7c192ab0c0 (patch) | |
tree | 79bdf29227eabee935fde364d264f240ceea2f3c | |
parent | 127e0c3e22e64d752b2ad9091400e921f0f623b7 (diff) | |
download | libusb-fec3f8c6de4683f7107d5b68dd887c7c192ab0c0.tar.gz |
core: Add alternative API for backends to handle transfer completion
Currently all non-Linux POSIX backends emulate the Linux design of
having individual pollable file descriptors for each device. This
patch introduces a new internal API that allows backends to handle
transfer completion notification in a different way.
A new function, usbi_signal_transfer_completion(), is added. Each
backend can call this function when it detects a transfer has
completed. This function will place the transfer on a new
completed_transfers list and will signal the context's event.
Backends that use this new API will no longer provide a handle_events()
function but instead provide a handle_transfer_completion() function.
When a thread is doing event handling, it will call this backend
function for all transfers on the completed_transfers list.
With this change, backends that do not really have natively pollable
file descriptors can completely move away from this design and avoid
poll() altogether.
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r-- | libusb/libusbi.h | 42 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
2 files changed, 40 insertions, 4 deletions
diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 6d25884..757e1ec 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -303,6 +303,9 @@ struct libusb_context { /* A list of pending hotplug messages. Protected by event_data_lock. */ struct list_head hotplug_msgs; + /* A list of pending completed transfers. Protected by event_data_lock. */ + struct list_head completed_transfers; + #ifdef USBI_TIMERFD_AVAILABLE /* used for timeout handling, if supported by OS. * this timerfd is maintained to trigger on the next pending timeout */ @@ -314,7 +317,8 @@ struct libusb_context { /* Update the following macro if new event sources are added */ #define usbi_pending_events(ctx) \ - ((ctx)->device_close || (ctx)->pollfds_modified || !list_empty(&(ctx)->hotplug_msgs)) + ((ctx)->device_close || (ctx)->pollfds_modified \ + || !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers)) #ifdef USBI_TIMERFD_AVAILABLE #define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) @@ -460,6 +464,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle); int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status); int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer); +void usbi_signal_transfer_completion(struct usbi_transfer *transfer); int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, void *dest, int host_endian); @@ -971,8 +976,14 @@ struct usbi_os_backend { */ void (*clear_transfer_priv)(struct usbi_transfer *itransfer); - /* Handle any pending events. This involves monitoring any active - * transfers and processing their completion or cancellation. + /* Handle any pending events on file descriptors. Optional. + * + * Provide this function when file descriptors directly indicate device + * or transfer activity. If your backend does not have such file descriptors, + * implement the handle_transfer_completion function below. + * + * This involves monitoring any active transfers and processing their + * completion or cancellation. * * The function is passed an array of pollfd structures (size nfds) * as a result of the poll() system call. The num_ready parameter @@ -1000,6 +1011,31 @@ struct usbi_os_backend { int (*handle_events)(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); + /* Handle transfer completion. Optional. + * + * Provide this function when there are no file descriptors available + * that directly indicate device or transfer activity. If your backend does + * have such file descriptors, implement the handle_events function above. + * + * Your backend must tell the library when a transfer has completed by + * calling usbi_signal_transfer_completion(). You should store any private + * information about the transfer and its completion status in the transfer's + * private backend data. + * + * During event handling, this function will be called on each transfer for + * which usbi_signal_transfer_completion() was called. + * + * For any cancelled transfers, call usbi_handle_transfer_cancellation(). + * For completed transfers, call usbi_handle_transfer_completion(). + * For control/bulk/interrupt transfers, populate the "transferred" + * element of the appropriate usbi_transfer structure before calling the + * above functions. For isochronous transfers, populate the status and + * transferred fields of the iso packet descriptors of the transfer. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*handle_transfer_completion)(struct usbi_transfer *itransfer); + /* Get time from specified clock. At least two clocks must be implemented by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 395ea13..1006d74 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10949 +#define LIBUSB_NANO 10950 |