libusb 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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