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
[email protected]
https://lists.sourceforge.net/lists/listinfo/libusbx-devel