struct pollfd *fds = NULL;
int i = -1;
int timeout_ms;
- int special_event;
/* prevent attempts to recursively handle events (e.g. calling into
* libusb_handle_events() from within a hotplug or transfer callback) */
if (tv->tv_usec % 1000)
timeout_ms++;
-redo_poll:
usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms);
r = usbi_poll(fds, nfds, timeout_ms);
usbi_dbg("poll() returned %d", r);
if (r == 0) {
r = handle_timeouts(ctx);
goto done;
- }
- else if (r == -1 && errno == EINTR) {
+ } else if (r == -1 && errno == EINTR) {
r = LIBUSB_ERROR_INTERRUPTED;
goto done;
- }
- else if (r < 0) {
+ } else if (r < 0) {
usbi_err(ctx, "poll failed %d err=%d", r, errno);
r = LIBUSB_ERROR_IO;
goto done;
}
- special_event = 0;
-
/* fds[0] is always the event pipe */
if (fds[0].revents) {
- libusb_hotplug_message *message = NULL;
+ struct list_head hotplug_msgs;
struct usbi_transfer *itransfer;
int ret = 0;
+ list_init(&hotplug_msgs);
+
usbi_dbg("caught a fish on the event pipe");
/* take the the event data lock while processing events */
/* check for any pending hotplug messages */
if (!list_empty(&ctx->hotplug_msgs)) {
usbi_dbg("hotplug message received");
- special_event = 1;
- message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list);
- list_del(&message->list);
+ list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
}
/* complete any pending transfers */
usbi_mutex_unlock(&ctx->event_data_lock);
- /* process the hotplug message, if any */
- if (message) {
+ /* process the hotplug messages, if any */
+ while (!list_empty(&hotplug_msgs)) {
+ libusb_hotplug_message *message =
+ list_first_entry(&hotplug_msgs, libusb_hotplug_message, list);
+
usbi_hotplug_match(ctx, message->device, message->event);
/* the device left, dereference the device */
if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event)
libusb_unref_device(message->device);
+ list_del(&message->list);
free(message);
}
}
if (0 == --r)
- goto handled;
+ goto done;
}
#ifdef USBI_TIMERFD_AVAILABLE
/* timerfd indicates that a timeout has expired */
int ret;
usbi_dbg("timerfd triggered");
- special_event = 1;
ret = handle_timerfd_trigger(ctx);
if (ret < 0) {
}
if (0 == --r)
- goto handled;
+ goto done;
}
#endif
if (r)
usbi_err(ctx, "backend handle_events failed with error %d", r);
-handled:
- if (r == 0 && special_event) {
- timeout_ms = 0;
- goto redo_poll;
- }
-
done:
usbi_end_event_handling(ctx);
return r;