usb 1.7.2-prebuild

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 (183) hide show
  1. package/.github/workflows/prebuild.yml +62 -0
  2. package/.gitmodules +3 -0
  3. package/LICENSE +7 -0
  4. package/Readme.md +339 -0
  5. package/binding.gyp +90 -0
  6. package/libusb/.gitattributes +11 -0
  7. package/libusb/.private/README.txt +5 -0
  8. package/libusb/.private/bd.cmd +89 -0
  9. package/libusb/.private/bm.sh +54 -0
  10. package/libusb/.private/bwince.cmd +57 -0
  11. package/libusb/.private/post-rewrite.sh +28 -0
  12. package/libusb/.private/pre-commit.sh +42 -0
  13. package/libusb/.private/wbs.txt +61 -0
  14. package/libusb/.private/wbs_wince.txt +42 -0
  15. package/libusb/AUTHORS +78 -0
  16. package/libusb/COPYING +504 -0
  17. package/libusb/ChangeLog +211 -0
  18. package/libusb/INSTALL +234 -0
  19. package/libusb/INSTALL_WIN.txt +73 -0
  20. package/libusb/Makefile.am +28 -0
  21. package/libusb/NEWS +2 -0
  22. package/libusb/PORTING +94 -0
  23. package/libusb/README +28 -0
  24. package/libusb/README.git +41 -0
  25. package/libusb/TODO +2 -0
  26. package/libusb/Xcode/common.xcconfig +49 -0
  27. package/libusb/Xcode/debug.xcconfig +29 -0
  28. package/libusb/Xcode/libusb.xcconfig +21 -0
  29. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +1 -0
  30. package/libusb/Xcode/libusb_debug.xcconfig +21 -0
  31. package/libusb/Xcode/libusb_release.xcconfig +21 -0
  32. package/libusb/Xcode/release.xcconfig +30 -0
  33. package/libusb/android/README +114 -0
  34. package/libusb/android/jni/Android.mk +23 -0
  35. package/libusb/android/jni/Application.mk +24 -0
  36. package/libusb/android/jni/examples.mk +134 -0
  37. package/libusb/android/jni/libusb.mk +54 -0
  38. package/libusb/android/jni/tests.mk +56 -0
  39. package/libusb/autogen.sh +8 -0
  40. package/libusb/bootstrap.sh +19 -0
  41. package/libusb/configure.ac +304 -0
  42. package/libusb/doc/Makefile.am +9 -0
  43. package/libusb/doc/doxygen.cfg.in +1288 -0
  44. package/libusb/doc/libusb.png +0 -0
  45. package/libusb/examples/Makefile.am +19 -0
  46. package/libusb/examples/dpfp.c +506 -0
  47. package/libusb/examples/dpfp_threaded.c +544 -0
  48. package/libusb/examples/ezusb.c +831 -0
  49. package/libusb/examples/ezusb.h +120 -0
  50. package/libusb/examples/fxload.c +287 -0
  51. package/libusb/examples/getopt/getopt.c +1060 -0
  52. package/libusb/examples/getopt/getopt.h +180 -0
  53. package/libusb/examples/getopt/getopt1.c +188 -0
  54. package/libusb/examples/hotplugtest.c +104 -0
  55. package/libusb/examples/listdevs.c +71 -0
  56. package/libusb/examples/sam3u_benchmark.c +193 -0
  57. package/libusb/examples/xusb.c +1129 -0
  58. package/libusb/libusb/Makefile.am +75 -0
  59. package/libusb/libusb/core.c +2342 -0
  60. package/libusb/libusb/descriptor.c +1199 -0
  61. package/libusb/libusb/hotplug.c +327 -0
  62. package/libusb/libusb/hotplug.h +82 -0
  63. package/libusb/libusb/io.c +2631 -0
  64. package/libusb/libusb/libusb-1.0.def +166 -0
  65. package/libusb/libusb/libusb-1.0.rc +61 -0
  66. package/libusb/libusb/libusb.h +1998 -0
  67. package/libusb/libusb/libusbi.h +1040 -0
  68. package/libusb/libusb/os/darwin_usb.c +2009 -0
  69. package/libusb/libusb/os/darwin_usb.h +162 -0
  70. package/libusb/libusb/os/linux_netlink.c +369 -0
  71. package/libusb/libusb/os/linux_udev.c +307 -0
  72. package/libusb/libusb/os/linux_usbfs.c +2695 -0
  73. package/libusb/libusb/os/linux_usbfs.h +192 -0
  74. package/libusb/libusb/os/netbsd_usb.c +738 -0
  75. package/libusb/libusb/os/openbsd_usb.c +832 -0
  76. package/libusb/libusb/os/poll_posix.c +51 -0
  77. package/libusb/libusb/os/poll_posix.h +11 -0
  78. package/libusb/libusb/os/poll_windows.c +796 -0
  79. package/libusb/libusb/os/poll_windows.h +131 -0
  80. package/libusb/libusb/os/threads_posix.c +82 -0
  81. package/libusb/libusb/os/threads_posix.h +50 -0
  82. package/libusb/libusb/os/threads_windows.c +212 -0
  83. package/libusb/libusb/os/threads_windows.h +87 -0
  84. package/libusb/libusb/os/wince_usb.c +1032 -0
  85. package/libusb/libusb/os/wince_usb.h +131 -0
  86. package/libusb/libusb/os/windows_common.h +108 -0
  87. package/libusb/libusb/os/windows_usb.c +5347 -0
  88. package/libusb/libusb/os/windows_usb.h +971 -0
  89. package/libusb/libusb/strerror.c +199 -0
  90. package/libusb/libusb/sync.c +307 -0
  91. package/libusb/libusb/version.h +18 -0
  92. package/libusb/libusb/version_nano.h +1 -0
  93. package/libusb/libusb-1.0.pc.in +11 -0
  94. package/libusb/msvc/config.h +50 -0
  95. package/libusb/msvc/ddk_build.cmd +175 -0
  96. package/libusb/msvc/errno.h +102 -0
  97. package/libusb/msvc/fxload_2010.vcxproj +170 -0
  98. package/libusb/msvc/fxload_2010.vcxproj.filters +25 -0
  99. package/libusb/msvc/fxload_2012.vcxproj +174 -0
  100. package/libusb/msvc/fxload_2012.vcxproj.filters +25 -0
  101. package/libusb/msvc/fxload_2013.vcxproj +174 -0
  102. package/libusb/msvc/fxload_sources +23 -0
  103. package/libusb/msvc/getopt_2005.vcproj +288 -0
  104. package/libusb/msvc/getopt_2010.vcxproj +131 -0
  105. package/libusb/msvc/getopt_2010.vcxproj.filters +26 -0
  106. package/libusb/msvc/getopt_2012.vcxproj +136 -0
  107. package/libusb/msvc/getopt_2012.vcxproj.filters +26 -0
  108. package/libusb/msvc/getopt_2013.vcxproj +136 -0
  109. package/libusb/msvc/getopt_sources +20 -0
  110. package/libusb/msvc/hotplugtest_2010.vcxproj +163 -0
  111. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +14 -0
  112. package/libusb/msvc/hotplugtest_2012.vcxproj +167 -0
  113. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +14 -0
  114. package/libusb/msvc/hotplugtest_2013.vcxproj +167 -0
  115. package/libusb/msvc/hotplugtest_sources +20 -0
  116. package/libusb/msvc/inttypes.h +295 -0
  117. package/libusb/msvc/libusb.dsw +71 -0
  118. package/libusb/msvc/libusb_2005.sln +95 -0
  119. package/libusb/msvc/libusb_2010.sln +94 -0
  120. package/libusb/msvc/libusb_2012.sln +94 -0
  121. package/libusb/msvc/libusb_2013.sln +100 -0
  122. package/libusb/msvc/libusb_2015.sln +100 -0
  123. package/libusb/msvc/libusb_dll.dsp +194 -0
  124. package/libusb/msvc/libusb_dll_2005.vcproj +436 -0
  125. package/libusb/msvc/libusb_dll_2010.vcxproj +170 -0
  126. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +81 -0
  127. package/libusb/msvc/libusb_dll_2012.vcxproj +175 -0
  128. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +84 -0
  129. package/libusb/msvc/libusb_dll_2013.vcxproj +175 -0
  130. package/libusb/msvc/libusb_dll_wince.vcproj +1243 -0
  131. package/libusb/msvc/libusb_sources +38 -0
  132. package/libusb/msvc/libusb_static.dsp +174 -0
  133. package/libusb/msvc/libusb_static_2005.vcproj +362 -0
  134. package/libusb/msvc/libusb_static_2010.vcxproj +156 -0
  135. package/libusb/msvc/libusb_static_2010.vcxproj.filters +74 -0
  136. package/libusb/msvc/libusb_static_2012.vcxproj +160 -0
  137. package/libusb/msvc/libusb_static_2012.vcxproj.filters +74 -0
  138. package/libusb/msvc/libusb_static_2013.vcxproj +160 -0
  139. package/libusb/msvc/libusb_static_wince.vcproj +1185 -0
  140. package/libusb/msvc/libusb_wince.sln +246 -0
  141. package/libusb/msvc/listdevs.dsp +103 -0
  142. package/libusb/msvc/listdevs_2005.vcproj +360 -0
  143. package/libusb/msvc/listdevs_2010.vcxproj +165 -0
  144. package/libusb/msvc/listdevs_2010.vcxproj.filters +14 -0
  145. package/libusb/msvc/listdevs_2012.vcxproj +169 -0
  146. package/libusb/msvc/listdevs_2012.vcxproj.filters +14 -0
  147. package/libusb/msvc/listdevs_2013.vcxproj +169 -0
  148. package/libusb/msvc/listdevs_sources +19 -0
  149. package/libusb/msvc/listdevs_wince.vcproj +1120 -0
  150. package/libusb/msvc/missing.c +80 -0
  151. package/libusb/msvc/missing.h +32 -0
  152. package/libusb/msvc/stdint.h +256 -0
  153. package/libusb/msvc/stress_2005.vcproj +390 -0
  154. package/libusb/msvc/stress_2010.vcxproj +167 -0
  155. package/libusb/msvc/stress_2010.vcxproj.filters +25 -0
  156. package/libusb/msvc/stress_2012.vcxproj +171 -0
  157. package/libusb/msvc/stress_2012.vcxproj.filters +25 -0
  158. package/libusb/msvc/stress_2013.vcxproj +171 -0
  159. package/libusb/msvc/stress_wince.vcproj +1128 -0
  160. package/libusb/msvc/xusb.dsp +102 -0
  161. package/libusb/msvc/xusb_2005.vcproj +344 -0
  162. package/libusb/msvc/xusb_2010.vcxproj +163 -0
  163. package/libusb/msvc/xusb_2010.vcxproj.filters +14 -0
  164. package/libusb/msvc/xusb_2012.vcxproj +167 -0
  165. package/libusb/msvc/xusb_2012.vcxproj.filters +14 -0
  166. package/libusb/msvc/xusb_2013.vcxproj +167 -0
  167. package/libusb/msvc/xusb_sources +20 -0
  168. package/libusb/msvc/xusb_wince.vcproj +1120 -0
  169. package/libusb/tests/Makefile.am +6 -0
  170. package/libusb/tests/libusb_testlib.h +107 -0
  171. package/libusb/tests/stress.c +160 -0
  172. package/libusb/tests/testlib.c +281 -0
  173. package/libusb.gypi +136 -0
  174. package/libusb_config/config.h +1 -0
  175. package/package.json +69 -0
  176. package/src/device.cc +412 -0
  177. package/src/helpers.h +64 -0
  178. package/src/node_usb.cc +319 -0
  179. package/src/node_usb.h +120 -0
  180. package/src/transfer.cc +148 -0
  181. package/src/uv_async_queue.h +33 -0
  182. package/test/usb.coffee +191 -0
  183. package/usb.js +524 -0
