usb 2.1.3 → 2.3.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.
- package/CHANGELOG.md +23 -0
- package/README.md +19 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/usb/bindings.d.ts +4 -0
- package/dist/usb/device.js +5 -0
- package/dist/usb/device.js.map +1 -1
- package/dist/usb/index.js +7 -16
- package/dist/usb/index.js.map +1 -1
- package/dist/webusb/webusb-device.d.ts +0 -1
- package/dist/webusb/webusb-device.js +149 -243
- package/dist/webusb/webusb-device.js.map +1 -1
- package/libusb/.gitattributes +2 -6
- package/libusb/.private/appveyor_build.sh +22 -0
- package/libusb/.private/bm.sh +1 -1
- package/libusb/.private/ci-build.sh +67 -0
- package/libusb/.private/ci-container-build.sh +70 -0
- package/libusb/.private/post-rewrite.sh +5 -1
- package/libusb/.private/pre-commit.sh +5 -1
- package/libusb/.private/wbs.txt +4 -19
- package/libusb/.travis.yml +32 -23
- package/libusb/AUTHORS +86 -3
- package/libusb/ChangeLog +54 -3
- package/libusb/INSTALL_WIN.txt +22 -44
- package/libusb/Makefile.am +32 -10
- package/libusb/{README.md → README} +2 -2
- package/libusb/README.git +3 -3
- package/libusb/Xcode/common.xcconfig +23 -19
- package/libusb/Xcode/config.h +25 -13
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +511 -109
- package/libusb/android/README +90 -54
- package/libusb/android/config.h +23 -43
- package/libusb/android/examples/unrooted_android.c +300 -0
- package/libusb/android/examples/unrooted_android.h +36 -0
- package/libusb/android/jni/Android.mk +1 -1
- package/libusb/android/jni/Application.mk +16 -0
- package/libusb/android/jni/examples.mk +63 -29
- package/libusb/android/jni/libusb.mk +14 -8
- package/libusb/android/jni/tests.mk +13 -24
- package/libusb/appveyor.yml +73 -30
- package/libusb/autogen.sh +5 -3
- package/libusb/bootstrap.sh +6 -2
- package/libusb/configure.ac +314 -227
- package/libusb/doc/Makefile.in +22 -0
- package/libusb/doc/doxygen.cfg.in +460 -223
- package/libusb/examples/Makefile.am +6 -13
- package/libusb/examples/dpfp.c +276 -73
- package/libusb/examples/ezusb.c +18 -8
- package/libusb/examples/ezusb.h +6 -17
- package/libusb/examples/fxload.c +4 -5
- package/libusb/examples/hotplugtest.c +1 -1
- package/libusb/examples/sam3u_benchmark.c +59 -24
- package/libusb/examples/testlibusb.c +138 -104
- package/libusb/examples/xusb.c +26 -22
- package/libusb/libusb/Makefile.am +57 -70
- package/libusb/libusb/Makefile.am.extra +26 -0
- package/libusb/libusb/core.c +432 -423
- package/libusb/libusb/descriptor.c +365 -419
- package/libusb/libusb/hotplug.c +200 -104
- package/libusb/libusb/io.c +522 -535
- package/libusb/libusb/libusb-1.0.def +7 -3
- package/libusb/libusb/libusb-1.0.rc +1 -9
- package/libusb/libusb/libusb.h +302 -226
- package/libusb/libusb/libusbi.h +607 -316
- package/libusb/libusb/os/darwin_usb.c +703 -329
- package/libusb/libusb/os/darwin_usb.h +39 -15
- package/libusb/libusb/os/events_posix.c +300 -0
- package/libusb/libusb/os/events_posix.h +59 -0
- package/libusb/libusb/os/events_windows.c +214 -0
- package/libusb/{msvc/missing.h → libusb/os/events_windows.h} +25 -11
- package/libusb/libusb/os/haiku_pollfs.cpp +14 -9
- package/libusb/libusb/os/haiku_usb.h +12 -12
- package/libusb/libusb/os/haiku_usb_backend.cpp +36 -37
- package/libusb/libusb/os/haiku_usb_raw.cpp +80 -116
- package/libusb/libusb/os/linux_netlink.c +55 -63
- package/libusb/libusb/os/linux_udev.c +61 -69
- package/libusb/libusb/os/linux_usbfs.c +926 -1015
- package/libusb/libusb/os/linux_usbfs.h +74 -57
- package/libusb/libusb/os/netbsd_usb.c +103 -168
- package/libusb/libusb/os/null_usb.c +111 -0
- package/libusb/libusb/os/openbsd_usb.c +71 -120
- package/libusb/libusb/os/sunos_usb.c +289 -375
- package/libusb/libusb/os/sunos_usb.h +0 -1
- package/libusb/libusb/os/threads_posix.c +81 -32
- package/libusb/libusb/os/threads_posix.h +19 -23
- package/libusb/libusb/os/threads_windows.c +9 -95
- package/libusb/libusb/os/threads_windows.h +33 -31
- package/libusb/libusb/os/windows_common.c +915 -0
- package/libusb/libusb/os/windows_common.h +330 -42
- package/libusb/libusb/os/windows_usbdk.c +161 -267
- package/libusb/libusb/os/windows_usbdk.h +5 -2
- package/libusb/libusb/os/windows_winusb.c +1355 -1192
- package/libusb/libusb/os/windows_winusb.h +167 -167
- package/libusb/libusb/strerror.c +20 -30
- package/libusb/libusb/sync.c +20 -21
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/.gitattributes +3 -0
- package/libusb/msvc/config.h +27 -20
- package/libusb/msvc/{hotplugtest_2012.vcxproj → dpfp_2013.vcxproj} +14 -10
- package/libusb/msvc/dpfp_2013.vcxproj.filters +26 -0
- package/libusb/msvc/{hotplugtest_2010.vcxproj → dpfp_2015.vcxproj} +14 -9
- package/libusb/msvc/dpfp_2015.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_2017.vcxproj +106 -0
- package/libusb/msvc/dpfp_2017.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_2019.vcxproj +106 -0
- package/libusb/msvc/dpfp_2019.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_threaded_2013.vcxproj +87 -0
- package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_threaded_2015.vcxproj +87 -0
- package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +26 -0
- package/libusb/msvc/dpfp_threaded_2017.vcxproj +106 -0
- package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +26 -0
- package/libusb/msvc/{fxload_2012.vcxproj → dpfp_threaded_2019.vcxproj} +32 -17
- package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +26 -0
- package/libusb/msvc/fxload_2013.vcxproj +6 -3
- package/libusb/msvc/fxload_2013.vcxproj.filters +35 -0
- package/libusb/msvc/fxload_2015.vcxproj +6 -3
- package/libusb/msvc/fxload_2015.vcxproj.filters +35 -0
- package/libusb/msvc/fxload_2017.vcxproj +6 -7
- package/libusb/msvc/fxload_2017.vcxproj.filters +35 -0
- package/libusb/msvc/{fxload_2010.vcxproj → fxload_2019.vcxproj} +29 -6
- package/libusb/msvc/fxload_2019.vcxproj.filters +35 -0
- package/libusb/{examples → msvc}/getopt/getopt.c +0 -0
- package/libusb/{examples → msvc}/getopt/getopt.h +0 -0
- package/libusb/{examples → msvc}/getopt/getopt1.c +0 -0
- package/libusb/msvc/getopt_2013.vcxproj +4 -5
- package/libusb/msvc/getopt_2013.vcxproj.filters +26 -0
- package/libusb/msvc/getopt_2015.vcxproj +4 -4
- package/libusb/msvc/getopt_2015.vcxproj.filters +26 -0
- package/libusb/msvc/getopt_2017.vcxproj +4 -10
- package/libusb/msvc/getopt_2017.vcxproj.filters +26 -0
- package/libusb/msvc/{getopt_2010.vcxproj → getopt_2019.vcxproj} +25 -5
- package/libusb/msvc/getopt_2019.vcxproj.filters +26 -0
- package/libusb/msvc/hotplugtest_2013.vcxproj +6 -3
- package/libusb/msvc/hotplugtest_2013.vcxproj.filters +23 -0
- package/libusb/msvc/hotplugtest_2015.vcxproj +6 -3
- package/libusb/msvc/hotplugtest_2015.vcxproj.filters +23 -0
- package/libusb/msvc/hotplugtest_2017.vcxproj +6 -7
- package/libusb/msvc/hotplugtest_2017.vcxproj.filters +23 -0
- package/libusb/msvc/hotplugtest_2019.vcxproj +105 -0
- package/libusb/msvc/hotplugtest_2019.vcxproj.filters +23 -0
- package/libusb/msvc/libusb_2013.sln +50 -20
- package/libusb/msvc/libusb_2015.sln +51 -21
- package/libusb/msvc/libusb_2017.sln +90 -36
- package/libusb/msvc/libusb_2019.sln +240 -0
- package/libusb/msvc/libusb_dll_2013.vcxproj +6 -9
- package/libusb/msvc/libusb_dll_2013.vcxproj.filters +94 -0
- package/libusb/msvc/libusb_dll_2015.vcxproj +6 -8
- package/libusb/msvc/libusb_dll_2015.vcxproj.filters +94 -0
- package/libusb/msvc/libusb_dll_2017.vcxproj +6 -16
- package/libusb/msvc/libusb_dll_2017.vcxproj.filters +94 -0
- package/libusb/msvc/{libusb_dll_2010.vcxproj → libusb_dll_2019.vcxproj} +27 -9
- package/libusb/msvc/libusb_dll_2019.vcxproj.filters +94 -0
- package/libusb/msvc/libusb_static_2013.vcxproj +5 -9
- package/libusb/msvc/libusb_static_2013.vcxproj.filters +80 -0
- package/libusb/msvc/libusb_static_2015.vcxproj +5 -8
- package/libusb/msvc/libusb_static_2015.vcxproj.filters +80 -0
- package/libusb/msvc/libusb_static_2017.vcxproj +5 -8
- package/libusb/msvc/libusb_static_2017.vcxproj.filters +80 -0
- package/libusb/msvc/{libusb_static_2010.vcxproj → libusb_static_2019.vcxproj} +26 -9
- package/libusb/msvc/libusb_static_2019.vcxproj.filters +80 -0
- package/libusb/msvc/listdevs_2013.vcxproj +6 -3
- package/libusb/msvc/listdevs_2013.vcxproj.filters +23 -0
- package/libusb/msvc/listdevs_2015.vcxproj +6 -3
- package/libusb/msvc/listdevs_2015.vcxproj.filters +23 -0
- package/libusb/msvc/listdevs_2017.vcxproj +6 -7
- package/libusb/msvc/listdevs_2017.vcxproj.filters +23 -0
- package/libusb/msvc/listdevs_2019.vcxproj +105 -0
- package/libusb/msvc/listdevs_2019.vcxproj.filters +23 -0
- package/libusb/msvc/{listdevs_2010.vcxproj → sam3u_benchmark_2013.vcxproj} +13 -8
- package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +26 -0
- package/libusb/msvc/{listdevs_2012.vcxproj → sam3u_benchmark_2015.vcxproj} +13 -9
- package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +26 -0
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj +106 -0
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +26 -0
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj +106 -0
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +26 -0
- package/libusb/msvc/stress_2013.vcxproj +4 -2
- package/libusb/msvc/stress_2013.vcxproj.filters +32 -0
- package/libusb/msvc/stress_2015.vcxproj +4 -2
- package/libusb/msvc/stress_2015.vcxproj.filters +32 -0
- package/libusb/msvc/stress_2017.vcxproj +4 -6
- package/libusb/msvc/stress_2017.vcxproj.filters +32 -0
- package/libusb/msvc/{stress_2010.vcxproj → stress_2019.vcxproj} +26 -4
- package/libusb/msvc/stress_2019.vcxproj.filters +32 -0
- package/libusb/msvc/testlibusb_2013.vcxproj +6 -3
- package/libusb/msvc/testlibusb_2013.vcxproj.filters +23 -0
- package/libusb/msvc/testlibusb_2015.vcxproj +6 -3
- package/libusb/msvc/testlibusb_2015.vcxproj.filters +23 -0
- package/libusb/msvc/testlibusb_2017.vcxproj +6 -7
- package/libusb/msvc/testlibusb_2017.vcxproj.filters +23 -0
- package/libusb/msvc/{testlibusb_2010.vcxproj → testlibusb_2019.vcxproj} +28 -5
- package/libusb/msvc/testlibusb_2019.vcxproj.filters +23 -0
- package/libusb/msvc/xusb_2013.vcxproj +6 -3
- package/libusb/msvc/xusb_2013.vcxproj.filters +23 -0
- package/libusb/msvc/xusb_2015.vcxproj +6 -3
- package/libusb/msvc/xusb_2015.vcxproj.filters +23 -0
- package/libusb/msvc/xusb_2017.vcxproj +6 -7
- package/libusb/msvc/xusb_2017.vcxproj.filters +23 -0
- package/libusb/msvc/{xusb_2010.vcxproj → xusb_2019.vcxproj} +28 -5
- package/libusb/msvc/xusb_2019.vcxproj.filters +23 -0
- package/libusb/tests/Makefile.am +13 -1
- package/libusb/tests/libusb_testlib.h +12 -43
- package/libusb/tests/stress.c +59 -50
- package/libusb/tests/testlib.c +78 -171
- package/libusb/tests/umockdev.c +1175 -0
- package/libusb.gypi +10 -11
- package/package.json +1 -1
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +12 -7
- package/src/node_usb.cc +10 -0
- package/test/usb.coffee +6 -0
- package/tsc/index.ts +2 -0
- package/tsc/usb/bindings.ts +5 -0
- package/tsc/usb/device.ts +6 -0
- package/tsc/usb/index.ts +5 -8
- package/tsc/webusb/webusb-device.ts +67 -124
- package/dist/webusb/mutex.d.ts +0 -22
- package/dist/webusb/mutex.js +0 -89
- package/dist/webusb/mutex.js.map +0 -1
- package/libusb/.private/bd.cmd +0 -89
- package/libusb/.private/bwince.cmd +0 -57
- package/libusb/.private/wbs_wince.txt +0 -42
- package/libusb/Brewfile +0 -4
- package/libusb/appveyor_cygwin.bat +0 -11
- package/libusb/appveyor_minGW.bat +0 -19
- package/libusb/doc/Makefile.am +0 -9
- package/libusb/examples/dpfp_threaded.c +0 -557
- package/libusb/libusb/hotplug.h +0 -99
- package/libusb/libusb/os/poll_posix.c +0 -84
- package/libusb/libusb/os/poll_posix.h +0 -14
- package/libusb/libusb/os/poll_windows.c +0 -447
- package/libusb/libusb/os/poll_windows.h +0 -98
- package/libusb/libusb/os/wince_usb.c +0 -888
- package/libusb/libusb/os/wince_usb.h +0 -126
- package/libusb/libusb/os/windows_nt_common.c +0 -1010
- package/libusb/libusb/os/windows_nt_common.h +0 -110
- package/libusb/libusb/os/windows_nt_shared_types.h +0 -147
- package/libusb/msvc/appveyor.bat +0 -27
- package/libusb/msvc/ddk_build.cmd +0 -219
- package/libusb/msvc/errno.h +0 -102
- package/libusb/msvc/fxload_sources +0 -23
- package/libusb/msvc/getopt_2005.vcproj +0 -288
- package/libusb/msvc/getopt_2012.vcxproj +0 -73
- package/libusb/msvc/getopt_sources +0 -24
- package/libusb/msvc/hotplugtest_sources +0 -20
- package/libusb/msvc/inttypes.h +0 -295
- package/libusb/msvc/libusb.dsw +0 -71
- package/libusb/msvc/libusb_2005.sln +0 -95
- package/libusb/msvc/libusb_2010.sln +0 -105
- package/libusb/msvc/libusb_2012.sln +0 -105
- package/libusb/msvc/libusb_dll.dsp +0 -194
- package/libusb/msvc/libusb_dll_2005.vcproj +0 -464
- package/libusb/msvc/libusb_dll_2012.vcxproj +0 -107
- package/libusb/msvc/libusb_dll_wince.vcproj +0 -1251
- package/libusb/msvc/libusb_sources +0 -43
- package/libusb/msvc/libusb_static.dsp +0 -174
- package/libusb/msvc/libusb_static_2005.vcproj +0 -390
- package/libusb/msvc/libusb_static_2012.vcxproj +0 -98
- package/libusb/msvc/libusb_static_wince.vcproj +0 -1179
- package/libusb/msvc/libusb_wince.sln +0 -246
- package/libusb/msvc/listdevs.dsp +0 -103
- package/libusb/msvc/listdevs_2005.vcproj +0 -360
- package/libusb/msvc/listdevs_sources +0 -20
- package/libusb/msvc/listdevs_wince.vcproj +0 -1120
- package/libusb/msvc/missing.c +0 -80
- package/libusb/msvc/stdint.h +0 -256
- package/libusb/msvc/stress_2005.vcproj +0 -390
- package/libusb/msvc/stress_2012.vcxproj +0 -87
- package/libusb/msvc/stress_sources +0 -21
- package/libusb/msvc/stress_wince.vcproj +0 -1128
- package/libusb/msvc/testlibusb_2012.vcxproj +0 -83
- package/libusb/msvc/testlibusb_sources +0 -20
- package/libusb/msvc/xusb.dsp +0 -102
- package/libusb/msvc/xusb_2005.vcproj +0 -344
- package/libusb/msvc/xusb_2012.vcxproj +0 -83
- package/libusb/msvc/xusb_sources +0 -20
- package/libusb/msvc/xusb_wince.vcproj +0 -1120
- package/libusb/travis-autogen.sh +0 -39
- package/tsc/webusb/mutex.ts +0 -38
package/libusb/libusb/io.c
CHANGED
|
@@ -21,24 +21,7 @@
|
|
|
21
21
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
#include <config.h>
|
|
25
|
-
|
|
26
|
-
#include <assert.h>
|
|
27
|
-
#include <errno.h>
|
|
28
|
-
#include <stdint.h>
|
|
29
|
-
#include <stdlib.h>
|
|
30
|
-
#include <string.h>
|
|
31
|
-
#include <time.h>
|
|
32
|
-
#ifdef HAVE_SYS_TIME_H
|
|
33
|
-
#include <sys/time.h>
|
|
34
|
-
#endif
|
|
35
|
-
#ifdef USBI_TIMERFD_AVAILABLE
|
|
36
|
-
#include <unistd.h>
|
|
37
|
-
#include <sys/timerfd.h>
|
|
38
|
-
#endif
|
|
39
|
-
|
|
40
24
|
#include "libusbi.h"
|
|
41
|
-
#include "hotplug.h"
|
|
42
25
|
|
|
43
26
|
/**
|
|
44
27
|
* \page libusb_io Synchronous and asynchronous device I/O
|
|
@@ -89,7 +72,7 @@
|
|
|
89
72
|
* a single function call. When the function call returns, the transfer has
|
|
90
73
|
* completed and you can parse the results.
|
|
91
74
|
*
|
|
92
|
-
* If you have used
|
|
75
|
+
* If you have used libusb-0.1 before, this I/O style will seem familiar to
|
|
93
76
|
* you. libusb-0.1 only offered a synchronous interface.
|
|
94
77
|
*
|
|
95
78
|
* In our input device example, to read button presses you might write code
|
|
@@ -115,7 +98,7 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
|
115
98
|
* sleeping for that long. Execution will be tied up inside the library -
|
|
116
99
|
* the entire thread will be useless for that duration.
|
|
117
100
|
*
|
|
118
|
-
* Another issue is that by
|
|
101
|
+
* Another issue is that by tying up the thread with that single transaction
|
|
119
102
|
* there is no possibility of performing I/O with multiple endpoints and/or
|
|
120
103
|
* multiple devices simultaneously, unless you resort to creating one thread
|
|
121
104
|
* per transaction.
|
|
@@ -333,9 +316,40 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
|
333
316
|
* Freeing the transfer after it has been cancelled but before cancellation
|
|
334
317
|
* has completed will result in undefined behaviour.
|
|
335
318
|
*
|
|
319
|
+
* \attention
|
|
336
320
|
* When a transfer is cancelled, some of the data may have been transferred.
|
|
337
|
-
* libusb will communicate this to you in the transfer callback.
|
|
338
|
-
* that no data was transferred
|
|
321
|
+
* libusb will communicate this to you in the transfer callback.
|
|
322
|
+
* <b>Do not assume that no data was transferred.</b>
|
|
323
|
+
*
|
|
324
|
+
* \section asyncpartial Partial data transfer resulting from cancellation
|
|
325
|
+
*
|
|
326
|
+
* As noted above, some of the data may have been transferred at the time a
|
|
327
|
+
* transfer is cancelled. It is helpful to see how this is possible if you
|
|
328
|
+
* consider a bulk transfer to an endpoint with a packet size of 64 bytes.
|
|
329
|
+
* Supposing you submit a 512-byte transfer to this endpoint, the operating
|
|
330
|
+
* system will divide this transfer up into 8 separate 64-byte frames that the
|
|
331
|
+
* host controller will schedule for the device to transfer data. If this
|
|
332
|
+
* transfer is cancelled while the device is transferring data, a subset of
|
|
333
|
+
* these frames may be descheduled from the host controller before the device
|
|
334
|
+
* has the opportunity to finish transferring data to the host.
|
|
335
|
+
*
|
|
336
|
+
* What your application should do with a partial data transfer is a policy
|
|
337
|
+
* decision; there is no single answer that satisfies the needs of every
|
|
338
|
+
* application. The data that was successfully transferred should be
|
|
339
|
+
* considered entirely valid, but your application must decide what to do with
|
|
340
|
+
* the remaining data that was not transferred. Some possible actions to take
|
|
341
|
+
* are:
|
|
342
|
+
* - Resubmit another transfer for the remaining data, possibly with a shorter
|
|
343
|
+
* timeout
|
|
344
|
+
* - Discard the partially transferred data and report an error
|
|
345
|
+
*
|
|
346
|
+
* \section asynctimeout Timeouts
|
|
347
|
+
*
|
|
348
|
+
* When a transfer times out, libusb internally notes this and attempts to
|
|
349
|
+
* cancel the transfer. As noted in \ref asyncpartial "above", it is possible
|
|
350
|
+
* that some of the data may actually have been transferred. Your application
|
|
351
|
+
* should <b>always</b> check how much data was actually transferred once the
|
|
352
|
+
* transfer completes and act accordingly.
|
|
339
353
|
*
|
|
340
354
|
* \section bulk_overflows Overflows on device-to-host bulk/interrupt endpoints
|
|
341
355
|
*
|
|
@@ -393,7 +407,7 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
|
393
407
|
* wLength of the setup packet, rather than the size of the data buffer. So,
|
|
394
408
|
* if your wLength was 4, your transfer's <tt>length</tt> was 12, then you
|
|
395
409
|
* should expect an <tt>actual_length</tt> of 4 to indicate that the data was
|
|
396
|
-
* transferred in
|
|
410
|
+
* transferred in entirety.
|
|
397
411
|
*
|
|
398
412
|
* To simplify parsing of setup packets and obtaining the data from the
|
|
399
413
|
* correct offset, you may wish to use the libusb_control_transfer_get_data()
|
|
@@ -472,14 +486,21 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
|
472
486
|
* libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple()
|
|
473
487
|
* functions may help you here.
|
|
474
488
|
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
489
|
+
* \section asynclimits Transfer length limitations
|
|
490
|
+
*
|
|
491
|
+
* Some operating systems may impose limits on the length of the transfer data
|
|
492
|
+
* buffer or, in the case of isochronous transfers, the length of individual
|
|
493
|
+
* isochronous packets. Such limits can be difficult for libusb to detect, so
|
|
494
|
+
* in most cases the library will simply try and submit the transfer as set up
|
|
495
|
+
* by you. If the transfer fails to submit because it is too large,
|
|
480
496
|
* libusb_submit_transfer() will return
|
|
481
497
|
* \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM".
|
|
482
498
|
*
|
|
499
|
+
* The following are known limits for control transfer lengths. Note that this
|
|
500
|
+
* length includes the 8-byte setup packet.
|
|
501
|
+
* - Linux (4,096 bytes)
|
|
502
|
+
* - Windows (4,096 bytes)
|
|
503
|
+
*
|
|
483
504
|
* \section asyncmem Memory caveats
|
|
484
505
|
*
|
|
485
506
|
* In most circumstances, it is not safe to use stack memory for transfer
|
|
@@ -520,7 +541,14 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
|
520
541
|
* application must call into when libusb has work do to. This gives libusb
|
|
521
542
|
* the opportunity to reap pending transfers, invoke callbacks, etc.
|
|
522
543
|
*
|
|
523
|
-
*
|
|
544
|
+
* \note
|
|
545
|
+
* All event handling is performed by whichever thread calls the
|
|
546
|
+
* libusb_handle_events() function. libusb does not invoke any callbacks
|
|
547
|
+
* outside of this context. Consequently, any callbacks will be run on the
|
|
548
|
+
* thread that calls the libusb_handle_events() function.
|
|
549
|
+
*
|
|
550
|
+
* When to call the libusb_handle_events() function depends on which model
|
|
551
|
+
* your application decides to use. The 2 different approaches:
|
|
524
552
|
*
|
|
525
553
|
* -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated
|
|
526
554
|
* thread.
|
|
@@ -541,7 +569,7 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
|
541
569
|
*
|
|
542
570
|
* Lets begin with stating the obvious: If you're going to use a separate
|
|
543
571
|
* thread for libusb event handling, your callback functions MUST be
|
|
544
|
-
*
|
|
572
|
+
* thread-safe.
|
|
545
573
|
*
|
|
546
574
|
* Other then that doing event handling from a separate thread, is mostly
|
|
547
575
|
* simple. You can use an event thread function as follows:
|
|
@@ -781,7 +809,7 @@ while (user has not requested application exit) {
|
|
|
781
809
|
* system calls. This is directly exposed at the
|
|
782
810
|
* \ref libusb_asyncio "asynchronous interface" but it is important to note that the
|
|
783
811
|
* \ref libusb_syncio "synchronous interface" is implemented on top of the
|
|
784
|
-
*
|
|
812
|
+
* asynchronous interface, therefore the same considerations apply.
|
|
785
813
|
*
|
|
786
814
|
* The issue is that if two or more threads are concurrently calling poll()
|
|
787
815
|
* or select() on libusb's file descriptors then only one of those threads
|
|
@@ -889,6 +917,11 @@ void myfunc() {
|
|
|
889
917
|
* do is submit a single transfer and wait for its completion, then using
|
|
890
918
|
* one of the synchronous I/O functions is much easier.
|
|
891
919
|
*
|
|
920
|
+
* \note
|
|
921
|
+
* The `completed` variable must be modified while holding the event lock,
|
|
922
|
+
* otherwise a race condition can still exist. It is simplest to do so from
|
|
923
|
+
* within the transfer callback as shown above.
|
|
924
|
+
*
|
|
892
925
|
* \section eventlock The events lock
|
|
893
926
|
*
|
|
894
927
|
* The problem is when we consider the fact that libusb exposes file
|
|
@@ -986,7 +1019,7 @@ printf("completed!\n");
|
|
|
986
1019
|
* event handling), because the event waiter seems to have taken the event
|
|
987
1020
|
* waiters lock while waiting for an event. However, the system does support
|
|
988
1021
|
* multiple event waiters, because libusb_wait_for_event() actually drops
|
|
989
|
-
* the lock while waiting, and
|
|
1022
|
+
* the lock while waiting, and reacquires it before continuing.
|
|
990
1023
|
*
|
|
991
1024
|
* We have now implemented code which can dynamically handle situations where
|
|
992
1025
|
* nobody is handling events (so we should do it ourselves), and it can also
|
|
@@ -1131,46 +1164,40 @@ int usbi_io_init(struct libusb_context *ctx)
|
|
|
1131
1164
|
usbi_mutex_init(&ctx->event_data_lock);
|
|
1132
1165
|
usbi_tls_key_create(&ctx->event_handling_key);
|
|
1133
1166
|
list_init(&ctx->flying_transfers);
|
|
1134
|
-
list_init(&ctx->
|
|
1135
|
-
list_init(&ctx->
|
|
1167
|
+
list_init(&ctx->event_sources);
|
|
1168
|
+
list_init(&ctx->removed_event_sources);
|
|
1136
1169
|
list_init(&ctx->hotplug_msgs);
|
|
1137
1170
|
list_init(&ctx->completed_transfers);
|
|
1138
1171
|
|
|
1139
|
-
|
|
1140
|
-
r
|
|
1141
|
-
if (r < 0) {
|
|
1142
|
-
r = LIBUSB_ERROR_OTHER;
|
|
1172
|
+
r = usbi_create_event(&ctx->event);
|
|
1173
|
+
if (r < 0)
|
|
1143
1174
|
goto err;
|
|
1144
|
-
}
|
|
1145
1175
|
|
|
1146
|
-
r =
|
|
1176
|
+
r = usbi_add_event_source(ctx, USBI_EVENT_OS_HANDLE(&ctx->event), USBI_EVENT_POLL_EVENTS);
|
|
1147
1177
|
if (r < 0)
|
|
1148
|
-
goto
|
|
1149
|
-
|
|
1150
|
-
#ifdef
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN);
|
|
1178
|
+
goto err_destroy_event;
|
|
1179
|
+
|
|
1180
|
+
#ifdef HAVE_OS_TIMER
|
|
1181
|
+
r = usbi_create_timer(&ctx->timer);
|
|
1182
|
+
if (r == 0) {
|
|
1183
|
+
usbi_dbg(ctx, "using timer for timeouts");
|
|
1184
|
+
r = usbi_add_event_source(ctx, USBI_TIMER_OS_HANDLE(&ctx->timer), USBI_TIMER_POLL_EVENTS);
|
|
1156
1185
|
if (r < 0)
|
|
1157
|
-
goto
|
|
1186
|
+
goto err_destroy_timer;
|
|
1158
1187
|
} else {
|
|
1159
|
-
usbi_dbg("
|
|
1160
|
-
ctx->timerfd = -1;
|
|
1188
|
+
usbi_dbg(ctx, "timer not available for timeouts");
|
|
1161
1189
|
}
|
|
1162
1190
|
#endif
|
|
1163
1191
|
|
|
1164
1192
|
return 0;
|
|
1165
1193
|
|
|
1166
|
-
#ifdef
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1194
|
+
#ifdef HAVE_OS_TIMER
|
|
1195
|
+
err_destroy_timer:
|
|
1196
|
+
usbi_destroy_timer(&ctx->timer);
|
|
1197
|
+
usbi_remove_event_source(ctx, USBI_EVENT_OS_HANDLE(&ctx->event));
|
|
1170
1198
|
#endif
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
usbi_close(ctx->event_pipe[1]);
|
|
1199
|
+
err_destroy_event:
|
|
1200
|
+
usbi_destroy_event(&ctx->event);
|
|
1174
1201
|
err:
|
|
1175
1202
|
usbi_mutex_destroy(&ctx->flying_transfers_lock);
|
|
1176
1203
|
usbi_mutex_destroy(&ctx->events_lock);
|
|
@@ -1181,65 +1208,54 @@ err:
|
|
|
1181
1208
|
return r;
|
|
1182
1209
|
}
|
|
1183
1210
|
|
|
1184
|
-
static void
|
|
1211
|
+
static void cleanup_removed_event_sources(struct libusb_context *ctx)
|
|
1185
1212
|
{
|
|
1186
|
-
struct
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1213
|
+
struct usbi_event_source *ievent_source, *tmp;
|
|
1214
|
+
|
|
1215
|
+
for_each_removed_event_source_safe(ctx, ievent_source, tmp) {
|
|
1216
|
+
list_del(&ievent_source->list);
|
|
1217
|
+
free(ievent_source);
|
|
1190
1218
|
}
|
|
1191
1219
|
}
|
|
1192
1220
|
|
|
1193
1221
|
void usbi_io_exit(struct libusb_context *ctx)
|
|
1194
1222
|
{
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
if (usbi_using_timerfd(ctx)) {
|
|
1200
|
-
usbi_remove_pollfd(ctx, ctx->timerfd);
|
|
1201
|
-
close(ctx->timerfd);
|
|
1223
|
+
#ifdef HAVE_OS_TIMER
|
|
1224
|
+
if (usbi_using_timer(ctx)) {
|
|
1225
|
+
usbi_remove_event_source(ctx, USBI_TIMER_OS_HANDLE(&ctx->timer));
|
|
1226
|
+
usbi_destroy_timer(&ctx->timer);
|
|
1202
1227
|
}
|
|
1203
1228
|
#endif
|
|
1229
|
+
usbi_remove_event_source(ctx, USBI_EVENT_OS_HANDLE(&ctx->event));
|
|
1230
|
+
usbi_destroy_event(&ctx->event);
|
|
1204
1231
|
usbi_mutex_destroy(&ctx->flying_transfers_lock);
|
|
1205
1232
|
usbi_mutex_destroy(&ctx->events_lock);
|
|
1206
1233
|
usbi_mutex_destroy(&ctx->event_waiters_lock);
|
|
1207
1234
|
usbi_cond_destroy(&ctx->event_waiters_cond);
|
|
1208
1235
|
usbi_mutex_destroy(&ctx->event_data_lock);
|
|
1209
1236
|
usbi_tls_key_delete(ctx->event_handling_key);
|
|
1210
|
-
|
|
1211
|
-
|
|
1237
|
+
cleanup_removed_event_sources(ctx);
|
|
1238
|
+
free(ctx->event_data);
|
|
1212
1239
|
}
|
|
1213
1240
|
|
|
1214
|
-
static
|
|
1241
|
+
static void calculate_timeout(struct usbi_transfer *itransfer)
|
|
1215
1242
|
{
|
|
1216
|
-
int r;
|
|
1217
|
-
struct timespec current_time;
|
|
1218
1243
|
unsigned int timeout =
|
|
1219
|
-
USBI_TRANSFER_TO_LIBUSB_TRANSFER(
|
|
1244
|
+
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout;
|
|
1220
1245
|
|
|
1221
1246
|
if (!timeout) {
|
|
1222
|
-
|
|
1223
|
-
return
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time);
|
|
1227
|
-
if (r < 0) {
|
|
1228
|
-
usbi_err(ITRANSFER_CTX(transfer),
|
|
1229
|
-
"failed to read monotonic clock, errno=%d", errno);
|
|
1230
|
-
return r;
|
|
1247
|
+
TIMESPEC_CLEAR(&itransfer->timeout);
|
|
1248
|
+
return;
|
|
1231
1249
|
}
|
|
1232
1250
|
|
|
1233
|
-
|
|
1234
|
-
current_time.tv_nsec += (timeout % 1000) * 1000000;
|
|
1251
|
+
usbi_get_monotonic_time(&itransfer->timeout);
|
|
1235
1252
|
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1253
|
+
itransfer->timeout.tv_sec += timeout / 1000U;
|
|
1254
|
+
itransfer->timeout.tv_nsec += (timeout % 1000U) * 1000000L;
|
|
1255
|
+
if (itransfer->timeout.tv_nsec >= NSEC_PER_SEC) {
|
|
1256
|
+
++itransfer->timeout.tv_sec;
|
|
1257
|
+
itransfer->timeout.tv_nsec -= NSEC_PER_SEC;
|
|
1239
1258
|
}
|
|
1240
|
-
|
|
1241
|
-
TIMESPEC_TO_TIMEVAL(&transfer->timeout, ¤t_time);
|
|
1242
|
-
return 0;
|
|
1243
1259
|
}
|
|
1244
1260
|
|
|
1245
1261
|
/** \ingroup libusb_asyncio
|
|
@@ -1269,26 +1285,30 @@ DEFAULT_VISIBILITY
|
|
|
1269
1285
|
struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
|
|
1270
1286
|
int iso_packets)
|
|
1271
1287
|
{
|
|
1272
|
-
|
|
1273
|
-
size_t os_alloc_size;
|
|
1288
|
+
size_t priv_size;
|
|
1274
1289
|
size_t alloc_size;
|
|
1290
|
+
unsigned char *ptr;
|
|
1275
1291
|
struct usbi_transfer *itransfer;
|
|
1292
|
+
struct libusb_transfer *transfer;
|
|
1276
1293
|
|
|
1277
1294
|
assert(iso_packets >= 0);
|
|
1295
|
+
if (iso_packets < 0)
|
|
1296
|
+
return NULL;
|
|
1278
1297
|
|
|
1279
|
-
|
|
1280
|
-
alloc_size =
|
|
1298
|
+
priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
|
|
1299
|
+
alloc_size = priv_size
|
|
1300
|
+
+ sizeof(struct usbi_transfer)
|
|
1281
1301
|
+ sizeof(struct libusb_transfer)
|
|
1282
|
-
+ (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets)
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
if (!itransfer)
|
|
1302
|
+
+ (sizeof(struct libusb_iso_packet_descriptor) * (size_t)iso_packets);
|
|
1303
|
+
ptr = calloc(1, alloc_size);
|
|
1304
|
+
if (!ptr)
|
|
1286
1305
|
return NULL;
|
|
1287
1306
|
|
|
1307
|
+
itransfer = (struct usbi_transfer *)(ptr + priv_size);
|
|
1288
1308
|
itransfer->num_iso_packets = iso_packets;
|
|
1309
|
+
itransfer->priv = ptr;
|
|
1289
1310
|
usbi_mutex_init(&itransfer->lock);
|
|
1290
1311
|
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1291
|
-
usbi_dbg("transfer %p", transfer);
|
|
1292
1312
|
return transfer;
|
|
1293
1313
|
}
|
|
1294
1314
|
|
|
@@ -1312,67 +1332,60 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
|
|
|
1312
1332
|
void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
|
|
1313
1333
|
{
|
|
1314
1334
|
struct usbi_transfer *itransfer;
|
|
1335
|
+
size_t priv_size;
|
|
1336
|
+
unsigned char *ptr;
|
|
1337
|
+
|
|
1315
1338
|
if (!transfer)
|
|
1316
1339
|
return;
|
|
1317
1340
|
|
|
1318
|
-
usbi_dbg("transfer %p", transfer);
|
|
1341
|
+
usbi_dbg(TRANSFER_CTX(transfer), "transfer %p", transfer);
|
|
1319
1342
|
if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
|
|
1320
1343
|
free(transfer->buffer);
|
|
1321
1344
|
|
|
1322
1345
|
itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
|
|
1323
1346
|
usbi_mutex_destroy(&itransfer->lock);
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
#ifdef USBI_TIMERFD_AVAILABLE
|
|
1328
|
-
static int disarm_timerfd(struct libusb_context *ctx)
|
|
1329
|
-
{
|
|
1330
|
-
const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } };
|
|
1331
|
-
int r;
|
|
1347
|
+
if (itransfer->dev)
|
|
1348
|
+
libusb_unref_device(itransfer->dev);
|
|
1332
1349
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
else
|
|
1338
|
-
return 0;
|
|
1350
|
+
priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
|
|
1351
|
+
ptr = (unsigned char *)itransfer - priv_size;
|
|
1352
|
+
assert(ptr == itransfer->priv);
|
|
1353
|
+
free(ptr);
|
|
1339
1354
|
}
|
|
1340
1355
|
|
|
1341
|
-
/* iterates through the flying transfers, and rearms the
|
|
1356
|
+
/* iterates through the flying transfers, and rearms the timer based on the
|
|
1342
1357
|
* next upcoming timeout.
|
|
1343
1358
|
* must be called with flying_list locked.
|
|
1344
1359
|
* returns 0 on success or a LIBUSB_ERROR code on failure.
|
|
1345
1360
|
*/
|
|
1346
|
-
|
|
1361
|
+
#ifdef HAVE_OS_TIMER
|
|
1362
|
+
static int arm_timer_for_next_timeout(struct libusb_context *ctx)
|
|
1347
1363
|
{
|
|
1348
|
-
struct usbi_transfer *
|
|
1364
|
+
struct usbi_transfer *itransfer;
|
|
1349
1365
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1366
|
+
if (!usbi_using_timer(ctx))
|
|
1367
|
+
return 0;
|
|
1368
|
+
|
|
1369
|
+
for_each_transfer(ctx, itransfer) {
|
|
1370
|
+
struct timespec *cur_ts = &itransfer->timeout;
|
|
1352
1371
|
|
|
1353
1372
|
/* if we've reached transfers of infinite timeout, then we have no
|
|
1354
1373
|
* arming to do */
|
|
1355
|
-
if (!
|
|
1356
|
-
|
|
1374
|
+
if (!TIMESPEC_IS_SET(cur_ts))
|
|
1375
|
+
break;
|
|
1357
1376
|
|
|
1358
1377
|
/* act on first transfer that has not already been handled */
|
|
1359
|
-
if (!(
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
{ cur_tv->tv_sec, cur_tv->tv_usec * 1000 } };
|
|
1363
|
-
usbi_dbg("next timeout originally %dms", USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout);
|
|
1364
|
-
r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
|
|
1365
|
-
if (r < 0)
|
|
1366
|
-
return LIBUSB_ERROR_OTHER;
|
|
1367
|
-
return 0;
|
|
1378
|
+
if (!(itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) {
|
|
1379
|
+
usbi_dbg(ctx, "next timeout originally %ums", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout);
|
|
1380
|
+
return usbi_arm_timer(&ctx->timer, cur_ts);
|
|
1368
1381
|
}
|
|
1369
1382
|
}
|
|
1370
1383
|
|
|
1371
|
-
|
|
1372
|
-
return
|
|
1384
|
+
usbi_dbg(ctx, "no timeouts, disarming timer");
|
|
1385
|
+
return usbi_disarm_timer(&ctx->timer);
|
|
1373
1386
|
}
|
|
1374
1387
|
#else
|
|
1375
|
-
static int
|
|
1388
|
+
static inline int arm_timer_for_next_timeout(struct libusb_context *ctx)
|
|
1376
1389
|
{
|
|
1377
1390
|
UNUSED(ctx);
|
|
1378
1391
|
return 0;
|
|
@@ -1382,40 +1395,36 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
|
|
|
1382
1395
|
/* add a transfer to the (timeout-sorted) active transfers list.
|
|
1383
1396
|
* This function will return non 0 if fails to update the timer,
|
|
1384
1397
|
* in which case the transfer is *not* on the flying_transfers list. */
|
|
1385
|
-
static int add_to_flying_list(struct usbi_transfer *
|
|
1398
|
+
static int add_to_flying_list(struct usbi_transfer *itransfer)
|
|
1386
1399
|
{
|
|
1387
1400
|
struct usbi_transfer *cur;
|
|
1388
|
-
struct
|
|
1389
|
-
struct libusb_context *ctx = ITRANSFER_CTX(
|
|
1390
|
-
int r;
|
|
1401
|
+
struct timespec *timeout = &itransfer->timeout;
|
|
1402
|
+
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
|
|
1403
|
+
int r = 0;
|
|
1391
1404
|
int first = 1;
|
|
1392
1405
|
|
|
1393
|
-
|
|
1394
|
-
if (r)
|
|
1395
|
-
return r;
|
|
1406
|
+
calculate_timeout(itransfer);
|
|
1396
1407
|
|
|
1397
1408
|
/* if we have no other flying transfers, start the list with this one */
|
|
1398
1409
|
if (list_empty(&ctx->flying_transfers)) {
|
|
1399
|
-
list_add(&
|
|
1410
|
+
list_add(&itransfer->list, &ctx->flying_transfers);
|
|
1400
1411
|
goto out;
|
|
1401
1412
|
}
|
|
1402
1413
|
|
|
1403
1414
|
/* if we have infinite timeout, append to end of list */
|
|
1404
|
-
if (!
|
|
1405
|
-
list_add_tail(&
|
|
1415
|
+
if (!TIMESPEC_IS_SET(timeout)) {
|
|
1416
|
+
list_add_tail(&itransfer->list, &ctx->flying_transfers);
|
|
1406
1417
|
/* first is irrelevant in this case */
|
|
1407
1418
|
goto out;
|
|
1408
1419
|
}
|
|
1409
1420
|
|
|
1410
1421
|
/* otherwise, find appropriate place in list */
|
|
1411
|
-
|
|
1422
|
+
for_each_transfer(ctx, cur) {
|
|
1412
1423
|
/* find first timeout that occurs after the transfer in question */
|
|
1413
|
-
struct
|
|
1424
|
+
struct timespec *cur_ts = &cur->timeout;
|
|
1414
1425
|
|
|
1415
|
-
if (!
|
|
1416
|
-
|
|
1417
|
-
cur_tv->tv_usec > timeout->tv_usec)) {
|
|
1418
|
-
list_add_tail(&transfer->list, &cur->list);
|
|
1426
|
+
if (!TIMESPEC_IS_SET(cur_ts) || TIMESPEC_CMP(cur_ts, timeout, >)) {
|
|
1427
|
+
list_add_tail(&itransfer->list, &cur->list);
|
|
1419
1428
|
goto out;
|
|
1420
1429
|
}
|
|
1421
1430
|
first = 0;
|
|
@@ -1423,28 +1432,22 @@ static int add_to_flying_list(struct usbi_transfer *transfer)
|
|
|
1423
1432
|
/* first is 0 at this stage (list not empty) */
|
|
1424
1433
|
|
|
1425
1434
|
/* otherwise we need to be inserted at the end */
|
|
1426
|
-
list_add_tail(&
|
|
1435
|
+
list_add_tail(&itransfer->list, &ctx->flying_transfers);
|
|
1427
1436
|
out:
|
|
1428
|
-
#ifdef
|
|
1429
|
-
if (first &&
|
|
1437
|
+
#ifdef HAVE_OS_TIMER
|
|
1438
|
+
if (first && usbi_using_timer(ctx) && TIMESPEC_IS_SET(timeout)) {
|
|
1430
1439
|
/* if this transfer has the lowest timeout of all active transfers,
|
|
1431
|
-
* rearm the
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout);
|
|
1436
|
-
r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL);
|
|
1437
|
-
if (r < 0) {
|
|
1438
|
-
usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno);
|
|
1439
|
-
r = LIBUSB_ERROR_OTHER;
|
|
1440
|
-
}
|
|
1440
|
+
* rearm the timer with this transfer's timeout */
|
|
1441
|
+
usbi_dbg(ctx, "arm timer for timeout in %ums (first in line)",
|
|
1442
|
+
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->timeout);
|
|
1443
|
+
r = usbi_arm_timer(&ctx->timer, timeout);
|
|
1441
1444
|
}
|
|
1442
1445
|
#else
|
|
1443
1446
|
UNUSED(first);
|
|
1444
1447
|
#endif
|
|
1445
1448
|
|
|
1446
1449
|
if (r)
|
|
1447
|
-
list_del(&
|
|
1450
|
+
list_del(&itransfer->list);
|
|
1448
1451
|
|
|
1449
1452
|
return r;
|
|
1450
1453
|
}
|
|
@@ -1453,18 +1456,18 @@ out:
|
|
|
1453
1456
|
* This function will *always* remove the transfer from the
|
|
1454
1457
|
* flying_transfers list. It will return a LIBUSB_ERROR code
|
|
1455
1458
|
* if it fails to update the timer for the next timeout. */
|
|
1456
|
-
static int remove_from_flying_list(struct usbi_transfer *
|
|
1459
|
+
static int remove_from_flying_list(struct usbi_transfer *itransfer)
|
|
1457
1460
|
{
|
|
1458
|
-
struct libusb_context *ctx = ITRANSFER_CTX(
|
|
1459
|
-
int
|
|
1461
|
+
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
|
|
1462
|
+
int rearm_timer;
|
|
1460
1463
|
int r = 0;
|
|
1461
1464
|
|
|
1462
1465
|
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
|
1463
|
-
|
|
1464
|
-
list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) ==
|
|
1465
|
-
list_del(&
|
|
1466
|
-
if (
|
|
1467
|
-
r =
|
|
1466
|
+
rearm_timer = (TIMESPEC_IS_SET(&itransfer->timeout) &&
|
|
1467
|
+
list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == itransfer);
|
|
1468
|
+
list_del(&itransfer->list);
|
|
1469
|
+
if (rearm_timer)
|
|
1470
|
+
r = arm_timer_for_next_timeout(ctx);
|
|
1468
1471
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
1469
1472
|
|
|
1470
1473
|
return r;
|
|
@@ -1481,17 +1484,23 @@ static int remove_from_flying_list(struct usbi_transfer *transfer)
|
|
|
1481
1484
|
* \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported
|
|
1482
1485
|
* by the operating system.
|
|
1483
1486
|
* \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
|
|
1484
|
-
* the operating system and/or hardware can support
|
|
1487
|
+
* the operating system and/or hardware can support (see \ref asynclimits)
|
|
1485
1488
|
* \returns another LIBUSB_ERROR code on other failure
|
|
1486
1489
|
*/
|
|
1487
1490
|
int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
|
1488
1491
|
{
|
|
1489
1492
|
struct usbi_transfer *itransfer =
|
|
1490
1493
|
LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
|
|
1491
|
-
struct libusb_context *ctx
|
|
1494
|
+
struct libusb_context *ctx;
|
|
1492
1495
|
int r;
|
|
1493
1496
|
|
|
1494
|
-
|
|
1497
|
+
assert(transfer->dev_handle);
|
|
1498
|
+
if (itransfer->dev)
|
|
1499
|
+
libusb_unref_device(itransfer->dev);
|
|
1500
|
+
itransfer->dev = libusb_ref_device(transfer->dev_handle->dev);
|
|
1501
|
+
|
|
1502
|
+
ctx = HANDLE_CTX(transfer->dev_handle);
|
|
1503
|
+
usbi_dbg(ctx, "transfer %p", transfer);
|
|
1495
1504
|
|
|
1496
1505
|
/*
|
|
1497
1506
|
* Important note on locking, this function takes / releases locks
|
|
@@ -1543,15 +1552,13 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
|
|
1543
1552
|
}
|
|
1544
1553
|
/*
|
|
1545
1554
|
* We must release the flying transfers lock here, because with
|
|
1546
|
-
* some backends the submit_transfer method is
|
|
1555
|
+
* some backends the submit_transfer method is synchronous.
|
|
1547
1556
|
*/
|
|
1548
1557
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
1549
1558
|
|
|
1550
1559
|
r = usbi_backend.submit_transfer(itransfer);
|
|
1551
1560
|
if (r == LIBUSB_SUCCESS) {
|
|
1552
1561
|
itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
|
|
1553
|
-
/* keep a reference to this device */
|
|
1554
|
-
libusb_ref_device(transfer->dev_handle->dev);
|
|
1555
1562
|
}
|
|
1556
1563
|
usbi_mutex_unlock(&itransfer->lock);
|
|
1557
1564
|
|
|
@@ -1569,6 +1576,26 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
|
|
1569
1576
|
* \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED
|
|
1570
1577
|
* "LIBUSB_TRANSFER_CANCELLED."
|
|
1571
1578
|
*
|
|
1579
|
+
* This function behaves differently on Darwin-based systems (macOS and iOS):
|
|
1580
|
+
*
|
|
1581
|
+
* - Calling this function for one transfer will cause all transfers on the
|
|
1582
|
+
* same endpoint to be cancelled. Your callback function will be invoked with
|
|
1583
|
+
* a transfer status of
|
|
1584
|
+
* \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED
|
|
1585
|
+
* "LIBUSB_TRANSFER_CANCELLED" for each transfer that was cancelled.
|
|
1586
|
+
|
|
1587
|
+
* - Calling this function also sends a \c ClearFeature(ENDPOINT_HALT) request
|
|
1588
|
+
* for the transfer's endpoint. If the device does not handle this request
|
|
1589
|
+
* correctly, the data toggle bits for the endpoint can be left out of sync
|
|
1590
|
+
* between host and device, which can have unpredictable results when the
|
|
1591
|
+
* next data is sent on the endpoint, including data being silently lost.
|
|
1592
|
+
* A call to \ref libusb_clear_halt will not resolve this situation, since
|
|
1593
|
+
* that function uses the same request. Therefore, if your program runs on
|
|
1594
|
+
* Darwin and uses a device that does not correctly implement
|
|
1595
|
+
* \c ClearFeature(ENDPOINT_HALT) requests, it may only be safe to cancel
|
|
1596
|
+
* transfers when followed by a device reset using
|
|
1597
|
+
* \ref libusb_reset_device.
|
|
1598
|
+
*
|
|
1572
1599
|
* \param transfer the transfer to cancel
|
|
1573
1600
|
* \returns 0 on success
|
|
1574
1601
|
* \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress,
|
|
@@ -1579,9 +1606,10 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
|
|
|
1579
1606
|
{
|
|
1580
1607
|
struct usbi_transfer *itransfer =
|
|
1581
1608
|
LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
|
|
1609
|
+
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
|
|
1582
1610
|
int r;
|
|
1583
1611
|
|
|
1584
|
-
usbi_dbg("transfer %p", transfer );
|
|
1612
|
+
usbi_dbg(ctx, "transfer %p", transfer );
|
|
1585
1613
|
usbi_mutex_lock(&itransfer->lock);
|
|
1586
1614
|
if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT)
|
|
1587
1615
|
|| (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) {
|
|
@@ -1592,10 +1620,9 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
|
|
|
1592
1620
|
if (r < 0) {
|
|
1593
1621
|
if (r != LIBUSB_ERROR_NOT_FOUND &&
|
|
1594
1622
|
r != LIBUSB_ERROR_NO_DEVICE)
|
|
1595
|
-
usbi_err(
|
|
1596
|
-
"cancel transfer failed error %d", r);
|
|
1623
|
+
usbi_err(ctx, "cancel transfer failed error %d", r);
|
|
1597
1624
|
else
|
|
1598
|
-
usbi_dbg("cancel transfer failed error %d", r);
|
|
1625
|
+
usbi_dbg(ctx, "cancel transfer failed error %d", r);
|
|
1599
1626
|
|
|
1600
1627
|
if (r == LIBUSB_ERROR_NO_DEVICE)
|
|
1601
1628
|
itransfer->state_flags |= USBI_TRANSFER_DEVICE_DISAPPEARED;
|
|
@@ -1658,13 +1685,13 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
|
|
1658
1685
|
{
|
|
1659
1686
|
struct libusb_transfer *transfer =
|
|
1660
1687
|
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1661
|
-
struct
|
|
1688
|
+
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
|
|
1662
1689
|
uint8_t flags;
|
|
1663
1690
|
int r;
|
|
1664
1691
|
|
|
1665
1692
|
r = remove_from_flying_list(itransfer);
|
|
1666
1693
|
if (r < 0)
|
|
1667
|
-
usbi_err(
|
|
1694
|
+
usbi_err(ctx, "failed to set timer for next timeout");
|
|
1668
1695
|
|
|
1669
1696
|
usbi_mutex_lock(&itransfer->lock);
|
|
1670
1697
|
itransfer->state_flags &= ~USBI_TRANSFER_IN_FLIGHT;
|
|
@@ -1676,7 +1703,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
|
|
1676
1703
|
if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL)
|
|
1677
1704
|
rqlen -= LIBUSB_CONTROL_SETUP_SIZE;
|
|
1678
1705
|
if (rqlen != itransfer->transferred) {
|
|
1679
|
-
usbi_dbg("interpreting short transfer as error");
|
|
1706
|
+
usbi_dbg(ctx, "interpreting short transfer as error");
|
|
1680
1707
|
status = LIBUSB_TRANSFER_ERROR;
|
|
1681
1708
|
}
|
|
1682
1709
|
}
|
|
@@ -1684,14 +1711,13 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
|
|
1684
1711
|
flags = transfer->flags;
|
|
1685
1712
|
transfer->status = status;
|
|
1686
1713
|
transfer->actual_length = itransfer->transferred;
|
|
1687
|
-
usbi_dbg("transfer %p has callback %p", transfer, transfer->callback);
|
|
1714
|
+
usbi_dbg(ctx, "transfer %p has callback %p", transfer, transfer->callback);
|
|
1688
1715
|
if (transfer->callback)
|
|
1689
1716
|
transfer->callback(transfer);
|
|
1690
1717
|
/* transfer might have been freed by the above call, do not use from
|
|
1691
1718
|
* this point. */
|
|
1692
1719
|
if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
|
|
1693
1720
|
libusb_free_transfer(transfer);
|
|
1694
|
-
libusb_unref_device(dev_handle->dev);
|
|
1695
1721
|
return r;
|
|
1696
1722
|
}
|
|
1697
1723
|
|
|
@@ -1701,41 +1727,42 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
|
|
1701
1727
|
* Do not call this function with the usbi_transfer lock held. User-specified
|
|
1702
1728
|
* callback functions may attempt to directly resubmit the transfer, which
|
|
1703
1729
|
* will attempt to take the lock. */
|
|
1704
|
-
int usbi_handle_transfer_cancellation(struct usbi_transfer *
|
|
1730
|
+
int usbi_handle_transfer_cancellation(struct usbi_transfer *itransfer)
|
|
1705
1731
|
{
|
|
1706
|
-
struct libusb_context *ctx = ITRANSFER_CTX(
|
|
1732
|
+
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
|
|
1707
1733
|
uint8_t timed_out;
|
|
1708
1734
|
|
|
1709
1735
|
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
|
1710
|
-
timed_out =
|
|
1736
|
+
timed_out = itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT;
|
|
1711
1737
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
1712
1738
|
|
|
1713
1739
|
/* if the URB was cancelled due to timeout, report timeout to the user */
|
|
1714
1740
|
if (timed_out) {
|
|
1715
|
-
usbi_dbg("detected timeout cancellation");
|
|
1716
|
-
return usbi_handle_transfer_completion(
|
|
1741
|
+
usbi_dbg(ctx, "detected timeout cancellation");
|
|
1742
|
+
return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_TIMED_OUT);
|
|
1717
1743
|
}
|
|
1718
1744
|
|
|
1719
1745
|
/* otherwise its a normal async cancel */
|
|
1720
|
-
return usbi_handle_transfer_completion(
|
|
1746
|
+
return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_CANCELLED);
|
|
1721
1747
|
}
|
|
1722
1748
|
|
|
1723
1749
|
/* Add a completed transfer to the completed_transfers list of the
|
|
1724
1750
|
* context and signal the event. The backend's handle_transfer_completion()
|
|
1725
1751
|
* function will be called the next time an event handler runs. */
|
|
1726
|
-
void usbi_signal_transfer_completion(struct usbi_transfer *
|
|
1752
|
+
void usbi_signal_transfer_completion(struct usbi_transfer *itransfer)
|
|
1727
1753
|
{
|
|
1728
|
-
|
|
1754
|
+
struct libusb_device *dev = itransfer->dev;
|
|
1729
1755
|
|
|
1730
|
-
if (
|
|
1731
|
-
struct libusb_context *ctx =
|
|
1732
|
-
int
|
|
1756
|
+
if (dev) {
|
|
1757
|
+
struct libusb_context *ctx = DEVICE_CTX(dev);
|
|
1758
|
+
unsigned int event_flags;
|
|
1733
1759
|
|
|
1734
1760
|
usbi_mutex_lock(&ctx->event_data_lock);
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1761
|
+
event_flags = ctx->event_flags;
|
|
1762
|
+
ctx->event_flags |= USBI_EVENT_TRANSFER_COMPLETED;
|
|
1763
|
+
list_add_tail(&itransfer->completed_list, &ctx->completed_transfers);
|
|
1764
|
+
if (!event_flags)
|
|
1765
|
+
usbi_signal_event(&ctx->event);
|
|
1739
1766
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
1740
1767
|
}
|
|
1741
1768
|
}
|
|
@@ -1763,7 +1790,8 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx)
|
|
|
1763
1790
|
{
|
|
1764
1791
|
int r;
|
|
1765
1792
|
unsigned int ru;
|
|
1766
|
-
|
|
1793
|
+
|
|
1794
|
+
ctx = usbi_get_context(ctx);
|
|
1767
1795
|
|
|
1768
1796
|
/* is someone else waiting to close a device? if so, don't let this thread
|
|
1769
1797
|
* start event handling */
|
|
@@ -1771,12 +1799,12 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx)
|
|
|
1771
1799
|
ru = ctx->device_close;
|
|
1772
1800
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
1773
1801
|
if (ru) {
|
|
1774
|
-
usbi_dbg("someone else is closing a device");
|
|
1802
|
+
usbi_dbg(ctx, "someone else is closing a device");
|
|
1775
1803
|
return 1;
|
|
1776
1804
|
}
|
|
1777
1805
|
|
|
1778
1806
|
r = usbi_mutex_trylock(&ctx->events_lock);
|
|
1779
|
-
if (r)
|
|
1807
|
+
if (!r)
|
|
1780
1808
|
return 1;
|
|
1781
1809
|
|
|
1782
1810
|
ctx->event_handler_active = 1;
|
|
@@ -1803,7 +1831,7 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx)
|
|
|
1803
1831
|
*/
|
|
1804
1832
|
void API_EXPORTED libusb_lock_events(libusb_context *ctx)
|
|
1805
1833
|
{
|
|
1806
|
-
|
|
1834
|
+
ctx = usbi_get_context(ctx);
|
|
1807
1835
|
usbi_mutex_lock(&ctx->events_lock);
|
|
1808
1836
|
ctx->event_handler_active = 1;
|
|
1809
1837
|
}
|
|
@@ -1818,7 +1846,7 @@ void API_EXPORTED libusb_lock_events(libusb_context *ctx)
|
|
|
1818
1846
|
*/
|
|
1819
1847
|
void API_EXPORTED libusb_unlock_events(libusb_context *ctx)
|
|
1820
1848
|
{
|
|
1821
|
-
|
|
1849
|
+
ctx = usbi_get_context(ctx);
|
|
1822
1850
|
ctx->event_handler_active = 0;
|
|
1823
1851
|
usbi_mutex_unlock(&ctx->events_lock);
|
|
1824
1852
|
|
|
@@ -1854,7 +1882,8 @@ void API_EXPORTED libusb_unlock_events(libusb_context *ctx)
|
|
|
1854
1882
|
int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
|
|
1855
1883
|
{
|
|
1856
1884
|
unsigned int r;
|
|
1857
|
-
|
|
1885
|
+
|
|
1886
|
+
ctx = usbi_get_context(ctx);
|
|
1858
1887
|
|
|
1859
1888
|
/* is someone else waiting to close a device? if so, don't let this thread
|
|
1860
1889
|
* continue event handling */
|
|
@@ -1862,7 +1891,7 @@ int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
|
|
|
1862
1891
|
r = ctx->device_close;
|
|
1863
1892
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
1864
1893
|
if (r) {
|
|
1865
|
-
usbi_dbg("someone else is closing a device");
|
|
1894
|
+
usbi_dbg(ctx, "someone else is closing a device");
|
|
1866
1895
|
return 0;
|
|
1867
1896
|
}
|
|
1868
1897
|
|
|
@@ -1882,7 +1911,8 @@ int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
|
|
|
1882
1911
|
int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
|
|
1883
1912
|
{
|
|
1884
1913
|
unsigned int r;
|
|
1885
|
-
|
|
1914
|
+
|
|
1915
|
+
ctx = usbi_get_context(ctx);
|
|
1886
1916
|
|
|
1887
1917
|
/* is someone else waiting to close a device? if so, don't let this thread
|
|
1888
1918
|
* start event handling -- indicate that event handling is happening */
|
|
@@ -1890,7 +1920,7 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
|
|
|
1890
1920
|
r = ctx->device_close;
|
|
1891
1921
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
1892
1922
|
if (r) {
|
|
1893
|
-
usbi_dbg("someone else is closing a device");
|
|
1923
|
+
usbi_dbg(ctx, "someone else is closing a device");
|
|
1894
1924
|
return 1;
|
|
1895
1925
|
}
|
|
1896
1926
|
|
|
@@ -1909,16 +1939,17 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
|
|
|
1909
1939
|
*/
|
|
1910
1940
|
void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
|
|
1911
1941
|
{
|
|
1912
|
-
int
|
|
1913
|
-
|
|
1942
|
+
unsigned int event_flags;
|
|
1943
|
+
|
|
1944
|
+
usbi_dbg(ctx, " ");
|
|
1914
1945
|
|
|
1915
|
-
|
|
1946
|
+
ctx = usbi_get_context(ctx);
|
|
1916
1947
|
usbi_mutex_lock(&ctx->event_data_lock);
|
|
1917
1948
|
|
|
1918
|
-
|
|
1949
|
+
event_flags = ctx->event_flags;
|
|
1919
1950
|
ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
|
|
1920
|
-
if (!
|
|
1921
|
-
usbi_signal_event(ctx);
|
|
1951
|
+
if (!event_flags)
|
|
1952
|
+
usbi_signal_event(&ctx->event);
|
|
1922
1953
|
|
|
1923
1954
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
1924
1955
|
}
|
|
@@ -1934,7 +1965,7 @@ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
|
|
|
1934
1965
|
*
|
|
1935
1966
|
* You only need to use this lock if you are developing an application
|
|
1936
1967
|
* which calls poll() or select() on libusb's file descriptors directly,
|
|
1937
|
-
* <b>and</b> may potentially be handling events from 2 threads
|
|
1968
|
+
* <b>and</b> may potentially be handling events from 2 threads simultaneously.
|
|
1938
1969
|
* If you stick to libusb's event handling loop functions (e.g.
|
|
1939
1970
|
* libusb_handle_events()) then you do not need to be concerned with this
|
|
1940
1971
|
* locking.
|
|
@@ -1944,7 +1975,7 @@ void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
|
|
|
1944
1975
|
*/
|
|
1945
1976
|
void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx)
|
|
1946
1977
|
{
|
|
1947
|
-
|
|
1978
|
+
ctx = usbi_get_context(ctx);
|
|
1948
1979
|
usbi_mutex_lock(&ctx->event_waiters_lock);
|
|
1949
1980
|
}
|
|
1950
1981
|
|
|
@@ -1955,7 +1986,7 @@ void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx)
|
|
|
1955
1986
|
*/
|
|
1956
1987
|
void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx)
|
|
1957
1988
|
{
|
|
1958
|
-
|
|
1989
|
+
ctx = usbi_get_context(ctx);
|
|
1959
1990
|
usbi_mutex_unlock(&ctx->event_waiters_lock);
|
|
1960
1991
|
}
|
|
1961
1992
|
|
|
@@ -1982,25 +2013,28 @@ void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx)
|
|
|
1982
2013
|
* indicates unlimited timeout.
|
|
1983
2014
|
* \returns 0 after a transfer completes or another thread stops event handling
|
|
1984
2015
|
* \returns 1 if the timeout expired
|
|
2016
|
+
* \returns LIBUSB_ERROR_INVALID_PARAM if timeval is invalid
|
|
1985
2017
|
* \ref libusb_mtasync
|
|
1986
2018
|
*/
|
|
1987
2019
|
int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
|
|
1988
2020
|
{
|
|
1989
2021
|
int r;
|
|
1990
2022
|
|
|
1991
|
-
|
|
1992
|
-
if (tv
|
|
2023
|
+
ctx = usbi_get_context(ctx);
|
|
2024
|
+
if (!tv) {
|
|
1993
2025
|
usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock);
|
|
1994
2026
|
return 0;
|
|
1995
2027
|
}
|
|
1996
2028
|
|
|
2029
|
+
if (!TIMEVAL_IS_VALID(tv))
|
|
2030
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2031
|
+
|
|
1997
2032
|
r = usbi_cond_timedwait(&ctx->event_waiters_cond,
|
|
1998
2033
|
&ctx->event_waiters_lock, tv);
|
|
1999
|
-
|
|
2000
2034
|
if (r < 0)
|
|
2001
|
-
return r;
|
|
2002
|
-
|
|
2003
|
-
|
|
2035
|
+
return r == LIBUSB_ERROR_TIMEOUT;
|
|
2036
|
+
|
|
2037
|
+
return 0;
|
|
2004
2038
|
}
|
|
2005
2039
|
|
|
2006
2040
|
static void handle_timeout(struct usbi_transfer *itransfer)
|
|
@@ -2015,78 +2049,146 @@ static void handle_timeout(struct usbi_transfer *itransfer)
|
|
|
2015
2049
|
itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
|
|
2016
2050
|
else
|
|
2017
2051
|
usbi_warn(TRANSFER_CTX(transfer),
|
|
2018
|
-
"async cancel failed %d
|
|
2052
|
+
"async cancel failed %d", r);
|
|
2019
2053
|
}
|
|
2020
2054
|
|
|
2021
|
-
static
|
|
2055
|
+
static void handle_timeouts_locked(struct libusb_context *ctx)
|
|
2022
2056
|
{
|
|
2023
|
-
|
|
2024
|
-
struct
|
|
2025
|
-
struct timeval systime;
|
|
2026
|
-
struct usbi_transfer *transfer;
|
|
2057
|
+
struct timespec systime;
|
|
2058
|
+
struct usbi_transfer *itransfer;
|
|
2027
2059
|
|
|
2028
2060
|
if (list_empty(&ctx->flying_transfers))
|
|
2029
|
-
return
|
|
2061
|
+
return;
|
|
2030
2062
|
|
|
2031
2063
|
/* get current time */
|
|
2032
|
-
|
|
2033
|
-
if (r < 0)
|
|
2034
|
-
return r;
|
|
2035
|
-
|
|
2036
|
-
TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
|
|
2064
|
+
usbi_get_monotonic_time(&systime);
|
|
2037
2065
|
|
|
2038
2066
|
/* iterate through flying transfers list, finding all transfers that
|
|
2039
2067
|
* have expired timeouts */
|
|
2040
|
-
|
|
2041
|
-
struct
|
|
2068
|
+
for_each_transfer(ctx, itransfer) {
|
|
2069
|
+
struct timespec *cur_ts = &itransfer->timeout;
|
|
2042
2070
|
|
|
2043
2071
|
/* if we've reached transfers of infinite timeout, we're all done */
|
|
2044
|
-
if (!
|
|
2045
|
-
return
|
|
2072
|
+
if (!TIMESPEC_IS_SET(cur_ts))
|
|
2073
|
+
return;
|
|
2046
2074
|
|
|
2047
2075
|
/* ignore timeouts we've already handled */
|
|
2048
|
-
if (
|
|
2076
|
+
if (itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
|
|
2049
2077
|
continue;
|
|
2050
2078
|
|
|
2051
2079
|
/* if transfer has non-expired timeout, nothing more to do */
|
|
2052
|
-
if ((
|
|
2053
|
-
|
|
2054
|
-
cur_tv->tv_usec > systime.tv_usec))
|
|
2055
|
-
return 0;
|
|
2080
|
+
if (TIMESPEC_CMP(cur_ts, &systime, >))
|
|
2081
|
+
return;
|
|
2056
2082
|
|
|
2057
2083
|
/* otherwise, we've got an expired timeout to handle */
|
|
2058
|
-
handle_timeout(
|
|
2084
|
+
handle_timeout(itransfer);
|
|
2059
2085
|
}
|
|
2060
|
-
return 0;
|
|
2061
2086
|
}
|
|
2062
2087
|
|
|
2063
|
-
static
|
|
2088
|
+
static void handle_timeouts(struct libusb_context *ctx)
|
|
2064
2089
|
{
|
|
2065
|
-
|
|
2066
|
-
USBI_GET_CONTEXT(ctx);
|
|
2090
|
+
ctx = usbi_get_context(ctx);
|
|
2067
2091
|
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
|
2068
|
-
|
|
2092
|
+
handle_timeouts_locked(ctx);
|
|
2069
2093
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
static int handle_event_trigger(struct libusb_context *ctx)
|
|
2097
|
+
{
|
|
2098
|
+
struct list_head hotplug_msgs;
|
|
2099
|
+
int hotplug_event = 0;
|
|
2100
|
+
int r = 0;
|
|
2101
|
+
|
|
2102
|
+
usbi_dbg(ctx, "event triggered");
|
|
2103
|
+
|
|
2104
|
+
list_init(&hotplug_msgs);
|
|
2105
|
+
|
|
2106
|
+
/* take the the event data lock while processing events */
|
|
2107
|
+
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2108
|
+
|
|
2109
|
+
/* check if someone modified the event sources */
|
|
2110
|
+
if (ctx->event_flags & USBI_EVENT_EVENT_SOURCES_MODIFIED)
|
|
2111
|
+
usbi_dbg(ctx, "someone updated the event sources");
|
|
2112
|
+
|
|
2113
|
+
if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) {
|
|
2114
|
+
usbi_dbg(ctx, "someone purposefully interrupted");
|
|
2115
|
+
ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) {
|
|
2119
|
+
usbi_dbg(ctx, "someone unregistered a hotplug cb");
|
|
2120
|
+
ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
|
|
2121
|
+
hotplug_event = 1;
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
/* check if someone is closing a device */
|
|
2125
|
+
if (ctx->event_flags & USBI_EVENT_DEVICE_CLOSE)
|
|
2126
|
+
usbi_dbg(ctx, "someone is closing a device");
|
|
2127
|
+
|
|
2128
|
+
/* check for any pending hotplug messages */
|
|
2129
|
+
if (ctx->event_flags & USBI_EVENT_HOTPLUG_MSG_PENDING) {
|
|
2130
|
+
usbi_dbg(ctx, "hotplug message received");
|
|
2131
|
+
ctx->event_flags &= ~USBI_EVENT_HOTPLUG_MSG_PENDING;
|
|
2132
|
+
hotplug_event = 1;
|
|
2133
|
+
assert(!list_empty(&ctx->hotplug_msgs));
|
|
2134
|
+
list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
/* complete any pending transfers */
|
|
2138
|
+
if (ctx->event_flags & USBI_EVENT_TRANSFER_COMPLETED) {
|
|
2139
|
+
struct usbi_transfer *itransfer, *tmp;
|
|
2140
|
+
struct list_head completed_transfers;
|
|
2141
|
+
|
|
2142
|
+
assert(!list_empty(&ctx->completed_transfers));
|
|
2143
|
+
list_cut(&completed_transfers, &ctx->completed_transfers);
|
|
2144
|
+
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2145
|
+
|
|
2146
|
+
__for_each_completed_transfer_safe(&completed_transfers, itransfer, tmp) {
|
|
2147
|
+
list_del(&itransfer->completed_list);
|
|
2148
|
+
r = usbi_backend.handle_transfer_completion(itransfer);
|
|
2149
|
+
if (r) {
|
|
2150
|
+
usbi_err(ctx, "backend handle_transfer_completion failed with error %d", r);
|
|
2151
|
+
break;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2156
|
+
if (!list_empty(&completed_transfers)) {
|
|
2157
|
+
/* an error occurred, put the remaining transfers back on the list */
|
|
2158
|
+
list_splice_front(&completed_transfers, &ctx->completed_transfers);
|
|
2159
|
+
} else if (list_empty(&ctx->completed_transfers)) {
|
|
2160
|
+
ctx->event_flags &= ~USBI_EVENT_TRANSFER_COMPLETED;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
/* if no further pending events, clear the event */
|
|
2165
|
+
if (!ctx->event_flags)
|
|
2166
|
+
usbi_clear_event(&ctx->event);
|
|
2167
|
+
|
|
2168
|
+
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2169
|
+
|
|
2170
|
+
/* process the hotplug events, if any */
|
|
2171
|
+
if (hotplug_event)
|
|
2172
|
+
usbi_hotplug_process(ctx, &hotplug_msgs);
|
|
2173
|
+
|
|
2070
2174
|
return r;
|
|
2071
2175
|
}
|
|
2072
2176
|
|
|
2073
|
-
#ifdef
|
|
2074
|
-
static int
|
|
2177
|
+
#ifdef HAVE_OS_TIMER
|
|
2178
|
+
static int handle_timer_trigger(struct libusb_context *ctx)
|
|
2075
2179
|
{
|
|
2076
2180
|
int r;
|
|
2077
2181
|
|
|
2078
2182
|
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
|
2079
2183
|
|
|
2080
2184
|
/* process the timeout that just happened */
|
|
2081
|
-
|
|
2082
|
-
if (r < 0)
|
|
2083
|
-
goto out;
|
|
2185
|
+
handle_timeouts_locked(ctx);
|
|
2084
2186
|
|
|
2085
|
-
/* arm for next timeout*/
|
|
2086
|
-
r =
|
|
2187
|
+
/* arm for next timeout */
|
|
2188
|
+
r = arm_timer_for_next_timeout(ctx);
|
|
2087
2189
|
|
|
2088
|
-
out:
|
|
2089
2190
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
2191
|
+
|
|
2090
2192
|
return r;
|
|
2091
2193
|
}
|
|
2092
2194
|
#endif
|
|
@@ -2095,81 +2197,38 @@ out:
|
|
|
2095
2197
|
* doing the same thing. */
|
|
2096
2198
|
static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|
2097
2199
|
{
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
POLL_NFDS_TYPE nfds = 0;
|
|
2101
|
-
POLL_NFDS_TYPE internal_nfds;
|
|
2102
|
-
struct pollfd *fds = NULL;
|
|
2103
|
-
int i = -1;
|
|
2104
|
-
int timeout_ms;
|
|
2200
|
+
struct usbi_reported_events reported_events;
|
|
2201
|
+
int r, timeout_ms;
|
|
2105
2202
|
|
|
2106
2203
|
/* prevent attempts to recursively handle events (e.g. calling into
|
|
2107
2204
|
* libusb_handle_events() from within a hotplug or transfer callback) */
|
|
2108
|
-
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2109
|
-
r = 0;
|
|
2110
2205
|
if (usbi_handling_events(ctx))
|
|
2111
|
-
|
|
2112
|
-
else
|
|
2113
|
-
usbi_start_event_handling(ctx);
|
|
2114
|
-
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2115
|
-
|
|
2116
|
-
if (r)
|
|
2117
|
-
return r;
|
|
2118
|
-
|
|
2119
|
-
/* there are certain fds that libusb uses internally, currently:
|
|
2120
|
-
*
|
|
2121
|
-
* 1) event pipe
|
|
2122
|
-
* 2) timerfd
|
|
2123
|
-
*
|
|
2124
|
-
* the backend will never need to attempt to handle events on these fds, so
|
|
2125
|
-
* we determine how many fds are in use internally for this context and when
|
|
2126
|
-
* handle_events() is called in the backend, the pollfd list and count will
|
|
2127
|
-
* be adjusted to skip over these internal fds */
|
|
2128
|
-
if (usbi_using_timerfd(ctx))
|
|
2129
|
-
internal_nfds = 2;
|
|
2130
|
-
else
|
|
2131
|
-
internal_nfds = 1;
|
|
2206
|
+
return LIBUSB_ERROR_BUSY;
|
|
2132
2207
|
|
|
2133
|
-
/* only reallocate the
|
|
2134
|
-
* since the last
|
|
2208
|
+
/* only reallocate the event source data when the list of event sources has
|
|
2209
|
+
* been modified since the last handle_events(), otherwise reuse them to
|
|
2210
|
+
* save the additional overhead */
|
|
2135
2211
|
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) {
|
|
2139
|
-
usbi_dbg("poll fds modified, reallocating");
|
|
2212
|
+
if (ctx->event_flags & USBI_EVENT_EVENT_SOURCES_MODIFIED) {
|
|
2213
|
+
usbi_dbg(ctx, "event sources modified, reallocating event data");
|
|
2140
2214
|
|
|
2141
|
-
free
|
|
2142
|
-
ctx
|
|
2215
|
+
/* free anything removed since we last ran */
|
|
2216
|
+
cleanup_removed_event_sources(ctx);
|
|
2143
2217
|
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
assert(ctx->pollfds_cnt >= internal_nfds);
|
|
2147
|
-
|
|
2148
|
-
ctx->pollfds = calloc(ctx->pollfds_cnt, sizeof(*ctx->pollfds));
|
|
2149
|
-
if (!ctx->pollfds) {
|
|
2218
|
+
r = usbi_alloc_event_data(ctx);
|
|
2219
|
+
if (r) {
|
|
2150
2220
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2151
|
-
r
|
|
2152
|
-
goto done;
|
|
2153
|
-
}
|
|
2154
|
-
|
|
2155
|
-
list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) {
|
|
2156
|
-
struct libusb_pollfd *pollfd = &ipollfd->pollfd;
|
|
2157
|
-
i++;
|
|
2158
|
-
ctx->pollfds[i].fd = pollfd->fd;
|
|
2159
|
-
ctx->pollfds[i].events = pollfd->events;
|
|
2221
|
+
return r;
|
|
2160
2222
|
}
|
|
2161
2223
|
|
|
2162
2224
|
/* reset the flag now that we have the updated list */
|
|
2163
|
-
ctx->event_flags &= ~
|
|
2225
|
+
ctx->event_flags &= ~USBI_EVENT_EVENT_SOURCES_MODIFIED;
|
|
2164
2226
|
|
|
2165
|
-
/* if no further pending events, clear the event
|
|
2166
|
-
* not immediately return from
|
|
2167
|
-
if (!
|
|
2168
|
-
usbi_clear_event(ctx);
|
|
2227
|
+
/* if no further pending events, clear the event so that we do
|
|
2228
|
+
* not immediately return from the wait function */
|
|
2229
|
+
if (!ctx->event_flags)
|
|
2230
|
+
usbi_clear_event(&ctx->event);
|
|
2169
2231
|
}
|
|
2170
|
-
fds = ctx->pollfds;
|
|
2171
|
-
nfds = ctx->pollfds_cnt;
|
|
2172
|
-
usbi_inc_fds_ref(fds, nfds);
|
|
2173
2232
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2174
2233
|
|
|
2175
2234
|
timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
|
|
@@ -2178,145 +2237,47 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|
|
2178
2237
|
if (tv->tv_usec % 1000)
|
|
2179
2238
|
timeout_ms++;
|
|
2180
2239
|
|
|
2181
|
-
|
|
2182
|
-
r = usbi_poll(fds, nfds, timeout_ms);
|
|
2183
|
-
usbi_dbg("poll() returned %d", r);
|
|
2184
|
-
if (r == 0) {
|
|
2185
|
-
r = handle_timeouts(ctx);
|
|
2186
|
-
goto done;
|
|
2187
|
-
} else if (r == -1 && errno == EINTR) {
|
|
2188
|
-
r = LIBUSB_ERROR_INTERRUPTED;
|
|
2189
|
-
goto done;
|
|
2190
|
-
} else if (r < 0) {
|
|
2191
|
-
usbi_err(ctx, "poll failed %d err=%d", r, errno);
|
|
2192
|
-
r = LIBUSB_ERROR_IO;
|
|
2193
|
-
goto done;
|
|
2194
|
-
}
|
|
2195
|
-
|
|
2196
|
-
/* fds[0] is always the event pipe */
|
|
2197
|
-
if (fds[0].revents) {
|
|
2198
|
-
struct list_head hotplug_msgs;
|
|
2199
|
-
struct usbi_transfer *itransfer;
|
|
2200
|
-
int hotplug_cb_deregistered = 0;
|
|
2201
|
-
int ret = 0;
|
|
2202
|
-
|
|
2203
|
-
list_init(&hotplug_msgs);
|
|
2204
|
-
|
|
2205
|
-
usbi_dbg("caught a fish on the event pipe");
|
|
2206
|
-
|
|
2207
|
-
/* take the the event data lock while processing events */
|
|
2208
|
-
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2209
|
-
|
|
2210
|
-
/* check if someone added a new poll fd */
|
|
2211
|
-
if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED)
|
|
2212
|
-
usbi_dbg("someone updated the poll fds");
|
|
2213
|
-
|
|
2214
|
-
if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) {
|
|
2215
|
-
usbi_dbg("someone purposely interrupted");
|
|
2216
|
-
ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
|
|
2217
|
-
}
|
|
2218
|
-
|
|
2219
|
-
if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) {
|
|
2220
|
-
usbi_dbg("someone unregistered a hotplug cb");
|
|
2221
|
-
ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
|
|
2222
|
-
hotplug_cb_deregistered = 1;
|
|
2223
|
-
}
|
|
2224
|
-
|
|
2225
|
-
/* check if someone is closing a device */
|
|
2226
|
-
if (ctx->device_close)
|
|
2227
|
-
usbi_dbg("someone is closing a device");
|
|
2228
|
-
|
|
2229
|
-
/* check for any pending hotplug messages */
|
|
2230
|
-
if (!list_empty(&ctx->hotplug_msgs)) {
|
|
2231
|
-
usbi_dbg("hotplug message received");
|
|
2232
|
-
list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
|
|
2233
|
-
}
|
|
2234
|
-
|
|
2235
|
-
/* complete any pending transfers */
|
|
2236
|
-
while (ret == 0 && !list_empty(&ctx->completed_transfers)) {
|
|
2237
|
-
itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list);
|
|
2238
|
-
list_del(&itransfer->completed_list);
|
|
2239
|
-
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2240
|
-
ret = usbi_backend.handle_transfer_completion(itransfer);
|
|
2241
|
-
if (ret)
|
|
2242
|
-
usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret);
|
|
2243
|
-
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2244
|
-
}
|
|
2245
|
-
|
|
2246
|
-
/* if no further pending events, clear the event pipe */
|
|
2247
|
-
if (!usbi_pending_events(ctx))
|
|
2248
|
-
usbi_clear_event(ctx);
|
|
2240
|
+
reported_events.event_bits = 0;
|
|
2249
2241
|
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
if (hotplug_cb_deregistered)
|
|
2253
|
-
usbi_hotplug_deregister(ctx, 0);
|
|
2254
|
-
|
|
2255
|
-
/* process the hotplug messages, if any */
|
|
2256
|
-
while (!list_empty(&hotplug_msgs)) {
|
|
2257
|
-
struct libusb_hotplug_message *message =
|
|
2258
|
-
list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list);
|
|
2242
|
+
usbi_start_event_handling(ctx);
|
|
2259
2243
|
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
list_del(&message->list);
|
|
2267
|
-
free(message);
|
|
2244
|
+
r = usbi_wait_for_events(ctx, &reported_events, timeout_ms);
|
|
2245
|
+
if (r != LIBUSB_SUCCESS) {
|
|
2246
|
+
if (r == LIBUSB_ERROR_TIMEOUT) {
|
|
2247
|
+
handle_timeouts(ctx);
|
|
2248
|
+
r = LIBUSB_SUCCESS;
|
|
2268
2249
|
}
|
|
2250
|
+
goto done;
|
|
2251
|
+
}
|
|
2269
2252
|
|
|
2270
|
-
|
|
2253
|
+
if (reported_events.event_triggered) {
|
|
2254
|
+
r = handle_event_trigger(ctx);
|
|
2255
|
+
if (r) {
|
|
2271
2256
|
/* return error code */
|
|
2272
|
-
r = ret;
|
|
2273
2257
|
goto done;
|
|
2274
2258
|
}
|
|
2275
|
-
|
|
2276
|
-
if (0 == --r)
|
|
2277
|
-
goto done;
|
|
2278
2259
|
}
|
|
2279
2260
|
|
|
2280
|
-
#ifdef
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
int ret;
|
|
2285
|
-
usbi_dbg("timerfd triggered");
|
|
2286
|
-
|
|
2287
|
-
ret = handle_timerfd_trigger(ctx);
|
|
2288
|
-
if (ret < 0) {
|
|
2261
|
+
#ifdef HAVE_OS_TIMER
|
|
2262
|
+
if (reported_events.timer_triggered) {
|
|
2263
|
+
r = handle_timer_trigger(ctx);
|
|
2264
|
+
if (r) {
|
|
2289
2265
|
/* return error code */
|
|
2290
|
-
r = ret;
|
|
2291
2266
|
goto done;
|
|
2292
2267
|
}
|
|
2293
|
-
|
|
2294
|
-
if (0 == --r)
|
|
2295
|
-
goto done;
|
|
2296
2268
|
}
|
|
2297
2269
|
#endif
|
|
2298
2270
|
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
if (ipollfd->pollfd.fd == fds[i].fd) {
|
|
2302
|
-
/* pollfd was removed between the creation of the fd
|
|
2303
|
-
* array and here. remove any triggered revent as
|
|
2304
|
-
* it is no longer relevant */
|
|
2305
|
-
usbi_dbg("pollfd %d was removed. ignoring raised events",
|
|
2306
|
-
fds[i].fd);
|
|
2307
|
-
fds[i].revents = 0;
|
|
2308
|
-
break;
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2271
|
+
if (!reported_events.num_ready)
|
|
2272
|
+
goto done;
|
|
2312
2273
|
|
|
2313
|
-
r = usbi_backend.handle_events(ctx,
|
|
2274
|
+
r = usbi_backend.handle_events(ctx, reported_events.event_data,
|
|
2275
|
+
reported_events.event_data_count, reported_events.num_ready);
|
|
2314
2276
|
if (r)
|
|
2315
2277
|
usbi_err(ctx, "backend handle_events failed with error %d", r);
|
|
2316
2278
|
|
|
2317
2279
|
done:
|
|
2318
2280
|
usbi_end_event_handling(ctx);
|
|
2319
|
-
usbi_dec_fds_ref(fds, nfds);
|
|
2320
2281
|
return r;
|
|
2321
2282
|
}
|
|
2322
2283
|
|
|
@@ -2370,7 +2331,9 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv,
|
|
|
2370
2331
|
* \param tv the maximum time to block waiting for events, or an all zero
|
|
2371
2332
|
* timeval struct for non-blocking mode
|
|
2372
2333
|
* \param completed pointer to completion integer to check, or NULL
|
|
2373
|
-
* \returns 0 on success
|
|
2334
|
+
* \returns 0 on success
|
|
2335
|
+
* \returns LIBUSB_ERROR_INVALID_PARAM if timeval is invalid
|
|
2336
|
+
* \returns another LIBUSB_ERROR code on other failure
|
|
2374
2337
|
* \ref libusb_mtasync
|
|
2375
2338
|
*/
|
|
2376
2339
|
int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx,
|
|
@@ -2379,18 +2342,22 @@ int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx,
|
|
|
2379
2342
|
int r;
|
|
2380
2343
|
struct timeval poll_timeout;
|
|
2381
2344
|
|
|
2382
|
-
|
|
2345
|
+
if (!TIMEVAL_IS_VALID(tv))
|
|
2346
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2347
|
+
|
|
2348
|
+
ctx = usbi_get_context(ctx);
|
|
2383
2349
|
r = get_next_timeout(ctx, tv, &poll_timeout);
|
|
2384
2350
|
if (r) {
|
|
2385
2351
|
/* timeout already expired */
|
|
2386
|
-
|
|
2352
|
+
handle_timeouts(ctx);
|
|
2353
|
+
return 0;
|
|
2387
2354
|
}
|
|
2388
2355
|
|
|
2389
2356
|
retry:
|
|
2390
2357
|
if (libusb_try_lock_events(ctx) == 0) {
|
|
2391
2358
|
if (completed == NULL || !*completed) {
|
|
2392
2359
|
/* we obtained the event lock: do our own event handling */
|
|
2393
|
-
usbi_dbg("doing our own event handling");
|
|
2360
|
+
usbi_dbg(ctx, "doing our own event handling");
|
|
2394
2361
|
r = handle_events(ctx, &poll_timeout);
|
|
2395
2362
|
}
|
|
2396
2363
|
libusb_unlock_events(ctx);
|
|
@@ -2408,11 +2375,11 @@ retry:
|
|
|
2408
2375
|
/* we hit a race: whoever was event handling earlier finished in the
|
|
2409
2376
|
* time it took us to reach this point. try the cycle again. */
|
|
2410
2377
|
libusb_unlock_event_waiters(ctx);
|
|
2411
|
-
usbi_dbg("event handler was active but went away, retrying");
|
|
2378
|
+
usbi_dbg(ctx, "event handler was active but went away, retrying");
|
|
2412
2379
|
goto retry;
|
|
2413
2380
|
}
|
|
2414
2381
|
|
|
2415
|
-
usbi_dbg("another thread is doing event handling");
|
|
2382
|
+
usbi_dbg(ctx, "another thread is doing event handling");
|
|
2416
2383
|
r = libusb_wait_for_event(ctx, &poll_timeout);
|
|
2417
2384
|
|
|
2418
2385
|
already_done:
|
|
@@ -2421,9 +2388,8 @@ already_done:
|
|
|
2421
2388
|
if (r < 0)
|
|
2422
2389
|
return r;
|
|
2423
2390
|
else if (r == 1)
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
return 0;
|
|
2391
|
+
handle_timeouts(ctx);
|
|
2392
|
+
return 0;
|
|
2427
2393
|
}
|
|
2428
2394
|
|
|
2429
2395
|
/** \ingroup libusb_poll
|
|
@@ -2450,7 +2416,7 @@ int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx,
|
|
|
2450
2416
|
|
|
2451
2417
|
/** \ingroup libusb_poll
|
|
2452
2418
|
* Handle any pending events in blocking mode. There is currently a timeout
|
|
2453
|
-
*
|
|
2419
|
+
* hard-coded at 60 seconds but we plan to make it unlimited in future. For
|
|
2454
2420
|
* finer control over whether this function is blocking or non-blocking, or
|
|
2455
2421
|
* for control over the timeout, use libusb_handle_events_timeout_completed()
|
|
2456
2422
|
* instead.
|
|
@@ -2507,7 +2473,9 @@ int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx,
|
|
|
2507
2473
|
* \param ctx the context to operate on, or NULL for the default context
|
|
2508
2474
|
* \param tv the maximum time to block waiting for events, or zero for
|
|
2509
2475
|
* non-blocking mode
|
|
2510
|
-
* \returns 0 on success
|
|
2476
|
+
* \returns 0 on success
|
|
2477
|
+
* \returns LIBUSB_ERROR_INVALID_PARAM if timeval is invalid
|
|
2478
|
+
* \returns another LIBUSB_ERROR code on other failure
|
|
2511
2479
|
* \ref libusb_mtasync
|
|
2512
2480
|
*/
|
|
2513
2481
|
int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx,
|
|
@@ -2516,11 +2484,15 @@ int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx,
|
|
|
2516
2484
|
int r;
|
|
2517
2485
|
struct timeval poll_timeout;
|
|
2518
2486
|
|
|
2519
|
-
|
|
2487
|
+
if (!TIMEVAL_IS_VALID(tv))
|
|
2488
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
|
2489
|
+
|
|
2490
|
+
ctx = usbi_get_context(ctx);
|
|
2520
2491
|
r = get_next_timeout(ctx, tv, &poll_timeout);
|
|
2521
2492
|
if (r) {
|
|
2522
2493
|
/* timeout already expired */
|
|
2523
|
-
|
|
2494
|
+
handle_timeouts(ctx);
|
|
2495
|
+
return 0;
|
|
2524
2496
|
}
|
|
2525
2497
|
|
|
2526
2498
|
return handle_events(ctx, &poll_timeout);
|
|
@@ -2556,13 +2528,8 @@ int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx,
|
|
|
2556
2528
|
*/
|
|
2557
2529
|
int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx)
|
|
2558
2530
|
{
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
return usbi_using_timerfd(ctx);
|
|
2562
|
-
#else
|
|
2563
|
-
UNUSED(ctx);
|
|
2564
|
-
return 0;
|
|
2565
|
-
#endif
|
|
2531
|
+
ctx = usbi_get_context(ctx);
|
|
2532
|
+
return usbi_using_timer(ctx);
|
|
2566
2533
|
}
|
|
2567
2534
|
|
|
2568
2535
|
/** \ingroup libusb_poll
|
|
@@ -2596,55 +2563,49 @@ int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx)
|
|
|
2596
2563
|
int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
|
|
2597
2564
|
struct timeval *tv)
|
|
2598
2565
|
{
|
|
2599
|
-
struct usbi_transfer *
|
|
2600
|
-
struct timespec
|
|
2601
|
-
struct
|
|
2602
|
-
struct timeval next_timeout = { 0, 0 };
|
|
2603
|
-
int r;
|
|
2566
|
+
struct usbi_transfer *itransfer;
|
|
2567
|
+
struct timespec systime;
|
|
2568
|
+
struct timespec next_timeout = { 0, 0 };
|
|
2604
2569
|
|
|
2605
|
-
|
|
2606
|
-
if (
|
|
2570
|
+
ctx = usbi_get_context(ctx);
|
|
2571
|
+
if (usbi_using_timer(ctx))
|
|
2607
2572
|
return 0;
|
|
2608
2573
|
|
|
2609
2574
|
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
|
2610
2575
|
if (list_empty(&ctx->flying_transfers)) {
|
|
2611
2576
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
2612
|
-
usbi_dbg("no URBs, no timeout!");
|
|
2577
|
+
usbi_dbg(ctx, "no URBs, no timeout!");
|
|
2613
2578
|
return 0;
|
|
2614
2579
|
}
|
|
2615
2580
|
|
|
2616
2581
|
/* find next transfer which hasn't already been processed as timed out */
|
|
2617
|
-
|
|
2618
|
-
if (
|
|
2582
|
+
for_each_transfer(ctx, itransfer) {
|
|
2583
|
+
if (itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
|
|
2619
2584
|
continue;
|
|
2620
2585
|
|
|
2621
|
-
/* if we've reached transfers of
|
|
2622
|
-
if (!
|
|
2586
|
+
/* if we've reached transfers of infinite timeout, we're done looking */
|
|
2587
|
+
if (!TIMESPEC_IS_SET(&itransfer->timeout))
|
|
2623
2588
|
break;
|
|
2624
2589
|
|
|
2625
|
-
next_timeout =
|
|
2590
|
+
next_timeout = itransfer->timeout;
|
|
2626
2591
|
break;
|
|
2627
2592
|
}
|
|
2628
2593
|
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
2629
2594
|
|
|
2630
|
-
if (!
|
|
2631
|
-
usbi_dbg("no URB with timeout or all handled by OS; no timeout!");
|
|
2595
|
+
if (!TIMESPEC_IS_SET(&next_timeout)) {
|
|
2596
|
+
usbi_dbg(ctx, "no URB with timeout or all handled by OS; no timeout!");
|
|
2632
2597
|
return 0;
|
|
2633
2598
|
}
|
|
2634
2599
|
|
|
2635
|
-
|
|
2636
|
-
if (r < 0) {
|
|
2637
|
-
usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno);
|
|
2638
|
-
return 0;
|
|
2639
|
-
}
|
|
2640
|
-
TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
|
|
2600
|
+
usbi_get_monotonic_time(&systime);
|
|
2641
2601
|
|
|
2642
|
-
if (!
|
|
2643
|
-
usbi_dbg("first timeout already expired");
|
|
2602
|
+
if (!TIMESPEC_CMP(&systime, &next_timeout, <)) {
|
|
2603
|
+
usbi_dbg(ctx, "first timeout already expired");
|
|
2644
2604
|
timerclear(tv);
|
|
2645
2605
|
} else {
|
|
2646
|
-
|
|
2647
|
-
|
|
2606
|
+
TIMESPEC_SUB(&next_timeout, &systime, &next_timeout);
|
|
2607
|
+
TIMESPEC_TO_TIMEVAL(tv, &next_timeout);
|
|
2608
|
+
usbi_dbg(ctx, "next timeout in %ld.%06lds", (long)tv->tv_sec, (long)tv->tv_usec);
|
|
2648
2609
|
}
|
|
2649
2610
|
|
|
2650
2611
|
return 1;
|
|
@@ -2675,79 +2636,92 @@ void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx,
|
|
|
2675
2636
|
libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
|
|
2676
2637
|
void *user_data)
|
|
2677
2638
|
{
|
|
2678
|
-
|
|
2639
|
+
#if !defined(PLATFORM_WINDOWS)
|
|
2640
|
+
ctx = usbi_get_context(ctx);
|
|
2679
2641
|
ctx->fd_added_cb = added_cb;
|
|
2680
2642
|
ctx->fd_removed_cb = removed_cb;
|
|
2681
2643
|
ctx->fd_cb_user_data = user_data;
|
|
2644
|
+
#else
|
|
2645
|
+
usbi_err(ctx, "external polling of libusb's internal event sources " \
|
|
2646
|
+
"is not yet supported on Windows");
|
|
2647
|
+
UNUSED(added_cb);
|
|
2648
|
+
UNUSED(removed_cb);
|
|
2649
|
+
UNUSED(user_data);
|
|
2650
|
+
#endif
|
|
2682
2651
|
}
|
|
2683
2652
|
|
|
2684
2653
|
/*
|
|
2685
2654
|
* Interrupt the iteration of the event handling thread, so that it picks
|
|
2686
|
-
* up the
|
|
2655
|
+
* up the event source change. Callers of this function must hold the event_data_lock.
|
|
2687
2656
|
*/
|
|
2688
|
-
static void
|
|
2657
|
+
static void usbi_event_source_notification(struct libusb_context *ctx)
|
|
2689
2658
|
{
|
|
2690
|
-
int
|
|
2659
|
+
unsigned int event_flags;
|
|
2691
2660
|
|
|
2692
2661
|
/* Record that there is a new poll fd.
|
|
2693
2662
|
* Only signal an event if there are no prior pending events. */
|
|
2694
|
-
|
|
2695
|
-
ctx->event_flags |=
|
|
2696
|
-
if (!
|
|
2697
|
-
usbi_signal_event(ctx);
|
|
2663
|
+
event_flags = ctx->event_flags;
|
|
2664
|
+
ctx->event_flags |= USBI_EVENT_EVENT_SOURCES_MODIFIED;
|
|
2665
|
+
if (!event_flags)
|
|
2666
|
+
usbi_signal_event(&ctx->event);
|
|
2698
2667
|
}
|
|
2699
2668
|
|
|
2700
|
-
/* Add
|
|
2701
|
-
*
|
|
2669
|
+
/* Add an event source to the list of event sources to be monitored.
|
|
2670
|
+
* poll_events should be specified as a bitmask of events passed to poll(), e.g.
|
|
2702
2671
|
* POLLIN and/or POLLOUT. */
|
|
2703
|
-
int
|
|
2672
|
+
int usbi_add_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle, short poll_events)
|
|
2704
2673
|
{
|
|
2705
|
-
struct
|
|
2706
|
-
|
|
2674
|
+
struct usbi_event_source *ievent_source = malloc(sizeof(*ievent_source));
|
|
2675
|
+
|
|
2676
|
+
if (!ievent_source)
|
|
2707
2677
|
return LIBUSB_ERROR_NO_MEM;
|
|
2708
2678
|
|
|
2709
|
-
usbi_dbg("add
|
|
2710
|
-
|
|
2711
|
-
|
|
2679
|
+
usbi_dbg(ctx, "add " USBI_OS_HANDLE_FORMAT_STRING " events %d", os_handle, poll_events);
|
|
2680
|
+
ievent_source->data.os_handle = os_handle;
|
|
2681
|
+
ievent_source->data.poll_events = poll_events;
|
|
2712
2682
|
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2713
|
-
list_add_tail(&
|
|
2714
|
-
ctx
|
|
2715
|
-
usbi_fd_notification(ctx);
|
|
2683
|
+
list_add_tail(&ievent_source->list, &ctx->event_sources);
|
|
2684
|
+
usbi_event_source_notification(ctx);
|
|
2716
2685
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2717
2686
|
|
|
2687
|
+
#if !defined(PLATFORM_WINDOWS)
|
|
2718
2688
|
if (ctx->fd_added_cb)
|
|
2719
|
-
ctx->fd_added_cb(
|
|
2689
|
+
ctx->fd_added_cb(os_handle, poll_events, ctx->fd_cb_user_data);
|
|
2690
|
+
#endif
|
|
2691
|
+
|
|
2720
2692
|
return 0;
|
|
2721
2693
|
}
|
|
2722
2694
|
|
|
2723
|
-
/* Remove
|
|
2724
|
-
void
|
|
2695
|
+
/* Remove an event source from the list of event sources to be monitored. */
|
|
2696
|
+
void usbi_remove_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle)
|
|
2725
2697
|
{
|
|
2726
|
-
struct
|
|
2698
|
+
struct usbi_event_source *ievent_source;
|
|
2727
2699
|
int found = 0;
|
|
2728
2700
|
|
|
2729
|
-
usbi_dbg("remove
|
|
2701
|
+
usbi_dbg(ctx, "remove " USBI_OS_HANDLE_FORMAT_STRING, os_handle);
|
|
2730
2702
|
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2731
|
-
|
|
2732
|
-
if (
|
|
2703
|
+
for_each_event_source(ctx, ievent_source) {
|
|
2704
|
+
if (ievent_source->data.os_handle == os_handle) {
|
|
2733
2705
|
found = 1;
|
|
2734
2706
|
break;
|
|
2735
2707
|
}
|
|
2708
|
+
}
|
|
2736
2709
|
|
|
2737
2710
|
if (!found) {
|
|
2738
|
-
usbi_dbg("couldn't find
|
|
2711
|
+
usbi_dbg(ctx, "couldn't find " USBI_OS_HANDLE_FORMAT_STRING " to remove", os_handle);
|
|
2739
2712
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2740
2713
|
return;
|
|
2741
2714
|
}
|
|
2742
2715
|
|
|
2743
|
-
list_del(&
|
|
2744
|
-
list_add_tail(&
|
|
2745
|
-
ctx
|
|
2746
|
-
usbi_fd_notification(ctx);
|
|
2716
|
+
list_del(&ievent_source->list);
|
|
2717
|
+
list_add_tail(&ievent_source->list, &ctx->removed_event_sources);
|
|
2718
|
+
usbi_event_source_notification(ctx);
|
|
2747
2719
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2748
2720
|
|
|
2721
|
+
#if !defined(PLATFORM_WINDOWS)
|
|
2749
2722
|
if (ctx->fd_removed_cb)
|
|
2750
|
-
ctx->fd_removed_cb(
|
|
2723
|
+
ctx->fd_removed_cb(os_handle, ctx->fd_cb_user_data);
|
|
2724
|
+
#endif
|
|
2751
2725
|
}
|
|
2752
2726
|
|
|
2753
2727
|
/** \ingroup libusb_poll
|
|
@@ -2769,28 +2743,36 @@ DEFAULT_VISIBILITY
|
|
|
2769
2743
|
const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
|
|
2770
2744
|
libusb_context *ctx)
|
|
2771
2745
|
{
|
|
2772
|
-
#
|
|
2746
|
+
#if !defined(PLATFORM_WINDOWS)
|
|
2773
2747
|
struct libusb_pollfd **ret = NULL;
|
|
2774
|
-
struct
|
|
2775
|
-
size_t i
|
|
2776
|
-
|
|
2748
|
+
struct usbi_event_source *ievent_source;
|
|
2749
|
+
size_t i;
|
|
2750
|
+
|
|
2751
|
+
static_assert(sizeof(struct usbi_event_source_data) == sizeof(struct libusb_pollfd),
|
|
2752
|
+
"mismatch between usbi_event_source_data and libusb_pollfd sizes");
|
|
2753
|
+
|
|
2754
|
+
ctx = usbi_get_context(ctx);
|
|
2777
2755
|
|
|
2778
2756
|
usbi_mutex_lock(&ctx->event_data_lock);
|
|
2779
2757
|
|
|
2780
|
-
|
|
2758
|
+
i = 0;
|
|
2759
|
+
for_each_event_source(ctx, ievent_source)
|
|
2760
|
+
i++;
|
|
2761
|
+
|
|
2762
|
+
ret = calloc(i + 1, sizeof(struct libusb_pollfd *));
|
|
2781
2763
|
if (!ret)
|
|
2782
2764
|
goto out;
|
|
2783
2765
|
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2766
|
+
i = 0;
|
|
2767
|
+
for_each_event_source(ctx, ievent_source)
|
|
2768
|
+
ret[i++] = (struct libusb_pollfd *)ievent_source;
|
|
2787
2769
|
|
|
2788
2770
|
out:
|
|
2789
2771
|
usbi_mutex_unlock(&ctx->event_data_lock);
|
|
2790
|
-
return (const struct libusb_pollfd **)
|
|
2772
|
+
return (const struct libusb_pollfd **)ret;
|
|
2791
2773
|
#else
|
|
2792
|
-
usbi_err(ctx, "external polling of libusb's internal
|
|
2793
|
-
"is not yet supported on Windows
|
|
2774
|
+
usbi_err(ctx, "external polling of libusb's internal event sources " \
|
|
2775
|
+
"is not yet supported on Windows");
|
|
2794
2776
|
return NULL;
|
|
2795
2777
|
#endif
|
|
2796
2778
|
}
|
|
@@ -2808,7 +2790,11 @@ out:
|
|
|
2808
2790
|
*/
|
|
2809
2791
|
void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
|
|
2810
2792
|
{
|
|
2793
|
+
#if !defined(PLATFORM_WINDOWS)
|
|
2811
2794
|
free((void *)pollfds);
|
|
2795
|
+
#else
|
|
2796
|
+
UNUSED(pollfds);
|
|
2797
|
+
#endif
|
|
2812
2798
|
}
|
|
2813
2799
|
|
|
2814
2800
|
/* Backends may call this from handle_events to report disconnection of a
|
|
@@ -2817,10 +2803,11 @@ void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds)
|
|
|
2817
2803
|
*/
|
|
2818
2804
|
void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
|
|
2819
2805
|
{
|
|
2806
|
+
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
|
2820
2807
|
struct usbi_transfer *cur;
|
|
2821
2808
|
struct usbi_transfer *to_cancel;
|
|
2822
2809
|
|
|
2823
|
-
usbi_dbg("device %d.%d",
|
|
2810
|
+
usbi_dbg(ctx, "device %d.%d",
|
|
2824
2811
|
dev_handle->dev->bus_number, dev_handle->dev->device_address);
|
|
2825
2812
|
|
|
2826
2813
|
/* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE
|
|
@@ -2838,8 +2825,8 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
|
|
|
2838
2825
|
|
|
2839
2826
|
while (1) {
|
|
2840
2827
|
to_cancel = NULL;
|
|
2841
|
-
usbi_mutex_lock(&
|
|
2842
|
-
|
|
2828
|
+
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
|
2829
|
+
for_each_transfer(ctx, cur) {
|
|
2843
2830
|
if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) {
|
|
2844
2831
|
usbi_mutex_lock(&cur->lock);
|
|
2845
2832
|
if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT)
|
|
@@ -2849,12 +2836,13 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
|
|
|
2849
2836
|
if (to_cancel)
|
|
2850
2837
|
break;
|
|
2851
2838
|
}
|
|
2852
|
-
|
|
2839
|
+
}
|
|
2840
|
+
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
|
2853
2841
|
|
|
2854
2842
|
if (!to_cancel)
|
|
2855
2843
|
break;
|
|
2856
2844
|
|
|
2857
|
-
usbi_dbg("cancelling transfer %p from disconnect",
|
|
2845
|
+
usbi_dbg(ctx, "cancelling transfer %p from disconnect",
|
|
2858
2846
|
USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
|
|
2859
2847
|
|
|
2860
2848
|
usbi_mutex_lock(&to_cancel->lock);
|
|
@@ -2862,5 +2850,4 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
|
|
|
2862
2850
|
usbi_mutex_unlock(&to_cancel->lock);
|
|
2863
2851
|
usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
|
|
2864
2852
|
}
|
|
2865
|
-
|
|
2866
2853
|
}
|