@mcesystems/usb-device-listener 1.0.95 → 1.0.97
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/LICENSE +15 -15
- package/binding.gyp +67 -67
- package/native/addon.cc +129 -129
- package/native/usb_listener.h +22 -22
- package/native/usb_listener_common.h +56 -56
- package/native/usb_listener_mac.cc +663 -663
- package/native/usb_listener_mac.h +80 -80
- package/native/usb_listener_win.cc +635 -635
- package/native/usb_listener_win.h +101 -101
- package/package.json +1 -1
- package/prebuilds/win32-x64/@mcesystems+usb-device-listener.node +0 -0
- package/build/Release/usb_device_listener.node +0 -0
package/LICENSE
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
ISC License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 MCE Systems
|
|
4
|
-
|
|
5
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
-
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
-
copyright notice and this permission notice appear in all copies.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
-
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
-
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
-
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
-
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
-
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 MCE Systems
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/binding.gyp
CHANGED
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
{
|
|
2
|
-
"targets": [
|
|
3
|
-
{
|
|
4
|
-
"target_name": "usb_device_listener",
|
|
5
|
-
"sources": [
|
|
6
|
-
"native/addon.cc"
|
|
7
|
-
],
|
|
8
|
-
"include_dirs": [
|
|
9
|
-
"<!@(node -p \"require('node-addon-api').include\")"
|
|
10
|
-
],
|
|
11
|
-
"dependencies": [
|
|
12
|
-
"<!(node -p \"require('node-addon-api').gyp\")"
|
|
13
|
-
],
|
|
14
|
-
"defines": [
|
|
15
|
-
"NAPI_DISABLE_CPP_EXCEPTIONS"
|
|
16
|
-
],
|
|
17
|
-
"conditions": [
|
|
18
|
-
[
|
|
19
|
-
"OS=='win'",
|
|
20
|
-
{
|
|
21
|
-
"sources": [
|
|
22
|
-
"native/usb_listener_win.cc"
|
|
23
|
-
],
|
|
24
|
-
"defines": [
|
|
25
|
-
"UNICODE",
|
|
26
|
-
"_UNICODE"
|
|
27
|
-
],
|
|
28
|
-
"libraries": [
|
|
29
|
-
"Setupapi.lib",
|
|
30
|
-
"Cfgmgr32.lib"
|
|
31
|
-
],
|
|
32
|
-
"msvs_settings": {
|
|
33
|
-
"VCCLCompilerTool": {
|
|
34
|
-
"ExceptionHandling": 1,
|
|
35
|
-
"AdditionalOptions": [
|
|
36
|
-
"/std:c++20"
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
[
|
|
43
|
-
"OS=='mac'",
|
|
44
|
-
{
|
|
45
|
-
"sources": [
|
|
46
|
-
"native/usb_listener_mac.cc"
|
|
47
|
-
],
|
|
48
|
-
"xcode_settings": {
|
|
49
|
-
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
|
50
|
-
"CLANG_CXX_LANGUAGE_STANDARD": "c++20",
|
|
51
|
-
"MACOSX_DEPLOYMENT_TARGET": "10.15",
|
|
52
|
-
"OTHER_CFLAGS": [
|
|
53
|
-
"-fno-strict-aliasing"
|
|
54
|
-
]
|
|
55
|
-
},
|
|
56
|
-
"link_settings": {
|
|
57
|
-
"libraries": [
|
|
58
|
-
"-framework CoreFoundation",
|
|
59
|
-
"-framework IOKit"
|
|
60
|
-
]
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
]
|
|
67
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "usb_device_listener",
|
|
5
|
+
"sources": [
|
|
6
|
+
"native/addon.cc"
|
|
7
|
+
],
|
|
8
|
+
"include_dirs": [
|
|
9
|
+
"<!@(node -p \"require('node-addon-api').include\")"
|
|
10
|
+
],
|
|
11
|
+
"dependencies": [
|
|
12
|
+
"<!(node -p \"require('node-addon-api').gyp\")"
|
|
13
|
+
],
|
|
14
|
+
"defines": [
|
|
15
|
+
"NAPI_DISABLE_CPP_EXCEPTIONS"
|
|
16
|
+
],
|
|
17
|
+
"conditions": [
|
|
18
|
+
[
|
|
19
|
+
"OS=='win'",
|
|
20
|
+
{
|
|
21
|
+
"sources": [
|
|
22
|
+
"native/usb_listener_win.cc"
|
|
23
|
+
],
|
|
24
|
+
"defines": [
|
|
25
|
+
"UNICODE",
|
|
26
|
+
"_UNICODE"
|
|
27
|
+
],
|
|
28
|
+
"libraries": [
|
|
29
|
+
"Setupapi.lib",
|
|
30
|
+
"Cfgmgr32.lib"
|
|
31
|
+
],
|
|
32
|
+
"msvs_settings": {
|
|
33
|
+
"VCCLCompilerTool": {
|
|
34
|
+
"ExceptionHandling": 1,
|
|
35
|
+
"AdditionalOptions": [
|
|
36
|
+
"/std:c++20"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"OS=='mac'",
|
|
44
|
+
{
|
|
45
|
+
"sources": [
|
|
46
|
+
"native/usb_listener_mac.cc"
|
|
47
|
+
],
|
|
48
|
+
"xcode_settings": {
|
|
49
|
+
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
|
50
|
+
"CLANG_CXX_LANGUAGE_STANDARD": "c++20",
|
|
51
|
+
"MACOSX_DEPLOYMENT_TARGET": "10.15",
|
|
52
|
+
"OTHER_CFLAGS": [
|
|
53
|
+
"-fno-strict-aliasing"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"link_settings": {
|
|
57
|
+
"libraries": [
|
|
58
|
+
"-framework CoreFoundation",
|
|
59
|
+
"-framework IOKit"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
package/native/addon.cc
CHANGED
|
@@ -1,129 +1,129 @@
|
|
|
1
|
-
#include <napi.h>
|
|
2
|
-
#include "usb_listener.h"
|
|
3
|
-
#include <memory>
|
|
4
|
-
|
|
5
|
-
static std::unique_ptr<USBListener> g_listener;
|
|
6
|
-
|
|
7
|
-
Napi::Value StartListening(const Napi::CallbackInfo& info) {
|
|
8
|
-
Napi::Env env = info.Env();
|
|
9
|
-
|
|
10
|
-
if (!g_listener) {
|
|
11
|
-
g_listener = std::make_unique<USBListener>();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
std::string errorMsg;
|
|
15
|
-
if (!g_listener->StartListening(errorMsg)) {
|
|
16
|
-
Napi::Error::New(env, errorMsg).ThrowAsJavaScriptException();
|
|
17
|
-
return env.Undefined();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return env.Undefined();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
Napi::Value StopListening(const Napi::CallbackInfo& info) {
|
|
24
|
-
Napi::Env env = info.Env();
|
|
25
|
-
|
|
26
|
-
if (g_listener) {
|
|
27
|
-
g_listener->StopListening();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return env.Undefined();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
Napi::Value OnDeviceAdd(const Napi::CallbackInfo& info) {
|
|
34
|
-
Napi::Env env = info.Env();
|
|
35
|
-
|
|
36
|
-
if (info.Length() < 1 || !info[0].IsFunction()) {
|
|
37
|
-
Napi::TypeError::New(env, "Callback function expected").ThrowAsJavaScriptException();
|
|
38
|
-
return env.Undefined();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
Napi::Function callback = info[0].As<Napi::Function>();
|
|
42
|
-
|
|
43
|
-
if (!g_listener) {
|
|
44
|
-
g_listener = std::make_unique<USBListener>();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
Napi::ThreadSafeFunction tsfn = Napi::ThreadSafeFunction::New(
|
|
48
|
-
env,
|
|
49
|
-
callback,
|
|
50
|
-
"DeviceAddCallback",
|
|
51
|
-
0,
|
|
52
|
-
1
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
g_listener->SetAddCallback(tsfn);
|
|
56
|
-
|
|
57
|
-
return env.Undefined();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
Napi::Value OnDeviceRemove(const Napi::CallbackInfo& info) {
|
|
61
|
-
Napi::Env env = info.Env();
|
|
62
|
-
|
|
63
|
-
if (info.Length() < 1 || !info[0].IsFunction()) {
|
|
64
|
-
Napi::TypeError::New(env, "Callback function expected").ThrowAsJavaScriptException();
|
|
65
|
-
return env.Undefined();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
Napi::Function callback = info[0].As<Napi::Function>();
|
|
69
|
-
|
|
70
|
-
if (!g_listener) {
|
|
71
|
-
g_listener = std::make_unique<USBListener>();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
Napi::ThreadSafeFunction tsfn = Napi::ThreadSafeFunction::New(
|
|
75
|
-
env,
|
|
76
|
-
callback,
|
|
77
|
-
"DeviceRemoveCallback",
|
|
78
|
-
0,
|
|
79
|
-
1
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
g_listener->SetRemoveCallback(tsfn);
|
|
83
|
-
|
|
84
|
-
return env.Undefined();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
Napi::Value ListDevices(const Napi::CallbackInfo& info) {
|
|
88
|
-
Napi::Env env = info.Env();
|
|
89
|
-
|
|
90
|
-
if (!g_listener) {
|
|
91
|
-
g_listener = std::make_unique<USBListener>();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
std::vector<DeviceInfo> devices = g_listener->ListAllDevices();
|
|
95
|
-
|
|
96
|
-
Napi::Array result = Napi::Array::New(env, devices.size());
|
|
97
|
-
for (size_t i = 0; i < devices.size(); i++) {
|
|
98
|
-
const DeviceInfo& d = devices[i];
|
|
99
|
-
Napi::Object obj = Napi::Object::New(env);
|
|
100
|
-
obj.Set("deviceId", Napi::String::New(env, d.deviceId));
|
|
101
|
-
obj.Set("serialNumber", Napi::String::New(env, d.serialNumber));
|
|
102
|
-
obj.Set("deviceName", Napi::String::New(env, d.deviceName));
|
|
103
|
-
obj.Set("vid", Napi::Number::New(env, d.vid));
|
|
104
|
-
obj.Set("pid", Napi::Number::New(env, d.pid));
|
|
105
|
-
obj.Set("locationInfo", Napi::String::New(env, d.locationInfo));
|
|
106
|
-
obj.Set("logicalPort", env.Null());
|
|
107
|
-
Napi::Array pathArr = Napi::Array::New(env, d.portPath.size());
|
|
108
|
-
for (size_t j = 0; j < d.portPath.size(); j++) {
|
|
109
|
-
pathArr[j] = Napi::Number::New(env, d.portPath[j]);
|
|
110
|
-
}
|
|
111
|
-
obj.Set("portPath", pathArr);
|
|
112
|
-
obj.Set("parentHubVid", Napi::Number::New(env, d.parentHubVid));
|
|
113
|
-
obj.Set("parentHubPid", Napi::Number::New(env, d.parentHubPid));
|
|
114
|
-
result[i] = obj;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
121
|
-
exports.Set("startListening", Napi::Function::New(env, StartListening));
|
|
122
|
-
exports.Set("stopListening", Napi::Function::New(env, StopListening));
|
|
123
|
-
exports.Set("onDeviceAdd", Napi::Function::New(env, OnDeviceAdd));
|
|
124
|
-
exports.Set("onDeviceRemove", Napi::Function::New(env, OnDeviceRemove));
|
|
125
|
-
exports.Set("listDevices", Napi::Function::New(env, ListDevices));
|
|
126
|
-
return exports;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
NODE_API_MODULE(usb_device_listener, Init)
|
|
1
|
+
#include <napi.h>
|
|
2
|
+
#include "usb_listener.h"
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
static std::unique_ptr<USBListener> g_listener;
|
|
6
|
+
|
|
7
|
+
Napi::Value StartListening(const Napi::CallbackInfo& info) {
|
|
8
|
+
Napi::Env env = info.Env();
|
|
9
|
+
|
|
10
|
+
if (!g_listener) {
|
|
11
|
+
g_listener = std::make_unique<USBListener>();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
std::string errorMsg;
|
|
15
|
+
if (!g_listener->StartListening(errorMsg)) {
|
|
16
|
+
Napi::Error::New(env, errorMsg).ThrowAsJavaScriptException();
|
|
17
|
+
return env.Undefined();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return env.Undefined();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Napi::Value StopListening(const Napi::CallbackInfo& info) {
|
|
24
|
+
Napi::Env env = info.Env();
|
|
25
|
+
|
|
26
|
+
if (g_listener) {
|
|
27
|
+
g_listener->StopListening();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return env.Undefined();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Napi::Value OnDeviceAdd(const Napi::CallbackInfo& info) {
|
|
34
|
+
Napi::Env env = info.Env();
|
|
35
|
+
|
|
36
|
+
if (info.Length() < 1 || !info[0].IsFunction()) {
|
|
37
|
+
Napi::TypeError::New(env, "Callback function expected").ThrowAsJavaScriptException();
|
|
38
|
+
return env.Undefined();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Napi::Function callback = info[0].As<Napi::Function>();
|
|
42
|
+
|
|
43
|
+
if (!g_listener) {
|
|
44
|
+
g_listener = std::make_unique<USBListener>();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Napi::ThreadSafeFunction tsfn = Napi::ThreadSafeFunction::New(
|
|
48
|
+
env,
|
|
49
|
+
callback,
|
|
50
|
+
"DeviceAddCallback",
|
|
51
|
+
0,
|
|
52
|
+
1
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
g_listener->SetAddCallback(tsfn);
|
|
56
|
+
|
|
57
|
+
return env.Undefined();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Napi::Value OnDeviceRemove(const Napi::CallbackInfo& info) {
|
|
61
|
+
Napi::Env env = info.Env();
|
|
62
|
+
|
|
63
|
+
if (info.Length() < 1 || !info[0].IsFunction()) {
|
|
64
|
+
Napi::TypeError::New(env, "Callback function expected").ThrowAsJavaScriptException();
|
|
65
|
+
return env.Undefined();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Napi::Function callback = info[0].As<Napi::Function>();
|
|
69
|
+
|
|
70
|
+
if (!g_listener) {
|
|
71
|
+
g_listener = std::make_unique<USBListener>();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
Napi::ThreadSafeFunction tsfn = Napi::ThreadSafeFunction::New(
|
|
75
|
+
env,
|
|
76
|
+
callback,
|
|
77
|
+
"DeviceRemoveCallback",
|
|
78
|
+
0,
|
|
79
|
+
1
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
g_listener->SetRemoveCallback(tsfn);
|
|
83
|
+
|
|
84
|
+
return env.Undefined();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Napi::Value ListDevices(const Napi::CallbackInfo& info) {
|
|
88
|
+
Napi::Env env = info.Env();
|
|
89
|
+
|
|
90
|
+
if (!g_listener) {
|
|
91
|
+
g_listener = std::make_unique<USBListener>();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
std::vector<DeviceInfo> devices = g_listener->ListAllDevices();
|
|
95
|
+
|
|
96
|
+
Napi::Array result = Napi::Array::New(env, devices.size());
|
|
97
|
+
for (size_t i = 0; i < devices.size(); i++) {
|
|
98
|
+
const DeviceInfo& d = devices[i];
|
|
99
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
100
|
+
obj.Set("deviceId", Napi::String::New(env, d.deviceId));
|
|
101
|
+
obj.Set("serialNumber", Napi::String::New(env, d.serialNumber));
|
|
102
|
+
obj.Set("deviceName", Napi::String::New(env, d.deviceName));
|
|
103
|
+
obj.Set("vid", Napi::Number::New(env, d.vid));
|
|
104
|
+
obj.Set("pid", Napi::Number::New(env, d.pid));
|
|
105
|
+
obj.Set("locationInfo", Napi::String::New(env, d.locationInfo));
|
|
106
|
+
obj.Set("logicalPort", env.Null());
|
|
107
|
+
Napi::Array pathArr = Napi::Array::New(env, d.portPath.size());
|
|
108
|
+
for (size_t j = 0; j < d.portPath.size(); j++) {
|
|
109
|
+
pathArr[j] = Napi::Number::New(env, d.portPath[j]);
|
|
110
|
+
}
|
|
111
|
+
obj.Set("portPath", pathArr);
|
|
112
|
+
obj.Set("parentHubVid", Napi::Number::New(env, d.parentHubVid));
|
|
113
|
+
obj.Set("parentHubPid", Napi::Number::New(env, d.parentHubPid));
|
|
114
|
+
result[i] = obj;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
121
|
+
exports.Set("startListening", Napi::Function::New(env, StartListening));
|
|
122
|
+
exports.Set("stopListening", Napi::Function::New(env, StopListening));
|
|
123
|
+
exports.Set("onDeviceAdd", Napi::Function::New(env, OnDeviceAdd));
|
|
124
|
+
exports.Set("onDeviceRemove", Napi::Function::New(env, OnDeviceRemove));
|
|
125
|
+
exports.Set("listDevices", Napi::Function::New(env, ListDevices));
|
|
126
|
+
return exports;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
NODE_API_MODULE(usb_device_listener, Init)
|
package/native/usb_listener.h
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
#ifndef USB_LISTENER_H
|
|
2
|
-
#define USB_LISTENER_H
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Platform-specific USB Listener
|
|
6
|
-
*
|
|
7
|
-
* This header includes the appropriate platform-specific implementation
|
|
8
|
-
* based on the target OS. Both implementations expose the same USBListener class
|
|
9
|
-
* that inherits from USBListenerBase.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
#include "usb_listener_common.h"
|
|
13
|
-
|
|
14
|
-
#if defined(_WIN32) || defined(_WIN64)
|
|
15
|
-
#include "usb_listener_win.h"
|
|
16
|
-
#elif defined(__APPLE__)
|
|
17
|
-
#include "usb_listener_mac.h"
|
|
18
|
-
#else
|
|
19
|
-
#error "Unsupported platform. Only Windows and macOS are supported."
|
|
20
|
-
#endif
|
|
21
|
-
|
|
22
|
-
#endif // USB_LISTENER_H
|
|
1
|
+
#ifndef USB_LISTENER_H
|
|
2
|
+
#define USB_LISTENER_H
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Platform-specific USB Listener
|
|
6
|
+
*
|
|
7
|
+
* This header includes the appropriate platform-specific implementation
|
|
8
|
+
* based on the target OS. Both implementations expose the same USBListener class
|
|
9
|
+
* that inherits from USBListenerBase.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#include "usb_listener_common.h"
|
|
13
|
+
|
|
14
|
+
#if defined(_WIN32) || defined(_WIN64)
|
|
15
|
+
#include "usb_listener_win.h"
|
|
16
|
+
#elif defined(__APPLE__)
|
|
17
|
+
#include "usb_listener_mac.h"
|
|
18
|
+
#else
|
|
19
|
+
#error "Unsupported platform. Only Windows and macOS are supported."
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#endif // USB_LISTENER_H
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
#ifndef USB_LISTENER_COMMON_H
|
|
2
|
-
#define USB_LISTENER_COMMON_H
|
|
3
|
-
|
|
4
|
-
#include <napi.h>
|
|
5
|
-
#include <string>
|
|
6
|
-
#include <vector>
|
|
7
|
-
#include <unordered_map>
|
|
8
|
-
#include <atomic>
|
|
9
|
-
#include <shared_mutex>
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Device information structure
|
|
13
|
-
* Contains all relevant USB device identification and location data
|
|
14
|
-
* Platform-agnostic: used by both Windows and macOS implementations
|
|
15
|
-
*/
|
|
16
|
-
struct DeviceInfo {
|
|
17
|
-
std::string deviceId; // Device ID (serial number if available, otherwise platform-specific)
|
|
18
|
-
std::string serialNumber; // USB serial number (raw, without formatting)
|
|
19
|
-
std::string deviceName; // USB product name / device description
|
|
20
|
-
uint16_t vid{0}; // Vendor ID
|
|
21
|
-
uint16_t pid{0}; // Product ID
|
|
22
|
-
std::string locationInfo; // Physical port location (platform-specific format)
|
|
23
|
-
int logicalPort{-1}; // User-defined logical port number (-1 if not mapped)
|
|
24
|
-
std::vector<int> portPath; // Port numbers from root to device (e.g. [2, 3, 1])
|
|
25
|
-
uint16_t parentHubVid{0}; // VID of hub device is directly connected to (0 if on root)
|
|
26
|
-
uint16_t parentHubPid{0}; // PID of that hub
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Abstract USB Device Listener Interface
|
|
31
|
-
*
|
|
32
|
-
* Defines the common interface for platform-specific implementations.
|
|
33
|
-
* Each platform (Windows, macOS) provides its own implementation.
|
|
34
|
-
*/
|
|
35
|
-
class USBListenerBase {
|
|
36
|
-
public:
|
|
37
|
-
virtual ~USBListenerBase() = default;
|
|
38
|
-
|
|
39
|
-
// Start monitoring USB device events
|
|
40
|
-
virtual bool StartListening(std::string& errorMsg) = 0;
|
|
41
|
-
|
|
42
|
-
// Stop monitoring and clean up resources
|
|
43
|
-
virtual void StopListening() = 0;
|
|
44
|
-
|
|
45
|
-
// Set callback for device connection events
|
|
46
|
-
virtual void SetAddCallback(Napi::ThreadSafeFunction callback) = 0;
|
|
47
|
-
|
|
48
|
-
// Set callback for device disconnection events
|
|
49
|
-
virtual void SetRemoveCallback(Napi::ThreadSafeFunction callback) = 0;
|
|
50
|
-
|
|
51
|
-
// Get list of all currently connected USB devices
|
|
52
|
-
virtual std::vector<DeviceInfo> ListAllDevices() = 0;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
#endif // USB_LISTENER_COMMON_H
|
|
56
|
-
|
|
1
|
+
#ifndef USB_LISTENER_COMMON_H
|
|
2
|
+
#define USB_LISTENER_COMMON_H
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <vector>
|
|
7
|
+
#include <unordered_map>
|
|
8
|
+
#include <atomic>
|
|
9
|
+
#include <shared_mutex>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Device information structure
|
|
13
|
+
* Contains all relevant USB device identification and location data
|
|
14
|
+
* Platform-agnostic: used by both Windows and macOS implementations
|
|
15
|
+
*/
|
|
16
|
+
struct DeviceInfo {
|
|
17
|
+
std::string deviceId; // Device ID (serial number if available, otherwise platform-specific)
|
|
18
|
+
std::string serialNumber; // USB serial number (raw, without formatting)
|
|
19
|
+
std::string deviceName; // USB product name / device description
|
|
20
|
+
uint16_t vid{0}; // Vendor ID
|
|
21
|
+
uint16_t pid{0}; // Product ID
|
|
22
|
+
std::string locationInfo; // Physical port location (platform-specific format)
|
|
23
|
+
int logicalPort{-1}; // User-defined logical port number (-1 if not mapped)
|
|
24
|
+
std::vector<int> portPath; // Port numbers from root to device (e.g. [2, 3, 1])
|
|
25
|
+
uint16_t parentHubVid{0}; // VID of hub device is directly connected to (0 if on root)
|
|
26
|
+
uint16_t parentHubPid{0}; // PID of that hub
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Abstract USB Device Listener Interface
|
|
31
|
+
*
|
|
32
|
+
* Defines the common interface for platform-specific implementations.
|
|
33
|
+
* Each platform (Windows, macOS) provides its own implementation.
|
|
34
|
+
*/
|
|
35
|
+
class USBListenerBase {
|
|
36
|
+
public:
|
|
37
|
+
virtual ~USBListenerBase() = default;
|
|
38
|
+
|
|
39
|
+
// Start monitoring USB device events
|
|
40
|
+
virtual bool StartListening(std::string& errorMsg) = 0;
|
|
41
|
+
|
|
42
|
+
// Stop monitoring and clean up resources
|
|
43
|
+
virtual void StopListening() = 0;
|
|
44
|
+
|
|
45
|
+
// Set callback for device connection events
|
|
46
|
+
virtual void SetAddCallback(Napi::ThreadSafeFunction callback) = 0;
|
|
47
|
+
|
|
48
|
+
// Set callback for device disconnection events
|
|
49
|
+
virtual void SetRemoveCallback(Napi::ThreadSafeFunction callback) = 0;
|
|
50
|
+
|
|
51
|
+
// Get list of all currently connected USB devices
|
|
52
|
+
virtual std::vector<DeviceInfo> ListAllDevices() = 0;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
#endif // USB_LISTENER_COMMON_H
|
|
56
|
+
|