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/test/usb.coffee
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
assert = require('assert')
|
|
2
|
+
util = require('util')
|
|
3
|
+
usb = require("../usb.js")
|
|
4
|
+
|
|
5
|
+
if typeof gc is 'function'
|
|
6
|
+
# running with --expose-gc, do a sweep between tests so valgrind blames the right one
|
|
7
|
+
afterEach -> gc()
|
|
8
|
+
|
|
9
|
+
describe 'Module', ->
|
|
10
|
+
it 'should describe basic constants', ->
|
|
11
|
+
assert.notEqual(usb, undefined, "usb must be undefined")
|
|
12
|
+
assert.ok((usb.LIBUSB_CLASS_PER_INTERFACE != undefined), "Constants must be described")
|
|
13
|
+
assert.ok((usb.LIBUSB_ENDPOINT_IN == 128))
|
|
14
|
+
|
|
15
|
+
it 'should handle abuse without crashing', ->
|
|
16
|
+
assert.throws -> new usb.Device()
|
|
17
|
+
assert.throws -> usb.Device()
|
|
18
|
+
assert.throws -> usb.Device.prototype.open.call({})
|
|
19
|
+
|
|
20
|
+
describe 'setDebugLevel', ->
|
|
21
|
+
it 'should throw when passed invalid args', ->
|
|
22
|
+
assert.throws((-> usb.setDebugLevel()), TypeError)
|
|
23
|
+
assert.throws((-> usb.setDebugLevel(-1)), TypeError)
|
|
24
|
+
assert.throws((-> usb.setDebugLevel(5)), TypeError)
|
|
25
|
+
|
|
26
|
+
it 'should succeed with good args', ->
|
|
27
|
+
assert.doesNotThrow(-> usb.setDebugLevel(0))
|
|
28
|
+
|
|
29
|
+
describe 'getDeviceList', ->
|
|
30
|
+
it 'should return at least one device', ->
|
|
31
|
+
l = usb.getDeviceList()
|
|
32
|
+
assert.ok((l.length > 0))
|
|
33
|
+
|
|
34
|
+
describe 'findByIds', ->
|
|
35
|
+
it 'should return an array with length > 0', ->
|
|
36
|
+
dev = usb.findByIds(0x59e3, 0x0a23)
|
|
37
|
+
assert.ok(dev, "Demo device is not attached")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
describe 'Device', ->
|
|
41
|
+
device = null
|
|
42
|
+
before ->
|
|
43
|
+
device = usb.findByIds(0x59e3, 0x0a23)
|
|
44
|
+
|
|
45
|
+
it 'should have sane properties', ->
|
|
46
|
+
assert.ok((device.busNumber > 0), "busNumber must be larger than 0")
|
|
47
|
+
assert.ok((device.deviceAddress > 0), "deviceAddress must be larger than 0")
|
|
48
|
+
if process.platform != 'darwin' || process.arch != 'arm64'
|
|
49
|
+
assert.ok((util.isArray(device.portNumbers)), "portNumbers must be an array")
|
|
50
|
+
|
|
51
|
+
it 'should have a deviceDescriptor property', ->
|
|
52
|
+
assert.ok(((deviceDesc = device.deviceDescriptor) != undefined))
|
|
53
|
+
|
|
54
|
+
it 'should have a configDescriptor property', ->
|
|
55
|
+
assert.ok(device.configDescriptor != undefined)
|
|
56
|
+
|
|
57
|
+
it 'should open', ->
|
|
58
|
+
device.open()
|
|
59
|
+
|
|
60
|
+
it 'gets string descriptors', (done) ->
|
|
61
|
+
device.getStringDescriptor device.deviceDescriptor.iManufacturer, (e, s) ->
|
|
62
|
+
assert.ok(e == undefined, e)
|
|
63
|
+
assert.equal(s, 'Nonolith Labs')
|
|
64
|
+
done()
|
|
65
|
+
|
|
66
|
+
describe 'control transfer', ->
|
|
67
|
+
b = Buffer.from([0x30...0x40])
|
|
68
|
+
it 'should OUT transfer when the IN bit is not set', (done) ->
|
|
69
|
+
device.controlTransfer 0x40, 0x81, 0, 0, b, (e) ->
|
|
70
|
+
assert.ok(e == undefined, e)
|
|
71
|
+
done()
|
|
72
|
+
|
|
73
|
+
it "should fail when bmRequestType doesn't match buffer / length", ->
|
|
74
|
+
assert.throws(-> device.controlTransfer(0x40, 0x81, 0, 0, 64))
|
|
75
|
+
|
|
76
|
+
it 'should IN transfer when the IN bit is set', (done) ->
|
|
77
|
+
device.controlTransfer 0xc0, 0x81, 0, 0, 128, (e, d) ->
|
|
78
|
+
#console.log("ControlTransferIn", d, e)
|
|
79
|
+
assert.ok(e == undefined, e)
|
|
80
|
+
assert.equal(d.toString(), b.toString())
|
|
81
|
+
done()
|
|
82
|
+
|
|
83
|
+
it 'should signal errors', (done) ->
|
|
84
|
+
device.controlTransfer 0xc0, 0xff, 0, 0, 64, (e, d) ->
|
|
85
|
+
assert.equal e.errno, usb.LIBUSB_TRANSFER_STALL
|
|
86
|
+
done()
|
|
87
|
+
|
|
88
|
+
describe 'Interface', ->
|
|
89
|
+
iface = null
|
|
90
|
+
before ->
|
|
91
|
+
iface = device.interfaces[0]
|
|
92
|
+
iface.claim()
|
|
93
|
+
|
|
94
|
+
it 'should have one interface', ->
|
|
95
|
+
assert.notEqual(iface, undefined)
|
|
96
|
+
|
|
97
|
+
it 'should be the same as the interfaceNo 0', ->
|
|
98
|
+
assert.strictEqual iface, device.interface(0)
|
|
99
|
+
|
|
100
|
+
if process.platform == 'linux'
|
|
101
|
+
it "shouldn't have a kernel driver", ->
|
|
102
|
+
assert.equal iface.isKernelDriverActive(), false
|
|
103
|
+
|
|
104
|
+
it "should fail to detach the kernel driver", ->
|
|
105
|
+
assert.throws -> iface.detachKernelDriver()
|
|
106
|
+
|
|
107
|
+
it "should fail to attach the kernel driver", ->
|
|
108
|
+
assert.throws -> iface.attachKernelDriver()
|
|
109
|
+
|
|
110
|
+
describe 'IN endpoint', ->
|
|
111
|
+
inEndpoint = null
|
|
112
|
+
before ->
|
|
113
|
+
inEndpoint = iface.endpoints[0]
|
|
114
|
+
|
|
115
|
+
it 'should be able to get the endpoint', ->
|
|
116
|
+
assert.ok inEndpoint?
|
|
117
|
+
|
|
118
|
+
it 'should be able to get the endpoint by address', ->
|
|
119
|
+
assert.equal(inEndpoint, iface.endpoint(0x81))
|
|
120
|
+
|
|
121
|
+
it 'should have the IN direction flag', ->
|
|
122
|
+
assert.equal(inEndpoint.direction, 'in')
|
|
123
|
+
|
|
124
|
+
it 'should have a descriptor', ->
|
|
125
|
+
assert.equal(inEndpoint.descriptor.bEndpointAddress, 0x81)
|
|
126
|
+
assert.equal(inEndpoint.descriptor.wMaxPacketSize, 64)
|
|
127
|
+
|
|
128
|
+
it 'should fail to write', ->
|
|
129
|
+
assert.throws -> inEndpoint.transfer(b)
|
|
130
|
+
|
|
131
|
+
it 'should support read', (done) ->
|
|
132
|
+
inEndpoint.transfer 64, (e, d) ->
|
|
133
|
+
assert.ok(e == undefined, e)
|
|
134
|
+
assert.ok(d.length == 64)
|
|
135
|
+
done()
|
|
136
|
+
|
|
137
|
+
it 'times out', (done) ->
|
|
138
|
+
iface.endpoints[2].timeout = 20
|
|
139
|
+
iface.endpoints[2].transfer 64, (e, d) ->
|
|
140
|
+
assert.equal e.errno, usb.LIBUSB_TRANSFER_TIMED_OUT
|
|
141
|
+
done()
|
|
142
|
+
|
|
143
|
+
it 'polls the device', (done) ->
|
|
144
|
+
pkts = 0
|
|
145
|
+
|
|
146
|
+
inEndpoint.startPoll 8, 64
|
|
147
|
+
inEndpoint.on 'data', (d) ->
|
|
148
|
+
assert.equal d.length, 64
|
|
149
|
+
pkts++
|
|
150
|
+
|
|
151
|
+
if pkts == 100
|
|
152
|
+
inEndpoint.stopPoll()
|
|
153
|
+
|
|
154
|
+
inEndpoint.on 'error', (e) ->
|
|
155
|
+
throw e
|
|
156
|
+
|
|
157
|
+
inEndpoint.on 'end', ->
|
|
158
|
+
#console.log("Stream stopped")
|
|
159
|
+
done()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
describe 'OUT endpoint', ->
|
|
163
|
+
outEndpoint = null
|
|
164
|
+
before ->
|
|
165
|
+
outEndpoint = iface.endpoints[1]
|
|
166
|
+
|
|
167
|
+
it 'should be able to get the endpoint', ->
|
|
168
|
+
assert.ok outEndpoint?
|
|
169
|
+
|
|
170
|
+
it 'should be able to get the endpoint by address', ->
|
|
171
|
+
assert.equal(outEndpoint, iface.endpoint(0x02))
|
|
172
|
+
|
|
173
|
+
it 'should have the OUT direction flag', ->
|
|
174
|
+
assert.equal(outEndpoint.direction, 'out')
|
|
175
|
+
|
|
176
|
+
it 'should support write', (done) ->
|
|
177
|
+
outEndpoint.transfer [1,2,3,4], (e) ->
|
|
178
|
+
assert.ok(e == undefined, e)
|
|
179
|
+
done()
|
|
180
|
+
|
|
181
|
+
it 'times out', (done) ->
|
|
182
|
+
iface.endpoints[3].timeout = 20
|
|
183
|
+
iface.endpoints[3].transfer [1,2,3,4], (e) ->
|
|
184
|
+
assert.equal e.errno, usb.LIBUSB_TRANSFER_TIMED_OUT
|
|
185
|
+
done()
|
|
186
|
+
|
|
187
|
+
after (cb) ->
|
|
188
|
+
iface.release(cb)
|
|
189
|
+
|
|
190
|
+
after ->
|
|
191
|
+
device.close()
|
package/usb.js
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
var usb = exports = module.exports = require('node-gyp-build')(__dirname);
|
|
2
|
+
var events = require('events')
|
|
3
|
+
var util = require('util')
|
|
4
|
+
|
|
5
|
+
var isBuffer = function(obj) {
|
|
6
|
+
return obj && obj instanceof Uint8Array
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (usb.INIT_ERROR) {
|
|
10
|
+
console.warn("Failed to initialize libusb.")
|
|
11
|
+
usb.Device = function () { throw new Error("Device cannot be instantiated directly.") };
|
|
12
|
+
usb.Transfer = function () { throw new Error("Transfer cannot be instantiated directly.") };
|
|
13
|
+
usb.setDebugLevel = function () { };
|
|
14
|
+
usb.getDeviceList = function () { return []; };
|
|
15
|
+
usb._enableHotplugEvents = function () { };
|
|
16
|
+
usb._disableHotplugEvents = function () { };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Object.keys(events.EventEmitter.prototype).forEach(function (key) {
|
|
20
|
+
exports[key] = events.EventEmitter.prototype[key];
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// convenience method for finding a device by vendor and product id
|
|
24
|
+
exports.findByIds = function(vid, pid) {
|
|
25
|
+
var devices = usb.getDeviceList()
|
|
26
|
+
|
|
27
|
+
for (var i = 0; i < devices.length; i++) {
|
|
28
|
+
var deviceDesc = devices[i].deviceDescriptor
|
|
29
|
+
if ((deviceDesc.idVendor == vid) && (deviceDesc.idProduct == pid)) {
|
|
30
|
+
return devices[i]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
usb.Device.prototype.timeout = 1000
|
|
36
|
+
|
|
37
|
+
usb.Device.prototype.open = function(defaultConfig){
|
|
38
|
+
this.__open()
|
|
39
|
+
if (defaultConfig === false) return
|
|
40
|
+
this.interfaces = []
|
|
41
|
+
var len = this.configDescriptor ? this.configDescriptor.interfaces.length : 0
|
|
42
|
+
for (var i=0; i<len; i++){
|
|
43
|
+
this.interfaces[i] = new Interface(this, i)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
usb.Device.prototype.close = function(){
|
|
48
|
+
this.__close()
|
|
49
|
+
this.interfaces = null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Object.defineProperty(usb.Device.prototype, "configDescriptor", {
|
|
53
|
+
get: function() {
|
|
54
|
+
try {
|
|
55
|
+
return this._configDescriptor || (this._configDescriptor = this.__getConfigDescriptor())
|
|
56
|
+
} catch(e) {
|
|
57
|
+
// Check descriptor exists
|
|
58
|
+
if (e.errno == usb.LIBUSB_ERROR_NOT_FOUND) return null;
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
Object.defineProperty(usb.Device.prototype, "allConfigDescriptors", {
|
|
65
|
+
get: function() {
|
|
66
|
+
try {
|
|
67
|
+
return this._allConfigDescriptors || (this._allConfigDescriptors = this.__getAllConfigDescriptors())
|
|
68
|
+
} catch(e) {
|
|
69
|
+
// Check descriptors exist
|
|
70
|
+
if (e.errno == usb.LIBUSB_ERROR_NOT_FOUND) return [];
|
|
71
|
+
throw e;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
Object.defineProperty(usb.Device.prototype, "parent", {
|
|
77
|
+
get: function() {
|
|
78
|
+
return this._parent || (this._parent = this.__getParent())
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
usb.Device.prototype.interface = function(addr){
|
|
83
|
+
if (!this.interfaces){
|
|
84
|
+
throw new Error("Device must be open before searching for interfaces")
|
|
85
|
+
}
|
|
86
|
+
addr = addr || 0
|
|
87
|
+
for (var i=0; i<this.interfaces.length; i++){
|
|
88
|
+
if (this.interfaces[i].interfaceNumber == addr){
|
|
89
|
+
return this.interfaces[i]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
var SETUP_SIZE = usb.LIBUSB_CONTROL_SETUP_SIZE
|
|
95
|
+
|
|
96
|
+
usb.Device.prototype.controlTransfer =
|
|
97
|
+
function(bmRequestType, bRequest, wValue, wIndex, data_or_length, callback){
|
|
98
|
+
var self = this
|
|
99
|
+
var isIn = !!(bmRequestType & usb.LIBUSB_ENDPOINT_IN)
|
|
100
|
+
var wLength
|
|
101
|
+
|
|
102
|
+
if (isIn){
|
|
103
|
+
if (!(data_or_length >= 0)){
|
|
104
|
+
throw new TypeError("Expected size number for IN transfer (based on bmRequestType)")
|
|
105
|
+
}
|
|
106
|
+
wLength = data_or_length
|
|
107
|
+
}else{
|
|
108
|
+
if (!isBuffer(data_or_length)){
|
|
109
|
+
throw new TypeError("Expected buffer for OUT transfer (based on bmRequestType)")
|
|
110
|
+
}
|
|
111
|
+
wLength = data_or_length.length
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Buffer for the setup packet
|
|
115
|
+
// http://libusbx.sourceforge.net/api-1.0/structlibusb__control__setup.html
|
|
116
|
+
var buf = Buffer.alloc(wLength + SETUP_SIZE)
|
|
117
|
+
buf.writeUInt8( bmRequestType, 0)
|
|
118
|
+
buf.writeUInt8( bRequest, 1)
|
|
119
|
+
buf.writeUInt16LE(wValue, 2)
|
|
120
|
+
buf.writeUInt16LE(wIndex, 4)
|
|
121
|
+
buf.writeUInt16LE(wLength, 6)
|
|
122
|
+
|
|
123
|
+
if (!isIn){
|
|
124
|
+
buf.set(data_or_length, SETUP_SIZE)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
var transfer = new usb.Transfer(this, 0, usb.LIBUSB_TRANSFER_TYPE_CONTROL, this.timeout,
|
|
128
|
+
function(error, buf, actual){
|
|
129
|
+
if (callback){
|
|
130
|
+
if (isIn){
|
|
131
|
+
callback.call(self, error, buf.slice(SETUP_SIZE, SETUP_SIZE + actual))
|
|
132
|
+
}else{
|
|
133
|
+
callback.call(self, error)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
transfer.submit(buf)
|
|
141
|
+
} catch (e) {
|
|
142
|
+
if (callback){
|
|
143
|
+
process.nextTick(function() { callback.call(self, e); });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
usb.Device.prototype.getStringDescriptor = function (desc_index, callback) {
|
|
150
|
+
var langid = 0x0409;
|
|
151
|
+
var length = 255;
|
|
152
|
+
this.controlTransfer(
|
|
153
|
+
usb.LIBUSB_ENDPOINT_IN,
|
|
154
|
+
usb.LIBUSB_REQUEST_GET_DESCRIPTOR,
|
|
155
|
+
((usb.LIBUSB_DT_STRING << 8) | desc_index),
|
|
156
|
+
langid,
|
|
157
|
+
length,
|
|
158
|
+
function (error, buf) {
|
|
159
|
+
if (error) return callback(error);
|
|
160
|
+
callback(undefined, buf.toString('utf16le', 2));
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
usb.Device.prototype.getBosDescriptor = function (callback) {
|
|
166
|
+
|
|
167
|
+
if (this._bosDescriptor) {
|
|
168
|
+
// Cached descriptor
|
|
169
|
+
return callback(undefined, this._bosDescriptor);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (this.deviceDescriptor.bcdUSB < 0x201) {
|
|
173
|
+
// BOS is only supported from USB 2.0.1
|
|
174
|
+
return callback(undefined, null);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this.controlTransfer(
|
|
178
|
+
usb.LIBUSB_ENDPOINT_IN,
|
|
179
|
+
usb.LIBUSB_REQUEST_GET_DESCRIPTOR,
|
|
180
|
+
(usb.LIBUSB_DT_BOS << 8),
|
|
181
|
+
0,
|
|
182
|
+
usb.LIBUSB_DT_BOS_SIZE,
|
|
183
|
+
function (error, buffer) {
|
|
184
|
+
if (error) {
|
|
185
|
+
// Check BOS descriptor exists
|
|
186
|
+
if (error.errno == usb.LIBUSB_TRANSFER_STALL) return callback(undefined, null);
|
|
187
|
+
return callback(error, null);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
var totalLength = buffer.readUInt16LE(2);
|
|
191
|
+
this.controlTransfer(
|
|
192
|
+
usb.LIBUSB_ENDPOINT_IN,
|
|
193
|
+
usb.LIBUSB_REQUEST_GET_DESCRIPTOR,
|
|
194
|
+
(usb.LIBUSB_DT_BOS << 8),
|
|
195
|
+
0,
|
|
196
|
+
totalLength,
|
|
197
|
+
function (error, buffer) {
|
|
198
|
+
if (error) {
|
|
199
|
+
// Check BOS descriptor exists
|
|
200
|
+
if (error.errno == usb.LIBUSB_TRANSFER_STALL) return callback(undefined, null);
|
|
201
|
+
return callback(error, null);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
var descriptor = {
|
|
205
|
+
bLength: buffer.readUInt8(0),
|
|
206
|
+
bDescriptorType: buffer.readUInt8(1),
|
|
207
|
+
wTotalLength: buffer.readUInt16LE(2),
|
|
208
|
+
bNumDeviceCaps: buffer.readUInt8(4),
|
|
209
|
+
capabilities: []
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
var i = usb.LIBUSB_DT_BOS_SIZE;
|
|
213
|
+
while (i < descriptor.wTotalLength) {
|
|
214
|
+
var capability = {
|
|
215
|
+
bLength: buffer.readUInt8(i + 0),
|
|
216
|
+
bDescriptorType: buffer.readUInt8(i + 1),
|
|
217
|
+
bDevCapabilityType: buffer.readUInt8(i + 2)
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
capability.dev_capability_data = buffer.slice(i + 3, i + capability.bLength);
|
|
221
|
+
descriptor.capabilities.push(capability);
|
|
222
|
+
i += capability.bLength;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Cache descriptor
|
|
226
|
+
this._bosDescriptor = descriptor;
|
|
227
|
+
callback(undefined, this._bosDescriptor);
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
usb.Device.prototype.getCapabilities = function (callback) {
|
|
235
|
+
var capabilities = [];
|
|
236
|
+
var self = this;
|
|
237
|
+
|
|
238
|
+
this.getBosDescriptor(function(error, descriptor) {
|
|
239
|
+
if (error) return callback(error, null);
|
|
240
|
+
|
|
241
|
+
var len = descriptor ? descriptor.capabilities.length : 0
|
|
242
|
+
for (var i=0; i<len; i++){
|
|
243
|
+
capabilities.push(new Capability(self, i))
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
callback(undefined, capabilities);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
usb.Device.prototype.setConfiguration = function(desired, cb) {
|
|
251
|
+
var self = this;
|
|
252
|
+
this.__setConfiguration(desired, function(err) {
|
|
253
|
+
if (!err) {
|
|
254
|
+
this.interfaces = []
|
|
255
|
+
var len = this.configDescriptor ? this.configDescriptor.interfaces.length : 0
|
|
256
|
+
for (var i=0; i<len; i++) {
|
|
257
|
+
this.interfaces[i] = new Interface(this, i)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
cb.call(self, err)
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function Interface(device, id){
|
|
265
|
+
this.device = device
|
|
266
|
+
this.id = id
|
|
267
|
+
this.altSetting = 0;
|
|
268
|
+
this.__refresh()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
Interface.prototype.__refresh = function(){
|
|
272
|
+
this.descriptor = this.device.configDescriptor.interfaces[this.id][this.altSetting]
|
|
273
|
+
this.interfaceNumber = this.descriptor.bInterfaceNumber
|
|
274
|
+
this.endpoints = []
|
|
275
|
+
var len = this.descriptor.endpoints.length
|
|
276
|
+
for (var i=0; i<len; i++){
|
|
277
|
+
var desc = this.descriptor.endpoints[i]
|
|
278
|
+
var c = (desc.bEndpointAddress&usb.LIBUSB_ENDPOINT_IN)?InEndpoint:OutEndpoint
|
|
279
|
+
this.endpoints[i] = new c(this.device, desc)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
Interface.prototype.claim = function(){
|
|
284
|
+
this.device.__claimInterface(this.id)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
Interface.prototype.release = function(closeEndpoints, cb){
|
|
288
|
+
var self = this;
|
|
289
|
+
if (typeof closeEndpoints == 'function') {
|
|
290
|
+
cb = closeEndpoints;
|
|
291
|
+
closeEndpoints = null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (!closeEndpoints || this.endpoints.length == 0) {
|
|
295
|
+
next();
|
|
296
|
+
} else {
|
|
297
|
+
var n = self.endpoints.length;
|
|
298
|
+
self.endpoints.forEach(function (ep, i) {
|
|
299
|
+
if (ep.pollActive) {
|
|
300
|
+
ep.once('end', function () {
|
|
301
|
+
if (--n == 0) next();
|
|
302
|
+
});
|
|
303
|
+
ep.stopPoll();
|
|
304
|
+
} else {
|
|
305
|
+
if (--n == 0) next();
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function next () {
|
|
311
|
+
self.device.__releaseInterface(self.id, function(err){
|
|
312
|
+
if (!err){
|
|
313
|
+
self.altSetting = 0;
|
|
314
|
+
self.__refresh()
|
|
315
|
+
}
|
|
316
|
+
cb.call(self, err)
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
Interface.prototype.isKernelDriverActive = function(){
|
|
322
|
+
return this.device.__isKernelDriverActive(this.id)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
Interface.prototype.detachKernelDriver = function() {
|
|
326
|
+
return this.device.__detachKernelDriver(this.id)
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
Interface.prototype.attachKernelDriver = function() {
|
|
330
|
+
return this.device.__attachKernelDriver(this.id)
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
Interface.prototype.setAltSetting = function(altSetting, cb){
|
|
335
|
+
var self = this;
|
|
336
|
+
this.device.__setInterface(this.id, altSetting, function(err){
|
|
337
|
+
if (!err){
|
|
338
|
+
self.altSetting = altSetting;
|
|
339
|
+
self.__refresh();
|
|
340
|
+
}
|
|
341
|
+
cb.call(self, err)
|
|
342
|
+
})
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
Interface.prototype.endpoint = function(addr){
|
|
346
|
+
for (var i=0; i<this.endpoints.length; i++){
|
|
347
|
+
if (this.endpoints[i].address == addr){
|
|
348
|
+
return this.endpoints[i]
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function Capability(device, id){
|
|
354
|
+
this.device = device
|
|
355
|
+
this.id = id
|
|
356
|
+
this.descriptor = this.device._bosDescriptor.capabilities[this.id]
|
|
357
|
+
this.type = this.descriptor.bDevCapabilityType
|
|
358
|
+
this.data = this.descriptor.dev_capability_data
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function Endpoint(device, descriptor){
|
|
362
|
+
this.device = device
|
|
363
|
+
this.descriptor = descriptor
|
|
364
|
+
this.address = descriptor.bEndpointAddress
|
|
365
|
+
this.transferType = descriptor.bmAttributes&0x03
|
|
366
|
+
}
|
|
367
|
+
util.inherits(Endpoint, events.EventEmitter)
|
|
368
|
+
|
|
369
|
+
Endpoint.prototype.timeout = 0
|
|
370
|
+
|
|
371
|
+
Endpoint.prototype.clearHalt = function(callback){
|
|
372
|
+
return this.device.__clearHalt(this.address, callback);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
Endpoint.prototype.makeTransfer = function(timeout, callback){
|
|
376
|
+
return new usb.Transfer(this.device, this.address, this.transferType, timeout, callback)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
Endpoint.prototype.startPoll = function(nTransfers, transferSize, callback){
|
|
380
|
+
if (this.pollTransfers){
|
|
381
|
+
throw new Error("Polling already active")
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
nTransfers = nTransfers || 3;
|
|
385
|
+
this.pollTransferSize = transferSize || this.descriptor.wMaxPacketSize;
|
|
386
|
+
this.pollActive = true
|
|
387
|
+
this.pollPending = 0
|
|
388
|
+
|
|
389
|
+
var transfers = []
|
|
390
|
+
for (var i=0; i<nTransfers; i++){
|
|
391
|
+
transfers[i] = this.makeTransfer(0, callback)
|
|
392
|
+
}
|
|
393
|
+
return transfers;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
Endpoint.prototype.stopPoll = function(cb){
|
|
397
|
+
if (!this.pollTransfers) {
|
|
398
|
+
throw new Error('Polling is not active.');
|
|
399
|
+
}
|
|
400
|
+
for (var i=0; i<this.pollTransfers.length; i++){
|
|
401
|
+
try {
|
|
402
|
+
this.pollTransfers[i].cancel()
|
|
403
|
+
} catch (err) {
|
|
404
|
+
this.emit('error', err);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
this.pollActive = false
|
|
408
|
+
if (cb) this.once('end', cb);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function InEndpoint(device, descriptor){
|
|
412
|
+
Endpoint.call(this, device, descriptor)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
exports.InEndpoint = InEndpoint
|
|
416
|
+
util.inherits(InEndpoint, Endpoint)
|
|
417
|
+
InEndpoint.prototype.direction = "in"
|
|
418
|
+
|
|
419
|
+
InEndpoint.prototype.transfer = function(length, cb){
|
|
420
|
+
var self = this
|
|
421
|
+
var buffer = Buffer.alloc(length)
|
|
422
|
+
|
|
423
|
+
function callback(error, buf, actual){
|
|
424
|
+
cb.call(self, error, buffer.slice(0, actual))
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
try {
|
|
428
|
+
this.makeTransfer(this.timeout, callback).submit(buffer)
|
|
429
|
+
} catch (e) {
|
|
430
|
+
process.nextTick(function() { cb.call(self, e); });
|
|
431
|
+
}
|
|
432
|
+
return this;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
InEndpoint.prototype.startPoll = function(nTransfers, transferSize){
|
|
436
|
+
var self = this
|
|
437
|
+
this.pollTransfers = InEndpoint.super_.prototype.startPoll.call(this, nTransfers, transferSize, transferDone)
|
|
438
|
+
|
|
439
|
+
function transferDone(error, buf, actual){
|
|
440
|
+
if (!error){
|
|
441
|
+
self.emit("data", buf.slice(0, actual))
|
|
442
|
+
}else if (error.errno != usb.LIBUSB_TRANSFER_CANCELLED){
|
|
443
|
+
self.emit("error", error)
|
|
444
|
+
self.stopPoll()
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (self.pollActive){
|
|
448
|
+
startTransfer(this)
|
|
449
|
+
}else{
|
|
450
|
+
self.pollPending--
|
|
451
|
+
|
|
452
|
+
if (self.pollPending == 0){
|
|
453
|
+
delete self.pollTransfers;
|
|
454
|
+
self.emit('end')
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function startTransfer(t){
|
|
460
|
+
try {
|
|
461
|
+
t.submit(Buffer.alloc(self.pollTransferSize), transferDone);
|
|
462
|
+
} catch (e) {
|
|
463
|
+
self.emit("error", e);
|
|
464
|
+
self.stopPoll();
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
this.pollTransfers.forEach(startTransfer)
|
|
469
|
+
self.pollPending = this.pollTransfers.length
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
function OutEndpoint(device, descriptor){
|
|
475
|
+
Endpoint.call(this, device, descriptor)
|
|
476
|
+
}
|
|
477
|
+
exports.OutEndpoint = OutEndpoint
|
|
478
|
+
util.inherits(OutEndpoint, Endpoint)
|
|
479
|
+
OutEndpoint.prototype.direction = "out"
|
|
480
|
+
|
|
481
|
+
OutEndpoint.prototype.transfer = function(buffer, cb){
|
|
482
|
+
var self = this
|
|
483
|
+
if (!buffer){
|
|
484
|
+
buffer = Buffer.alloc(0)
|
|
485
|
+
}else if (!isBuffer(buffer)){
|
|
486
|
+
buffer = Buffer.from(buffer)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function callback(error, buf, actual){
|
|
490
|
+
if (cb) cb.call(self, error)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
try {
|
|
494
|
+
this.makeTransfer(this.timeout, callback).submit(buffer);
|
|
495
|
+
} catch (e) {
|
|
496
|
+
process.nextTick(function() { callback(e); });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return this;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
OutEndpoint.prototype.transferWithZLP = function (buf, cb) {
|
|
503
|
+
if (buf.length % this.descriptor.wMaxPacketSize == 0) {
|
|
504
|
+
this.transfer(buf);
|
|
505
|
+
this.transfer(Buffer.alloc(0), cb);
|
|
506
|
+
} else {
|
|
507
|
+
this.transfer(buf, cb);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
var hotplugListeners = 0;
|
|
512
|
+
exports.on('newListener', function(name) {
|
|
513
|
+
if (name !== 'attach' && name !== 'detach') return;
|
|
514
|
+
if (++hotplugListeners === 1) {
|
|
515
|
+
usb._enableHotplugEvents();
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
exports.on('removeListener', function(name) {
|
|
520
|
+
if (name !== 'attach' && name !== 'detach') return;
|
|
521
|
+
if (--hotplugListeners === 0) {
|
|
522
|
+
usb._disableHotplugEvents();
|
|
523
|
+
}
|
|
524
|
+
});
|