libusb 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +1 -0
  5. data/History.md +8 -0
  6. data/README.md +5 -15
  7. data/Rakefile +8 -1
  8. data/ext/extconf.rb +49 -12
  9. data/ext/{libusb-1.0.19 → libusb-1.0.20}/AUTHORS +12 -1
  10. data/ext/{libusb-1.0.19 → libusb-1.0.20}/COPYING +0 -0
  11. data/ext/{libusb-1.0.19 → libusb-1.0.20}/ChangeLog +18 -2
  12. data/ext/{libusb-1.0.19 → libusb-1.0.20}/INSTALL +0 -0
  13. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Makefile.am +0 -0
  14. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Makefile.in +31 -18
  15. data/ext/{libusb-1.0.19 → libusb-1.0.20}/NEWS +0 -0
  16. data/ext/{libusb-1.0.19 → libusb-1.0.20}/PORTING +0 -0
  17. data/ext/{libusb-1.0.19 → libusb-1.0.20}/README +5 -3
  18. data/ext/{libusb-1.0.19 → libusb-1.0.20}/TODO +0 -0
  19. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/common.xcconfig +0 -0
  20. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/config.h +0 -0
  21. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/debug.xcconfig +0 -0
  22. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb.xcconfig +0 -0
  23. data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +865 -0
  24. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb_debug.xcconfig +0 -0
  25. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb_release.xcconfig +0 -0
  26. data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/release.xcconfig +0 -0
  27. data/ext/{libusb-1.0.19 → libusb-1.0.20}/aclocal.m4 +35 -32
  28. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/README +0 -0
  29. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/config.h +0 -0
  30. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/Android.mk +0 -0
  31. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/Application.mk +0 -0
  32. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/examples.mk +0 -0
  33. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/libusb.mk +0 -0
  34. data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/tests.mk +0 -0
  35. data/ext/{libusb-1.0.19 → libusb-1.0.20}/compile +1 -1
  36. data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.guess +13 -160
  37. data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.h.in +6 -0
  38. data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.sub +26 -12
  39. data/ext/{libusb-1.0.19 → libusb-1.0.20}/configure +244 -20
  40. data/ext/{libusb-1.0.19 → libusb-1.0.20}/configure.ac +27 -4
  41. data/ext/{libusb-1.0.19 → libusb-1.0.20}/depcomp +1 -1
  42. data/ext/{libusb-1.0.19 → libusb-1.0.20}/doc/Makefile.am +0 -0
  43. data/ext/{libusb-1.0.19 → libusb-1.0.20}/doc/Makefile.in +19 -6
  44. data/ext/libusb-1.0.20/doc/doxygen.cfg.in +2334 -0
  45. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/Makefile.am +0 -0
  46. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/Makefile.in +19 -6
  47. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/dpfp.c +0 -0
  48. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/dpfp_threaded.c +15 -10
  49. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/ezusb.c +0 -0
  50. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/ezusb.h +0 -0
  51. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/fxload.c +28 -7
  52. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt1.c +0 -0
  55. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/hotplugtest.c +21 -3
  56. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/listdevs.c +0 -0
  57. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/sam3u_benchmark.c +0 -0
  58. data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/xusb.c +2 -1
  59. data/ext/{libusb-1.0.19 → libusb-1.0.20}/install-sh +170 -196
  60. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb-1.0.pc.in +0 -0
  61. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/Makefile.am +15 -0
  62. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/Makefile.in +192 -53
  63. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/core.c +218 -100
  64. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/descriptor.c +3 -1
  65. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/hotplug.c +26 -9
  66. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/hotplug.h +8 -0
  67. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/io.c +432 -290
  68. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb-1.0.def +2 -0
  69. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb-1.0.rc +0 -0
  70. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb.h +11 -10
  71. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusbi.h +106 -29
  72. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/darwin_usb.c +27 -67
  73. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/darwin_usb.h +3 -7
  74. data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +5 -0
  75. data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +810 -0
  76. data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +1193 -0
  77. data/ext/libusb-1.0.20/libusb/os/haiku/compile +347 -0
  78. data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +1421 -0
  79. data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +1807 -0
  80. data/ext/libusb-1.0.20/libusb/os/haiku/configure +17579 -0
  81. data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +8 -0
  82. data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +791 -0
  83. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +378 -0
  84. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +112 -0
  85. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +550 -0
  86. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +255 -0
  87. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +180 -0
  88. data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +501 -0
  89. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/ltmain.sh +0 -0
  90. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/libtool.m4 +0 -0
  91. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltoptions.m4 +0 -0
  92. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltsugar.m4 +0 -0
  93. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltversion.m4 +0 -0
  94. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/lt~obsolete.m4 +0 -0
  95. data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/missing +1 -1
  96. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_netlink.c +4 -4
  97. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_udev.c +1 -2
  98. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_usbfs.c +46 -49
  99. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_usbfs.h +1 -1
  100. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/netbsd_usb.c +9 -73
  101. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/openbsd_usb.c +9 -73
  102. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_posix.c +2 -0
  103. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_posix.h +0 -0
  104. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_windows.c +3 -1
  105. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_windows.h +0 -0
  106. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_posix.c +3 -3
  107. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_posix.h +0 -0
  108. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_windows.c +3 -1
  109. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_windows.h +0 -0
  110. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/wince_usb.c +87 -250
  111. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/wince_usb.h +0 -0
  112. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_common.h +1 -1
  113. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_usb.c +267 -181
  114. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_usb.h +22 -7
  115. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/strerror.c +5 -2
  116. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/sync.c +2 -1
  117. data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/version.h +1 -1
  118. data/ext/libusb-1.0.20/libusb/version_nano.h +1 -0
  119. data/ext/libusb-1.0.20/ltmain.sh +9655 -0
  120. data/ext/libusb-1.0.20/m4/libtool.m4 +7992 -0
  121. data/ext/libusb-1.0.20/m4/ltoptions.m4 +384 -0
  122. data/ext/libusb-1.0.20/m4/ltsugar.m4 +123 -0
  123. data/ext/libusb-1.0.20/m4/ltversion.m4 +23 -0
  124. data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +98 -0
  125. data/ext/libusb-1.0.20/missing +215 -0
  126. data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/Makefile.am +0 -0
  127. data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/Makefile.in +19 -6
  128. data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/libusb_testlib.h +0 -0
  129. data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/stress.c +0 -0
  130. data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/testlib.c +0 -0
  131. data/lib/libusb.rb +1 -0
  132. data/lib/libusb/call.rb +1 -0
  133. data/lib/libusb/context.rb +5 -2
  134. data/lib/libusb/stdio.rb +25 -0
  135. data/lib/libusb/version_gem.rb +1 -1
  136. data/libusb.gemspec +2 -1
  137. metadata +152 -115
  138. metadata.gz.sig +0 -0
  139. data/ext/libusb-1.0.19/Xcode/libusb.xcodeproj/project.pbxproj +0 -1
  140. data/ext/libusb-1.0.19/doc/doxygen.cfg.in +0 -1288
  141. data/ext/libusb-1.0.19/libusb/version_nano.h +0 -1
@@ -19,6 +19,8 @@
19
19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
  */
21
21
 
22
+ #include <config.h>
23
+
22
24
  #include <errno.h>
23
25
  #include <stdint.h>
24
26
  #include <stdlib.h>
@@ -453,7 +455,7 @@ static int parse_configuration(struct libusb_context *ctx,
453
455
  (header.bDescriptorType == LIBUSB_DT_DEVICE))
454
456
  break;
455
457
 
456
- usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
458
+ usbi_dbg("skipping descriptor 0x%x", header.bDescriptorType);
457
459
  buffer += header.bLength;
458
460
  size -= header.bLength;
459
461
  }
@@ -43,7 +43,7 @@
43
43
  *
44
44
  * \page hotplug Device hotplug event notification
45
45
  *
46
- * \section intro Introduction
46
+ * \section hotplug_intro Introduction
47
47
  *
48
48
  * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support
49
49
  * for hotplug events on <b>some</b> platforms (you should test if your platform
@@ -203,6 +203,30 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
203
203
  /* the backend is expected to call the callback for each active transfer */
204
204
  }
