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

Reply via email to