usb 2.4.3 → 2.5.2-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitmodules +2 -2
- package/CHANGELOG.md +11 -0
- package/README.md +42 -2
- package/binding.gyp +48 -25
- package/dist/usb/bindings.d.ts +1 -0
- package/dist/usb/index.d.ts +6 -0
- package/dist/usb/index.js +82 -53
- package/dist/usb/index.js.map +1 -1
- package/package.json +4 -5
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +309 -309
- package/src/helpers.h +36 -36
- package/src/hotplug/hotplug.h +22 -0
- package/src/hotplug/libusb.cc +90 -0
- package/src/hotplug/windows.cc +166 -0
- package/src/node_usb.cc +246 -282
- package/src/node_usb.h +64 -67
- package/src/thread_name.cc +1 -1
- package/src/transfer.cc +114 -114
- package/test/usb.coffee +178 -178
- package/test/webusb.coffee +140 -140
- package/tsc/usb/bindings.ts +1 -0
- package/tsc/usb/index.ts +73 -32
package/test/usb.coffee
CHANGED
|
@@ -7,208 +7,208 @@ findBySerialNumber = require('../').findBySerialNumber
|
|
|
7
7
|
Worker = require('worker_threads').Worker
|
|
8
8
|
|
|
9
9
|
if typeof gc is 'function'
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# running with --expose-gc, do a sweep between tests so valgrind blames the right one
|
|
11
|
+
afterEach -> gc()
|
|
12
12
|
|
|
13
13
|
describe 'USB Module', ->
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
it 'should describe basic constants', ->
|
|
15
|
+
assert.notEqual(usb, undefined, "usb must be undefined")
|
|
16
|
+
assert.ok((usb.LIBUSB_CLASS_PER_INTERFACE != undefined), "Constants must be described")
|
|
17
|
+
assert.ok((usb.LIBUSB_ENDPOINT_IN == 128))
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
it 'should handle abuse without crashing', ->
|
|
20
|
+
assert.throws -> new usb.Device()
|
|
21
|
+
assert.throws -> usb.Device()
|
|
22
|
+
assert.throws -> usb.Device.prototype.open.call({})
|
|
23
23
|
|
|
24
24
|
describe 'setDebugLevel', ->
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
it 'should throw when passed invalid args', ->
|
|
26
|
+
assert.throws((-> usb.setDebugLevel()), TypeError)
|
|
27
|
+
assert.throws((-> usb.setDebugLevel(-1)), TypeError)
|
|
28
|
+
assert.throws((-> usb.setDebugLevel(5)), TypeError)
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
it 'should succeed with good args', ->
|
|
31
|
+
assert.doesNotThrow(-> usb.setDebugLevel(0))
|
|
32
32
|
|
|
33
33
|
describe 'getDeviceList', ->
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
it 'should return at least one device', ->
|
|
35
|
+
l = getDeviceList()
|
|
36
|
+
assert.ok((l.length > 0))
|
|
37
37
|
|
|
38
38
|
describe 'findByIds', ->
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
it 'should return an array with length > 0', ->
|
|
40
|
+
dev = findByIds(0x59e3, 0x0a23)
|
|
41
|
+
assert.ok(dev, "Demo device is not attached")
|
|
42
42
|
|
|
43
43
|
describe 'findBySerialNumber', ->
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
it 'should return a single device ', ->
|
|
45
|
+
dev = findBySerialNumber('TEST_DEVICE')
|
|
46
|
+
assert.ok(dev, "Demo device is not attached")
|
|
47
47
|
|
|
48
48
|
describe 'Device', ->
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
49
|
+
device = null
|
|
50
|
+
before ->
|
|
51
|
+
device = findByIds(0x59e3, 0x0a23)
|
|
52
|
+
|
|
53
|
+
it 'should have sane properties', ->
|
|
54
|
+
assert.ok((device.busNumber > 0), "busNumber must be larger than 0")
|
|
55
|
+
assert.ok((device.deviceAddress > 0), "deviceAddress must be larger than 0")
|
|
56
|
+
if process.platform != 'darwin' || process.arch != 'arm64'
|
|
57
|
+
assert.ok((util.isArray(device.portNumbers)), "portNumbers must be an array")
|
|
58
|
+
|
|
59
|
+
it 'should have a deviceDescriptor property', ->
|
|
60
|
+
assert.ok(((deviceDesc = device.deviceDescriptor) != undefined))
|
|
61
|
+
|
|
62
|
+
it 'should have a configDescriptor property', ->
|
|
63
|
+
assert.ok(device.configDescriptor != undefined)
|
|
64
|
+
|
|
65
|
+
it 'should open', ->
|
|
66
|
+
device.open()
|
|
67
|
+
|
|
68
|
+
it 'gets string descriptors', (done) ->
|
|
69
|
+
device.getStringDescriptor device.deviceDescriptor.iManufacturer, (e, s) ->
|
|
70
|
+
assert.ok(e == undefined, e)
|
|
71
|
+
assert.equal(s, 'Nonolith Labs')
|
|
72
|
+
done()
|
|
73
|
+
|
|
74
|
+
it 'supports null string descriptors', (done) ->
|
|
75
|
+
device.getStringDescriptor device.configDescriptor.iConfiguration, (e, s) ->
|
|
76
|
+
assert.ok(e == undefined, e)
|
|
77
|
+
assert.equal(s, undefined)
|
|
78
|
+
done()
|
|
79
|
+
|
|
80
|
+
describe 'control transfer', ->
|
|
81
|
+
b = Buffer.from([0x30...0x40])
|
|
82
|
+
it 'should OUT transfer when the IN bit is not set', (done) ->
|
|
83
|
+
device.controlTransfer 0x40, 0x81, 0, 0, b, (e) ->
|
|
84
|
+
assert.ok(e == undefined, e)
|
|
85
|
+
done()
|
|
86
|
+
|
|
87
|
+
it 'should fail when bmRequestType doesn\'t match buffer / length', ->
|
|
88
|
+
assert.throws(-> device.controlTransfer(0x40, 0x81, 0, 0, 64))
|
|
89
|
+
|
|
90
|
+
it 'should IN transfer when the IN bit is set', (done) ->
|
|
91
|
+
device.controlTransfer 0xc0, 0x81, 0, 0, 128, (e, d) ->
|
|
92
|
+
#console.log("ControlTransferIn", d, e)
|
|
93
|
+
assert.ok(e == undefined, e)
|
|
94
|
+
assert.equal(d.toString(), b.toString())
|
|
95
|
+
done()
|
|
96
|
+
|
|
97
|
+
it 'should signal errors', (done) ->
|
|
98
|
+
device.controlTransfer 0xc0, 0xff, 0, 0, 64, (e, d) ->
|
|
99
|
+
assert.equal e.errno, usb.LIBUSB_TRANSFER_STALL
|
|
100
|
+
done()
|
|
101
|
+
|
|
102
|
+
describe 'Interface', ->
|
|
103
|
+
iface = null
|
|
104
|
+
before ->
|
|
105
|
+
iface = device.interfaces[0]
|
|
106
|
+
iface.claim()
|
|
107
|
+
|
|
108
|
+
it 'should have one interface', ->
|
|
109
|
+
assert.notEqual(iface, undefined)
|
|
110
|
+
|
|
111
|
+
it 'should be the same as the interfaceNo 0', ->
|
|
112
|
+
assert.strictEqual iface, device.interface(0)
|
|
113
|
+
|
|
114
|
+
if process.platform == 'linux'
|
|
115
|
+
it "shouldn't have a kernel driver", ->
|
|
116
|
+
assert.equal iface.isKernelDriverActive(), false
|
|
117
|
+
|
|
118
|
+
it "should fail to detach the kernel driver", ->
|
|
119
|
+
assert.throws -> iface.detachKernelDriver()
|
|
120
|
+
|
|
121
|
+
it "should fail to attach the kernel driver", ->
|
|
122
|
+
assert.throws -> iface.attachKernelDriver()
|
|
123
|
+
|
|
124
|
+
describe 'IN endpoint', ->
|
|
125
|
+
inEndpoint = null
|
|
126
|
+
before ->
|
|
127
|
+
inEndpoint = iface.endpoints[0]
|
|
128
|
+
|
|
129
|
+
it 'should be able to get the endpoint', ->
|
|
130
|
+
assert.ok inEndpoint?
|
|
131
|
+
|
|
132
|
+
it 'should be able to get the endpoint by address', ->
|
|
133
|
+
assert.equal(inEndpoint, iface.endpoint(0x81))
|
|
134
|
+
|
|
135
|
+
it 'should have the IN direction flag', ->
|
|
136
|
+
assert.equal(inEndpoint.direction, 'in')
|
|
137
|
+
|
|
138
|
+
it 'should have a descriptor', ->
|
|
139
|
+
assert.equal(inEndpoint.descriptor.bEndpointAddress, 0x81)
|
|
140
|
+
assert.equal(inEndpoint.descriptor.wMaxPacketSize, 64)
|
|
141
|
+
|
|
142
|
+
it 'should fail to write', ->
|
|
143
|
+
assert.throws -> inEndpoint.transfer(b)
|
|
144
|
+
|
|
145
|
+
it 'should support read', (done) ->
|
|
146
|
+
inEndpoint.transfer 64, (e, d) ->
|
|
147
|
+
assert.ok(e == undefined, e)
|
|
148
|
+
assert.ok(d.length == 64)
|
|
149
|
+
done()
|
|
150
|
+
|
|
151
|
+
it 'times out', (done) ->
|
|
152
|
+
iface.endpoints[2].timeout = 20
|
|
153
|
+
iface.endpoints[2].transfer 64, (e, d) ->
|
|
154
|
+
assert.equal e.errno, usb.LIBUSB_TRANSFER_TIMED_OUT
|
|
155
|
+
done()
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
it 'polls the device', (done) ->
|
|
158
|
+
pkts = 0
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
inEndpoint.startPoll 8, 64
|
|
161
|
+
inEndpoint.on 'data', (d) ->
|
|
162
|
+
assert.equal d.length, 64
|
|
163
|
+
pkts++
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
if pkts == 100
|
|
166
|
+
inEndpoint.stopPoll()
|
|
167
167
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
168
|
+
inEndpoint.on 'error', (e) ->
|
|
169
|
+
throw e
|
|
170
|
+
|
|
171
|
+
inEndpoint.on 'end', ->
|
|
172
|
+
#console.log("Stream stopped")
|
|
173
|
+
done()
|
|
174
|
+
|
|
175
|
+
describe 'OUT endpoint', ->
|
|
176
|
+
outEndpoint = null
|
|
177
|
+
before ->
|
|
178
|
+
outEndpoint = iface.endpoints[1]
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
it 'should be able to get the endpoint', ->
|
|
181
|
+
assert.ok outEndpoint?
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
it 'should be able to get the endpoint by address', ->
|
|
184
|
+
assert.equal(outEndpoint, iface.endpoint(0x02))
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
it 'should have the OUT direction flag', ->
|
|
187
|
+
assert.equal(outEndpoint.direction, 'out')
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
it 'should support write', (done) ->
|
|
190
|
+
outEndpoint.transfer [1,2,3,4], (e) ->
|
|
191
|
+
assert.ok(e == undefined, e)
|
|
192
|
+
done()
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
194
|
+
it 'times out', (done) ->
|
|
195
|
+
iface.endpoints[3].timeout = 20
|
|
196
|
+
iface.endpoints[3].transfer [1,2,3,4], (e) ->
|
|
197
|
+
assert.equal e.errno, usb.LIBUSB_TRANSFER_TIMED_OUT
|
|
198
|
+
done()
|
|
199
199
|
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
after (cb) ->
|
|
201
|
+
iface.release(cb)
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
after ->
|
|
204
|
+
device.close()
|
|
205
205
|
|
|
206
206
|
if process.platform != 'win32'
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
207
|
+
describe 'Context Aware', ->
|
|
208
|
+
it 'should handle opening the same device from different contexts', ->
|
|
209
|
+
for n in [1..5]
|
|
210
|
+
worker = new Worker('./test/worker.cjs')
|
|
211
|
+
worker.on 'message', (serial) ->
|
|
212
|
+
assert.equal(serial, 'TEST_DEVICE')
|
|
213
|
+
worker.on 'exit', (code) ->
|
|
214
|
+
assert.equal(code, 0)
|