205
205
 
206
+ void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
207
+ libusb_hotplug_event event)
208
+ {
209
+ int pending_events;
210
+ libusb_hotplug_message *message = calloc(1, sizeof(*message));
211
+
212
+ if (!message) {
213
+ usbi_err(ctx, "error allocating hotplug message");
214
+ return;
215
+ }
216
+
217
+ message->event = event;
218
+ message->device = dev;
219
+
220
+ /* Take the event data lock and add this message to the list.
221
+ * Only signal an event if there are no prior pending events. */
222
+ usbi_mutex_lock(&ctx->event_data_lock);
223
+ pending_events = usbi_pending_events(ctx);
224
+ list_add_tail(&message->list, &ctx->hotplug_msgs);
225
+ if (!pending_events)
226
+ usbi_signal_event(ctx);
227
+ usbi_mutex_unlock(&ctx->event_data_lock);
228
+ }
229
+
206
230
  int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
207
231
  libusb_hotplug_event events, libusb_hotplug_flag flags,
208
232
  int vendor_id, int product_id, int dev_class,
@@ -285,8 +309,6 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
285
309
  libusb_hotplug_callback_handle handle)
286
310
  {
287
311
  struct libusb_hotplug_callback *hotplug_cb;
288
- libusb_hotplug_message message;
289
- ssize_t ret;
290
312
 
291
313
  /* check for hotplug support */
292
314
  if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
@@ -305,12 +327,7 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
305
327
  }
306
328
  usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
307
329
 
308
- /* wakeup handle_events to do the actual free */
309
- memset(&message, 0, sizeof(message));
310
- ret = usbi_write(ctx->hotplug_pipe[1], &message, sizeof(message));
311
- if (sizeof(message) != ret) {
312
- usbi_err(ctx, "error writing hotplug message");
313
- }
330
+ usbi_hotplug_notification(ctx, NULL, 0);
314
331
  }
315
332
 
316
333
  void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
@@ -69,8 +69,14 @@ struct libusb_hotplug_callback {
69
69
  typedef struct libusb_hotplug_callback libusb_hotplug_callback;
70
70
 
71
71
  struct libusb_hotplug_message {
72
+ /** The hotplug event that occurred */
72
73
  libusb_hotplug_event event;
74
+
75
+ /** The device for which this hotplug event occurred */
73
76
  struct libusb_device *device;
77
+
78
+ /** List this message is contained in (ctx->hotplug_msgs) */
79
+ struct list_head list;
74
80
  };
75
81
 
76
82
  typedef struct libusb_hotplug_message libusb_hotplug_message;
@@ -78,5 +84,7 @@ typedef struct libusb_hotplug_message libusb_hotplug_message;
78
84
  void usbi_hotplug_deregister_all(struct libusb_context *ctx);
79
85
  void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
80
86
  libusb_hotplug_event event);
87
+ void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
88
+ libusb_hotplug_event event);
81
89
 
82
90
  #endif
@@ -19,7 +19,9 @@
19
19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
  */
21
21
 
22
- #include "config.h"
22
+ #include <config.h>
23
+
24
+ #include <assert.h>
23
25
  #include <errno.h>
24
26
  #include <stdint.h>
25
27
  #include <stdlib.h>
@@ -41,7 +43,7 @@
41
43
  /**
42
44
  * \page io Synchronous and asynchronous device I/O
43
45
  *
44
- * \section intro Introduction
46
+ * \section io_intro Introduction
45
47
  *
46
48
  * If you're using libusb in your application, you're probably wanting to
47
49
  * perform I/O with devices - you want to perform USB data transfers.
@@ -464,6 +466,14 @@ if (r == 0 && actual_length == sizeof(data)) {
464
466
  * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple()
465
467
  * functions may help you here.
466
468
  *
469
+ * <b>Note</b>: Some operating systems (e.g. Linux) may impose limits on the
470
+ * length of individual isochronous packets and/or the total length of the
471
+ * isochronous transfer. Such limits can be difficult for libusb to detect,
472
+ * so the library will simply try and submit the transfer as set up by you.
473
+ * If the transfer fails to submit because it is too large,
474
+ * libusb_submit_transfer() will return
475
+ * \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM".
476
+ *
467
477
  * \section asyncmem Memory caveats
468
478
  *
469
479
  * In most circumstances, it is not safe to use stack memory for transfer
@@ -1030,7 +1040,7 @@ printf("completed!\n");
1030
1040
  *
1031
1041
  * -# During initialization, libusb opens an internal pipe, and it adds the read
1032
1042
  * end of this pipe to the set of file descriptors to be polled.
1033
- * -# During libusb_close(), libusb writes some dummy data on this control pipe.
1043
+ * -# During libusb_close(), libusb writes some dummy data on this event pipe.
1034
1044
  * This immediately interrupts the event handler. libusb also records
1035
1045
  * internally that it is trying to interrupt event handlers for this
1036
1046
  * high-priority event.
@@ -1063,7 +1073,7 @@ printf("completed!\n");
1063
1073
  * call to libusb_open():
1064
1074
  *
1065
1075
  * -# The device is opened and a file descriptor is added to the poll set.
1066
- * -# libusb sends some dummy data on the control pipe, and records that it
1076
+ * -# libusb sends some dummy data on the event pipe, and records that it
1067
1077
  * is trying to modify the poll descriptor set.
1068
1078
  * -# The event handler is interrupted, and the same behaviour change as for
1069
1079
  * libusb_close() takes effect, causing all event handling threads to become
@@ -1109,47 +1119,34 @@ int usbi_io_init(struct libusb_context *ctx)
1109
1119
  int r;
1110
1120
 
1111
1121
  usbi_mutex_init(&ctx->flying_transfers_lock, NULL);
1112
- usbi_mutex_init(&ctx->pollfds_lock, NULL);
1113
- usbi_mutex_init(&ctx->pollfd_modify_lock, NULL);
1114
1122
  usbi_mutex_init_recursive(&ctx->events_lock, NULL);
1115
1123
  usbi_mutex_init(&ctx->event_waiters_lock, NULL);
1116
1124
  usbi_cond_init(&ctx->event_waiters_cond, NULL);
1125
+ usbi_mutex_init(&ctx->event_data_lock, NULL);
1117
1126
  list_init(&ctx->flying_transfers);
1118
- list_init(&ctx->pollfds);
1127
+ list_init(&ctx->ipollfds);
1128
+ list_init(&ctx->hotplug_msgs);
1129
+ list_init(&ctx->completed_transfers);
1119
1130
 
1120
1131
  /* FIXME should use an eventfd on kernels that support it */
1121
- r = usbi_pipe(ctx->ctrl_pipe);
1132
+ r = usbi_pipe(ctx->event_pipe);
1122
1133
  if (r < 0) {
1123
1134
  r = LIBUSB_ERROR_OTHER;
1124
1135
  goto err;
1125
1136
  }
1126
1137
 
1127
- r = usbi_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN);
1138
+ r = usbi_add_pollfd(ctx, ctx->event_pipe[0], POLLIN);
1128
1139
  if (r < 0)
1129
1140
  goto err_close_pipe;
1130
1141
 
1131
- /* create hotplug pipe */
1132
- r = usbi_pipe(ctx->hotplug_pipe);
1133
- if (r < 0) {
1134
- r = LIBUSB_ERROR_OTHER;
1135
- goto err;
1136
- }
1137
-
1138
- r = usbi_add_pollfd(ctx, ctx->hotplug_pipe[0], POLLIN);
1139
- if (r < 0)
1140
- goto err_close_hp_pipe;
1141
-
1142
1142
  #ifdef USBI_TIMERFD_AVAILABLE
1143
1143
  ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(),
1144
1144
  TFD_NONBLOCK);
1145
1145
  if (ctx->timerfd >= 0) {
1146
1146
  usbi_dbg("using timerfd for timeouts");
1147
1147
  r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN);
1148
- if (r < 0) {
1149
- usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
1150
- close(ctx->timerfd);
1151
- goto err_close_hp_pipe;
1152
- }
1148
+ if (r < 0)
1149
+ goto err_close_timerfd;
1153
1150
  } else {
1154
1151
  usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno);
