Blob Blame History Raw
From 3daf9625c7f9212a762927239b2f0f14d68f4361 Mon Sep 17 00:00:00 2001
From: Chris Dickens <christopher.a.dickens@gmail.com>
Date: Thu, 10 Dec 2015 00:20:18 -0800
Subject: [PATCH 2/3] API: Add libusb_interrupt_event_handler() function

This new function will allow the user to purposely interrupt an
event handling thread, causing it to return from the event handling
function. This is mainly useful for cleanly exiting from a dedicated
event handling thread during application shutdown.

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
---
 libusb/io.c           | 28 ++++++++++++++++++++++++++++
 libusb/libusb-1.0.def |  2 ++
 libusb/libusb.h       |  3 ++-
 libusb/libusbi.h      |  3 +++
 libusb/version_nano.h |  2 +-
 5 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/libusb/io.c b/libusb/io.c
index ce0abb9..bc85438 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1848,6 +1848,29 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
 }
 
 /** \ingroup poll
+ * Interrupt any active thread that is handling events. This is mainly useful
+ * for interrupting a dedicated event handling thread when an application
+ * wishes to call libusb_exit().
+ *
+ * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105
+ *
+ * \param ctx the context to operate on, or NULL for the default context
+ * \ref mtasync
+ */
+void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
+{
+	USBI_GET_CONTEXT(ctx);
+
+	usbi_dbg("");
+	usbi_mutex_lock(&ctx->event_data_lock);
+	if (!usbi_pending_events(ctx)) {
+		ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
+		usbi_signal_event(ctx);
+	}
+	usbi_mutex_unlock(&ctx->event_data_lock);
+}
+
+/** \ingroup poll
  * Acquire the event waiters lock. This lock is designed to be obtained under
  * the situation where you want to be aware when events are completed, but
  * some other thread is event handling so calling libusb_handle_events() is not
@@ -2128,6 +2151,11 @@ redo_poll:
 		if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED)
 			usbi_dbg("someone updated the poll fds");
 
+		if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) {
+			usbi_dbg("someone purposely interrupted");
+			ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
+		}
+
 		/* check if someone is closing a device */
 		if (ctx->device_close)
 			usbi_dbg("someone is closing a device");
diff --git a/libusb/libusb-1.0.def b/libusb/libusb-1.0.def
index cbcf3e9..050b4b9 100644
--- a/libusb/libusb-1.0.def
+++ b/libusb/libusb-1.0.def
@@ -116,6 +116,8 @@ EXPORTS
   libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
   libusb_init
   libusb_init@4 = libusb_init
+  libusb_interrupt_event_handler
+  libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler
   libusb_interrupt_transfer
   libusb_interrupt_transfer@24 = libusb_interrupt_transfer
   libusb_kernel_driver_active
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 513945f..ba82c36 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -141,7 +141,7 @@ typedef unsigned __int32  uint32_t;
  * Internally, LIBUSB_API_VERSION is defined as follows:
  * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
  */
-#define LIBUSB_API_VERSION 0x01000104
+#define LIBUSB_API_VERSION 0x01000105
 
 /* The following is kept for compatibility, but will be deprecated in the future */
 #define LIBUSBX_API_VERSION LIBUSB_API_VERSION
@@ -1801,6 +1801,7 @@ void LIBUSB_CALL libusb_lock_events(libusb_context *ctx);
 void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx);
 int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx);
 int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx);
+void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx);
 void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx);
 void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx);
 int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv);
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 40ae608..a39cbe1 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -319,6 +319,9 @@ struct libusb_context {
 enum usbi_event_flags {
 	/* The list of pollfds has been modified */
 	USBI_EVENT_POLLFDS_MODIFIED = 1 << 0,
+
+	/* The user has interrupted the event handler */
+	USBI_EVENT_USER_INTERRUPT = 1 << 1,
 };
 
 /* Update the following macro if new event sources are added */
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 7abae0e..ea79210 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11005
+#define LIBUSB_NANO 11006
-- 
2.7.4