usb 2.0.0-alpha.2 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.gitmodules +1 -1
  2. package/CHANGELOG.md +81 -0
  3. package/README.md +570 -0
  4. package/binding.gyp +2 -2
  5. package/dist/usb/bindings.d.ts +13 -0
  6. package/dist/usb/bindings.js +2 -1
  7. package/dist/usb/bindings.js.map +1 -1
  8. package/dist/usb/index.js +86 -2
  9. package/dist/usb/index.js.map +1 -1
  10. package/dist/usb/interface.js.map +1 -1
  11. package/dist/webusb/index.d.ts +28 -19
  12. package/dist/webusb/index.js +152 -66
  13. package/dist/webusb/index.js.map +1 -1
  14. package/dist/webusb/webusb-device.d.ts +1 -1
  15. package/dist/webusb/webusb-device.js +9 -4
  16. package/dist/webusb/webusb-device.js.map +1 -1
  17. package/libusb/.private/pre-commit.sh +7 -1
  18. package/libusb/.travis.yml +49 -0
  19. package/libusb/AUTHORS +44 -3
  20. package/libusb/Brewfile +4 -0
  21. package/libusb/ChangeLog +74 -2
  22. package/libusb/README.md +32 -0
  23. package/libusb/TODO +1 -1
  24. package/libusb/Xcode/common.xcconfig +12 -0
  25. package/libusb/Xcode/config.h +25 -0
  26. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
  27. package/libusb/android/README +4 -2
  28. package/libusb/android/config.h +75 -0
  29. package/libusb/appveyor.yml +41 -0
  30. package/libusb/appveyor_cygwin.bat +11 -0
  31. package/libusb/appveyor_minGW.bat +19 -0
  32. package/libusb/autogen.sh +1 -1
  33. package/libusb/bootstrap.sh +3 -16
  34. package/libusb/configure.ac +108 -80
  35. package/libusb/doc/doxygen.cfg.in +1785 -739
  36. package/libusb/examples/Makefile.am +1 -1
  37. package/libusb/examples/dpfp.c +3 -1
  38. package/libusb/examples/dpfp_threaded.c +23 -10
  39. package/libusb/examples/ezusb.c +3 -3
  40. package/libusb/examples/ezusb.h +2 -2
  41. package/libusb/examples/fxload.c +31 -9
  42. package/libusb/examples/hotplugtest.c +35 -7
  43. package/libusb/examples/listdevs.c +3 -1
  44. package/libusb/examples/sam3u_benchmark.c +3 -3
  45. package/libusb/examples/testlibusb.c +277 -0
  46. package/libusb/examples/xusb.c +40 -34
  47. package/libusb/libusb/Makefile.am +49 -23
  48. package/libusb/libusb/core.c +855 -457
  49. package/libusb/libusb/descriptor.c +72 -78
  50. package/libusb/libusb/hotplug.c +122 -76
  51. package/libusb/libusb/hotplug.h +42 -25
  52. package/libusb/libusb/io.c +625 -390
  53. package/libusb/libusb/libusb-1.0.def +12 -0
  54. package/libusb/libusb/libusb.h +218 -150
  55. package/libusb/libusb/libusbi.h +346 -176
  56. package/libusb/libusb/os/darwin_usb.c +604 -319
  57. package/libusb/libusb/os/darwin_usb.h +61 -20
  58. package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
  59. package/libusb/libusb/os/haiku_usb.h +113 -0
  60. package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
  61. package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
  62. package/libusb/libusb/os/haiku_usb_raw.h +188 -0
  63. package/libusb/libusb/os/linux_netlink.c +186 -146
  64. package/libusb/libusb/os/linux_udev.c +36 -14
  65. package/libusb/libusb/os/linux_usbfs.c +426 -225
  66. package/libusb/libusb/os/linux_usbfs.h +5 -3
  67. package/libusb/libusb/os/netbsd_usb.c +21 -77
  68. package/libusb/libusb/os/openbsd_usb.c +32 -115
  69. package/libusb/libusb/os/poll_posix.c +38 -5
  70. package/libusb/libusb/os/poll_posix.h +3 -0
  71. package/libusb/libusb/os/poll_windows.c +277 -626
  72. package/libusb/libusb/os/poll_windows.h +11 -44
  73. package/libusb/libusb/os/sunos_usb.c +1695 -0
  74. package/libusb/libusb/os/sunos_usb.h +80 -0
  75. package/libusb/libusb/os/threads_posix.c +24 -26
  76. package/libusb/libusb/os/threads_posix.h +73 -21
  77. package/libusb/libusb/os/threads_windows.c +71 -157
  78. package/libusb/libusb/os/threads_windows.h +68 -44
  79. package/libusb/libusb/os/wince_usb.c +276 -420
  80. package/libusb/libusb/os/wince_usb.h +23 -28
  81. package/libusb/libusb/os/windows_common.h +78 -58
  82. package/libusb/libusb/os/windows_nt_common.c +1010 -0
  83. package/libusb/libusb/os/windows_nt_common.h +110 -0
  84. package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
  85. package/libusb/libusb/os/windows_usbdk.c +830 -0
  86. package/libusb/libusb/os/windows_usbdk.h +103 -0
  87. package/libusb/libusb/os/windows_winusb.c +4391 -0
  88. package/libusb/libusb/os/windows_winusb.h +783 -0
  89. package/libusb/libusb/strerror.c +41 -7
  90. package/libusb/libusb/sync.c +41 -13
  91. package/libusb/libusb/version.h +1 -1
  92. package/libusb/libusb/version_nano.h +1 -1
  93. package/libusb/libusb-1.0.pc.in +1 -1
  94. package/libusb/msvc/appveyor.bat +27 -0
  95. package/libusb/msvc/config.h +5 -4
  96. package/libusb/msvc/ddk_build.cmd +87 -43
  97. package/libusb/msvc/fxload_2010.vcxproj +24 -104
  98. package/libusb/msvc/fxload_2012.vcxproj +24 -107
  99. package/libusb/msvc/fxload_2013.vcxproj +24 -107
  100. package/libusb/msvc/fxload_2015.vcxproj +91 -0
  101. package/libusb/msvc/fxload_2017.vcxproj +114 -0
  102. package/libusb/msvc/fxload_sources +1 -1
  103. package/libusb/msvc/getopt_2010.vcxproj +16 -75
  104. package/libusb/msvc/getopt_2012.vcxproj +16 -79
  105. package/libusb/msvc/getopt_2013.vcxproj +16 -79
  106. package/libusb/msvc/getopt_2015.vcxproj +73 -0
  107. package/libusb/msvc/getopt_2017.vcxproj +98 -0
  108. package/libusb/msvc/getopt_sources +6 -2
  109. package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
  110. package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
  111. package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
  112. package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
  113. package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
  114. package/libusb/msvc/hotplugtest_sources +1 -1
  115. package/libusb/msvc/libusb_2005.sln +20 -20
  116. package/libusb/msvc/libusb_2010.sln +57 -46
  117. package/libusb/msvc/libusb_2012.sln +57 -46
  118. package/libusb/msvc/libusb_2013.sln +57 -50
  119. package/libusb/msvc/libusb_2015.sln +59 -52
  120. package/libusb/msvc/libusb_2017.sln +186 -0
  121. package/libusb/msvc/libusb_dll.dsp +2 -2
  122. package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
  123. package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
  124. package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
  125. package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
  126. package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
  127. package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
  128. package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
  129. package/libusb/msvc/libusb_sources +10 -5
  130. package/libusb/msvc/libusb_static.dsp +2 -2
  131. package/libusb/msvc/libusb_static_2005.vcproj +32 -4
  132. package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
  133. package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
  134. package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
  135. package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
  136. package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
  137. package/libusb/msvc/libusb_static_wince.vcproj +20 -26
  138. package/libusb/msvc/libusb_wince.sln +88 -88
  139. package/libusb/msvc/listdevs_2010.vcxproj +16 -99
  140. package/libusb/msvc/listdevs_2012.vcxproj +16 -102
  141. package/libusb/msvc/listdevs_2013.vcxproj +16 -102
  142. package/libusb/msvc/listdevs_2015.vcxproj +83 -0
  143. package/libusb/msvc/listdevs_2017.vcxproj +106 -0
  144. package/libusb/msvc/listdevs_sources +2 -1
  145. package/libusb/msvc/stress_2010.vcxproj +20 -101
  146. package/libusb/msvc/stress_2012.vcxproj +20 -104
  147. package/libusb/msvc/stress_2013.vcxproj +20 -104
  148. package/libusb/msvc/stress_2015.vcxproj +87 -0
  149. package/libusb/msvc/stress_2017.vcxproj +110 -0
  150. package/libusb/msvc/stress_sources +21 -0
  151. package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
  152. package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
  153. package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
  154. package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
  155. package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
  156. package/libusb/msvc/testlibusb_sources +20 -0
  157. package/libusb/msvc/xusb_2010.vcxproj +17 -98
  158. package/libusb/msvc/xusb_2012.vcxproj +17 -101
  159. package/libusb/msvc/xusb_2013.vcxproj +17 -101
  160. package/libusb/msvc/xusb_2015.vcxproj +83 -0
  161. package/libusb/msvc/xusb_2017.vcxproj +106 -0
  162. package/libusb/msvc/xusb_sources +1 -1
  163. package/libusb/tests/stress.c +2 -2
  164. package/libusb/tests/testlib.c +0 -4
  165. package/libusb/travis-autogen.sh +39 -0
  166. package/libusb.gypi +13 -2
  167. package/package.json +23 -13
  168. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  169. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  170. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  171. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  172. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  173. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  174. package/prebuilds/linux-ia32/node.napi.node +0 -0
  175. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  176. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  177. package/prebuilds/win32-ia32/node.napi.node +0 -0
  178. package/prebuilds/win32-x64/node.napi.node +0 -0
  179. package/src/device.cc +7 -7
  180. package/src/node_usb.cc +43 -1
  181. package/src/uv_async_queue.h +33 -25
  182. package/test/usb.coffee +6 -0
  183. package/tsc/index.ts +1 -1
  184. package/tsc/usb/bindings.ts +19 -1
  185. package/tsc/usb/index.ts +67 -19
  186. package/tsc/usb/interface.ts +2 -2
  187. package/tsc/webusb/index.ts +187 -75
  188. package/tsc/webusb/webusb-device.ts +19 -15
  189. package/.github/workflows/prebuild.yml +0 -48
  190. package/Readme.md +0 -339
  191. package/dist/webusb/typed-event-target.d.ts +0 -11
  192. package/dist/webusb/typed-event-target.js +0 -21
  193. package/dist/webusb/typed-event-target.js.map +0 -1
  194. package/docs/assets/css/main.css +0 -2660
  195. package/docs/assets/images/icons.png +0 -0
  196. package/docs/assets/images/icons@2x.png +0 -0
  197. package/docs/assets/images/widgets.png +0 -0
  198. package/docs/assets/images/widgets@2x.png +0 -0
  199. package/docs/assets/js/main.js +0 -248
  200. package/docs/assets/js/search.js +0 -1
  201. package/docs/classes/usb_bindings.device.html +0 -1338
  202. package/docs/classes/usb_bindings.libusbexception.html +0 -234
  203. package/docs/classes/usb_bindings.transfer.html +0 -344
  204. package/docs/classes/usb_capability.capability.html +0 -297
  205. package/docs/classes/usb_device.extendeddevice.html +0 -766
  206. package/docs/classes/usb_endpoint.endpoint.html +0 -472
  207. package/docs/classes/usb_endpoint.inendpoint.html +0 -766
  208. package/docs/classes/usb_endpoint.outendpoint.html +0 -582
  209. package/docs/classes/usb_interface.interface.html +0 -648
  210. package/docs/classes/webusb.webusb-1.html +0 -615
  211. package/docs/classes/webusb_mutex.mutex.html +0 -270
  212. package/docs/classes/webusb_typed_event_target.typedeventtarget.html +0 -443
  213. package/docs/classes/webusb_webusb_device.webusbdevice.html +0 -904
  214. package/docs/index.html +0 -500
  215. package/docs/interfaces/usb.deviceevents.html +0 -242
  216. package/docs/interfaces/usb_descriptors.bosdescriptor.html +0 -293
  217. package/docs/interfaces/usb_descriptors.capabilitydescriptor.html +0 -274
  218. package/docs/interfaces/usb_descriptors.configdescriptor.html +0 -388
  219. package/docs/interfaces/usb_descriptors.devicedescriptor.html +0 -464
  220. package/docs/interfaces/usb_descriptors.endpointdescriptor.html +0 -370
  221. package/docs/interfaces/usb_descriptors.interfacedescriptor.html +0 -407
  222. package/docs/interfaces/webusb.usboptions.html +0 -226
  223. package/docs/modules/index.html +0 -304
  224. package/docs/modules/usb.html +0 -173
  225. package/docs/modules/usb_bindings.html +0 -2248
  226. package/docs/modules/usb_capability.html +0 -156
  227. package/docs/modules/usb_descriptors.html +0 -176
  228. package/docs/modules/usb_device.html +0 -156
  229. package/docs/modules/usb_endpoint.html +0 -164
  230. package/docs/modules/usb_interface.html +0 -156
  231. package/docs/modules/webusb.html +0 -165
  232. package/docs/modules/webusb_mutex.html +0 -156
  233. package/docs/modules/webusb_typed_event_target.html +0 -156
  234. package/docs/modules/webusb_webusb_device.html +0 -156
  235. package/docs/modules.html +0 -156
  236. package/libusb/INSTALL +0 -234
  237. package/libusb/README +0 -28
  238. package/libusb/libusb/os/windows_usb.c +0 -5347
  239. package/libusb/libusb/os/windows_usb.h +0 -971
  240. package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
  241. package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
  242. package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
  243. package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
  244. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
  245. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
  246. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
  247. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
  248. package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
  249. package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
  250. package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
  251. package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
  252. package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
  253. package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
  254. package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
  255. package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
  256. package/tsc/webusb/typed-event-target.ts +0 -23