1155
1152
  ctx->timerfd = -1;
@@ -1158,30 +1155,28 @@ int usbi_io_init(struct libusb_context *ctx)
1158
1155
 
1159
1156
  return 0;
1160
1157
 
1161
- err_close_hp_pipe:
1162
- usbi_close(ctx->hotplug_pipe[0]);
1163
- usbi_close(ctx->hotplug_pipe[1]);
1158
+ #ifdef USBI_TIMERFD_AVAILABLE
1159
+ err_close_timerfd:
1160
+ close(ctx->timerfd);
1161
+ usbi_remove_pollfd(ctx, ctx->event_pipe[0]);
1162
+ #endif
1164
1163
  err_close_pipe:
1165
- usbi_close(ctx->ctrl_pipe[0]);
1166
- usbi_close(ctx->ctrl_pipe[1]);
1164
+ usbi_close(ctx->event_pipe[0]);
1165
+ usbi_close(ctx->event_pipe[1]);
1167
1166
  err:
1168
1167
  usbi_mutex_destroy(&ctx->flying_transfers_lock);
1169
- usbi_mutex_destroy(&ctx->pollfds_lock);
1170
- usbi_mutex_destroy(&ctx->pollfd_modify_lock);
1171
1168
  usbi_mutex_destroy(&ctx->events_lock);
1172
1169
  usbi_mutex_destroy(&ctx->event_waiters_lock);
1173
1170
  usbi_cond_destroy(&ctx->event_waiters_cond);
1171
+ usbi_mutex_destroy(&ctx->event_data_lock);
1174
1172
  return r;
1175
1173
  }
1176
1174
 
1177
1175
  void usbi_io_exit(struct libusb_context *ctx)
1178
1176
  {
1179
- usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
1180
- usbi_close(ctx->ctrl_pipe[0]);
1181
- usbi_close(ctx->ctrl_pipe[1]);
1182
- usbi_remove_pollfd(ctx, ctx->hotplug_pipe[0]);
1183
- usbi_close(ctx->hotplug_pipe[0]);
1184
- usbi_close(ctx->hotplug_pipe[1]);
1177
+ usbi_remove_pollfd(ctx, ctx->event_pipe[0]);
1178
+ usbi_close(ctx->event_pipe[0]);
1179
+ usbi_close(ctx->event_pipe[1]);
1185
1180
  #ifdef USBI_TIMERFD_AVAILABLE
1186
1181
  if (usbi_using_timerfd(ctx)) {
1187
1182
  usbi_remove_pollfd(ctx, ctx->timerfd);
@@ -1189,11 +1184,12 @@ void usbi_io_exit(struct libusb_context *ctx)
1189
1184
  }
1190
1185
  #endif
1191
1186
  usbi_mutex_destroy(&ctx->flying_transfers_lock);
1192
- usbi_mutex_destroy(&ctx->pollfds_lock);
1193
- usbi_mutex_destroy(&ctx->pollfd_modify_lock);
1194
1187
  usbi_mutex_destroy(&ctx->events_lock);
1195
1188
  usbi_mutex_destroy(&ctx->event_waiters_lock);
1196
1189
  usbi_cond_destroy(&ctx->event_waiters_cond);
1190
+ usbi_mutex_destroy(&ctx->event_data_lock);
1191
+ if (ctx->pollfds)
1192
+ free(ctx->pollfds);
1197
1193
  }
1198
1194
 
1199
1195
  static int calculate_timeout(struct usbi_transfer *transfer)
@@ -1225,71 +1221,6 @@ static int calculate_timeout(struct usbi_transfer *transfer)
1225
1221
  return 0;
1226
1222
  }
1227
1223
 
1228
- /* add a transfer to the (timeout-sorted) active transfers list.
1229
- * Callers of this function must hold the flying_transfers_lock.
1230
- * This function *always* adds the transfer to the flying_transfers list,
1231
- * it will return non 0 if it fails to update the timer, but even then the
1232
- * transfer is added to the flying_transfers list. */
1233
- static int add_to_flying_list(struct usbi_transfer *transfer)
1234
- {
1235
- struct usbi_transfer *cur;
1236
- struct timeval *timeout = &transfer->timeout;
1237
- struct libusb_context *ctx = ITRANSFER_CTX(transfer);
1238
- int r = 0;
1239
- int first = 1;
1240
-
1241
- /* if we have no other flying transfers, start the list with this one */
1242
- if (list_empty(&ctx->flying_transfers)) {
1243
- list_add(&transfer->list, &ctx->flying_transfers);
1244
- goto out;
1245
- }
1246
-
1247
- /* if we have infinite timeout, append to end of list */
1248
- if (!timerisset(timeout)) {
1249
- list_add_tail(&transfer->list, &ctx->flying_transfers);
1250
- /* first is irrelevant in this case */
1251
- goto out;
1252
- }
1253
-
1254
- /* otherwise, find appropriate place in list */
1255
- list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) {
1256
- /* find first timeout that occurs after the transfer in question */
1257
- struct timeval *cur_tv = &cur->timeout;
1258
-
1259
- if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
1260
- (cur_tv->tv_sec == timeout->tv_sec &&
1261
- cur_tv->tv_usec > timeout->tv_usec)) {
1262
- list_add_tail(&transfer->list, &cur->list);
1263
- goto out;
1264
- }
1265
- first = 0;
1266
- }
1267
- /* first is 0 at this stage (list not empty) */
1268
-
1269
- /* otherwise we need to be inserted at the end */
1270
- list_add_tail(&transfer->list, &ctx->flying_transfers);
1271
- out:
1272
- #ifdef USBI_TIMERFD_AVAILABLE
1273
- if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) {
1274
- /* if this transfer has the lowest timeout of all active transfers,
1275
- * rearm the timerfd with this transfer's timeout */
1276
- const struct itimerspec it = { {0, 0},
1277
- { timeout->tv_sec, timeout->tv_usec * 1000 } };
1278
- usbi_dbg("arm timerfd for timeout in %dms (first in line)",
1279
- USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout);
1280
- r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
1281
- if (r < 0) {
1282
- usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno);
1283
- r = LIBUSB_ERROR_OTHER;
1284
- }
1285
- }
1286
- #else
1287
- UNUSED(first);
1288
- #endif
1289
-
1290
- return r;
1291
- }
1292
-
1293
1224
  /** \ingroup asyncio
1294
1225
  * Allocate a libusb transfer with a specified number of isochronous packet
1295
1226
  * descriptors. The returned transfer is pre-initialized for you. When the new
@@ -1317,8 +1248,8 @@ DEFAULT_VISIBILITY
1317
1248
  struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
1318
1249
  int iso_packets)
1319
1250
  {
1320
- size_t os_alloc_size = usbi_backend->transfer_priv_size
1321
- + (usbi_backend->add_iso_packet_size * iso_packets);
1251
+ struct libusb_transfer *transfer;
1252
+ size_t os_alloc_size = usbi_backend->transfer_priv_size;
1322
1253
  size_t alloc_size = sizeof(struct usbi_transfer)
1323
1254
  + sizeof(struct libusb_transfer)
1324
1255
  + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets)
@@ -1329,7 +1260,10 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
1329
1260
 
1330
1261
  itransfer->num_iso_packets = iso_packets;
1331
1262
  usbi_mutex_init(&itransfer->lock, NULL);
1332
- return USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1263
+ usbi_mutex_init(&itransfer->flags_lock, NULL);
1264
+ transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1265
+ usbi_dbg("transfer %p", transfer);
1266
+ return transfer;
1333
1267
  }
1334
1268
 
1335
1269
  /** \ingroup asyncio
@@ -1355,11 +1289,13 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
1355
1289
  if (!transfer)
1356
1290
  return;
1357
1291
 
1292
+ usbi_dbg("transfer %p", transfer);
1358
1293
  if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer)
1359
1294
  free(transfer->buffer);
1360
1295
 
1361
1296
  itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
1362
1297
  usbi_mutex_destroy(&itransfer->lock);
1298
+ usbi_mutex_destroy(&itransfer->flags_lock);
1363
1299
  free(itransfer);
1364
1300
  }
1365
1301
 
@@ -1380,8 +1316,7 @@ static int disarm_timerfd(struct libusb_context *ctx)
1380
1316
  /* iterates through the flying transfers, and rearms the timerfd based on the
1381
1317
  * next upcoming timeout.
1382
1318
  * must be called with flying_list locked.
1383
- * returns 0 if there was no timeout to arm, 1 if the next timeout was armed,
1384
- * or a LIBUSB_ERROR code on failure.
1319
+ * returns 0 on success or a LIBUSB_ERROR code on failure.
1385
1320
  */
