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

Reply via email to