This change makes the internals of libusb make use of the libusb_event_handle typedef instead of int when dealing with file descriptors. --- libusb/io.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++------- libusb/libusb.h | 5 ++- libusb/libusbi.h | 10 ++--- 3 files changed, 116 insertions(+), 22 deletions(-)
diff --git a/libusb/io.c b/libusb/io.c index 67c0d8b..314184f 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1860,6 +1860,27 @@ out: } #endif +/* Maps the bitmaps in libusb_event_direction into poll() directions */ +static int event_dirs_to_poll_events(enum libusb_event_direction dir) +{ + int ret = 0; + if ((dir & LIBUSB_EVENT_DIR_IN) == LIBUSB_EVENT_DIR_IN) + ret |= POLLIN; + if ((dir & LIBUSB_EVENT_DIR_OUT) == LIBUSB_EVENT_DIR_OUT) + ret |= POLLOUT; + return ret; +} +/* Maps the bitmaps in libusb_event_direction into poll() directions */ +static enum libusb_event_direction poll_events_to_event_dirs(short events) +{ + enum libusb_event_direction ret = 0; + if ((events & POLLIN) == POLLIN) + ret |= LIBUSB_EVENT_DIR_IN; + if ((events & POLLOUT) == POLLOUT) + ret |= LIBUSB_EVENT_DIR_OUT; + return ret; +} + /* do the actual event handling. assumes that no other thread is concurrently * doing the same thing. */ static int handle_events(struct libusb_context *ctx, struct timeval *tv) @@ -1884,11 +1905,11 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) } list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) { - struct libusb_pollfd *pollfd = &ipollfd->pollfd; - int fd = pollfd->fd; + struct libusb_event *pollfd = &ipollfd->pollfd; + libusb_event_handle fd = pollfd->handle; i++; fds[i].fd = fd; - fds[i].events = pollfd->events; + fds[i].events = event_dirs_to_poll_events(pollfd->direction); fds[i].revents = 0; } usbi_mutex_unlock(&ctx->pollfds_lock); @@ -2389,28 +2410,30 @@ void API_EXPORTED libusb_set_event_notifiers(libusb_context *ctx, /* 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) +int usbi_add_pollfd(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 handle %d events %d", handle, events); - ipollfd->pollfd.fd = handle; - ipollfd->pollfd.events = events; + ipollfd->pollfd.handle = handle; + ipollfd->pollfd.direction = poll_events_to_event_dirs(events); usbi_mutex_lock(&ctx->pollfds_lock); list_add_tail(&ipollfd->list, &ctx->pollfds); usbi_mutex_unlock(&ctx->pollfds_lock); +#ifdef LIBUSB_EVENT_HANDLE_IS_FD if (ctx->fd_added_cb) ctx->fd_added_cb(handle, events, ctx->fd_cb_user_data); +#endif if (ctx->event_added_cb) ctx->event_added_cb(handle, events, ctx->event_cb_user_data); return 0; } /* 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) +void usbi_remove_pollfd(struct libusb_context *ctx, libusb_event_handle handle) { struct usbi_pollfd *ipollfd; int found = 0; @@ -2418,7 +2441,7 @@ void usbi_remove_event_handle(struct libusb_context *ctx, libusb_event_handle ha 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 == handle) { + if (ipollfd->pollfd.handle == handle) { found = 1; break; } @@ -2432,8 +2455,10 @@ void usbi_remove_event_handle(struct libusb_context *ctx, libusb_event_handle ha list_del(&ipollfd->list); usbi_mutex_unlock(&ctx->pollfds_lock); free(ipollfd); +#ifdef LIBUSB_EVENT_HANDLE_IS_FD if (ctx->fd_removed_cb) ctx->fd_removed_cb(handle, ctx->fd_cb_user_data); +#endif if (ctx->event_removed_cb) ctx->event_removed_cb(handle, ctx->event_cb_user_data); } @@ -2457,23 +2482,41 @@ DEFAULT_VISIBILITY const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( libusb_context *ctx) { -#ifndef OS_WINDOWS +#ifdef LIBUSB_EVENT_HANDLE_IS_FD struct libusb_pollfd **ret = NULL; + struct libusb_pollfd * current = NULL; struct usbi_pollfd *ipollfd; size_t i = 0; size_t cnt = 0; + size_t alloc_size = 0; USBI_GET_CONTEXT(ctx); usbi_mutex_lock(&ctx->pollfds_lock); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) cnt++; - ret = calloc(cnt + 1, sizeof(struct libusb_pollfd *)); + /* Allocate enough space for the pointers and the libusb_event + * structures after the last pointer. */ + alloc_size = ((cnt + 1) * sizeof(struct libusb_pollfd *)) + + (cnt * sizeof(struct libusb_pollfd)); + ret = calloc(1, alloc_size); if (!ret) goto out; + /* Calculate the place after all the pointers for the contents of + * the structures. */ + current = (struct libusb_pollfd*) + (((uint8_t*)ret) + ((cnt + 1) * sizeof(struct libusb_pollfd *))); list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) - ret[i++] = (struct libusb_pollfd *) ipollfd; + { + ret[i] = current; + /* Convert from libusb_event to libusb_pollfd */ + current->fd = ipollfd->pollfd.handle; + current->events = event_dirs_to_poll_events(ipollfd->pollfd.direction); + /* Move to the next pointer and structure location */ + ++current; + ++i; + } ret[cnt] = NULL; out: @@ -2481,7 +2524,7 @@ out: return (const struct libusb_pollfd **) ret; #else usbi_err(ctx, "external polling of libusbx's internal descriptors "\ - "is not yet supported on Windows platforms"); + "is not supported on Windows platforms"); return NULL; #endif } @@ -2490,18 +2533,66 @@ out: * 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. + * The returned list is NULL-terminated and should be freed with libusb_destroy_events() when + * done. * * \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( +struct libusb_event ** LIBUSB_CALL libusb_get_events( libusb_context *ctx) { - /* TODO */ + struct libusb_event **ret = NULL; + struct libusb_event * current = NULL; + struct usbi_pollfd *ipollfd; + size_t i = 0; + size_t cnt = 0; + size_t alloc_size = 0; + USBI_GET_CONTEXT(ctx); + + usbi_mutex_lock(&ctx->pollfds_lock); + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) + cnt++; + + /* Allocate enough space for the pointers and the libusb_event + * structures after the last pointer. */ + alloc_size = ((cnt + 1) * sizeof(struct libusb_event *)) + + (cnt * sizeof(struct libusb_event)); + ret = calloc(1, alloc_size); + if (!ret) + goto out; + /* Work out where the first libusb_event should be placed */ + current = (struct libusb_event*) + (((uint8_t*)ret) + ((cnt + 1) * sizeof(struct libusb_event *))); + + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) + { + ret[i] = current; + *current = ipollfd->pollfd; + /* Move to the next pointer and structure location */ + ++current; + ++i; + } + ret[cnt] = NULL; + +out: + usbi_mutex_unlock(&ctx->pollfds_lock); + return ret; +} + +/** \ingroup events + * Frees a list of events provided by libusb_get_events(). + * + * \param ctx the context to operate on, or NULL for the default context + * \param events the event list to destroy + */ +DEFAULT_VISIBILITY +void LIBUSB_CALL libusb_destroy_events(libusb_context* ctx, + struct libusb_event ** events) +{ + free(events); } /* Backends may call this from handle_events to report disconnection of a diff --git a/libusb/libusb.h b/libusb/libusb.h index 2c08aa7..a09e36d 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -1941,6 +1941,7 @@ void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, typedef HANDLE libusb_event_handle; #else /* All other platforms, including cygwin, use fds */ +#define LIBUSB_EVENT_HANDLE_IS_FD typedef int libusb_event_handle; #endif @@ -1992,8 +1993,10 @@ typedef void (LIBUSB_CALL *libusb_event_added_cb)(libusb_event_handle handle, typedef void (LIBUSB_CALL *libusb_event_removed_cb)(libusb_event_handle handle, void *user_data); -const struct libusb_event ** LIBUSB_CALL libusb_get_events( +struct libusb_event ** LIBUSB_CALL libusb_get_events( libusb_context *ctx); +void LIBUSB_CALL libusb_destroy_events( + libusb_context* ctx, struct libusb_event ** events); 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); diff --git a/libusb/libusbi.h b/libusb/libusbi.h index e72d9ad..7c4f1f1 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -223,7 +223,7 @@ struct libusb_context { /* internal control pipe, used for interrupting event handling when * something needs to modify poll fds. */ - int ctrl_pipe[2]; + libusb_event_handle ctrl_pipe[2]; struct list_head usb_devs; usbi_mutex_t usb_devs_lock; @@ -236,7 +236,7 @@ struct libusb_context { /* A list of registered hotplug callbacks */ struct list_head hotplug_cbs; usbi_mutex_t hotplug_cbs_lock; - int hotplug_pipe[2]; + libusb_event_handle hotplug_pipe[2]; /* this is a list of in-flight transfer handles, sorted by timeout * expiration. URBs to timeout the soonest are placed at the beginning of @@ -464,13 +464,13 @@ int usbi_gettimeofday(struct timeval *tp, void *tzp); struct usbi_pollfd { /* must come first */ - struct libusb_pollfd pollfd; + struct libusb_event pollfd; struct list_head list; }; -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); +int usbi_add_pollfd(struct libusb_context *ctx, libusb_event_handle handle, short events); +void usbi_remove_pollfd(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