1386
1321
  static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
1387
1322
  {
@@ -1396,7 +1331,7 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
1396
1331
  goto disarm;
1397
1332
 
1398
1333
  /* act on first transfer that is not already cancelled */
1399
- if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) {
1334
+ if (!(transfer->flags & USBI_TRANSFER_TIMEOUT_HANDLED)) {
1400
1335
  int r;
1401
1336
  const struct itimerspec it = { {0, 0},
1402
1337
  { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } };
@@ -1404,7 +1339,7 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
1404
1339
  r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
1405
1340
  if (r < 0)
1406
1341
  return LIBUSB_ERROR_OTHER;
1407
- return 1;
1342
+ return 0;
1408
1343
  }
1409
1344
  }
1410
1345
 
@@ -1419,6 +1354,96 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
1419
1354
  }
1420
1355
  #endif
1421
1356
 
1357
+ /* add a transfer to the (timeout-sorted) active transfers list.
1358
+ * This function will return non 0 if fails to update the timer,
1359
+ * in which case the transfer is *not* on the flying_transfers list. */
1360
+ static int add_to_flying_list(struct usbi_transfer *transfer)
1361
+ {
1362
+ struct usbi_transfer *cur;
1363
+ struct timeval *timeout = &transfer->timeout;
1364
+ struct libusb_context *ctx = ITRANSFER_CTX(transfer);
1365
+ int r = 0;
1366
+ int first = 1;
1367
+
1368
+ usbi_mutex_lock(&ctx->flying_transfers_lock);
1369
+
1370
+ /* if we have no other flying transfers, start the list with this one */
1371
+ if (list_empty(&ctx->flying_transfers)) {
1372
+ list_add(&transfer->list, &ctx->flying_transfers);
1373
+ goto out;
1374
+ }
1375
+
1376
+ /* if we have infinite timeout, append to end of list */
1377
+ if (!timerisset(timeout)) {
1378
+ list_add_tail(&transfer->list, &ctx->flying_transfers);
1379
+ /* first is irrelevant in this case */
1380
+ goto out;
1381
+ }
1382
+
1383
+ /* otherwise, find appropriate place in list */
1384
+ list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) {
1385
+ /* find first timeout that occurs after the transfer in question */
1386
+ struct timeval *cur_tv = &cur->timeout;
1387
+
1388
+ if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
1389
+ (cur_tv->tv_sec == timeout->tv_sec &&
1390
+ cur_tv->tv_usec > timeout->tv_usec)) {
1391
+ list_add_tail(&transfer->list, &cur->list);
1392
+ goto out;
1393
+ }
1394
+ first = 0;
1395
+ }
1396
+ /* first is 0 at this stage (list not empty) */
1397
+
1398
+ /* otherwise we need to be inserted at the end */
1399
+ list_add_tail(&transfer->list, &ctx->flying_transfers);
1400
+ out:
1401
+ #ifdef USBI_TIMERFD_AVAILABLE
1402
+ if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) {
1403
+ /* if this transfer has the lowest timeout of all active transfers,
1404
+ * rearm the timerfd with this transfer's timeout */
1405
+ const struct itimerspec it = { {0, 0},
1406
+ { timeout->tv_sec, timeout->tv_usec * 1000 } };
1407
+ usbi_dbg("arm timerfd for timeout in %dms (first in line)",
1408
+ USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout);
1409
+ r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
1410
+ if (r < 0) {
1411
+ usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno);
1412
+ r = LIBUSB_ERROR_OTHER;
1413
+ }
1414
+ }
1415
+ #else
1416
+ UNUSED(first);
1417
+ #endif
1418
+
1419
+ if (r)
1420
+ list_del(&transfer->list);
1421
+
1422
+ usbi_mutex_unlock(&ctx->flying_transfers_lock);
1423
+ return r;
1424
+ }
1425
+
1426
+ /* remove a transfer from the active transfers list.
1427
+ * This function will *always* remove the transfer from the
1428
+ * flying_transfers list. It will return a LIBUSB_ERROR code
1429
+ * if it fails to update the timer for the next timeout. */
1430
+ static int remove_from_flying_list(struct usbi_transfer *transfer)
1431
+ {
1432
+ struct libusb_context *ctx = ITRANSFER_CTX(transfer);
1433
+ int rearm_timerfd;
1434
+ int r = 0;
1435
+
1436
+ usbi_mutex_lock(&ctx->flying_transfers_lock);
1437
+ rearm_timerfd = (timerisset(&transfer->timeout) &&
1438
+ list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == transfer);
1439
+ list_del(&transfer->list);
1440
+ if (usbi_using_timerfd(ctx) && rearm_timerfd)
1441
+ r = arm_timerfd_for_next_timeout(ctx);
1442
+ usbi_mutex_unlock(&ctx->flying_transfers_lock);
1443
+
1444
+ return r;
1445
+ }
1446
+
1422
1447
  /** \ingroup asyncio
1423
1448
  * Submit a transfer. This function will fire off the USB transfer and then
1424
1449
  * return immediately.
@@ -1433,14 +1458,18 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
1433
1458
  */
1434
1459
  int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
1435
1460
  {
1436
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
1437
1461
  struct usbi_transfer *itransfer =
1438
1462
  LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
1463
+ int remove = 0;
1439
1464
  int r;
1440
- int updated_fds;
1441
1465
 
1442
- usbi_mutex_lock(&ctx->flying_transfers_lock);
1466
+ usbi_dbg("transfer %p", transfer);
1443
1467
  usbi_mutex_lock(&itransfer->lock);
1468
+ usbi_mutex_lock(&itransfer->flags_lock);
1469
+ if (itransfer->flags & USBI_TRANSFER_IN_FLIGHT) {
1470
+ r = LIBUSB_ERROR_BUSY;
1471
+ goto out;
1472
+ }
1444
1473
  itransfer->transferred = 0;
1445
1474
  itransfer->flags = 0;
1446
1475
  r = calculate_timeout(itransfer);
@@ -1448,24 +1477,45 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
1448
1477
  r = LIBUSB_ERROR_OTHER;
1449
1478
  goto out;
1450
1479
  }
1480
+ itransfer->flags |= USBI_TRANSFER_SUBMITTING;
1481
+ usbi_mutex_unlock(&itransfer->flags_lock);
1451
1482
 
1452
1483
  r = add_to_flying_list(itransfer);
