libusb 0.7.0-x64-mingw-ucrt
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.
- checksums.yaml +7 -0
- data/.appveyor.yml +33 -0
- data/.github/workflows/ci.yml +185 -0
- data/.gitignore +9 -0
- data/.travis.yml +26 -0
- data/.yardopts +6 -0
- data/COPYING +165 -0
- data/Gemfile +19 -0
- data/History.md +193 -0
- data/README.md +184 -0
- data/Rakefile +79 -0
- data/lib/libusb/bos.rb +362 -0
- data/lib/libusb/call.rb +622 -0
- data/lib/libusb/compat.rb +376 -0
- data/lib/libusb/configuration.rb +154 -0
- data/lib/libusb/constants.rb +170 -0
- data/lib/libusb/context.rb +576 -0
- data/lib/libusb/context_reference.rb +38 -0
- data/lib/libusb/dependencies.rb +7 -0
- data/lib/libusb/dev_handle.rb +574 -0
- data/lib/libusb/device.rb +407 -0
- data/lib/libusb/endpoint.rb +195 -0
- data/lib/libusb/eventmachine.rb +187 -0
- data/lib/libusb/gem_helper.rb +151 -0
- data/lib/libusb/interface.rb +60 -0
- data/lib/libusb/libusb_recipe.rb +29 -0
- data/lib/libusb/setting.rb +132 -0
- data/lib/libusb/ss_companion.rb +72 -0
- data/lib/libusb/stdio.rb +25 -0
- data/lib/libusb/transfer.rb +418 -0
- data/lib/libusb/version_gem.rb +19 -0
- data/lib/libusb/version_struct.rb +63 -0
- data/lib/libusb-1.0.dll +0 -0
- data/lib/libusb.rb +146 -0
- data/libusb.gemspec +28 -0
- data/test/test_libusb.rb +42 -0
- data/test/test_libusb_bos.rb +140 -0
- data/test/test_libusb_bulk_stream_transfer.rb +61 -0
- data/test/test_libusb_compat.rb +78 -0
- data/test/test_libusb_compat_mass_storage.rb +81 -0
- data/test/test_libusb_context.rb +88 -0
- data/test/test_libusb_descriptors.rb +245 -0
- data/test/test_libusb_event_machine.rb +118 -0
- data/test/test_libusb_gc.rb +52 -0
- data/test/test_libusb_hotplug.rb +129 -0
- data/test/test_libusb_iso_transfer.rb +56 -0
- data/test/test_libusb_mass_storage.rb +268 -0
- data/test/test_libusb_mass_storage2.rb +96 -0
- data/test/test_libusb_structs.rb +87 -0
- data/test/test_libusb_threads.rb +89 -0
- data/wireshark-usb-sniffer.png +0 -0
- metadata +112 -0
@@ -0,0 +1,268 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
#
|
16
|
+
# This test requires a connected, but not mounted mass storage device with
|
17
|
+
# read/write access allowed. Based on the following specifications:
|
18
|
+
# http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
|
19
|
+
# http://en.wikipedia.org/wiki/SCSI_command
|
20
|
+
#
|
21
|
+
|
22
|
+
require "minitest/autorun"
|
23
|
+
require "libusb"
|
24
|
+
|
25
|
+
class TestLibusbMassStorage < Minitest::Test
|
26
|
+
include LIBUSB
|
27
|
+
|
28
|
+
class CSWError < RuntimeError; end
|
29
|
+
BOMS_RESET = 0xFF
|
30
|
+
BOMS_GET_MAX_LUN = 0xFE
|
31
|
+
|
32
|
+
attr_accessor :usb
|
33
|
+
attr_accessor :device
|
34
|
+
attr_accessor :dev
|
35
|
+
attr_accessor :endpoint_in
|
36
|
+
attr_accessor :endpoint_out
|
37
|
+
|
38
|
+
def setup
|
39
|
+
@usb = Context.new
|
40
|
+
@usb.debug = 3
|
41
|
+
@asynchron = false
|
42
|
+
|
43
|
+
@device = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 ).last
|
44
|
+
skip "no mass storage device found" unless @device
|
45
|
+
|
46
|
+
@endpoint_in = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
|
47
|
+
@endpoint_out = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN == 0 }
|
48
|
+
@dev = @device.open
|
49
|
+
|
50
|
+
if RUBY_PLATFORM=~/linux/i && dev.kernel_driver_active?(0)
|
51
|
+
dev.detach_kernel_driver(0)
|
52
|
+
end
|
53
|
+
dev.claim_interface(0)
|
54
|
+
|
55
|
+
# clear any pending data
|
56
|
+
dev.clear_halt(endpoint_in)
|
57
|
+
end
|
58
|
+
|
59
|
+
def teardown
|
60
|
+
dev.release_interface(0) if dev
|
61
|
+
dev.close if dev
|
62
|
+
end
|
63
|
+
|
64
|
+
def do_transfer(method, **args)
|
65
|
+
if @asynchron
|
66
|
+
stop = false
|
67
|
+
transfer = dev.send(method, args) do |tr|
|
68
|
+
stop = true
|
69
|
+
assert_equal transfer, tr, "block argument should be the transfer instance"
|
70
|
+
# p transfer.status
|
71
|
+
end
|
72
|
+
|
73
|
+
transfer.submit
|
74
|
+
usb.handle_events
|
75
|
+
until stop
|
76
|
+
sleep 0.001
|
77
|
+
usb.handle_events
|
78
|
+
end
|
79
|
+
transfer.result
|
80
|
+
else
|
81
|
+
dev.send(method, **args)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
def control_transfer(**args)
|
85
|
+
do_transfer(:control_transfer, **args)
|
86
|
+
end
|
87
|
+
def bulk_transfer(**args)
|
88
|
+
do_transfer(:bulk_transfer, **args)
|
89
|
+
end
|
90
|
+
|
91
|
+
def send_mass_storage_command(cdb, data_length, direction=ENDPOINT_IN)
|
92
|
+
@tag ||= 0
|
93
|
+
@tag += 1
|
94
|
+
expected_tag = @tag
|
95
|
+
lun = 0
|
96
|
+
|
97
|
+
cbw = ['USBC', expected_tag, data_length, direction, lun, cdb.length, cdb].pack('a*VVCCCa*')
|
98
|
+
cbw = cbw.ljust(31, "\0")
|
99
|
+
|
100
|
+
num_bytes = bulk_transfer(endpoint: endpoint_out, dataOut: cbw)
|
101
|
+
assert_equal 31, num_bytes, "31 bytes CBW should be sent"
|
102
|
+
|
103
|
+
recv = bulk_transfer(endpoint: endpoint_in, dataIn: data_length)
|
104
|
+
|
105
|
+
get_mass_storage_status(expected_tag)
|
106
|
+
return recv
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_mass_storage_status(expected_tag)
|
110
|
+
retries = 5
|
111
|
+
buffer = begin
|
112
|
+
bulk_transfer(endpoint: endpoint_in, dataIn: 13)
|
113
|
+
rescue LIBUSB::ERROR_PIPE
|
114
|
+
if (retries-=1)>=0
|
115
|
+
dev.clear_halt(endpoint_in)
|
116
|
+
retry
|
117
|
+
end
|
118
|
+
raise
|
119
|
+
end
|
120
|
+
assert_equal 13, buffer.bytesize, "CSW should be 13 bytes long"
|
121
|
+
|
122
|
+
dCSWSignature, dCSWTag, dCSWDataResidue, bCSWStatus = buffer.unpack('a4VVC')
|
123
|
+
|
124
|
+
assert_equal 'USBS', dCSWSignature, "CSW should start with USBS"
|
125
|
+
assert_kind_of Integer, dCSWDataResidue
|
126
|
+
assert_equal expected_tag, dCSWTag, "CSW-tag should be like CBW-tag"
|
127
|
+
raise CSWError, "CSW returned error #{bCSWStatus}" unless bCSWStatus==0
|
128
|
+
buffer
|
129
|
+
end
|
130
|
+
|
131
|
+
def send_inquiry
|
132
|
+
expected_length = 0x24 # INQUIRY_LENGTH
|
133
|
+
cdb = [ 0x12, 0, 0, # Inquiry
|
134
|
+
expected_length, 0,
|
135
|
+
].pack('CCCnC')
|
136
|
+
|
137
|
+
send_mass_storage_command( cdb, expected_length )
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_capacity
|
141
|
+
expected_length = 0x08 # READ_CAPACITY_LENGTH
|
142
|
+
cdb = [ 0x25, # Read Capacity
|
143
|
+
].pack('Cx9')
|
144
|
+
|
145
|
+
cap = send_mass_storage_command( cdb, expected_length )
|
146
|
+
|
147
|
+
max_lba, block_size = cap.unpack('NN')
|
148
|
+
device_size = (max_lba + 1) * block_size / (1024*1024*1024.0);
|
149
|
+
printf(" Max LBA: %08X, Block Size: %08X (%.2f GB)\n", max_lba, block_size, device_size);
|
150
|
+
end
|
151
|
+
|
152
|
+
def read_block(start, nr_blocks)
|
153
|
+
expected_length = 0x200 * nr_blocks
|
154
|
+
cdb = [ 0x28, 0, # Read(10)
|
155
|
+
start, 0,
|
156
|
+
nr_blocks, 0,
|
157
|
+
].pack('CCNCnC')
|
158
|
+
send_mass_storage_command( cdb, expected_length )
|
159
|
+
end
|
160
|
+
|
161
|
+
def invalid_command
|
162
|
+
expected_length = 0x100
|
163
|
+
cdb = [ 0x26, 0, # invalid command
|
164
|
+
].pack('CC')
|
165
|
+
send_mass_storage_command( cdb, expected_length )
|
166
|
+
end
|
167
|
+
|
168
|
+
def mass_storage_reset
|
169
|
+
res = control_transfer(
|
170
|
+
bmRequestType: ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
171
|
+
bRequest: BOMS_RESET,
|
172
|
+
wValue: 0, wIndex: 0)
|
173
|
+
assert_equal 0, res, "BOMS_RESET response should be 0 byte"
|
174
|
+
|
175
|
+
res = control_transfer(
|
176
|
+
bmRequestType: ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
177
|
+
bRequest: BOMS_RESET,
|
178
|
+
wValue: 0, wIndex: 0, dataOut: '')
|
179
|
+
assert_equal 0, res, "BOMS_RESET response should be 0 byte"
|
180
|
+
end
|
181
|
+
|
182
|
+
def read_max_lun
|
183
|
+
res = control_transfer(
|
184
|
+
bmRequestType: ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
185
|
+
bRequest: BOMS_GET_MAX_LUN,
|
186
|
+
wValue: 0, wIndex: 0, dataIn: 1)
|
187
|
+
assert [0].pack("C")==res || [1].pack("C")==res, "BOMS_GET_MAX_LUN response is usually 0 or 1"
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_read_access
|
191
|
+
send_inquiry
|
192
|
+
get_capacity
|
193
|
+
|
194
|
+
data = read_block(0, 1)
|
195
|
+
assert_equal 512, data.length, "Read block should be 512 bytes"
|
196
|
+
|
197
|
+
# closing device handle shouldn't matter, in the meantime
|
198
|
+
dev.close
|
199
|
+
@dev = @device.open
|
200
|
+
dev.claim_interface(0)
|
201
|
+
|
202
|
+
data = read_block(0, 2)
|
203
|
+
assert_equal 1024, data.length, "Read block should be 1024 bytes"
|
204
|
+
end
|
205
|
+
# def test_read_access_async
|
206
|
+
# @asynchron = true
|
207
|
+
# test_read_access
|
208
|
+
# end
|
209
|
+
|
210
|
+
def test_read_failed
|
211
|
+
count = 0
|
212
|
+
th = Thread.new do
|
213
|
+
loop do
|
214
|
+
count+=1
|
215
|
+
sleep 0.01
|
216
|
+
end
|
217
|
+
end
|
218
|
+
assert_raises(LIBUSB::ERROR_TIMEOUT) do
|
219
|
+
begin
|
220
|
+
bulk_transfer(endpoint: endpoint_in, dataIn: 123)
|
221
|
+
rescue LIBUSB::ERROR_TIMEOUT => err
|
222
|
+
assert_kind_of String, err.transferred
|
223
|
+
raise
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
th.kill
|
228
|
+
dev.clear_halt(endpoint_in)
|
229
|
+
dev.clear_halt(endpoint_out)
|
230
|
+
assert_operator 20, :<=, count, "libusb_handle_events should not block a parallel Thread"
|
231
|
+
end
|
232
|
+
# def test_read_failed_async
|
233
|
+
# @asynchron = true
|
234
|
+
# test_read_failed
|
235
|
+
# end
|
236
|
+
|
237
|
+
def test_max_lun
|
238
|
+
read_max_lun
|
239
|
+
end
|
240
|
+
# def test_max_lun_async
|
241
|
+
# @asynchron = true
|
242
|
+
# read_max_lun
|
243
|
+
# end
|
244
|
+
|
245
|
+
def test_mass_storage_reset
|
246
|
+
mass_storage_reset
|
247
|
+
end
|
248
|
+
# def test_mass_storage_reset_async
|
249
|
+
# @asynchron = true
|
250
|
+
# mass_storage_reset
|
251
|
+
# end
|
252
|
+
|
253
|
+
def test_read_long
|
254
|
+
1000.times do |bl|
|
255
|
+
data = read_block(bl, 1)
|
256
|
+
assert_equal 512, data.length, "Read block should be 512 bytes"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_wrong_argument
|
261
|
+
assert_raises(ArgumentError){ dev.bulk_transfer(endpoint: endpoint_in, dataOut: "data") }
|
262
|
+
assert_raises(ArgumentError){ dev.interrupt_transfer(endpoint: endpoint_in, dataOut: "data") }
|
263
|
+
assert_raises(ArgumentError){ dev.control_transfer(
|
264
|
+
bmRequestType: ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
265
|
+
bRequest: BOMS_RESET,
|
266
|
+
wValue: 0, wIndex: 0, dataIn: 123) }
|
267
|
+
end
|
268
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
#
|
16
|
+
|
17
|
+
require "minitest/autorun"
|
18
|
+
require "libusb"
|
19
|
+
|
20
|
+
class TestLibusbMassStorage2 < Minitest::Test
|
21
|
+
include LIBUSB
|
22
|
+
|
23
|
+
attr_accessor :usb
|
24
|
+
attr_accessor :device
|
25
|
+
attr_accessor :interface
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@usb = Context.new
|
29
|
+
@usb.debug = 3
|
30
|
+
@device = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 ).last
|
31
|
+
skip "no mass storage device found" unless @device
|
32
|
+
|
33
|
+
@interface = device.interfaces.first
|
34
|
+
|
35
|
+
# Ensure kernel driver is detached
|
36
|
+
device.open do |dev|
|
37
|
+
if RUBY_PLATFORM=~/linux/i && dev.kernel_driver_active?(interface)
|
38
|
+
dev.detach_kernel_driver(interface)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def teardown
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_open_with_block
|
47
|
+
device.open do |dev|
|
48
|
+
assert_kind_of DevHandle, dev
|
49
|
+
assert_kind_of String, dev.string_descriptor_ascii(1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_claim_interface_with_block
|
54
|
+
res = device.open do |dev|
|
55
|
+
dev.claim_interface(interface) do |dev2|
|
56
|
+
assert_kind_of DevHandle, dev2
|
57
|
+
assert_kind_of String, dev2.string_descriptor_ascii(1)
|
58
|
+
12345
|
59
|
+
end
|
60
|
+
end
|
61
|
+
assert_equal 12345, res, "Block versions should pass through the result"
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_open_interface
|
65
|
+
res = device.open_interface(interface) do |dev|
|
66
|
+
assert_kind_of DevHandle, dev
|
67
|
+
assert_kind_of String, dev.string_descriptor_ascii(1)
|
68
|
+
12345
|
69
|
+
end
|
70
|
+
assert_equal 12345, res, "Block versions should pass through the result"
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_attach_kernel_driver
|
74
|
+
# Should work with both Fixnum and Interface parameter
|
75
|
+
[0, interface].each do |i|
|
76
|
+
device.open do |dev|
|
77
|
+
dev.attach_kernel_driver(i)
|
78
|
+
assert dev.kernel_driver_active?(i), "kernel driver should be active again"
|
79
|
+
dev.detach_kernel_driver(i)
|
80
|
+
refute dev.kernel_driver_active?(i), "kernel driver should be detached"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_auto_detach_kernel_driver
|
86
|
+
assert LIBUSB.has_capability?(:CAP_SUPPORTS_DETACH_KERNEL_DRIVER), "libusb should have CAP_SUPPORTS_DETACH_KERNEL_DRIVER"
|
87
|
+
|
88
|
+
device.open do |dev|
|
89
|
+
dev.attach_kernel_driver 0
|
90
|
+
assert dev.kernel_driver_active?(0), "kernel driver should attached, now"
|
91
|
+
dev.auto_detach_kernel_driver = true
|
92
|
+
dev.claim_interface(0)
|
93
|
+
refute dev.kernel_driver_active?(0), "kernel driver should get detached automatically"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require "minitest/autorun"
|
17
|
+
require "libusb"
|
18
|
+
|
19
|
+
class TestLibusbStructs < Minitest::Test
|
20
|
+
def test_struct_Timeval
|
21
|
+
s = LIBUSB::Call::Timeval.new
|
22
|
+
assert_equal 0, s.in_ms
|
23
|
+
s.in_ms = 12345678
|
24
|
+
assert_equal 12345, s[:tv_sec]
|
25
|
+
assert_equal 678000, s[:tv_usec]
|
26
|
+
assert_equal 12345678, s.in_ms
|
27
|
+
|
28
|
+
s.in_s = 1234.5678
|
29
|
+
assert_equal 1234, s[:tv_sec]
|
30
|
+
assert_equal 567800, s[:tv_usec]
|
31
|
+
assert_equal 1234.5678, s.in_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_struct_CompletionFlag
|
35
|
+
s = LIBUSB::Context::CompletionFlag.new
|
36
|
+
assert_equal 0, s[:completed]
|
37
|
+
assert_equal false, s.completed?
|
38
|
+
s.completed = true
|
39
|
+
assert_equal 1, s[:completed]
|
40
|
+
assert_equal true, s.completed?
|
41
|
+
s.completed = false
|
42
|
+
assert_equal false, s.completed?
|
43
|
+
assert_equal 0, s[:completed]
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_Transfer_buffer
|
47
|
+
t = LIBUSB::InterruptTransfer.new allow_device_memory: true
|
48
|
+
assert_equal :TRANSFER_COMPLETED, t.status
|
49
|
+
assert_equal true, t.allow_device_memory
|
50
|
+
assert_nil t.memory_type
|
51
|
+
|
52
|
+
t.alloc_buffer(10)
|
53
|
+
assert_equal :user_space, t.memory_type, "no device assigned -> should use memory from user space"
|
54
|
+
|
55
|
+
t.free_buffer
|
56
|
+
assert_nil t.memory_type
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_Transfer_new
|
60
|
+
assert_raises(NoMethodError){ LIBUSB::Transfer.new }
|
61
|
+
LIBUSB::BulkStreamTransfer.new
|
62
|
+
LIBUSB::BulkTransfer.new
|
63
|
+
LIBUSB::ControlTransfer.new
|
64
|
+
LIBUSB::InterruptTransfer.new
|
65
|
+
LIBUSB::IsochronousTransfer.new(0)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_ControlTransfer_attributes
|
69
|
+
t = LIBUSB::ControlTransfer.new
|
70
|
+
t.timeout = 123
|
71
|
+
assert_equal 123, t.timeout
|
72
|
+
t.allow_device_memory = true
|
73
|
+
assert_equal true, t.allow_device_memory
|
74
|
+
assert_nil t.dev_handle
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_ControlTransfer_new_args
|
78
|
+
t = LIBUSB::ControlTransfer.new allow_device_memory: false, timeout: 444
|
79
|
+
assert_equal false, t.allow_device_memory
|
80
|
+
assert_equal 444, t.timeout
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_Transfer_no_dev_handle
|
84
|
+
t = LIBUSB::ControlTransfer.new
|
85
|
+
assert_raises(ArgumentError){ t.submit_and_wait }
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
#
|
16
|
+
# This test requires two connected, but not mounted mass storage device with
|
17
|
+
# read/write access allowed.
|
18
|
+
|
19
|
+
require "minitest/autorun"
|
20
|
+
require "libusb"
|
21
|
+
|
22
|
+
class TestLibusbThreads < Minitest::Test
|
23
|
+
include LIBUSB
|
24
|
+
|
25
|
+
BOMS_GET_MAX_LUN = 0xFE
|
26
|
+
|
27
|
+
attr_accessor :usb
|
28
|
+
attr_accessor :devices
|
29
|
+
attr_accessor :devs
|
30
|
+
attr_accessor :endpoints_in
|
31
|
+
attr_accessor :endpoints_out
|
32
|
+
|
33
|
+
def setup
|
34
|
+
@usb = Context.new
|
35
|
+
@usb.debug = 3
|
36
|
+
|
37
|
+
@devices = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 )
|
38
|
+
skip "less than two mass storage devices found" unless @devices.length >= 2
|
39
|
+
|
40
|
+
@devs = @devices.map do |device|
|
41
|
+
dev = device.open
|
42
|
+
if RUBY_PLATFORM=~/linux/i && dev.kernel_driver_active?(0)
|
43
|
+
dev.detach_kernel_driver(0)
|
44
|
+
end
|
45
|
+
dev.claim_interface(0)
|
46
|
+
dev
|
47
|
+
end
|
48
|
+
|
49
|
+
@endpoints_in = {}
|
50
|
+
@endpoints_out = {}
|
51
|
+
|
52
|
+
@devs.each do |dev|
|
53
|
+
@endpoints_in[dev] = dev.device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
|
54
|
+
@endpoints_out[dev] = dev.device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN == 0 }
|
55
|
+
end
|
56
|
+
|
57
|
+
Thread.abort_on_exception = true
|
58
|
+
end
|
59
|
+
|
60
|
+
def teardown
|
61
|
+
if devs
|
62
|
+
devs.each do |dev|
|
63
|
+
dev.release_interface(0)
|
64
|
+
dev.close
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def thread_worker(dev)
|
70
|
+
endpoint = endpoints_in[dev]
|
71
|
+
1.times do
|
72
|
+
st = Time.now
|
73
|
+
assert_raises LIBUSB::ERROR_TIMEOUT do
|
74
|
+
dev.bulk_transfer(endpoint: endpoint, dataIn: 123, timeout: 100)
|
75
|
+
end
|
76
|
+
assert_operator Time.now-st, :<, 5
|
77
|
+
dev.clear_halt(endpoint)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_sync_api
|
82
|
+
threads = devs.map do |dev|
|
83
|
+
Thread.new do
|
84
|
+
thread_worker(dev)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
threads.map(&:join)
|
88
|
+
end
|
89
|
+
end
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: libusb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
|
+
platform: x64-mingw-ucrt
|
6
|
+
authors:
|
7
|
+
- Lars Kanis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-04-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
description: LIBUSB is a Ruby binding that gives Ruby programmers access to arbitrary
|
28
|
+
USB devices
|
29
|
+
email:
|
30
|
+
- lars@greiz-reinsdorf.de
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".appveyor.yml"
|
36
|
+
- ".github/workflows/ci.yml"
|
37
|
+
- ".gitignore"
|
38
|
+
- ".travis.yml"
|
39
|
+
- ".yardopts"
|
40
|
+
- COPYING
|
41
|
+
- Gemfile
|
42
|
+
- History.md
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- lib/libusb-1.0.dll
|
46
|
+
- lib/libusb.rb
|
47
|
+
- lib/libusb/bos.rb
|
48
|
+
- lib/libusb/call.rb
|
49
|
+
- lib/libusb/compat.rb
|
50
|
+
- lib/libusb/configuration.rb
|
51
|
+
- lib/libusb/constants.rb
|
52
|
+
- lib/libusb/context.rb
|
53
|
+
- lib/libusb/context_reference.rb
|
54
|
+
- lib/libusb/dependencies.rb
|
55
|
+
- lib/libusb/dev_handle.rb
|
56
|
+
- lib/libusb/device.rb
|
57
|
+
- lib/libusb/endpoint.rb
|
58
|
+
- lib/libusb/eventmachine.rb
|
59
|
+
- lib/libusb/gem_helper.rb
|
60
|
+
- lib/libusb/interface.rb
|
61
|
+
- lib/libusb/libusb_recipe.rb
|
62
|
+
- lib/libusb/setting.rb
|
63
|
+
- lib/libusb/ss_companion.rb
|
64
|
+
- lib/libusb/stdio.rb
|
65
|
+
- lib/libusb/transfer.rb
|
66
|
+
- lib/libusb/version_gem.rb
|
67
|
+
- lib/libusb/version_struct.rb
|
68
|
+
- libusb.gemspec
|
69
|
+
- test/test_libusb.rb
|
70
|
+
- test/test_libusb_bos.rb
|
71
|
+
- test/test_libusb_bulk_stream_transfer.rb
|
72
|
+
- test/test_libusb_compat.rb
|
73
|
+
- test/test_libusb_compat_mass_storage.rb
|
74
|
+
- test/test_libusb_context.rb
|
75
|
+
- test/test_libusb_descriptors.rb
|
76
|
+
- test/test_libusb_event_machine.rb
|
77
|
+
- test/test_libusb_gc.rb
|
78
|
+
- test/test_libusb_hotplug.rb
|
79
|
+
- test/test_libusb_iso_transfer.rb
|
80
|
+
- test/test_libusb_mass_storage.rb
|
81
|
+
- test/test_libusb_mass_storage2.rb
|
82
|
+
- test/test_libusb_structs.rb
|
83
|
+
- test/test_libusb_threads.rb
|
84
|
+
- wireshark-usb-sniffer.png
|
85
|
+
homepage: http://github.com/larskanis/libusb
|
86
|
+
licenses:
|
87
|
+
- LGPL-3.0
|
88
|
+
metadata:
|
89
|
+
yard.run: yri
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options:
|
92
|
+
- "--main"
|
93
|
+
- README.md
|
94
|
+
- "--charset=UTF-8"
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.5.0
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubygems_version: 3.3.26
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: Access USB devices from Ruby via libusb-1.0
|
112
|
+
test_files: []
|