@@ -0,0 +1,319 @@
1
+ #include "node_usb.h"
2
+ #include "uv_async_queue.h"
3
+ #include <thread>
4
+
5
+ Napi::Value SetDebugLevel(const Napi::CallbackInfo& info);
6
+ Napi::Value GetDeviceList(const Napi::CallbackInfo& info);
7
+ Napi::Value EnableHotplugEvents(const Napi::CallbackInfo& info);
8
+ Napi::Value DisableHotplugEvents(const Napi::CallbackInfo& info);
9
+ void initConstants(Napi::Object target);
10
+
11
+ libusb_context* usb_context;
12
+ struct HotPlug {
13
+ libusb_device* device;
14
+ libusb_hotplug_event event;
15
+ };
16
+
17
+ #ifdef USE_POLL
18
+ #include <poll.h>
19
+ #include <sys/time.h>
20
+
21
+ std::map<int, uv_poll_t*> pollByFD;
22
+
23
+ struct timeval zero_tv = {0, 0};
24
+
25
+ void onPollSuccess(uv_poll_t* handle, int status, int events){
26
+ libusb_handle_events_timeout(usb_context, &zero_tv);
27
+ }
28
+
29
+ void LIBUSB_CALL onPollFDAdded(int fd, short events, void *user_data){
30
+ uv_poll_t *poll_fd;
31
+ auto it = pollByFD.find(fd);
32
+ if (it != pollByFD.end()){
33
+ poll_fd = it->second;
34
+ }else{
35
+ poll_fd = (uv_poll_t*) malloc(sizeof(uv_poll_t));
36
+ uv_poll_init(uv_default_loop(), poll_fd, fd);
37
+ pollByFD.insert(std::make_pair(fd, poll_fd));
38
+ }
39
+
40
+ DEBUG_LOG("Added pollfd %i, %p", fd, poll_fd);
41
+ unsigned flags = ((events&POLLIN) ? UV_READABLE:0)
42
+ | ((events&POLLOUT)? UV_WRITABLE:0);
43
+ uv_poll_start(poll_fd, flags, onPollSuccess);
44
+ }
45
+
46
+ void LIBUSB_CALL onPollFDRemoved(int fd, void *user_data){
47
+ auto it = pollByFD.find(fd);
48
+ if (it != pollByFD.end()){
49
+ DEBUG_LOG("Removed pollfd %i, %p", fd, it->second);
50
+ uv_poll_stop(it->second);
51
+ uv_close((uv_handle_t*) it->second, (uv_close_cb) free);
52
+ pollByFD.erase(it);
53
+ }
54
+ }
55
+
56
+ #else
57
+ std::thread usb_thread;
58
+
59
+ void USBThreadFn(){
60
+ while(1) libusb_handle_events(usb_context);
61
+ }
62
+ #endif
63
+
64
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
65
+ Napi::HandleScope scope(env);
66
+
67
+ initConstants(exports);
68
+
69
+ // Initialize libusb. On error, halt initialization.
70
+ int res = libusb_init(&usb_context);
71
+ exports.Set("INIT_ERROR", Napi::Number::New(env, res));
72
+ if (res != 0) {
73
+ return exports;
74
+ }
75
+
76
+ #ifdef USE_POLL
77
+ assert(libusb_pollfds_handle_timeouts(usb_context));
78
+ libusb_set_pollfd_notifiers(usb_context, onPollFDAdded, onPollFDRemoved, NULL);
79
+
80
+ const struct libusb_pollfd** pollfds = libusb_get_pollfds(usb_context);
81
+ assert(pollfds);
82
+ for(const struct libusb_pollfd** i=pollfds; *i; i++){
83
+ onPollFDAdded((*i)->fd, (*i)->events, NULL);
84
+ }
85
+ free(pollfds);
86
+
87
+ #else
88
+ usb_thread = std::thread(USBThreadFn);
89
+ usb_thread.detach();
90
+ #endif
91
+
92
+ Device::Init(env, exports);
93
+ Transfer::Init(env, exports);
94
+
95
+ exports.Set("setDebugLevel", Napi::Function::New(env, SetDebugLevel));
96
+ exports.Set("getDeviceList", Napi::Function::New(env, GetDeviceList));
97
+ exports.Set("_enableHotplugEvents", Napi::Function::New(env, EnableHotplugEvents));
98
+ exports.Set("_disableHotplugEvents", Napi::Function::New(env, DisableHotplugEvents));
99
+ return exports;
100
+ }
101
+
102
+ NODE_API_MODULE(usb_bindings, Init)
103
+
104
+ Napi::Value SetDebugLevel(const Napi::CallbackInfo& info) {
105
+ Napi::Env env = info.Env();
106
+ Napi::HandleScope scope(env);
107
+ if (info.Length() != 1 || !info[0].IsNumber() || info[0].As<Napi::Number>().Uint32Value() > 4) {
108
+ THROW_BAD_ARGS("Usb::SetDebugLevel argument is invalid. [uint:[0-4]]!")
109
+ }
110
+
111
+ libusb_set_debug(usb_context, info[0].As<Napi::Number>().Int32Value());
112
+ return env.Undefined();
113
+ }
114
+
115
+ Napi::Value GetDeviceList(const Napi::CallbackInfo& info) {
116
+ Napi::Env env = info.Env();
117
+ Napi::HandleScope scope(env);
118
+ libusb_device **devs;
119
+ int cnt = libusb_get_device_list(usb_context, &devs);
120
+ CHECK_USB(cnt);
121
+
122
+ Napi::Array arr = Napi::Array::New(env, cnt);
123
+
124
+ for(int i = 0; i < cnt; i++) {
125
+ arr.Set(i, Device::get(env, devs[i]));
126
+ }
127
+ libusb_free_device_list(devs, true);
128
+ return arr;
129
+ }
130
+
131
+ Napi::ObjectReference hotplugThis;
132
+
133
+ void handleHotplug(HotPlug* info){
134
+ Napi::Env env = hotplugThis.Env();
135
+ Napi::HandleScope scope(env);
136
+
137
+ libusb_device* dev = info->device;
138
+ libusb_hotplug_event event = info->event;
139
+ delete info;
140
+
141
+ DEBUG_LOG("HandleHotplug %p %i", dev, event);
142
+
143
+ Napi::Value v8dev = Device::get(env, dev);
144
+ libusb_unref_device(dev);
145
+
146
+ Napi::String eventName;
147
+ if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
148
+ DEBUG_LOG("Device arrived");
149
+ eventName = Napi::String::New(env, "attach");
150
+
151
+ } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
152
+ DEBUG_LOG("Device left");
153
+ eventName = Napi::String::New(env, "detach");
154
+
155
+ } else {
156
+ DEBUG_LOG("Unhandled hotplug event %d\n", event);
157
+ return;
158
+ }
159
+
160
+ hotplugThis.Get("emit").As<Napi::Function>().MakeCallback(hotplugThis.Value(), { eventName, v8dev });
161
+ }
162
+
163
+ bool hotplugEnabled = 0;
164
+ libusb_hotplug_callback_handle hotplugHandle;
165
+ UVQueue<HotPlug*> hotplugQueue(handleHotplug);
166
+
167
+ int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *device,
168
+ libusb_hotplug_event event, void *user_data) {
169
+ libusb_ref_device(device);
170
+ hotplugQueue.post(new HotPlug {device, event});
171
+ return 0;
172
+ }
173
+
174
+ Napi::Value EnableHotplugEvents(const Napi::CallbackInfo& info) {
175
+ Napi::Env env = info.Env();
176
+ Napi::HandleScope scope(env);
177
+
178
+ if (!hotplugEnabled) {
179
+ hotplugThis.Reset(info.This().As<Napi::Object>(), 1);
180
+ hotplugThis.SuppressDestruct();
181
+ CHECK_USB(libusb_hotplug_register_callback(usb_context,
182
+ (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
183
+ (libusb_hotplug_flag)0, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
184
+ hotplug_callback, NULL, &hotplugHandle));
185
+ hotplugQueue.start(env);
186
+ hotplugEnabled = true;
187
+ }
188
+ return env.Undefined();
189
+ }
190
+
191
+ Napi::Value DisableHotplugEvents(const Napi::CallbackInfo& info) {
192
+ Napi::Env env = info.Env();
193
+ Napi::HandleScope scope(env);
194
+ if (hotplugEnabled) {
195
+ libusb_hotplug_deregister_callback(usb_context, hotplugHandle);
196
+ hotplugQueue.stop();
197
+ hotplugEnabled = false;
198
+ }
199
+ return env.Undefined();
200
+ }
201
+
202
+ #define DEFINE_CONSTANT(OBJ, VALUE) \
203
+ OBJ.DefineProperty(Napi::PropertyDescriptor::Value(#VALUE, Napi::Number::New(OBJ.Env(), VALUE), static_cast<napi_property_attributes>(napi_enumerable | napi_configurable)));
204
+
205
+
206
+ void initConstants(Napi::Object target){
207
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_PER_INTERFACE);
208
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_AUDIO);
209
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_COMM);
210
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_HID);
211
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_PRINTER);
212
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_PTP);
213
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_MASS_STORAGE);
214
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_HUB);
215
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_DATA);
216
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_WIRELESS);
217
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_APPLICATION);
218
+ DEFINE_CONSTANT(target, LIBUSB_CLASS_VENDOR_SPEC);
219
+ // libusb_standard_request
220
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_GET_STATUS);
221
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_CLEAR_FEATURE);
222
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_SET_FEATURE);
223
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_SET_ADDRESS );
224
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_GET_DESCRIPTOR);
225
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_SET_DESCRIPTOR);
226
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_GET_CONFIGURATION);
227
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_SET_CONFIGURATION );
228
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_GET_INTERFACE);
229
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_SET_INTERFACE);
230
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_SYNCH_FRAME);
231
+ // libusb_descriptor_type
232
+ DEFINE_CONSTANT(target, LIBUSB_DT_DEVICE);
233
+ DEFINE_CONSTANT(target, LIBUSB_DT_CONFIG);
234
+ DEFINE_CONSTANT(target, LIBUSB_DT_STRING);
235
+ DEFINE_CONSTANT(target, LIBUSB_DT_BOS);
236
+ DEFINE_CONSTANT(target, LIBUSB_DT_INTERFACE);
237
+ DEFINE_CONSTANT(target, LIBUSB_DT_ENDPOINT);
238
+ DEFINE_CONSTANT(target, LIBUSB_DT_HID);
239
+ DEFINE_CONSTANT(target, LIBUSB_DT_REPORT);
240
+ DEFINE_CONSTANT(target, LIBUSB_DT_PHYSICAL);
241
+ DEFINE_CONSTANT(target, LIBUSB_DT_HUB);
242
+ // libusb_endpoint_direction
243
+ DEFINE_CONSTANT(target, LIBUSB_ENDPOINT_IN);
244
+ DEFINE_CONSTANT(target, LIBUSB_ENDPOINT_OUT);
245
+ // libusb_transfer_type
246
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_TYPE_CONTROL);
247
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_TYPE_ISOCHRONOUS);
248
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_TYPE_BULK);
249
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_TYPE_INTERRUPT);
250
+ // libusb_iso_sync_type
251
+ DEFINE_CONSTANT(target, LIBUSB_ISO_SYNC_TYPE_NONE);
252
+ DEFINE_CONSTANT(target, LIBUSB_ISO_SYNC_TYPE_ASYNC);
253
+ DEFINE_CONSTANT(target, LIBUSB_ISO_SYNC_TYPE_ADAPTIVE);
254
+ DEFINE_CONSTANT(target, LIBUSB_ISO_SYNC_TYPE_SYNC);
255
+ // libusb_iso_usage_type
256
+ DEFINE_CONSTANT(target, LIBUSB_ISO_USAGE_TYPE_DATA);
257
+ DEFINE_CONSTANT(target, LIBUSB_ISO_USAGE_TYPE_FEEDBACK);
258
+ DEFINE_CONSTANT(target, LIBUSB_ISO_USAGE_TYPE_IMPLICIT);
259
+ // libusb_transfer_status
260
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_COMPLETED);
261
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_ERROR);
262
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_TIMED_OUT);
263
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_CANCELLED);
264
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_STALL);
265
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_NO_DEVICE);
266
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_OVERFLOW);
267
+ // libusb_transfer_flags
268
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_SHORT_NOT_OK);
269
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_FREE_BUFFER);
270
+ DEFINE_CONSTANT(target, LIBUSB_TRANSFER_FREE_TRANSFER);
271
+ // libusb_request_type
272
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_TYPE_STANDARD);
273
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_TYPE_CLASS);
274
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_TYPE_VENDOR);
275
+ DEFINE_CONSTANT(target, LIBUSB_REQUEST_TYPE_RESERVED);
276
+ // libusb_request_recipient
277
+ DEFINE_CONSTANT(target, LIBUSB_RECIPIENT_DEVICE);
278
+ DEFINE_CONSTANT(target, LIBUSB_RECIPIENT_INTERFACE);
279
+ DEFINE_CONSTANT(target, LIBUSB_RECIPIENT_ENDPOINT);
280
+ DEFINE_CONSTANT(target, LIBUSB_RECIPIENT_OTHER);
281
+
282
+ DEFINE_CONSTANT(target, LIBUSB_CONTROL_SETUP_SIZE);
283
+ DEFINE_CONSTANT(target, LIBUSB_DT_BOS_SIZE);
284
+
285
+ // libusb_error
286
+ // Input/output error
287
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_IO);
288
+ // Invalid parameter
289
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_INVALID_PARAM);
290
+ // Access denied (insufficient permissions)
291
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_ACCESS);
292
+ // No such device (it may have been disconnected)
293
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_NO_DEVICE);
294
+ // Entity not found
295
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_NOT_FOUND);
296
+ // Resource busy
297
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_BUSY);
298
+ // Operation timed out
299
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_TIMEOUT);
300
+ // Overflow
301
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_OVERFLOW);
302
+ // Pipe error
303
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_PIPE);
304
+ // System call interrupted (perhaps due to signal)
305
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_INTERRUPTED);
306
+ // Insufficient memory
307
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_NO_MEM);
308
+ // Operation not supported or unimplemented on this platform
309
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_NOT_SUPPORTED);
310
+ // Other error
311
+ DEFINE_CONSTANT(target, LIBUSB_ERROR_OTHER);
312
+ }
313
+
314
+ Napi::Error libusbException(napi_env env, int errorno) {
315
+ const char* err = libusb_error_name(errorno);
316
+ Napi::Error e = Napi::Error::New(env, err);
317
+ e.Set("errno", (double)errorno);
318
+ return e;
319
+ }
package/src/node_usb.h ADDED
@@ -0,0 +1,120 @@
1
+ #ifndef SRC_NODE_USB_H
2
+ #define SRC_NODE_USB_H
3
+
4
+ #include <assert.h>
5
+ #include <string>
6
+ #include <map>
7
+
8
+ #ifdef _WIN32
9
+ #include <WinSock2.h>
10
+ #endif
11
+ #include <libusb.h>
12
+
13
+ #include <napi.h>
14
+ #include <node_buffer.h>
15
+
16
+ #include "helpers.h"
17
+
18
+ #ifndef USE_POLL
19
+ #include "uv_async_queue.h"
20
+ #endif
21
+
22
+ struct Transfer;
23
+
24
+ Napi::Error libusbException(napi_env env, int errorno);
25
+ void handleCompletion(Transfer* self);
26
+
27
+ struct Device: public Napi::ObjectWrap<Device> {
28
+ libusb_device* device;
29
+ libusb_device_handle* device_handle;
30
+
31
+ int refs_;
32
+
33
+ #ifndef USE_POLL
34
+ UVQueue<Transfer*> completionQueue;
35
+ #endif
36
+
37
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
38
+ static Napi::Object get(napi_env env, libusb_device* handle);
39
+
40
+ inline void ref(){ refs_ = Ref();}
41
+ inline void unref(){ refs_ = Unref();}
42
+ inline bool canClose(){return refs_ == 0;}
43
+
44
+ Device(const Napi::CallbackInfo& info);
45
+ ~Device();
46
+
47
+ static Napi::Object cdesc2V8(napi_env env, libusb_config_descriptor * cdesc);
48
+
49
+
50
+ Napi::Value GetConfigDescriptor(const Napi::CallbackInfo& info);
51
+ Napi::Value GetAllConfigDescriptors(const Napi::CallbackInfo& info);
52
+ Napi::Value SetConfiguration(const Napi::CallbackInfo& info);
53
+
54
+ Napi::Value GetParent(const Napi::CallbackInfo& info);
55
+ Napi::Value Open(const Napi::CallbackInfo& info);
56
+ Napi::Value Reset(const Napi::CallbackInfo& info);
57
+ Napi::Value Close(const Napi::CallbackInfo& info);
58
+
59
+ Napi::Value IsKernelDriverActive(const Napi::CallbackInfo& info);
60
+ Napi::Value DetachKernelDriver(const Napi::CallbackInfo& info);
61
+ Napi::Value AttachKernelDriver(const Napi::CallbackInfo& info);
62
+
63
+ Napi::Value ClaimInterface(const Napi::CallbackInfo& info);
64
+ Napi::Value SetInterface(const Napi::CallbackInfo& info);
65
+ Napi::Value ReleaseInterface(const Napi::CallbackInfo& info);
66
+
67
+ Napi::Value ClearHalt(const Napi::CallbackInfo& info);
68
+ protected:
69
+ static std::map<libusb_device*, Device*> byPtr;
70
+ static Napi::FunctionReference constructor;
71
+
72
+ Napi::Value Constructor(const Napi::CallbackInfo& info);
73
+ };
74
+
75
+
76
+ struct Transfer: public Napi::ObjectWrap<Transfer> {
77
+ libusb_transfer* transfer;
78
+ Device* device;
79
+ Napi::ObjectReference v8buffer;
80
+ Napi::FunctionReference v8callback;
81
+
82
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
83
+
84
+ inline void ref(){Ref();}
85
+ inline void unref(){Unref();}
86
+
87
+ Transfer(const Napi::CallbackInfo& info);
88
+ ~Transfer();
89
+
90
+ Napi::Value Submit(const Napi::CallbackInfo& info);
91
+ Napi::Value Cancel(const Napi::CallbackInfo& info);
92
+ private:
93
+ Napi::Value Constructor(const Napi::CallbackInfo& info);
94
+ };
95
+
96
+
97
+
98
+ #define CHECK_USB(r) \
99
+ if (r < LIBUSB_SUCCESS) { \
100
+ throw libusbException(env, r); \
101
+ }
102
+
103
+ #define CALLBACK_ARG(CALLBACK_ARG_IDX) \
104
+ Napi::Function callback; \
105
+ if (info.Length() > (CALLBACK_ARG_IDX)) { \
106
+ if (!info[CALLBACK_ARG_IDX].IsFunction()) { \
107
+ throw Napi::TypeError::New(env, "Argument " #CALLBACK_ARG_IDX " must be a function"); \
108
+ } \
109
+ callback = info[CALLBACK_ARG_IDX].As<Napi::Function>(); \
110
+ } \
111
+
112
+ #ifdef DEBUG
113
+ #define DEBUG_HEADER fprintf(stderr, "node-usb [%s:%s() %d]: ", __FILE__, __FUNCTION__, __LINE__);
114
+ #define DEBUG_FOOTER fprintf(stderr, "\n");
115
+ #define DEBUG_LOG(...) DEBUG_HEADER fprintf(stderr, __VA_ARGS__); DEBUG_FOOTER
116
+ #else
117
+ #define DEBUG_LOG(...)
118
+ #endif
119
+
120
+ #endif
@@ -0,0 +1,148 @@
1
+ #include "node_usb.h"
2
+
3
+ extern "C" void LIBUSB_CALL usbCompletionCb(libusb_transfer *transfer);
4
+
5
+ Transfer::Transfer(const Napi::CallbackInfo& info)
6
+ : Napi::ObjectWrap<Transfer>(info) {
7
+ transfer = libusb_alloc_transfer(0);
8
+ transfer->callback = usbCompletionCb;
9
+ transfer->user_data = this;
10
+ DEBUG_LOG("Created Transfer %p", this);
11
+ Constructor(info);
12
+ }
13
+
14
+ Transfer::~Transfer(){
15
+ DEBUG_LOG("Freed Transfer %p", this);
16
+ v8callback.Reset();
17
+ libusb_free_transfer(transfer);
18
+ }
19
+
20
+ // new Transfer(device, endpointAddr, type, timeout)
21
+ Napi::Value Transfer::Constructor(const Napi::CallbackInfo& info) {
22
+ Napi::Env env = info.Env();
23
+ ENTER_CONSTRUCTOR(5);
24
+ UNWRAP_ARG(Device, device, 0);
25
+ int endpoint, type, timeout;
26
+ INT_ARG(endpoint, 1);
27
+ INT_ARG(type, 2);
28
+ INT_ARG(timeout, 3);
29
+ CALLBACK_ARG(4);
30
+
31
+ info.This().As<Napi::Object>().DefineProperty(Napi::PropertyDescriptor::Value(std::string("device"), info[0], CONST_PROP));
32
+ auto self = this;
33
+ self->device = device;
34
+ self->transfer->endpoint = endpoint;
35
+ self->transfer->type = type;
36
+ self->transfer->timeout = timeout;
37
+
38
+ self->v8callback.Reset(callback, 1);
39
+
40
+ return info.This();
41
+ }
42
+
43
+ // Transfer.submit(buffer, callback)
44
+ Napi::Value Transfer::Submit(const Napi::CallbackInfo& info) {
45
+ ENTER_METHOD(Transfer, 1);
46
+
47
+ if (self->transfer->buffer){
48
+ THROW_ERROR("Transfer is already active")
49
+ }
50
+
51
+ if (!info[0].IsBuffer()){
52
+ THROW_BAD_ARGS("Buffer arg [0] must be Buffer");
53
+ }
54
+ Napi::Buffer<unsigned char> buffer_obj = info[0].As<Napi::Buffer<unsigned char>>();
55
+ if (!self->device->device_handle){
56
+ THROW_ERROR("Device is not open");
57
+ }
58
+
59
+ // Can't be cached in constructor as device could be closed and re-opened
60
+ self->transfer->dev_handle = self->device->device_handle;
61
+
62
+ self->v8buffer.Reset(buffer_obj, 1);
63
+ self->transfer->buffer = (unsigned char*) buffer_obj.Data();
64
+ self->transfer->length = buffer_obj.ByteLength();
65
+
66
+ DEBUG_LOG("Submitting, %p %p %x %i %i %i %p",
67
+ self,
68
+ self->transfer->dev_handle,
69
+ self->transfer->endpoint,
70
+ self->transfer->type,
71
+ self->transfer->timeout,
72
+ self->transfer->length,
73
+ self->transfer->buffer
74
+ );
75
+
76
+ CHECK_USB(libusb_submit_transfer(self->transfer));
77
+ self->ref();
78
+ self->device->ref();
79
+
80
+ return info.This();
81
+ }
82
+
83
+ extern "C" void LIBUSB_CALL usbCompletionCb(libusb_transfer *transfer){
84
+ Transfer* t = static_cast<Transfer*>(transfer->user_data);
85
+ DEBUG_LOG("Completion callback %p", t);
86
+ assert(t != NULL);
87
+
88
+ #ifdef USE_POLL
89
+ handleCompletion(t);
90
+ #else
91
+ t->device->completionQueue.post(t);
92
+ #endif
93
+ }
94
+
95
+ void handleCompletion(Transfer* self){
96
+ Napi::Env env = self->Env();
97
+ Napi::HandleScope scope(env);
98
+ DEBUG_LOG("HandleCompletion %p", self);
99
+
100
+ self->device->unref();
101
+
102
+ // The callback may resubmit and overwrite these, so need to clear the
103
+ // persistent first.
104
+ Napi::Object buffer = self->v8buffer.Value();
105
+ self->v8buffer.Reset();
106
+ self->transfer->buffer = NULL;
107
+
108
+ if (!self->v8callback.IsEmpty()) {
109
+ Napi::Value error = env.Undefined();
110
+ if (self->transfer->status != 0){
111
+ error = libusbException(env, self->transfer->status).Value();
112
+ }
113
+ try {
114
+ self->v8callback.MakeCallback(self->Value(), { error, buffer,
115
+ Napi::Number::New(env, (uint32_t)self->transfer->actual_length) });
116
+ }
117
+ catch (const Napi::Error& e) {
118
+ Napi::Error::Fatal("", e.what());
119
+ }
120
+ }
121
+
122
+ self->unref();
123
+ }
124
+
125
+ Napi::Value Transfer::Cancel(const Napi::CallbackInfo& info){
126
+ ENTER_METHOD(Transfer, 0);
127
+ DEBUG_LOG("Cancel %p %i", self, !!self->transfer->buffer);
128
+ int r = libusb_cancel_transfer(self->transfer);
129
+ if (r == LIBUSB_ERROR_NOT_FOUND){
130
+ // Not useful to throw an error for this case
131
+ return Napi::Boolean::New(env, false);
132
+ } else {
133
+ CHECK_USB(r);
134
+ return Napi::Boolean::New(env, true);
135
+ }
136
+ }
137
+
138
+ Napi::Object Transfer::Init(Napi::Env env, Napi::Object exports) {
139
+ exports.Set("Transfer", Transfer::DefineClass(
140
+ env,
141
+ "Transfer",
142
+ {
143
+ Transfer::InstanceMethod("submit", &Transfer::Submit),
144
+ Transfer::InstanceMethod("cancel", &Transfer::Cancel),
145
+ }));
146
+
147
+ return exports;
148
+ }
@@ -0,0 +1,33 @@
1
+ #ifndef SRC_UV_ASYNC_QUEUE_H
2
+ #define SRC_UV_ASYNC_QUEUE_H
3
+
4
+ template <class T>
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;
31
+ };
32
+
33
+ #endif