1453
- if (r == LIBUSB_SUCCESS) {
1454
- r = usbi_backend->submit_transfer(itransfer);
1484
+ if (r) {
1485
+ usbi_mutex_lock(&itransfer->flags_lock);
1486
+ itransfer->flags = 0;
1487
+ goto out;
1455
1488
  }
1456
- if (r != LIBUSB_SUCCESS) {
1457
- list_del(&itransfer->list);
1458
- arm_timerfd_for_next_timeout(ctx);
1489
+
1490
+ /* keep a reference to this device */
1491
+ libusb_ref_device(transfer->dev_handle->dev);
1492
+ r = usbi_backend->submit_transfer(itransfer);
1493
+
1494
+ usbi_mutex_lock(&itransfer->flags_lock);
1495
+ itransfer->flags &= ~USBI_TRANSFER_SUBMITTING;
1496
+ if (r == LIBUSB_SUCCESS) {
1497
+ /* check for two possible special conditions:
1498
+ * 1) device disconnect occurred immediately after submission
1499
+ * 2) transfer completed before we got here to update the flags
1500
+ */
1501
+ if (itransfer->flags & USBI_TRANSFER_DEVICE_DISAPPEARED) {
1502
+ usbi_backend->clear_transfer_priv(itransfer);
1503
+ remove = 1;
1504
+ r = LIBUSB_ERROR_NO_DEVICE;
1505
+ }
1506
+ else if (!(itransfer->flags & USBI_TRANSFER_COMPLETED)) {
1507
+ itransfer->flags |= USBI_TRANSFER_IN_FLIGHT;
1508
+ }
1459
1509
  } else {
1460
- /* keep a reference to this device */
1461
- libusb_ref_device(transfer->dev_handle->dev);
1510
+ remove = 1;
1462
1511
  }
1463
1512
  out:
1464
- updated_fds = (itransfer->flags & USBI_TRANSFER_UPDATED_FDS);
1513
+ usbi_mutex_unlock(&itransfer->flags_lock);
1514
+ if (remove) {
1515
+ libusb_unref_device(transfer->dev_handle->dev);
1516
+ remove_from_flying_list(itransfer);
1517
+ }
1465
1518
  usbi_mutex_unlock(&itransfer->lock);
1466
- usbi_mutex_unlock(&ctx->flying_transfers_lock);
1467
- if (updated_fds)
1468
- usbi_fd_notification(ctx);
1469
1519
  return r;
1470
1520
  }
1471
1521
 
@@ -1479,8 +1529,8 @@ out:
1479
1529
  *
1480
1530
  * \param transfer the transfer to cancel
1481
1531
  * \returns 0 on success
1482
- * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is already complete or
1483
- * cancelled.
1532
+ * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress,
1533
+ * already complete, or already cancelled.
1484
1534
  * \returns a LIBUSB_ERROR code on failure
1485
1535
  */
1486
1536
  int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
@@ -1489,8 +1539,14 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
1489
1539
  LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
1490
1540
  int r;
1491
1541
 
1492
- usbi_dbg("");
1542
+ usbi_dbg("transfer %p", transfer );
1493
1543
  usbi_mutex_lock(&itransfer->lock);
1544
+ usbi_mutex_lock(&itransfer->flags_lock);
1545
+ if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT)
1546
+ || (itransfer->flags & USBI_TRANSFER_CANCELLING)) {
1547
+ r = LIBUSB_ERROR_NOT_FOUND;
1548
+ goto out;
1549
+ }
1494
1550
  r = usbi_backend->cancel_transfer(itransfer);
1495
1551
  if (r < 0) {
1496
1552
  if (r != LIBUSB_ERROR_NOT_FOUND &&
@@ -1506,6 +1562,8 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
1506
1562
 
1507
1563
  itransfer->flags |= USBI_TRANSFER_CANCELLING;
1508
1564
 
1565
+ out:
1566
+ usbi_mutex_unlock(&itransfer->flags_lock);
1509
1567
  usbi_mutex_unlock(&itransfer->lock);
1510
1568
  return r;
1511
1569
  }
@@ -1560,23 +1618,18 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
1560
1618
  {
1561
1619
  struct libusb_transfer *transfer =
1562
1620
  USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1563
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
1564
1621
  struct libusb_device_handle *handle = transfer->dev_handle;
1565
1622
  uint8_t flags;
1566
- int r = 0;
1623
+ int r;
1567
1624
 
1568
- /* FIXME: could be more intelligent with the timerfd here. we don't need
1569
- * to disarm the timerfd if there was no timer running, and we only need
1570
- * to rearm the timerfd if the transfer that expired was the one with
1571
- * the shortest timeout. */
1625
+ r = remove_from_flying_list(itransfer);
1626
+ if (r < 0)
1627
+ usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout, errno=%d", errno);
1572
1628
 
1573
- usbi_mutex_lock(&ctx->flying_transfers_lock);
1574
- list_del(&itransfer->list);
1575
- if (usbi_using_timerfd(ctx))
1576
- r = arm_timerfd_for_next_timeout(ctx);
1577
- usbi_mutex_unlock(&ctx->flying_transfers_lock);
1578
- if (usbi_using_timerfd(ctx) && (r < 0))
1579
- return r;
1629
+ usbi_mutex_lock(&itransfer->flags_lock);
1630
+ itransfer->flags &= ~USBI_TRANSFER_IN_FLIGHT;
1631
+ itransfer->flags |= USBI_TRANSFER_COMPLETED;
1632
+ usbi_mutex_unlock(&itransfer->flags_lock);
1580
1633
 
1581
1634
  if (status == LIBUSB_TRANSFER_COMPLETED
1582
1635
  && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
@@ -1599,11 +1652,8 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
1599
1652
  * this point. */
1600
1653
  if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
1601
1654
  libusb_free_transfer(transfer);
1602
- usbi_mutex_lock(&ctx->event_waiters_lock);
1603
- usbi_cond_broadcast(&ctx->event_waiters_cond);
1604
- usbi_mutex_unlock(&ctx->event_waiters_lock);
1605
1655
  libusb_unref_device(handle->dev);
1606
- return 0;
1656
+ return r;
1607
1657
  }
1608
1658
 
1609
1659
  /* Similar to usbi_handle_transfer_completion() but exclusively for transfers
@@ -1624,6 +1674,22 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer)
1624
1674
  return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED);
1625
1675
  }
1626
1676
 
1677
+ /* Add a completed transfer to the completed_transfers list of the
1678
+ * context and signal the event. The backend's handle_transfer_completion()
1679
+ * function will be called the next time an event handler runs. */
1680
+ void usbi_signal_transfer_completion(struct usbi_transfer *transfer)
1681
+ {
1682
+ struct libusb_context *ctx = ITRANSFER_CTX(transfer);
1683
+ int pending_events;
1684
+
1685
+ usbi_mutex_lock(&ctx->event_data_lock);
1686
+ pending_events = usbi_pending_events(ctx);
1687
+ list_add_tail(&transfer->completed_list, &ctx->completed_transfers);
1688
+ if (!pending_events)
1689
+ usbi_signal_event(ctx);
1690
+ usbi_mutex_unlock(&ctx->event_data_lock);
1691
+ }
1692
+
1627
1693
  /** \ingroup poll
1628
1694
  * Attempt to acquire the event handling lock. This lock is used to ensure that
1629
1695
  * only one thread is monitoring libusb event sources at any one time.
@@ -1649,13 +1715,13 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx)
1649
1715
  unsigned int ru;
1650
1716
  USBI_GET_CONTEXT(ctx);
1651
1717
 
1652
- /* is someone else waiting to modify poll fds? if so, don't let this thread
1718
+ /* is someone else waiting to close a device? if so, don't let this thread
1653
1719
  * start event handling */
1654
- usbi_mutex_lock(&ctx->pollfd_modify_lock);
1655
- ru = ctx->pollfd_modify;
1656
- usbi_mutex_unlock(&ctx->pollfd_modify_lock);
1720
+ usbi_mutex_lock(&ctx->event_data_lock);
1721
+ ru = ctx->device_close;
1722
+ usbi_mutex_unlock(&ctx->event_data_lock);
1657
1723
  if (ru) {
1658
- usbi_dbg("someone else is modifying poll fds");
1724
+ usbi_dbg("someone else is closing a device");
1659
1725
  return 1;
1660
1726
  }
1661
1727
 
@@ -1708,7 +1774,7 @@ void API_EXPORTED libusb_unlock_events(libusb_context *ctx)
1708
1774
 
1709
1775
  /* FIXME: perhaps we should be a bit more efficient by not broadcasting
1710
1776
  * the availability of the events lock when we are modifying pollfds
1711
- * (check ctx->pollfd_modify)? */
1777
+ * (check ctx->device_close)? */
1712
1778
  usbi_mutex_lock(&ctx->event_waiters_lock);
1713
1779
  usbi_cond_broadcast(&ctx->event_waiters_cond);
1714
1780
  usbi_mutex_unlock(&ctx->event_waiters_lock);
@@ -1740,13 +1806,13 @@ int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
1740
1806
  unsigned int r;
1741
1807
  USBI_GET_CONTEXT(ctx);
1742
1808
 
1743
- /* is someone else waiting to modify poll fds? if so, don't let this thread
1809
+ /* is someone else waiting to close a device? if so, don't let this thread
1744
1810
  * continue event handling */
1745
- usbi_mutex_lock(&ctx->pollfd_modify_lock);
1746
- r = ctx->pollfd_modify;
1747
- usbi_mutex_unlock(&ctx->pollfd_modify_lock);
1811
+ usbi_mutex_lock(&ctx->event_data_lock);
1812
+ r = ctx->device_close;
1813
+ usbi_mutex_unlock(&ctx->event_data_lock);
1748
1814
  if (r) {
1749
- usbi_dbg("someone else is modifying poll fds");
1815
+ usbi_dbg("someone else is closing a device");
1750
1816
  return 0;
1751
1817
  }
1752
1818
 
@@ -1768,13 +1834,13 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
1768
1834
  unsigned int r;
1769
1835
  USBI_GET_CONTEXT(ctx);
1770
1836
 
1771
- /* is someone else waiting to modify poll fds? if so, don't let this thread
1837
+ /* is someone else waiting to close a device? if so, don't let this thread
1772
1838
  * start event handling -- indicate that event handling is happening */
1773
- usbi_mutex_lock(&ctx->pollfd_modify_lock);
1774
- r = ctx->pollfd_modify;
1775
- usbi_mutex_unlock(&ctx->pollfd_modify_lock);
1839
+ usbi_mutex_lock(&ctx->event_data_lock);
1840
+ r = ctx->device_close;
1841
+ usbi_mutex_unlock(&ctx->event_data_lock);
1776
1842
  if (r) {
1777
- usbi_dbg("someone else is modifying poll fds");
1843
+ usbi_dbg("someone else is closing a device");
1778
1844
  return 1;
1779
1845
  }
1780
1846
 
@@ -1877,9 +1943,11 @@ static void handle_timeout(struct usbi_transfer *itransfer)
1877
1943
  USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1878
1944
  int r;
1879
1945
 
1880
- itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
1946
+ itransfer->flags |= USBI_TRANSFER_TIMEOUT_HANDLED;
1881
1947
  r = libusb_cancel_transfer(transfer);
1882
- if (r < 0)
1948
+ if (r == 0)
1949
+ itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
1950
+ else
1883
1951
  usbi_warn(TRANSFER_CTX(transfer),
1884
1952
  "async cancel failed %d errno=%d", r, errno);
1885
1953
  }
@@ -1911,7 +1979,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx)
1911
1979
  return 0;