package/package.json CHANGED
@@ -2,14 +2,14 @@
2
2
  "name": "usb",
3
3
  "description": "Library to access USB devices",
4
4
  "license": "MIT",
5
- "version": "2.0.0-alpha.2",
5
+ "version": "2.0.1",
6
6
  "main": "dist/index.js",
7
7
  "engines": {
8
- "node": ">=10"
8
+ "node": ">=10.16.0"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "https://github.com/tessel/node-usb.git"
12
+ "url": "https://github.com/node-usb/node-usb.git"
13
13
  },
14
14
  "contributors": [
15
15
  {
@@ -37,22 +37,29 @@
37
37
  ],
38
38
  "scripts": {
39
39
  "prepare": "yarn compile",
40
- "install": "prebuild-install --runtime napi --verbose || node-gyp rebuild",
41
- "prebuild": "prebuild --runtime napi -t 4 --force --strip --verbose",
40
+ "install": "node-gyp-build",
42
41
  "clean": "git clean -dfx",
43
42
  "compile": "tsc && yarn lint && yarn docs",
44
43
  "lint": "eslint . --ext .ts",
45
44
  "watch": "tsc -w --preserveWatchOutput",
46
45
  "test": "mocha --require coffeescript/register --grep Module test/*",
47
46
  "full-test": "mocha --require coffeescript/register test/*.coffee",
48
- "valgrind": "coffee -c test/usb.coffee; valgrind --leak-check=full --show-possibly-lost=no node --expose-gc --trace-gc node_modules/mocha/bin/_mocha -R spec",
49
- "docs": "typedoc"
47
+ "valgrind": "coffee -c test/*.coffee; valgrind --leak-check=full --show-possibly-lost=no node --expose-gc --trace-gc node_modules/mocha/bin/_mocha -R spec",
48
+ "docs": "typedoc",
49
+ "prebuild": "prebuildify --napi --strip",
50
+ "prebuild-darwin": "prebuildify --napi --strip --arch x64+arm64",
51
+ "prebuild-win32-x86": "prebuildify --napi --strip",
52
+ "prebuild-win32-x64": "prebuildify --napi --strip",
53
+ "prebuild-linux-x86": "prebuildify-cross -i ghcr.io/node-usb/linux-x86 --napi --strip",
54
+ "prebuild-linux-x64": "prebuildify-cross -i ghcr.io/node-usb/centos7-devtoolset7 -i ghcr.io/node-usb/alpine --napi --strip --tag-libc",
55
+ "prebuild-linux-arm": "prebuildify-cross -i ghcr.io/node-usb/linux-arm64 -i ghcr.io/node-usb/linux-armv7 -i ghcr.io/node-usb/linux-armv6 --napi --strip --tag-armv",
56
+ "prebuild-android-arm": "prebuildify-cross -i ghcr.io/node-usb/android-arm64 -i ghcr.io/node-usb/android-armv7 --napi --strip --tag-armv",
57
+ "prebuild-download": "prebuildify-ci download"
50
58
  },
51
59
  "dependencies": {
52
60
  "@types/w3c-web-usb": "^1.0.4",
53
- "bindings": "^1.4.0",
54
- "node-addon-api": "^3.1.0",
55
- "prebuild-install": "^6.1.1"
61
+ "node-addon-api": "^4.2.0",
62
+ "node-gyp-build": "^4.3.0"
56
63
  },
57
64
  "devDependencies": {
58
65
  "@types/node": "^14.14.41",
@@ -60,9 +67,12 @@
60
67
  "@typescript-eslint/parser": "^4.28.0",
61
68
  "coffeescript": "^2.5.1",
62
69
  "eslint": "^7.29.0",
63
- "mocha": "^8.3.2",
64
- "prebuild": "^10.0.1",
65
- "typedoc": "^0.20.36",
70
+ "mocha": "^9.1.3",
71
+ "node-gyp": "^7.1.2",
72
+ "prebuildify": "^4.2.1",
73
+ "prebuildify-ci": "^1.0.5",
74
+ "prebuildify-cross": "^4.0.1",
75
+ "typedoc": "^0.22.10",
66
76
  "typescript": "~4.2.4"
67
77
  },
68
78
  "binary": {
package/src/device.cc CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  Napi::FunctionReference Device::constructor;
13
13
 
14
- Device::Device(const Napi::CallbackInfo & info) : Napi::ObjectWrap<Device>(info), device_handle(0), refs_(1)
14
+ Device::Device(const Napi::CallbackInfo & info) : Napi::ObjectWrap<Device>(info), device_handle(0), refs_(0)
15
15
  #ifndef USE_POLL
16
16
  , completionQueue(handleCompletion)
17
17
  #endif
@@ -19,18 +19,12 @@ Device::Device(const Napi::CallbackInfo & info) : Napi::ObjectWrap<Device>(info)
19
19
  device = info[0].As<Napi::External<libusb_device>>().Data();
20
20
  libusb_ref_device(device);
21
21
  byPtr.insert(std::make_pair(device, this));
22
- #ifndef USE_POLL
23
- completionQueue.start(info.Env());
24
- #endif
25
22
  DEBUG_LOG("Created device %p", this);
26
23
  Constructor(info);
27
24
  }
28
25
 
29
26
  Device::~Device(){
30
27
  DEBUG_LOG("Freed device %p", this);
31
- #ifndef USE_POLL
32
- completionQueue.stop();
33
- #endif
34
28
  byPtr.erase(device);
35
29
  libusb_close(device_handle);
36
30
  libusb_unref_device(device);
@@ -194,6 +188,9 @@ Napi::Value Device::Open(const Napi::CallbackInfo& info) {
194
188
  ENTER_METHOD(Device, 0);
195
189
  if (!self->device_handle){
196
190
  CHECK_USB(libusb_open(self->device, &self->device_handle));
191
+ #ifndef USE_POLL
192
+ completionQueue.start(info.Env());
193
+ #endif
197
194
  }
198
195
  return env.Undefined();
199
196
  }
@@ -203,6 +200,9 @@ Napi::Value Device::Close(const Napi::CallbackInfo& info) {
203
200
  if (self->canClose()){
204
201
  libusb_close(self->device_handle);
205
202
  self->device_handle = NULL;
203
+ #ifndef USE_POLL
204
+ completionQueue.stop();
205
+ #endif
206
206
  }else{
207
207
  THROW_ERROR("Can't close device with a pending request");
208
208
  }
package/src/node_usb.cc CHANGED
@@ -4,8 +4,11 @@
4
4
 
5
5
  Napi::Value SetDebugLevel(const Napi::CallbackInfo& info);
6
6
  Napi::Value GetDeviceList(const Napi::CallbackInfo& info);
7
+ Napi::Value GetLibusbCapability(const Napi::CallbackInfo& info);
7
8
  Napi::Value EnableHotplugEvents(const Napi::CallbackInfo& info);
8
9
  Napi::Value DisableHotplugEvents(const Napi::CallbackInfo& info);
10
+ Napi::Value RefHotplugEvents(const Napi::CallbackInfo& info);
11
+ Napi::Value UnrefHotplugEvents(const Napi::CallbackInfo& info);
9
12
  void initConstants(Napi::Object target);
10
13
 
11
14
  libusb_context* usb_context;
@@ -16,6 +19,7 @@ struct HotPlug {
16
19
 
17
20
  #ifdef USE_POLL
18
21
  #include <poll.h>
22
+ #include <uv.h>
19
23
  #include <sys/time.h>
20
24
 
21
25
  std::map<int, uv_poll_t*> pollByFD;
@@ -94,8 +98,11 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
94
98
 
95
99
  exports.Set("setDebugLevel", Napi::Function::New(env, SetDebugLevel));
96
100
  exports.Set("getDeviceList", Napi::Function::New(env, GetDeviceList));
101
+ exports.Set("_getLibusbCapability", Napi::Function::New(env, GetLibusbCapability));
97
102
  exports.Set("_enableHotplugEvents", Napi::Function::New(env, EnableHotplugEvents));
98
103
  exports.Set("_disableHotplugEvents", Napi::Function::New(env, DisableHotplugEvents));
104
+ exports.Set("refHotplugEvents", Napi::Function::New(env, RefHotplugEvents));
105
+ exports.Set("unrefHotplugEvents", Napi::Function::New(env, UnrefHotplugEvents));
99
106
  return exports;
100
107
  }
101
108
 
@@ -128,6 +135,17 @@ Napi::Value GetDeviceList(const Napi::CallbackInfo& info) {
128
135
  return arr;
129
136
  }
130
137
 
138
+ Napi::Value GetLibusbCapability(const Napi::CallbackInfo& info) {
139
+ Napi::Env env = info.Env();
140
+
141
+ if (info.Length() != 1 || !info[0].IsNumber()) {
142
+ THROW_BAD_ARGS("Usb::GetLibusbCapability argument is invalid!")
143
+ }
144
+
145
+ int res = libusb_has_capability(info[0].As<Napi::Number>().Int32Value());
146
+ return Napi::Number::New(env, res);
147
+ }
148
+
131
149
  Napi::ObjectReference hotplugThis;
132
150
 
133
151
  void handleHotplug(HotPlug* info){
@@ -177,6 +195,7 @@ Napi::Value EnableHotplugEvents(const Napi::CallbackInfo& info) {
177
195
 
178
196
  if (!hotplugEnabled) {
179
197
  hotplugThis.Reset(info.This().As<Napi::Object>(), 1);
198
+ hotplugThis.SuppressDestruct();
180
199
  CHECK_USB(libusb_hotplug_register_callback(usb_context,
181
200
  (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
182
201
  (libusb_hotplug_flag)0, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
@@ -198,10 +217,27 @@ Napi::Value DisableHotplugEvents(const Napi::CallbackInfo& info) {
198
217
  return env.Undefined();
199
218
  }
200
219
 
220
+ Napi::Value RefHotplugEvents(const Napi::CallbackInfo& info) {
221
+ Napi::Env env = info.Env();
222
+ Napi::HandleScope scope(env);
223
+ if (hotplugEnabled) {
224
+ hotplugQueue.ref(env);
225
+ }
226
+ return env.Undefined();
227
+ }
228
+
229
+ Napi::Value UnrefHotplugEvents(const Napi::CallbackInfo& info) {
230
+ Napi::Env env = info.Env();
231
+ Napi::HandleScope scope(env);
232
+ if (hotplugEnabled) {
233
+ hotplugQueue.unref(env);
234
+ }
235
+ return env.Undefined();
236
+ }
237
+
201
238
  #define DEFINE_CONSTANT(OBJ, VALUE) \
202
239
  OBJ.DefineProperty(Napi::PropertyDescriptor::Value(#VALUE, Napi::Number::New(OBJ.Env(), VALUE), static_cast<napi_property_attributes>(napi_enumerable | napi_configurable)));
203
240
 
204
-
205
241
  void initConstants(Napi::Object target){
206
242
  DEFINE_CONSTANT(target, LIBUSB_CLASS_PER_INTERFACE);
207
243
  DEFINE_CONSTANT(target, LIBUSB_CLASS_AUDIO);
@@ -281,6 +317,12 @@ void initConstants(Napi::Object target){
281
317
  DEFINE_CONSTANT(target, LIBUSB_CONTROL_SETUP_SIZE);
282
318
  DEFINE_CONSTANT(target, LIBUSB_DT_BOS_SIZE);
283
319
 
320
+ // libusb_capability
321
+ DEFINE_CONSTANT(target, LIBUSB_CAP_HAS_CAPABILITY);
322
+ DEFINE_CONSTANT(target, LIBUSB_CAP_HAS_HOTPLUG);
323
+ DEFINE_CONSTANT(target, LIBUSB_CAP_HAS_HID_ACCESS);
324
+ DEFINE_CONSTANT(target, LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
325
+
284
326
  // libusb_error
285
327
  // Input/output error
286
328
  DEFINE_CONSTANT(target, LIBUSB_ERROR_IO);
@@ -3,31 +3,39 @@
3
3
 
4
4
  template <class T>
5
5
  class UVQueue{
6
- public:
7
- typedef void (*fptr)(T);
8
-
9
- Napi::ThreadSafeFunction tsfn;
10
-
11
- UVQueue(fptr cb): callback(cb) {}
12
-
13
- void start(Napi::Env env) {
14
- Napi::Function empty_func = Napi::Function::New(env, [](const Napi::CallbackInfo& cb) {});
15
- tsfn = Napi::ThreadSafeFunction::New(env, empty_func, "libusb", 0, 1);
16
- }
17
-
18
- void stop() {
19
- tsfn.Release();
20
- }
21
-
22
- void post(T value){
23
- auto cb = callback;
24
- tsfn.BlockingCall( value, [cb](Napi::Env _env, Napi::Function _jsCallback, T val) {
25
- cb(val);
26
- });
27
- }
28
-
29
- private:
30
- fptr callback;
6
+ public:
7
+ typedef void (*fptr)(T);
8
+
9
+ Napi::ThreadSafeFunction tsfn;
10
+
11
+ UVQueue(fptr cb): callback(cb) {}
12
+
13
+ void start(Napi::Env env) {
14
+ Napi::Function empty_func = Napi::Function::New(env, [](const Napi::CallbackInfo& cb) {});
15
+ tsfn = Napi::ThreadSafeFunction::New(env, empty_func, "libusb", 0, 1);
16
+ }
17
+
18
+ void stop() {
19
+ tsfn.Release();
20
+ }
21
+
22
+ void ref(Napi::Env env) {
23
+ tsfn.Ref(env);
24
+ }
25
+
26
+ void unref(Napi::Env env) {
27
+ tsfn.Unref(env);
28
+ }
29
+
30
+ void post(T value){
31
+ auto cb = callback;
32
+ tsfn.BlockingCall( value, [cb](Napi::Env _env, Napi::Function _jsCallback, T val) {
33
+ cb(val);
34
+ });
35
+ }
36
+
37
+ private:
38
+ fptr callback;
31
39
  };
32
40
 
33
41
  #endif
package/test/usb.coffee CHANGED
@@ -3,6 +3,7 @@ util = require('util')
3
3
  usb = require('../').usb
4
4
  getDeviceList = require('../').getDeviceList
5
5
  findByIds = require('../').findByIds
6
+ findBySerialNumber = require('../').findBySerialNumber
6
7
 
7
8
  if typeof gc is 'function'
8
9
  # running with --expose-gc, do a sweep between tests so valgrind blames the right one
@@ -38,6 +39,11 @@ describe 'findByIds', ->
38
39
  dev = findByIds(0x59e3, 0x0a23)
39
40
  assert.ok(dev, "Demo device is not attached")
40
41
 
42
+ describe 'findBySerialNumber', ->
43
+ it 'should return a single device ', ->
44
+ dev = findBySerialNumber('TEST_DEVICE')
45
+ assert.ok(dev, "Demo device is not attached")
46
+
41
47
  describe 'Device', ->
42
48
  device = null
43
49
  before ->
package/tsc/index.ts CHANGED
@@ -62,6 +62,6 @@ export {
62
62
  // WebUSB class for creating custom webusb instances
63
63
  WebUSB,
64
64
 
65
- // WebUSB Device class for turning a core usb.Device into a webusb device
65
+ // WebUSB Device class for turning a legacy usb.Device into a webusb device
66
66
  WebUSBDevice
67
67
  };
@@ -2,10 +2,11 @@
2
2
  // Eric Brody <https://github.com/underscorebrody>
3
3
  // Rob Moran <https://github.com/thegecko>
4
4
 
5
+ import { join } from 'path';
5
6
  import type { DeviceDescriptor, ConfigDescriptor, BosDescriptor } from './descriptors';
6
7
 
7
8
  /* eslint-disable @typescript-eslint/no-var-requires */
8
- const usb = require('bindings')('usb_bindings');
9
+ const usb = require('node-gyp-build')(join(__dirname, '..', '..'));
9
10
  module.exports = usb;
10
11
 
11
12
  /**
@@ -27,6 +28,17 @@ export declare function setDebugLevel(level: number): void;
27
28
 
28
29
  export declare function _enableHotplugEvents(): void;
29
30
  export declare function _disableHotplugEvents(): void;
31
+ export declare function _getLibusbCapability(capability: number): number;
32
+
33
+ /**
34
+ * Restore (re-reference) the hotplug events unreferenced by `unrefHotplugEvents()`
35
+ */
36
+ export declare function refHotplugEvents(): void;
37
+
38
+ /**
39
+ * Unreference the hotplug events from the event loop, allowing the process to exit even when listening for the `attach` and `detach` events
40
+ */
41
+ export declare function unrefHotplugEvents(): void;
30
42
 
31
43
  /** Represents a USB transfer */
32
44
  export declare class Transfer {
@@ -257,6 +269,12 @@ export declare const LIBUSB_RECIPIENT_OTHER: number;
257
269
  export declare const LIBUSB_CONTROL_SETUP_SIZE: number;
258
270
  export declare const LIBUSB_DT_BOS_SIZE: number;
259
271
 
272
+ // libusb_capability
273
+ export declare const LIBUSB_CAP_HAS_CAPABILITY: number;
274
+ export declare const LIBUSB_CAP_HAS_HOTPLUG: number;
275
+ export declare const LIBUSB_CAP_HAS_HID_ACCESS: number;
276
+ export declare const LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: number;
277
+
260
278
  // libusb_error
261
279
  /** Input/output error */
262
280
  export declare const LIBUSB_ERROR_IO: number;
package/tsc/usb/index.ts CHANGED
@@ -21,32 +21,76 @@ interface EventListeners<T> {
21
21
  declare module './bindings' {
22
22
 
23
23
  /* eslint-disable @typescript-eslint/no-empty-interface */
24
- interface Device extends ExtendedDevice {}
25
-
26
- interface DeviceEvents extends EventListeners<DeviceEvents> {
27
- attach: Device;
28
- detach: Device;
29
- }
30
-
31
- function addListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
32
- function removeListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
33
- function on<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
34
- function off<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
35
- function once<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
36
- function listeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[];
37
- function rawListeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[];
38
- function removeAllListeners<K extends keyof DeviceEvents>(event?: K): void;
39
- function emit<K extends keyof DeviceEvents>(event: K, arg: DeviceEvents[K]): boolean;
40
- function listenerCount<K extends keyof DeviceEvents>(event: K): number;
24
+ interface Device extends ExtendedDevice { }
25
+
26
+ interface DeviceEvents extends EventListeners<DeviceEvents> {
27
+ attach: Device;
28
+ detach: Device;
29
+ }
30
+
31
+ function addListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
32
+ function removeListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
33
+ function on<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
34
+ function off<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
35
+ function once<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
36
+ function listeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[];
37
+ function rawListeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[];
38
+ function removeAllListeners<K extends keyof DeviceEvents>(event?: K): void;
39
+ function emit<K extends keyof DeviceEvents>(event: K, arg: DeviceEvents[K]): boolean;
40
+ function listenerCount<K extends keyof DeviceEvents>(event: K): number;
41
41
  }
42
42
 
43
+ // Polling mechanism for discovering device changes until this is fixed:
44
+ // https://github.com/libusb/libusb/issues/86
45
+ const pollTimeout = 500;
46
+ const hotplugSupported = usb._getLibusbCapability(usb.LIBUSB_CAP_HAS_HOTPLUG) > 0;
47
+ let pollingHotplug = false;
48
+ let pollDevices: usb.Device[] = [];
49
+
50
+ const pollHotplug = (start = false) => {
51
+ if (start) {
52
+ pollingHotplug = true;
53
+ } else if (!pollingHotplug) {
54
+ return;
55
+ }
56
+
57
+ const devices = usb.getDeviceList();
58
+
59
+ if (!start) {
60
+ // Find attached devices
61
+ for (const device of devices) {
62
+ const found = pollDevices.find(item => item.deviceAddress === device.deviceAddress);
63
+ if (!found) {
64
+ usb.emit('attach', device);
65
+ }
66
+ }
67
+
68
+ // Find detached devices
69
+ for (const device of pollDevices) {
70
+ const found = devices.find(item => item.deviceAddress === device.deviceAddress);
71
+ if (!found) {
72
+ usb.emit('detach', device);
73
+ }
74
+ }
75
+ }
76
+
77
+ pollDevices = devices;
78
+ setTimeout(() => {
79
+ pollHotplug();
80
+ }, pollTimeout);
81
+ };
82
+
43
83
  usb.on('newListener', event => {
44
84
  if (event !== 'attach' && event !== 'detach') {
45
85
  return;
46
86
  }
47
87
  const listenerCount = usb.listenerCount('attach') + usb.listenerCount('detach');
48
88
  if (listenerCount === 0) {
49
- usb._enableHotplugEvents();
89
+ if (hotplugSupported) {
90
+ usb._enableHotplugEvents();
91
+ } else {
92
+ pollHotplug(true);
93
+ }
50
94
  }
51
95
  });
52
96
 
@@ -56,7 +100,11 @@ usb.on('removeListener', event => {
56
100
  }
57
101
  const listenerCount = usb.listenerCount('attach') + usb.listenerCount('detach');
58
102
  if (listenerCount === 0) {
59
- usb._disableHotplugEvents();
103
+ if (hotplugSupported) {
104
+ usb._disableHotplugEvents();
105
+ } else {
106
+ pollingHotplug = false;
107
+ }
60
108
  }
61
109
  });
62
110
 
@@ -28,7 +28,7 @@ export class Interface {
28
28
  this.interfaceNumber = this.descriptor.bInterfaceNumber;
29
29
  this.endpoints = [];
30
30
  const len = this.descriptor.endpoints.length;
31
- for (let i=0; i<len; i++){
31
+ for (let i = 0; i < len; i++) {
32
32
  const desc = this.descriptor.endpoints[i];
33
33
  const c = (desc.bEndpointAddress & LIBUSB_ENDPOINT_IN) ? InEndpoint : OutEndpoint;
34
34
  this.endpoints[i] = new c(this.device, desc);
@@ -145,7 +145,7 @@ export class Interface {
145
145
  */
146
146
  public setAltSetting(altSetting: number, callback?: (error: LibUSBException | undefined) => void): void {
147
147
  this.device.__setInterface(this.id, altSetting, error => {
148
- if (!error){
148
+ if (!error) {
149
149
  this.altSetting = altSetting;
150
150
  this.refresh();
151
151
  }