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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +1 -0
- data/History.md +8 -0
- data/README.md +5 -15
- data/Rakefile +8 -1
- data/ext/extconf.rb +49 -12
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/AUTHORS +12 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/COPYING +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/ChangeLog +18 -2
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/INSTALL +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Makefile.in +31 -18
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/NEWS +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/PORTING +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/README +5 -3
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/TODO +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/common.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/config.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/debug.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb.xcconfig +0 -0
- data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +865 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb_debug.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb_release.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/release.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/aclocal.m4 +35 -32
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/README +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/config.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/Android.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/Application.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/examples.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/libusb.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/tests.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/compile +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.guess +13 -160
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.h.in +6 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.sub +26 -12
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/configure +244 -20
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/configure.ac +27 -4
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/depcomp +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/doc/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/doc/Makefile.in +19 -6
- data/ext/libusb-1.0.20/doc/doxygen.cfg.in +2334 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/Makefile.in +19 -6
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/dpfp.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/dpfp_threaded.c +15 -10
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/ezusb.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/ezusb.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/fxload.c +28 -7
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt1.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/hotplugtest.c +21 -3
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/listdevs.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/sam3u_benchmark.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/xusb.c +2 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/install-sh +170 -196
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb-1.0.pc.in +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/Makefile.am +15 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/Makefile.in +192 -53
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/core.c +218 -100
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/descriptor.c +3 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/hotplug.c +26 -9
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/hotplug.h +8 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/io.c +432 -290
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb-1.0.def +2 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb-1.0.rc +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb.h +11 -10
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusbi.h +106 -29
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/darwin_usb.c +27 -67
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/darwin_usb.h +3 -7
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +5 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +810 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +1193 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/compile +347 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +1421 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +1807 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/configure +17579 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +8 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +791 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +378 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +112 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +550 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +255 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +180 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +501 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/ltmain.sh +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/libtool.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltoptions.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltsugar.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltversion.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/lt~obsolete.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/missing +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_netlink.c +4 -4
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_udev.c +1 -2
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_usbfs.c +46 -49
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_usbfs.h +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/netbsd_usb.c +9 -73
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/openbsd_usb.c +9 -73
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_posix.c +2 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_posix.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_windows.c +3 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_windows.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_posix.c +3 -3
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_posix.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_windows.c +3 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_windows.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/wince_usb.c +87 -250
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/wince_usb.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_common.h +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_usb.c +267 -181
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_usb.h +22 -7
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/strerror.c +5 -2
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/sync.c +2 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/version.h +1 -1
- data/ext/libusb-1.0.20/libusb/version_nano.h +1 -0
- data/ext/libusb-1.0.20/ltmain.sh +9655 -0
- data/ext/libusb-1.0.20/m4/libtool.m4 +7992 -0
- data/ext/libusb-1.0.20/m4/ltoptions.m4 +384 -0
- data/ext/libusb-1.0.20/m4/ltsugar.m4 +123 -0
- data/ext/libusb-1.0.20/m4/ltversion.m4 +23 -0
- data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +98 -0
- data/ext/libusb-1.0.20/missing +215 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/Makefile.in +19 -6
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/libusb_testlib.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/stress.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/testlib.c +0 -0
- data/lib/libusb.rb +1 -0
- data/lib/libusb/call.rb +1 -0
- data/lib/libusb/context.rb +5 -2
- data/lib/libusb/stdio.rb +25 -0
- data/lib/libusb/version_gem.rb +1 -1
- data/libusb.gemspec +2 -1
- metadata +152 -115
- metadata.gz.sig +0 -0
- data/ext/libusb-1.0.19/Xcode/libusb.xcodeproj/project.pbxproj +0 -1
- data/ext/libusb-1.0.19/doc/doxygen.cfg.in +0 -1288
- 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
|
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
|
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
|
-
|
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
|
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
|
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
|
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
|
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->
|
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->
|
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->
|
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
|
-
|
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
|
-
|
1162
|
-
|
1163
|
-
|
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->
|
1166
|
-
usbi_close(ctx->
|
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->
|
1180
|
-
usbi_close(ctx->
|
1181
|
-
usbi_close(ctx->
|
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
|
-
|
1321
|
-
|
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
|
-
|
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
|
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 &
|
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
|
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
|
-
|
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
|
1454
|
-
|
1484
|
+
if (r) {
|
1485
|
+
usbi_mutex_lock(&itransfer->flags_lock);
|
1486
|
+
itransfer->flags = 0;
|
1487
|
+
goto out;
|
1455
1488
|
}
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
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
|
-
|
1461
|
-
libusb_ref_device(transfer->dev_handle->dev);
|
1510
|
+
remove = 1;
|
1462
1511
|
}
|
1463
1512
|
out:
|
1464
|
-
|
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
|
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
|
1623
|
+
int r;
|
1567
1624
|
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
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(&
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
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
|
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
|
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->
|
1655
|
-
ru = ctx->
|
1656
|
-
usbi_mutex_unlock(&ctx->
|
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
|
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->
|
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
|
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->
|
1746
|
-
r = ctx->
|
1747
|
-
usbi_mutex_unlock(&ctx->
|
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
|
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
|
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->
|
1774
|
-
r = ctx->
|
1775
|
-
usbi_mutex_unlock(&ctx->
|
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
|
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 |=
|
1946
|
+
itransfer->flags |= USBI_TRANSFER_TIMEOUT_HANDLED;
|
1881
1947
|
r = libusb_cancel_transfer(transfer);
|
1882
|
-
if (r
|
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 & (
|
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
|
-
|
1973
|
-
|
1974
|
-
|
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
|
-
/*
|
1977
|
-
|
1978
|
-
|
1979
|
-
if (
|
1980
|
-
|
1981
|
-
|
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
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
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
|
-
|
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
|
-
|
2008
|
-
free(fds);
|
2107
|
+
else if (r == -1 && errno == EINTR)
|
2009
2108
|
return LIBUSB_ERROR_INTERRUPTED;
|
2010
|
-
|
2011
|
-
|
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
|
-
/*
|
2116
|
+
/* fds[0] is always the event pipe */
|
2019
2117
|
if (fds[0].revents) {
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
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
|
-
|
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
|
-
|
2036
|
-
|
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
|
-
|
2041
|
-
|
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
|
-
/*
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2049
|
-
|
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
|
-
|
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
|
2055
|
-
if (
|
2056
|
-
|
2160
|
+
/* process the hotplug message, if any */
|
2161
|
+
if (message) {
|
2162
|
+
usbi_hotplug_match(ctx, message->device, message->event);
|
2057
2163
|
|
2058
|
-
|
2059
|
-
|
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
|
-
|
2175
|
+
}
|
2176
|
+
|
2177
|
+
if (0 == --r)
|
2178
|
+
goto handled;
|
2179
|
+
}
|
2062
2180
|
|
2063
2181
|
#ifdef USBI_TIMERFD_AVAILABLE
|
2064
|
-
/* on timerfd configurations, fds[
|
2065
|
-
if (usbi_using_timerfd(ctx) && fds[
|
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
|
-
|
2095
|
-
|
2096
|
-
|
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
|
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 & (
|
2509
|
+
if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
|
2400
2510
|
continue;
|
2401
2511
|
|
2402
|
-
/*
|
2512
|
+
/* if we've reached transfers of infinte timeout, we're done looking */
|
2403
2513
|
if (!timerisset(&transfer->timeout))
|
2404
|
-
|
2514
|
+
break;
|
2405
2515
|
|
2406
|
-
|
2516
|
+
next_timeout = transfer->timeout;
|
2407
2517
|
break;
|
2408
2518
|
}
|
2409
2519
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
2410
2520
|
|
2411
|
-
if (!
|
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->
|
2480
|
-
list_add_tail(&ipollfd->list, &ctx->
|
2481
|
-
|
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->
|
2496
|
-
list_for_each_entry(ipollfd, &ctx->
|
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->
|
2630
|
+
usbi_mutex_unlock(&ctx->event_data_lock);
|
2505
2631
|
return;
|
2506
2632
|
}
|
2507
2633
|
|
2508
2634
|
list_del(&ipollfd->list);
|
2509
|
-
|
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
|
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->
|
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(
|
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->
|
2674
|
+
list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
|
2550
2675
|
ret[i++] = (struct libusb_pollfd *) ipollfd;
|
2551
|
-
ret[
|
2676
|
+
ret[ctx->pollfds_cnt] = NULL;
|
2552
2677
|
|
2553
2678
|
out:
|
2554
|
-
usbi_mutex_unlock(&ctx->
|
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
|
-
*
|
2579
|
-
*
|
2580
|
-
*
|
2581
|
-
*
|
2582
|
-
*
|
2583
|
-
*
|
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
|
-
|
2604
|
-
|
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
|
|