1912
1980
 
1913
1981
  /* ignore timeouts we've already handled */
1914
- if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
1982
+ if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
1915
1983
  continue;
1916
1984
 
1917
1985
  /* if transfer has non-expired timeout, nothing more to do */
@@ -1964,32 +2032,65 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
1964
2032
  int r;
1965
2033
  struct usbi_pollfd *ipollfd;
1966
2034
  POLL_NFDS_TYPE nfds = 0;
2035
+ POLL_NFDS_TYPE internal_nfds;
1967
2036
  struct pollfd *fds = NULL;
1968
2037
  int i = -1;
1969
2038
  int timeout_ms;
1970
2039
  int special_event;
1971
2040
 
1972
- usbi_mutex_lock(&ctx->pollfds_lock);
1973
- list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd)
1974
- nfds++;
2041
+ /* there are certain fds that libusb uses internally, currently:
2042
+ *
2043
+ * 1) event pipe
2044
+ * 2) timerfd
2045
+ *
2046
+ * the backend will never need to attempt to handle events on these fds, so
2047
+ * we determine how many fds are in use internally for this context and when
2048
+ * handle_events() is called in the backend, the pollfd list and count will
2049
+ * be adjusted to skip over these internal fds */
2050
+ if (usbi_using_timerfd(ctx))
2051
+ internal_nfds = 2;
2052
+ else
2053
+ internal_nfds = 1;
1975
2054
 
1976
- /* TODO: malloc when number of fd's changes, not on every poll */
1977
- if (nfds != 0)
1978
- fds = malloc(sizeof(*fds) * nfds);
1979
- if (!fds) {
1980
- usbi_mutex_unlock(&ctx->pollfds_lock);
1981
- return LIBUSB_ERROR_NO_MEM;
1982
- }
2055
+ /* only reallocate the poll fds when the list of poll fds has been modified
2056
+ * since the last poll, otherwise reuse them to save the additional overhead */
2057
+ usbi_mutex_lock(&ctx->event_data_lock);
2058
+ if (ctx->pollfds_modified) {
2059
+ usbi_dbg("poll fds modified, reallocating");
2060
+
2061
+ if (ctx->pollfds) {
2062
+ free(ctx->pollfds);
2063
+ ctx->pollfds = NULL;
2064
+ }
1983
2065
 
1984
- list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) {
1985
- struct libusb_pollfd *pollfd = &ipollfd->pollfd;
1986
- int fd = pollfd->fd;
1987
- i++;
1988
- fds[i].fd = fd;
1989
- fds[i].events = pollfd->events;
1990
- fds[i].revents = 0;
2066
+ /* sanity check - it is invalid for a context to have fewer than the
2067
+ * required internal fds (memory corruption?) */
2068
+ assert(ctx->pollfds_cnt >= internal_nfds);
2069
+
2070
+ ctx->pollfds = calloc(ctx->pollfds_cnt, sizeof(*ctx->pollfds));
2071
+ if (!ctx->pollfds) {
2072
+ usbi_mutex_unlock(&ctx->event_data_lock);
2073
+ return LIBUSB_ERROR_NO_MEM;
2074
+ }
2075
+
2076
+ list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) {
2077
+ struct libusb_pollfd *pollfd = &ipollfd->pollfd;
2078
+ i++;
2079
+ ctx->pollfds[i].fd = pollfd->fd;
2080
+ ctx->pollfds[i].events = pollfd->events;
2081
+ }
2082
+
2083
+ /* reset the flag now that we have the updated list */
2084
+ ctx->pollfds_modified = 0;
2085
+
2086
+ /* if no further pending events, clear the event pipe so that we do
2087
+ * not immediately return from poll */
2088
+ if (!usbi_pending_events(ctx))
2089
+ usbi_clear_event(ctx);
1991
2090
  }
1992
- usbi_mutex_unlock(&ctx->pollfds_lock);
2091
+ fds = ctx->pollfds;
2092
+ nfds = ctx->pollfds_cnt;
2093
+ usbi_mutex_unlock(&ctx->event_data_lock);
1993
2094
 
1994
2095
  timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
1995
2096
 
@@ -2001,68 +2102,85 @@ redo_poll:
2001
2102
  usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms);
2002
2103
  r = usbi_poll(fds, nfds, timeout_ms);
2003
2104
  usbi_dbg("poll() returned %d", r);
