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