diff options
author | Pete Batard <pbatard@gmail.com> | 2010-06-10 17:00:25 -0500 |
---|---|---|
committer | Daniel Drake <dan@reactivated.net> | 2010-06-10 17:00:25 -0500 |
commit | a7c056c14867e1cc3ef83682f2706cdbdca7c4ce (patch) | |
tree | c6e7e60bafbac67b581b500ba4289787cca65480 /libusb/core.c | |
parent | fc0af8e3f76925ad09e0fbc6d233d500753ee375 (diff) | |
download | libusbx-a7c056c14867e1cc3ef83682f2706cdbdca7c4ce.tar.gz |
Factorize event handler interruption code
This will be additionally used by the windows backend which modifies
the fd set frequently.
Diffstat (limited to 'libusb/core.c')
-rw-r--r-- | libusb/core.c | 79 |
1 files changed, 45 insertions, 34 deletions
diff --git a/libusb/core.c b/libusb/core.c index 08c23fa..227219b 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -845,6 +845,50 @@ API_EXPORTED void libusb_unref_device(libusb_device *dev) } } +/* + * Interrupt the iteration of the event handling thread, so that it picks + * up the new fd. + */ +void usbi_fd_notification(struct libusb_context *ctx) +{ + unsigned char dummy = 1; + ssize_t r; + + if (ctx == NULL) + return; + + /* record that we are messing with poll fds */ + usbi_mutex_lock(&ctx->pollfd_modify_lock); + ctx->pollfd_modify++; + usbi_mutex_unlock(&ctx->pollfd_modify_lock); + + /* write some data on control pipe to interrupt event handlers */ + r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); + if (r <= 0) { + usbi_warn(ctx, "internal signalling write failed"); + usbi_mutex_lock(&ctx->pollfd_modify_lock); + ctx->pollfd_modify--; + usbi_mutex_unlock(&ctx->pollfd_modify_lock); + return; + } + + /* take event handling lock */ + libusb_lock_events(ctx); + + /* read the dummy data */ + r = usbi_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); + if (r <= 0) + usbi_warn(ctx, "internal signalling read failed"); + + /* we're done with modifying poll fds */ + usbi_mutex_lock(&ctx->pollfd_modify_lock); + ctx->pollfd_modify--; + usbi_mutex_unlock(&ctx->pollfd_modify_lock); + + /* Release event handling lock and wake up event waiters */ + libusb_unlock_events(ctx); +} + /** \ingroup dev * Open a device and obtain a device handle. A handle allows you to perform * I/O on the device in question. @@ -869,9 +913,7 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) struct libusb_context *ctx = DEVICE_CTX(dev); struct libusb_device_handle *_handle; size_t priv_size = usbi_backend->device_handle_priv_size; - unsigned char dummy = 1; int r; - ssize_t tmp; usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); _handle = malloc(sizeof(*_handle) + priv_size); @@ -901,44 +943,13 @@ API_EXPORTED int libusb_open(libusb_device *dev, libusb_device_handle **handle) usbi_mutex_unlock(&ctx->open_devs_lock); *handle = _handle; - /* At this point, we want to interrupt any existing event handlers so * that they realise the addition of the new device's poll fd. One * example when this is desirable is if the user is running a separate * dedicated libusb events handling thread, which is running with a long * or infinite timeout. We want to interrupt that iteration of the loop, * so that it picks up the new fd, and then continues. */ - - /* record that we are messing with poll fds */ - usbi_mutex_lock(&ctx->pollfd_modify_lock); - ctx->pollfd_modify++; - usbi_mutex_unlock(&ctx->pollfd_modify_lock); - - /* write some data on control pipe to interrupt event handlers */ - tmp = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); - if (tmp <= 0) { - usbi_warn(ctx, "internal signalling write failed"); - usbi_mutex_lock(&ctx->pollfd_modify_lock); - ctx->pollfd_modify--; - usbi_mutex_unlock(&ctx->pollfd_modify_lock); - return 0; - } - - /* take event handling lock */ - libusb_lock_events(ctx); - - /* read the dummy data */ - tmp = read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); - if (tmp <= 0) - usbi_warn(ctx, "internal signalling read failed"); - - /* we're done with modifying poll fds */ - usbi_mutex_lock(&ctx->pollfd_modify_lock); - ctx->pollfd_modify--; - usbi_mutex_unlock(&ctx->pollfd_modify_lock); - - /* Release event handling lock and wake up event waiters */ - libusb_unlock_events(ctx); + usbi_fd_notification(ctx); return 0; } |