2004
- if (r == 0) {
2005
- free(fds);
2105
+ if (r == 0)
2006
2106
  return handle_timeouts(ctx);
2007
- } else if (r == -1 && errno == EINTR) {
2008
- free(fds);
2107
+ else if (r == -1 && errno == EINTR)
2009
2108
  return LIBUSB_ERROR_INTERRUPTED;
2010
- } else if (r < 0) {
2011
- free(fds);
2012
- usbi_err(ctx, "poll failed %d err=%d\n", r, errno);
2109
+ else if (r < 0) {
2110
+ usbi_err(ctx, "poll failed %d err=%d", r, errno);
2013
2111
  return LIBUSB_ERROR_IO;
2014
2112
  }
2015
2113
 
2016
2114
  special_event = 0;
2017
2115
 
2018
- /* fd[0] is always the ctrl pipe */
2116
+ /* fds[0] is always the event pipe */
2019
2117
  if (fds[0].revents) {
2020
- /* another thread wanted to interrupt event handling, and it succeeded!
2021
- * handle any other events that cropped up at the same time, and
2022
- * simply return */
2023
- usbi_dbg("caught a fish on the control pipe");
2118
+ libusb_hotplug_message *message = NULL;
2119
+ struct usbi_transfer *itransfer;
2120
+ int ret = 0;
2024
2121
 
2025
- if (r == 1) {
2026
- r = 0;
2027
- goto handled;
2028
- } else {
2029
- /* prevent OS backend from trying to handle events on ctrl pipe */
2030
- fds[0].revents = 0;
2031
- r--;
2032
- }
2033
- }
2122
+ usbi_dbg("caught a fish on the event pipe");
2034
2123
 
2035
- /* fd[1] is always the hotplug pipe */
2036
- if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && fds[1].revents) {
2037
- libusb_hotplug_message message;
2038
- ssize_t ret;
2124
+ /* take the the event data lock while processing events */
2125
+ usbi_mutex_lock(&ctx->event_data_lock);
2039
2126
 
2040
- usbi_dbg("caught a fish on the hotplug pipe");
2041
- special_event = 1;
2127
+ /* check if someone added a new poll fd */
2128
+ if (ctx->pollfds_modified)
2129
+ usbi_dbg("someone updated the poll fds");
2042
2130
 
2043
- /* read the message from the hotplug thread */
2044
- ret = usbi_read(ctx->hotplug_pipe[0], &message, sizeof (message));
2045
- if (ret != sizeof(message)) {
2046
- usbi_err(ctx, "hotplug pipe read error %d != %u",
2047
- ret, sizeof(message));
2048
- r = LIBUSB_ERROR_OTHER;
2049
- goto handled;
2131
+ /* check if someone is closing a device */
2132
+ if (ctx->device_close)
2133
+ usbi_dbg("someone is closing a device");
2134
+
2135
+ /* check for any pending hotplug messages */
2136
+ if (!list_empty(&ctx->hotplug_msgs)) {
2137
+ usbi_dbg("hotplug message received");
2138
+ special_event = 1;
2139
+ message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list);
2140
+ list_del(&message->list);
2141
+ }
2142
+
2143
+ /* complete any pending transfers */
2144
+ while (ret == 0 && !list_empty(&ctx->completed_transfers)) {
2145
+ itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list);
2146
+ list_del(&itransfer->completed_list);
2147
+ usbi_mutex_unlock(&ctx->event_data_lock);
2148
+ ret = usbi_backend->handle_transfer_completion(itransfer);
2149
+ if (ret)
2150
+ usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret);
2151
+ usbi_mutex_lock(&ctx->event_data_lock);
2050
2152
  }
2051
2153
 
2052
- usbi_hotplug_match(ctx, message.device, message.event);
2154
+ /* if no further pending events, clear the event pipe */
2155
+ if (!usbi_pending_events(ctx))
2156
+ usbi_clear_event(ctx);
2157
+
2158
+ usbi_mutex_unlock(&ctx->event_data_lock);
2053
2159
 
2054
- /* the device left. dereference the device */
2055
- if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message.event)
2056
- libusb_unref_device(message.device);
2160
+ /* process the hotplug message, if any */
2161
+ if (message) {
2162
+ usbi_hotplug_match(ctx, message->device, message->event);
2057
2163
 
2058
- fds[1].revents = 0;
2059
- if (1 == r--)
2164
+ /* the device left, dereference the device */
2165
+ if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event)
2166
+ libusb_unref_device(message->device);
2167
+
2168
+ free(message);
2169
+ }
2170
+
2171
+ if (ret) {
2172
+ /* return error code */
2173
+ r = ret;
2060
2174
  goto handled;
2061
- } /* else there shouldn't be anything on this pipe */
2175
+ }
2176
+
2177
+ if (0 == --r)
2178
+ goto handled;
2179
+ }
2062
2180
 
2063
2181
  #ifdef USBI_TIMERFD_AVAILABLE
2064
- /* on timerfd configurations, fds[2] is the timerfd */
2065
- if (usbi_using_timerfd(ctx) && fds[2].revents) {
2182
+ /* on timerfd configurations, fds[1] is the timerfd */
2183
+ if (usbi_using_timerfd(ctx) && fds[1].revents) {
2066
2184
  /* timerfd indicates that a timeout has expired */
2067
2185
  int ret;
2068
2186
  usbi_dbg("timerfd triggered");
@@ -2073,30 +2191,23 @@ redo_poll:
2073
2191
  /* return error code */
2074
2192
  r = ret;
2075
2193
  goto handled;
2076
- } else if (r == 1) {
2077
- /* no more active file descriptors, nothing more to do */
2078
- r = 0;
2079
- goto handled;
2080
- } else {
2081
- /* more events pending...
2082
- * prevent OS backend from trying to handle events on timerfd */
2083
- fds[2].revents = 0;
2084
- r--;
2085
2194
  }
2195
+
2196
+ if (0 == --r)
2197
+ goto handled;
2086
2198
  }
2087
2199
  #endif
2088
2200
 
2089
- r = usbi_backend->handle_events(ctx, fds, nfds, r);
2201
+ r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r);
2090
2202
  if (r)
2091
2203
  usbi_err(ctx, "backend handle_events failed with error %d", r);
2092
2204
 
2093
2205
  handled:
2094
- if (r == 0 && special_event) {
2095
- timeout_ms = 0;
2096
- goto redo_poll;
2097
- }
2206
+ if (r == 0 && special_event) {
2207
+ timeout_ms = 0;
2208
+ goto redo_poll;
2209
+ }
2098
2210
 
2099
- free(fds);
2100
2211
  return r;
2101
2212
  }
2102
2213
 
@@ -2379,9 +2490,8 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
2379
2490
  struct usbi_transfer *transfer;
2380
2491
  struct timespec cur_ts;
2381
2492
  struct timeval cur_tv;
2382
- struct timeval *next_timeout;
2493
+ struct timeval next_timeout = { 0, 0 };
2383
2494
  int r;
2384
- int found = 0;
2385
2495
 
2386
2496
  USBI_GET_CONTEXT(ctx);
2387
2497
  if (usbi_using_timerfd(ctx))
@@ -2396,25 +2506,23 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
2396
2506
 
2397
2507
  /* find next transfer which hasn't already been processed as timed out */
2398
2508
  list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
2399
- if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
2509
+ if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
2400
2510
  continue;
2401
2511
 
2402
- /* no timeout for this transfer? */
2512
+ /* if we've reached transfers of infinte timeout, we're done looking */
2403
2513
  if (!timerisset(&transfer->timeout))
2404
- continue;
2514
+ break;
2405
2515
 
2406
- found = 1;
2516
+ next_timeout = transfer->timeout;
2407
2517
  break;
2408
2518
  }
2409
2519
  usbi_mutex_unlock(&ctx->flying_transfers_lock);
2410
2520
 
2411
- if (!found) {
2521
+ if (!timerisset(&next_timeout)) {
2412
2522
  usbi_dbg("no URB with timeout or all handled by OS; no timeout!");
2413
2523
  return 0;
2414
2524
  }
2415
2525
 
2416
- next_timeout = &transfer->timeout;
2417
-
2418
2526
  r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts);
2419
2527
  if (r < 0) {
2420
2528
  usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno);
@@ -2422,11 +2530,11 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
2422
2530
  }
2423
2531
  TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
2424
2532
 
2425
- if (!timercmp(&cur_tv, next_timeout, <)) {
2533
+ if (!timercmp(&cur_tv, &next_timeout, <)) {
2426
2534
  usbi_dbg("first timeout already expired");
2427
2535
  timerclear(tv);
2428
2536
  } else {
2429
- timersub(next_timeout, &cur_tv, tv);
2537
+ timersub(&next_timeout, &cur_tv, tv);
2430
2538
  usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
2431
2539
  }
2432
2540
 
@@ -2464,6 +2572,22 @@ void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx,
2464
2572
  ctx->fd_cb_user_data = user_data;
2465
2573
  }
2466
2574
 
2575
+ /*
2576
+ * Interrupt the iteration of the event handling thread, so that it picks
2577
+ * up the fd change. Callers of this function must hold the event_data_lock.
2578
+ */
2579
+ static void usbi_fd_notification(struct libusb_context *ctx)
2580
+ {
2581
+ int pending_events;
2582
+
2583
+ /* Record that there is a new poll fd.
2584
+ * Only signal an event if there are no prior pending events. */
2585
+ pending_events = usbi_pending_events(ctx);
2586
+ ctx->pollfds_modified = 1;
2587
+ if (!pending_events)
2588
+ usbi_signal_event(ctx);
2589
+ }
2590
+
2467
2591
  /* Add a file descriptor to the list of file descriptors to be monitored.
2468
2592
  * events should be specified as a bitmask of events passed to poll(), e.g.
2469
2593
  * POLLIN and/or POLLOUT. */
