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.
- package/.github/workflows/prebuild.yml +62 -0
- package/.gitmodules +3 -0
- package/LICENSE +7 -0
- package/Readme.md +339 -0
- package/binding.gyp +90 -0
- package/libusb/.gitattributes +11 -0
- package/libusb/.private/README.txt +5 -0
- package/libusb/.private/bd.cmd +89 -0
- package/libusb/.private/bm.sh +54 -0
- package/libusb/.private/bwince.cmd +57 -0
- package/libusb/.private/post-rewrite.sh +28 -0
- package/libusb/.private/pre-commit.sh +42 -0
- package/libusb/.private/wbs.txt +61 -0
- package/libusb/.private/wbs_wince.txt +42 -0
- package/libusb/AUTHORS +78 -0
- package/libusb/COPYING +504 -0
- package/libusb/ChangeLog +211 -0
- package/libusb/INSTALL +234 -0
- package/libusb/INSTALL_WIN.txt +73 -0
- package/libusb/Makefile.am +28 -0
- package/libusb/NEWS +2 -0
- package/libusb/PORTING +94 -0
- package/libusb/README +28 -0
- package/libusb/README.git +41 -0
- package/libusb/TODO +2 -0
- package/libusb/Xcode/common.xcconfig +49 -0
- package/libusb/Xcode/debug.xcconfig +29 -0
- package/libusb/Xcode/libusb.xcconfig +21 -0
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +1 -0
- package/libusb/Xcode/libusb_debug.xcconfig +21 -0
- package/libusb/Xcode/libusb_release.xcconfig +21 -0
- package/libusb/Xcode/release.xcconfig +30 -0
- package/libusb/android/README +114 -0
- package/libusb/android/jni/Android.mk +23 -0
- package/libusb/android/jni/Application.mk +24 -0
- package/libusb/android/jni/examples.mk +134 -0
- package/libusb/android/jni/libusb.mk +54 -0
- package/libusb/android/jni/tests.mk +56 -0
- package/libusb/autogen.sh +8 -0
- package/libusb/bootstrap.sh +19 -0
- package/libusb/configure.ac +304 -0
- package/libusb/doc/Makefile.am +9 -0
- package/libusb/doc/doxygen.cfg.in +1288 -0
- package/libusb/doc/libusb.png +0 -0
- package/libusb/examples/Makefile.am +19 -0
- package/libusb/examples/dpfp.c +506 -0
- package/libusb/examples/dpfp_threaded.c +544 -0
- package/libusb/examples/ezusb.c +831 -0
- package/libusb/examples/ezusb.h +120 -0
- package/libusb/examples/fxload.c +287 -0
- package/libusb/examples/getopt/getopt.c +1060 -0
- package/libusb/examples/getopt/getopt.h +180 -0
- package/libusb/examples/getopt/getopt1.c +188 -0
- package/libusb/examples/hotplugtest.c +104 -0
- package/libusb/examples/listdevs.c +71 -0
- package/libusb/examples/sam3u_benchmark.c +193 -0
- package/libusb/examples/xusb.c +1129 -0
- package/libusb/libusb/Makefile.am +75 -0
- package/libusb/libusb/core.c +2342 -0
- package/libusb/libusb/descriptor.c +1199 -0
- package/libusb/libusb/hotplug.c +327 -0
- package/libusb/libusb/hotplug.h +82 -0
- package/libusb/libusb/io.c +2631 -0
- package/libusb/libusb/libusb-1.0.def +166 -0
- package/libusb/libusb/libusb-1.0.rc +61 -0
- package/libusb/libusb/libusb.h +1998 -0
- package/libusb/libusb/libusbi.h +1040 -0
- package/libusb/libusb/os/darwin_usb.c +2009 -0
- package/libusb/libusb/os/darwin_usb.h +162 -0
- package/libusb/libusb/os/linux_netlink.c +369 -0
- package/libusb/libusb/os/linux_udev.c +307 -0
- package/libusb/libusb/os/linux_usbfs.c +2695 -0
- package/libusb/libusb/os/linux_usbfs.h +192 -0
- package/libusb/libusb/os/netbsd_usb.c +738 -0
- package/libusb/libusb/os/openbsd_usb.c +832 -0
- package/libusb/libusb/os/poll_posix.c +51 -0
- package/libusb/libusb/os/poll_posix.h +11 -0
- package/libusb/libusb/os/poll_windows.c +796 -0
- package/libusb/libusb/os/poll_windows.h +131 -0
- package/libusb/libusb/os/threads_posix.c +82 -0
- package/libusb/libusb/os/threads_posix.h +50 -0
- package/libusb/libusb/os/threads_windows.c +212 -0
- package/libusb/libusb/os/threads_windows.h +87 -0
- package/libusb/libusb/os/wince_usb.c +1032 -0
- package/libusb/libusb/os/wince_usb.h +131 -0
- package/libusb/libusb/os/windows_common.h +108 -0
- package/libusb/libusb/os/windows_usb.c +5347 -0
- package/libusb/libusb/os/windows_usb.h +971 -0
- package/libusb/libusb/strerror.c +199 -0
- package/libusb/libusb/sync.c +307 -0
- package/libusb/libusb/version.h +18 -0
- package/libusb/libusb/version_nano.h +1 -0
- package/libusb/libusb-1.0.pc.in +11 -0
- package/libusb/msvc/config.h +50 -0
- package/libusb/msvc/ddk_build.cmd +175 -0
- package/libusb/msvc/errno.h +102 -0
- package/libusb/msvc/fxload_2010.vcxproj +170 -0
- package/libusb/msvc/fxload_2010.vcxproj.filters +25 -0
- package/libusb/msvc/fxload_2012.vcxproj +174 -0
- package/libusb/msvc/fxload_2012.vcxproj.filters +25 -0
- package/libusb/msvc/fxload_2013.vcxproj +174 -0
- package/libusb/msvc/fxload_sources +23 -0
- package/libusb/msvc/getopt_2005.vcproj +288 -0
- package/libusb/msvc/getopt_2010.vcxproj +131 -0
- package/libusb/msvc/getopt_2010.vcxproj.filters +26 -0
- package/libusb/msvc/getopt_2012.vcxproj +136 -0
- package/libusb/msvc/getopt_2012.vcxproj.filters +26 -0
- package/libusb/msvc/getopt_2013.vcxproj +136 -0
- package/libusb/msvc/getopt_sources +20 -0
- package/libusb/msvc/hotplugtest_2010.vcxproj +163 -0
- package/libusb/msvc/hotplugtest_2010.vcxproj.filters +14 -0
- package/libusb/msvc/hotplugtest_2012.vcxproj +167 -0
- package/libusb/msvc/hotplugtest_2012.vcxproj.filters +14 -0
- package/libusb/msvc/hotplugtest_2013.vcxproj +167 -0
- package/libusb/msvc/hotplugtest_sources +20 -0
- package/libusb/msvc/inttypes.h +295 -0
- package/libusb/msvc/libusb.dsw +71 -0
- package/libusb/msvc/libusb_2005.sln +95 -0
- package/libusb/msvc/libusb_2010.sln +94 -0
- package/libusb/msvc/libusb_2012.sln +94 -0
- package/libusb/msvc/libusb_2013.sln +100 -0
- package/libusb/msvc/libusb_2015.sln +100 -0
- package/libusb/msvc/libusb_dll.dsp +194 -0
- package/libusb/msvc/libusb_dll_2005.vcproj +436 -0
- package/libusb/msvc/libusb_dll_2010.vcxproj +170 -0
- package/libusb/msvc/libusb_dll_2010.vcxproj.filters +81 -0
- package/libusb/msvc/libusb_dll_2012.vcxproj +175 -0
- package/libusb/msvc/libusb_dll_2012.vcxproj.filters +84 -0
- package/libusb/msvc/libusb_dll_2013.vcxproj +175 -0
- package/libusb/msvc/libusb_dll_wince.vcproj +1243 -0
- package/libusb/msvc/libusb_sources +38 -0
- package/libusb/msvc/libusb_static.dsp +174 -0
- package/libusb/msvc/libusb_static_2005.vcproj +362 -0
- package/libusb/msvc/libusb_static_2010.vcxproj +156 -0
- package/libusb/msvc/libusb_static_2010.vcxproj.filters +74 -0
- package/libusb/msvc/libusb_static_2012.vcxproj +160 -0
- package/libusb/msvc/libusb_static_2012.vcxproj.filters +74 -0
- package/libusb/msvc/libusb_static_2013.vcxproj +160 -0
- package/libusb/msvc/libusb_static_wince.vcproj +1185 -0
- package/libusb/msvc/libusb_wince.sln +246 -0
- package/libusb/msvc/listdevs.dsp +103 -0
- package/libusb/msvc/listdevs_2005.vcproj +360 -0
- package/libusb/msvc/listdevs_2010.vcxproj +165 -0
- package/libusb/msvc/listdevs_2010.vcxproj.filters +14 -0
- package/libusb/msvc/listdevs_2012.vcxproj +169 -0
- package/libusb/msvc/listdevs_2012.vcxproj.filters +14 -0
- package/libusb/msvc/listdevs_2013.vcxproj +169 -0
- package/libusb/msvc/listdevs_sources +19 -0
- package/libusb/msvc/listdevs_wince.vcproj +1120 -0
- package/libusb/msvc/missing.c +80 -0
- package/libusb/msvc/missing.h +32 -0
- package/libusb/msvc/stdint.h +256 -0
- package/libusb/msvc/stress_2005.vcproj +390 -0
- package/libusb/msvc/stress_2010.vcxproj +167 -0
- package/libusb/msvc/stress_2010.vcxproj.filters +25 -0
- package/libusb/msvc/stress_2012.vcxproj +171 -0
- package/libusb/msvc/stress_2012.vcxproj.filters +25 -0
- package/libusb/msvc/stress_2013.vcxproj +171 -0
- package/libusb/msvc/stress_wince.vcproj +1128 -0
- package/libusb/msvc/xusb.dsp +102 -0
- package/libusb/msvc/xusb_2005.vcproj +344 -0
- package/libusb/msvc/xusb_2010.vcxproj +163 -0
- package/libusb/msvc/xusb_2010.vcxproj.filters +14 -0
- package/libusb/msvc/xusb_2012.vcxproj +167 -0
- package/libusb/msvc/xusb_2012.vcxproj.filters +14 -0
- package/libusb/msvc/xusb_2013.vcxproj +167 -0
- package/libusb/msvc/xusb_sources +20 -0
- package/libusb/msvc/xusb_wince.vcproj +1120 -0
- package/libusb/tests/Makefile.am +6 -0
- package/libusb/tests/libusb_testlib.h +107 -0
- package/libusb/tests/stress.c +160 -0
- package/libusb/tests/testlib.c +281 -0
- package/libusb.gypi +136 -0
- package/libusb_config/config.h +1 -0
- package/package.json +69 -0
- package/src/device.cc +412 -0
- package/src/helpers.h +64 -0
- package/src/node_usb.cc +319 -0
- package/src/node_usb.h +120 -0
- package/src/transfer.cc +148 -0
- package/src/uv_async_queue.h +33 -0
- package/test/usb.coffee +191 -0
- package/usb.js +524 -0
package/src/node_usb.cc
ADDED
|
@@ -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
|
package/src/transfer.cc
ADDED
|
@@ -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
|