This change adds the API and some stub implementations of a new cross platform supporting event API. --- libusb/io.c | 78 ++++++++++++++++++++++++++++++++++++++++--------- libusb/libusb-1.0.def | 4 +++ libusb/libusb.h | 65 +++++++++++++++++++++++++++++++++++++++++ libusb/libusbi.h | 9 ++++-- 4 files changed, 141 insertions(+), 15 deletions(-)
diff --git a/libusb/io.c b/libusb/io.c index b27e082..67c0d8b 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -2356,43 +2356,75 @@ void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx, ctx->fd_cb_user_data = user_data; } -/* Add a file descriptor to the list of file descriptors to be monitored. - * events should be specified as a bitmask of events passed to poll(), e.g. - * POLLIN and/or POLLOUT. */ -int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) +/** \ingroup events + * Register notification functions for event object additions/removals. + * These functions will be invoked for every new or removed file descriptor + * that libusbx uses as an event source. + * + * To remove notifiers, pass NULL values for the function pointers. + * + * Note that events may have been added even before you register + * these notifiers (e.g. at libusb_init() time). + * + * Additionally, note that the removal notifier may be called during + * libusb_exit() (e.g. when it is closing file descriptors that were opened + * and added to the poll set at libusb_init() time). If you don't want this, + * remove the notifiers immediately before calling libusb_exit(). + * + * \param ctx the context to operate on, or NULL for the default context + * \param added_cb pointer to function for addition notifications + * \param removed_cb pointer to function for removal notifications + * \param user_data User data to be passed back to callbacks (useful for + * passing context information) + */ +void API_EXPORTED libusb_set_event_notifiers(libusb_context *ctx, + libusb_event_added_cb added_cb, libusb_event_removed_cb removed_cb, + void *user_data) +{ + USBI_GET_CONTEXT(ctx); + ctx->event_added_cb = added_cb; + ctx->event_removed_cb = removed_cb; + ctx->event_cb_user_data = user_data; +} + +/* Add an event handle to the list of event handles to be monitored. + * events should be specified as a bitmask of libusb_event_direction. */ +int usbi_add_event_handle(struct libusb_context *ctx, libusb_event_handle handle, short events) { struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd)); if (!ipollfd) return LIBUSB_ERROR_NO_MEM; - usbi_dbg("add fd %d events %d", fd, events); - ipollfd->pollfd.fd = fd; + usbi_dbg("add handle %d events %d", handle, events); + ipollfd->pollfd.fd = handle; ipollfd->pollfd.events = events; usbi_mutex_lock(&ctx->pollfds_lock); list_add_tail(&ipollfd->list, &ctx->pollfds); usbi_mutex_unlock(&ctx->pollfds_lock); if (ctx->fd_added_cb) - ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); + ctx->fd_added_cb(handle, events, ctx->fd_cb_user_data); + if (ctx->event_added_cb) + ctx->event_added_cb(handle, events, ctx->event_cb_user_data); return 0; } -/* Remove a file descriptor from the list of file descriptors to be polled. */ -void usbi_remove_pollfd(struct libusb_context *ctx, int fd) +/* Remove an event handle from the list of event handles to be polled. */ +void usbi_remove_event_handle(struct libusb_context *ctx, libusb_event_handle handle) { struct usbi_pollfd *ipollfd; int found = 0; - usbi_dbg("remove fd %d", fd); + usbi_dbg("remove handle %d", handle); usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) - if (ipollfd->pollfd.fd == fd) { + if (ipollfd->pollfd.fd == handle) { found = 1; break; } if (!found) { - usbi_dbg("couldn't find fd %d to remove", fd); + usbi_dbg("couldn't find fd %d to remove", handle); usbi_mutex_unlock(&ctx->pollfds_lock); return; } @@ -2401,7 +2433,9 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) usbi_mutex_unlock(&ctx->pollfds_lock); free(ipollfd); if (ctx->fd_removed_cb) - ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); + ctx->fd_removed_cb(handle, ctx->fd_cb_user_data); + if (ctx->event_removed_cb) + ctx->event_removed_cb(handle, ctx->event_cb_user_data); } /** \ingroup poll @@ -2452,6 +2486,24 @@ out: #endif } +/** \ingroup events + * Retrieve a list of events that should be polled by your main loop + * as libusbx event sources. + * + * The returned list is NULL-terminated and should be freed with free() when + * done. The actual list contents must not be touched. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns a NULL-terminated list of libusb_pollfd structures + * \returns NULL on error + */ +DEFAULT_VISIBILITY +const struct libusb_event ** LIBUSB_CALL libusb_get_events( + libusb_context *ctx) +{ + /* TODO */ +} + /* Backends may call this from handle_events to report disconnection of a * device. This function ensures transfers get cancelled appropriately. * Callers of this function must hold the events_lock. diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def index cb0e32a..fbd2fb8 100644 --- a/libusb/libusb-1.0.def +++ b/libusb/libusb-1.0.def @@ -156,3 +156,7 @@ EXPORTS libusb_unref_device@4 = libusb_unref_device libusb_wait_for_event libusb_wait_for_event@8 = libusb_wait_for_event + libusb_get_events + libusb_get_events@4 = libusb_get_events + libusb_set_event_notifiers + libusb_set_event_notifiers@16 = libusb_set_event_notifiers diff --git a/libusb/libusb.h b/libusb/libusb.h index 5e1c23c..2c08aa7 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1934,6 +1934,71 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle handle); +/** \ingroup events + * Platform specific event handle type. + */ +#if defined(_WIN32) || defined(_WIN32_WCE) +typedef HANDLE libusb_event_handle; +#else +/* All other platforms, including cygwin, use fds */ +typedef int libusb_event_handle; +#endif + +/** \ingroup events + * The direction that a libusb_event_handle should be monitored for + * activity. + */ +enum libusb_event_direction { + /** The event handle doesn't have the concept of a direction. */ + LIBUSB_EVENT_DIR_NONE = 0x0, + /** Monitoring for incoming data, e.g. reading */ + LIBUSB_EVENT_DIR_IN = 0x1, + /** Monitoring for outgoing data, e.g. write */ + LIBUSB_EVENT_DIR_OUT = 0x2, + /** Monitoring for incoming or outgoing data, e.g. read or write */ + LIBUSB_EVENT_DIR_BOTH = (LIBUSB_EVENT_DIR_IN | LIBUSB_EVENT_DIR_OUT) +}; + +/** \ingroup events + * Event description for polling + */ +struct libusb_event { + libusb_event_handle handle; + enum libusb_event_direction direction; +}; + +/** \ingroup events + * Callback function, invoked when a new file descriptor should be added + * to the set of file descriptors monitored for events. + * \param fd the new file descriptor + * \param events events to monitor for, see \ref libusb_pollfd for a + * description + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_event_added_cb)(libusb_event_handle handle, + enum libusb_event_direction direction, void *user_data); + +/** \ingroup poll + * Callback function, invoked when a file descriptor should be removed from + * the set of file descriptors being monitored for events. After returning + * from this callback, do not use that file descriptor again. + * \param fd the file descriptor to stop monitoring + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_event_removed_cb)(libusb_event_handle handle, + void *user_data); + +const struct libusb_event ** LIBUSB_CALL libusb_get_events( + libusb_context *ctx); +void LIBUSB_CALL libusb_set_event_notifiers(libusb_context *ctx, + libusb_event_added_cb added_cb, libusb_event_removed_cb removed_cb, + void *user_data); + + #ifdef __cplusplus } #endif diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 7293901..e72d9ad 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -259,6 +259,11 @@ struct libusb_context { libusb_pollfd_removed_cb fd_removed_cb; void *fd_cb_user_data; + /* user callbacks for event changes */ + libusb_event_added_cb event_added_cb; + libusb_event_removed_cb event_removed_cb; + void *event_cb_user_data; + /* ensures that only one thread is handling events at any one time */ usbi_mutex_t events_lock; @@ -464,8 +469,8 @@ struct usbi_pollfd { struct list_head list; }; -int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); -void usbi_remove_pollfd(struct libusb_context *ctx, int fd); +int usbi_add_event_handle(struct libusb_context *ctx, libusb_event_handle handle, short events); +void usbi_remove_event_handle(struct libusb_context *ctx, libusb_event_handle handle); void usbi_fd_notification(struct libusb_context *ctx); /* device discovery */ -- 1.7.9.5 ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ libusbx-devel mailing list libusbx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libusbx-devel