@@ -2476,9 +2600,11 @@ int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events)
2476
2600
  usbi_dbg("add fd %d events %d", fd, events);
2477
2601
  ipollfd->pollfd.fd = fd;
2478
2602
  ipollfd->pollfd.events = events;
2479
- usbi_mutex_lock(&ctx->pollfds_lock);
2480
- list_add_tail(&ipollfd->list, &ctx->pollfds);
2481
- usbi_mutex_unlock(&ctx->pollfds_lock);
2603
+ usbi_mutex_lock(&ctx->event_data_lock);
2604
+ list_add_tail(&ipollfd->list, &ctx->ipollfds);
2605
+ ctx->pollfds_cnt++;
2606
+ usbi_fd_notification(ctx);
2607
+ usbi_mutex_unlock(&ctx->event_data_lock);
2482
2608
 
2483
2609
  if (ctx->fd_added_cb)
2484
2610
  ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
@@ -2492,8 +2618,8 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd)
2492
2618
  int found = 0;
2493
2619
 
2494
2620
  usbi_dbg("remove fd %d", fd);
2495
- usbi_mutex_lock(&ctx->pollfds_lock);
2496
- list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd)
2621
+ usbi_mutex_lock(&ctx->event_data_lock);
2622
+ list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
2497
2623
  if (ipollfd->pollfd.fd == fd) {
2498
2624
  found = 1;
2499
2625
  break;
@@ -2501,12 +2627,14 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd)
2501
2627
 
2502
2628
  if (!found) {
2503
2629
  usbi_dbg("couldn't find fd %d to remove", fd);
2504
- usbi_mutex_unlock(&ctx->pollfds_lock);
2630
+ usbi_mutex_unlock(&ctx->event_data_lock);
2505
2631
  return;
2506
2632
  }
2507
2633
 
2508
2634
  list_del(&ipollfd->list);
2509
- usbi_mutex_unlock(&ctx->pollfds_lock);
2635
+ ctx->pollfds_cnt--;
2636
+ usbi_fd_notification(ctx);
2637
+ usbi_mutex_unlock(&ctx->event_data_lock);
2510
2638
  free(ipollfd);
2511
2639
  if (ctx->fd_removed_cb)
2512
2640
  ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
@@ -2516,8 +2644,8 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd)
2516
2644
  * Retrieve a list of file descriptors that should be polled by your main loop
2517
2645
  * as libusb event sources.
2518
2646
  *
2519
- * The returned list is NULL-terminated and should be freed with free() when
2520
- * done. The actual list contents must not be touched.
2647
+ * The returned list is NULL-terminated and should be freed with libusb_free_pollfds()
2648
+ * when done. The actual list contents must not be touched.
2521
2649
  *
2522
2650
  * As file descriptors are a Unix-specific concept, this function is not
2523
2651
  * available on Windows and will always return NULL.
@@ -2535,23 +2663,20 @@ const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
2535
2663
  struct libusb_pollfd **ret = NULL;
2536
2664
  struct usbi_pollfd *ipollfd;
2537
2665
  size_t i = 0;
2538
- size_t cnt = 0;
2539
2666
  USBI_GET_CONTEXT(ctx);
2540
2667
 
2541
- usbi_mutex_lock(&ctx->pollfds_lock);
2542
- list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd)
2543
- cnt++;
2668
+ usbi_mutex_lock(&ctx->event_data_lock);
2544
2669
 
2545
- ret = calloc(cnt + 1, sizeof(struct libusb_pollfd *));
2670
+ ret = calloc(ctx->pollfds_cnt + 1, sizeof(struct libusb_pollfd *));
2546
2671
  if (!ret)
2547
2672
  goto out;
2548
2673
 
2549
- list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd)
2674
+ list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
2550
2675
  ret[i++] = (struct libusb_pollfd *) ipollfd;
2551
- ret[cnt] = NULL;
2676
+ ret[ctx->pollfds_cnt] = NULL;
2552
2677
 
2553
2678
  out:
2554
- usbi_mutex_unlock(&ctx->pollfds_lock);
2679
+ usbi_mutex_unlock(&ctx->event_data_lock);
2555
2680
  return (const struct libusb_pollfd **) ret;
2556
2681
  #else
2557
2682
  usbi_err(ctx, "external polling of libusb's internal descriptors "\
@@ -2560,6 +2685,25 @@ out:
2560
2685
  #endif
2561
2686
  }
2562
2687
 
2688
+ /** \ingroup poll
2689
+ * Free a list of libusb_pollfd structures. This should be called for all
2690
+ * pollfd lists allocated with libusb_get_pollfds().
2691
+ *
2692
+ * Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104
2693
+ *
2694
+ * It is legal to call this function with a NULL pollfd list. In this case,
2695
+ * the function will simply return safely.
2696
+ *
2697
+ * \param pollfds the list of libusb_pollfd structures to free
2698
+ */
2699
+ void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
2700
+ {
2701
+ if (!pollfds)
2702
+ return;
2703
+
2704
+ free((void *)pollfds);
2705
+ }
2706
+
2563
2707
  /* Backends may call this from handle_events to report disconnection of a
2564
2708
  * device. This function ensures transfers get cancelled appropriately.
2565
2709
  * Callers of this function must hold the events_lock.
@@ -2575,33 +2719,29 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle)
2575
2719
  /* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE
2576
2720
  * status code.
2577
2721
  *
2578
- * this is a bit tricky because:
2579
- * 1. we can't do transfer completion while holding flying_transfers_lock
2580
- * because the completion handler may try to re-submit the transfer
2581
- * 2. the transfers list can change underneath us - if we were to build a
2582
- * list of transfers to complete (while holding lock), the situation
2583
- * might be different by the time we come to free them
2584
- *
2585
- * so we resort to a loop-based approach as below
2586
- *
2587
- * This is safe because transfers are only removed from the
2588
- * flying_transfer list by usbi_handle_transfer_completion and
2589
- * libusb_close, both of which hold the events_lock while doing so,
2590
- * so usbi_handle_disconnect cannot be running at the same time.
2591
- *
2592
- * Note that libusb_submit_transfer also removes the transfer from
2593
- * the flying_transfer list on submission failure, but it keeps the
2594
- * flying_transfer list locked between addition and removal, so
2595
- * usbi_handle_disconnect never sees such transfers.
2722
+ * when we find a transfer for this device on the list, there are two
2723
+ * possible scenarios:
2724
+ * 1. the transfer is currently in-flight, in which case we terminate the
2725
+ * transfer here
2726
+ * 2. the transfer is not in-flight (or is but hasn't been marked as such),
2727
+ * in which case we record that the device disappeared and this will be
2728
+ * handled by libusb_submit_transfer()
2596
2729
  */
2597
2730
 
2598
2731
  while (1) {
2599
- usbi_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock);
2600
2732
  to_cancel = NULL;
2733
+ usbi_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock);
2601
2734
  list_for_each_entry(cur, &HANDLE_CTX(handle)->flying_transfers, list, struct usbi_transfer)
2602
2735
  if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == handle) {
2603
- to_cancel = cur;
2604
- break;
2736
+ usbi_mutex_lock(&cur->flags_lock);
2737
+ if (cur->flags & USBI_TRANSFER_IN_FLIGHT)
2738
+ to_cancel = cur;
2739
+ else
2740
+ cur->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED;
2741
+ usbi_mutex_unlock(&cur->flags_lock);
2742
+
2743
+ if (to_cancel)
2744
+ break;
2605
2745
  }
2606
2746
  usbi_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock);
2607
2747
 
@@ -2611,7 +2751,9 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle)
2611
2751
  usbi_dbg("cancelling transfer %p from disconnect",
2612
2752
  USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
2613
2753
 
2754
+ usbi_mutex_lock(&to_cancel->lock);
2614
2755
  usbi_backend->clear_transfer_priv(to_cancel);
2756
+ usbi_mutex_unlock(&to_cancel->lock);
2615
2757
  usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
2616
2758
  }
2617
2759