From 192adf437baec398bec36de50737a570e6c2f29c Mon Sep 17 00:00:00 2001 From: Chris Dickens Date: Mon, 17 Nov 2014 23:53:11 -0800 Subject: core: Add helper functions to signal and clear the event pipe Signed-off-by: Chris Dickens --- libusb/core.c | 60 ++++++++++++++++++++++++++++++++++----------------- libusb/io.c | 10 ++------- libusb/libusbi.h | 3 +++ libusb/version_nano.h | 2 +- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/libusb/core.c b/libusb/core.c index 042f7a5..32db2a6 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1172,18 +1172,50 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) } /* - * Interrupt the iteration of the event handling thread, so that it picks - * up the new fd. + * Signal the event pipe so that the event handling thread will be + * interrupted to process an internal event. */ -void usbi_fd_notification(struct libusb_context *ctx) +int usbi_signal_event(struct libusb_context *ctx) { unsigned char dummy = 1; ssize_t r; /* write some data on event pipe to interrupt event handlers */ r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy)); - if (r != sizeof(dummy)) + if (r != sizeof(dummy)) { usbi_warn(ctx, "internal signalling write failed"); + return LIBUSB_ERROR_IO; + } + + return 0; +} + +/* + * Clear the event pipe so that the event handling will no longer be + * interrupted. + */ +int usbi_clear_event(struct libusb_context *ctx) +{ + unsigned char dummy; + ssize_t r; + + /* read some data on event pipe to clear it */ + r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy)); + if (r != sizeof(dummy)) { + usbi_warn(ctx, "internal signalling read failed"); + return LIBUSB_ERROR_IO; + } + + return 0; +} + +/* + * Interrupt the iteration of the event handling thread, so that it picks + * up the new fd. + */ +void usbi_fd_notification(struct libusb_context *ctx) +{ + usbi_signal_event(ctx); } /** \ingroup dev @@ -1384,8 +1416,6 @@ static void do_close(struct libusb_context *ctx, void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) { struct libusb_context *ctx; - unsigned char dummy = 1; - ssize_t r; if (!dev_handle) return; @@ -1404,24 +1434,14 @@ void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) ctx->device_close++; usbi_mutex_unlock(&ctx->event_data_lock); - /* write some data on event pipe to interrupt event handlers */ - r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy)); - if (r <= 0) { - usbi_warn(ctx, "internal signalling write failed, closing anyway"); - do_close(ctx, dev_handle); - usbi_mutex_lock(&ctx->event_data_lock); - ctx->device_close--; - usbi_mutex_unlock(&ctx->event_data_lock); - return; - } + /* signal the event pipe to interrupt event handlers */ + usbi_signal_event(ctx); /* take event handling lock */ libusb_lock_events(ctx); - /* read the dummy data */ - r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) - usbi_warn(ctx, "internal signalling read failed, closing anyway"); + /* clear the event pipe */ + usbi_clear_event(ctx); /* Close the device */ do_close(ctx, dev_handle); diff --git a/libusb/io.c b/libusb/io.c index 97af568..f00af14 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -2051,8 +2051,6 @@ redo_poll: /* another thread wanted to interrupt event handling, and it succeeded! * handle any other events that cropped up at the same time, and * simply return */ - ssize_t ret; - unsigned char dummy; unsigned int ru; usbi_dbg("caught a fish on the event pipe"); @@ -2063,13 +2061,9 @@ redo_poll: ru = ctx->device_close; usbi_mutex_unlock(&ctx->event_data_lock); if (!ru) { - ret = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy)); - if (ret != sizeof(dummy)) { - usbi_err(ctx, "event pipe read error %d err=%d", - ret, errno); - r = LIBUSB_ERROR_OTHER; + r = usbi_clear_event(ctx); + if (r) goto handled; - } } if (0 == --r) diff --git a/libusb/libusbi.h b/libusb/libusbi.h index cdcc61a..ebcc0d3 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -462,6 +462,9 @@ int usbi_get_config_index_by_value(struct libusb_device *dev, void usbi_connect_device (struct libusb_device *dev); void usbi_disconnect_device (struct libusb_device *dev); +int usbi_signal_event(struct libusb_context *ctx); +int usbi_clear_event(struct libusb_context *ctx); + /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ #if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU) #include diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b41fc42..73d2ed1 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10935 +#define LIBUSB_NANO 10936 -- cgit v1.2.3