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,245 @@
|
|
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 TestLibusbDescriptors < Minitest::Test
|
20
|
+
include LIBUSB
|
21
|
+
|
22
|
+
attr_accessor :usb
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@usb = Context.new
|
26
|
+
@usb.debug = 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_descriptors
|
30
|
+
usb.devices.each do |dev|
|
31
|
+
assert_match(/Device/, dev.inspect, "Device#inspect should work")
|
32
|
+
|
33
|
+
assert_kind_of Integer, dev.bLength
|
34
|
+
assert_equal 1, dev.bDescriptorType
|
35
|
+
assert_kind_of Integer, dev.bcdUSB
|
36
|
+
assert_kind_of Integer, dev.bDeviceClass
|
37
|
+
assert_kind_of Integer, dev.bDeviceSubClass
|
38
|
+
assert_kind_of Integer, dev.bDeviceProtocol
|
39
|
+
assert_kind_of Integer, dev.bMaxPacketSize0
|
40
|
+
assert_kind_of Integer, dev.idVendor
|
41
|
+
assert_kind_of Integer, dev.idProduct
|
42
|
+
assert_kind_of Integer, dev.bcdDevice
|
43
|
+
assert_kind_of Integer, dev.iManufacturer
|
44
|
+
assert_kind_of Integer, dev.iProduct
|
45
|
+
assert_kind_of Integer, dev.iSerialNumber
|
46
|
+
assert_kind_of Integer, dev.bNumConfigurations
|
47
|
+
|
48
|
+
dev.configurations.each do |config_desc|
|
49
|
+
assert_match(/Configuration/, config_desc.inspect, "ConfigDescriptor#inspect should work")
|
50
|
+
assert dev.configurations.include?(config_desc), "Device#configurations should include this one"
|
51
|
+
|
52
|
+
assert_kind_of Integer, config_desc.bLength
|
53
|
+
assert_equal 2, config_desc.bDescriptorType
|
54
|
+
assert_kind_of Integer, config_desc.wTotalLength
|
55
|
+
assert_equal config_desc.interfaces.length, config_desc.bNumInterfaces
|
56
|
+
assert_kind_of Integer, config_desc.bConfigurationValue
|
57
|
+
assert_kind_of Integer, config_desc.iConfiguration
|
58
|
+
assert_kind_of Integer, config_desc.bmAttributes
|
59
|
+
assert_kind_of Integer, config_desc.bMaxPower
|
60
|
+
assert_kind_of Integer, config_desc.maxPower # deprecated
|
61
|
+
assert_kind_of String, config_desc.extra if config_desc.extra
|
62
|
+
|
63
|
+
config_desc.interfaces.each do |interface|
|
64
|
+
assert_match(/Interface/, interface.inspect, "Interface#inspect should work")
|
65
|
+
|
66
|
+
assert dev.interfaces.include?(interface), "Device#interfaces should include this one"
|
67
|
+
assert config_desc.interfaces.include?(interface), "ConfigDescriptor#interfaces should include this one"
|
68
|
+
|
69
|
+
interface.alt_settings.each do |if_desc|
|
70
|
+
assert_match(/Setting/, if_desc.inspect, "InterfaceDescriptor#inspect should work")
|
71
|
+
|
72
|
+
assert dev.settings.include?(if_desc), "Device#settings should include this one"
|
73
|
+
assert config_desc.settings.include?(if_desc), "ConfigDescriptor#settings should include this one"
|
74
|
+
assert interface.alt_settings.include?(if_desc), "Inteerface#alt_settings should include this one"
|
75
|
+
|
76
|
+
assert_kind_of Integer, if_desc.bLength
|
77
|
+
assert_equal 4, if_desc.bDescriptorType
|
78
|
+
assert_kind_of Integer, if_desc.bInterfaceNumber
|
79
|
+
assert_kind_of Integer, if_desc.bAlternateSetting
|
80
|
+
assert_equal if_desc.endpoints.length, if_desc.bNumEndpoints
|
81
|
+
assert_kind_of Integer, if_desc.bInterfaceClass
|
82
|
+
assert_kind_of Integer, if_desc.bInterfaceSubClass
|
83
|
+
assert_kind_of Integer, if_desc.bInterfaceProtocol
|
84
|
+
assert_kind_of Integer, if_desc.iInterface
|
85
|
+
assert_kind_of String, if_desc.extra if if_desc.extra
|
86
|
+
|
87
|
+
if_desc.endpoints.each do |ep|
|
88
|
+
assert_match(/Endpoint/, ep.inspect, "EndpointDescriptor#inspect should work")
|
89
|
+
|
90
|
+
assert dev.endpoints.include?(ep), "Device#endpoints should include this one"
|
91
|
+
assert config_desc.endpoints.include?(ep), "ConfigDescriptor#endpoints should include this one"
|
92
|
+
assert interface.endpoints.include?(ep), "Inteerface#endpoints should include this one"
|
93
|
+
assert if_desc.endpoints.include?(ep), "InterfaceDescriptor#endpoints should include this one"
|
94
|
+
|
95
|
+
assert_equal if_desc, ep.setting, "backref should be correct"
|
96
|
+
assert_equal interface, ep.interface, "backref should be correct"
|
97
|
+
assert_equal config_desc, ep.configuration, "backref should be correct"
|
98
|
+
assert_equal dev, ep.device, "backref should be correct"
|
99
|
+
|
100
|
+
assert_kind_of Integer, ep.bLength
|
101
|
+
assert_equal 5, ep.bDescriptorType
|
102
|
+
assert_kind_of Integer, ep.bEndpointAddress
|
103
|
+
assert_kind_of Integer, ep.bmAttributes
|
104
|
+
assert_operator 0, :<=, ep.wMaxPacketSize, "packet size should be > 0"
|
105
|
+
assert_kind_of Integer, ep.bInterval
|
106
|
+
assert_kind_of Integer, ep.bRefresh
|
107
|
+
assert_kind_of Integer, ep.bSynchAddress
|
108
|
+
assert_kind_of String, ep.extra if ep.extra
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_ss_companion
|
117
|
+
did_cc_companion = false
|
118
|
+
did_failing_cc_companion = false
|
119
|
+
|
120
|
+
usb.devices.each do |dev|
|
121
|
+
dev.endpoints.each do |ep|
|
122
|
+
if [:SPEED_SUPER, :SPEED_SUPER_PLUS].include?(dev.device_speed)
|
123
|
+
ss = ep.ss_companion
|
124
|
+
assert_match(/SsCompanion/, ss.inspect, "SsCompanion#inspect should work")
|
125
|
+
|
126
|
+
assert_kind_of Integer, ss.bLength
|
127
|
+
assert_equal LIBUSB::DT_SS_ENDPOINT_COMPANION, ss.bDescriptorType
|
128
|
+
assert_kind_of Integer, ss.bMaxBurst
|
129
|
+
assert_kind_of Integer, ss.bmAttributes
|
130
|
+
assert_kind_of Integer, ss.wBytesPerInterval
|
131
|
+
did_cc_companion = true
|
132
|
+
elsif !did_failing_cc_companion
|
133
|
+
assert_raises ERROR_NOT_FOUND do
|
134
|
+
ep.ss_companion
|
135
|
+
end
|
136
|
+
did_failing_cc_companion = true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
skip "no device with cc_companion available" unless did_cc_companion
|
142
|
+
skip "no device without cc_companion available" unless did_failing_cc_companion
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_constants
|
146
|
+
assert_equal 7, CLASS_PRINTER, "Printer class id should be defined"
|
147
|
+
assert_equal 48, ISO_USAGE_TYPE_MASK, "iso usage type should be defined"
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_device_filter_mass_storages
|
151
|
+
devs1 = []
|
152
|
+
usb.devices.each do |dev|
|
153
|
+
dev.settings.each do |if_desc|
|
154
|
+
if if_desc.bInterfaceClass == CLASS_MASS_STORAGE &&
|
155
|
+
( if_desc.bInterfaceSubClass == 0x01 ||
|
156
|
+
if_desc.bInterfaceSubClass == 0x06 ) &&
|
157
|
+
if_desc.bInterfaceProtocol == 0x50
|
158
|
+
|
159
|
+
devs1 << dev
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
devs2 = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: 0x01, bProtocol: 0x50 )
|
165
|
+
devs2 += usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: 0x06, bProtocol: 0x50 )
|
166
|
+
assert_equal devs1.sort, devs2.sort, "devices and devices with filter should deliver the same device"
|
167
|
+
|
168
|
+
devs3 = usb.devices( bClass: [CLASS_MASS_STORAGE], bSubClass: [0x01,0x06], bProtocol: [0x50] )
|
169
|
+
assert_equal devs1.sort, devs3.sort, "devices and devices with array-filter should deliver the same device"
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_device_filter_hubs
|
173
|
+
devs1 = []
|
174
|
+
usb.devices.each do |dev|
|
175
|
+
if dev.bDeviceClass==CLASS_PER_INTERFACE
|
176
|
+
dev.settings.each do |if_desc|
|
177
|
+
if if_desc.bInterfaceClass==CLASS_HUB
|
178
|
+
devs1 << dev
|
179
|
+
end
|
180
|
+
end
|
181
|
+
else
|
182
|
+
devs1 << dev if dev.bDeviceClass == CLASS_HUB
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
devs2 = usb.devices( bClass: CLASS_HUB )
|
187
|
+
|
188
|
+
assert_equal devs1.sort, devs2.sort, "devices and devices with filter should deliver the same device"
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_device_methods
|
192
|
+
usb.devices.each do |dev|
|
193
|
+
ep = dev.endpoints.first
|
194
|
+
if ep
|
195
|
+
assert_operator dev.max_packet_size(ep), :>, 0, "#{dev.inspect} should have a usable packet size"
|
196
|
+
assert_operator dev.max_packet_size(ep.bEndpointAddress), :>, 0, "#{dev.inspect} should have a usable packet size"
|
197
|
+
assert_operator dev.max_iso_packet_size(ep), :>=, 0, "#{dev.inspect} should have a usable iso packet size"
|
198
|
+
assert_operator dev.max_iso_packet_size(ep.bEndpointAddress), :>=, 0, "#{dev.inspect} should have a usable iso packet size"
|
199
|
+
assert_operator dev.bus_number, :>=, 0, "#{dev.inspect} should have a bus_number"
|
200
|
+
assert_operator dev.device_address, :>=, 0, "#{dev.inspect} should have a device_address"
|
201
|
+
assert_operator([:SPEED_UNKNOWN, :SPEED_LOW, :SPEED_FULL, :SPEED_HIGH, :SPEED_SUPER, :SPEED_SUPER_PLUS], :include?, dev.device_speed, "#{dev.inspect} should have a device_speed")
|
202
|
+
path = dev.port_numbers
|
203
|
+
assert_kind_of Array, path, "#{dev.inspect} should have port_numbers"
|
204
|
+
path = dev.port_path
|
205
|
+
assert_kind_of Array, path, "#{dev.inspect} should have a port_path"
|
206
|
+
path.each do |port|
|
207
|
+
assert_operator port, :>, 0, "#{dev.inspect} should have proper port_path entries"
|
208
|
+
end
|
209
|
+
if path.empty?
|
210
|
+
assert_nil dev.port_number
|
211
|
+
else
|
212
|
+
assert_equal path[-1], dev.port_number, "#{dev.inspect} should have a port number out of the port_path"
|
213
|
+
if parent=dev.parent
|
214
|
+
assert_kind_of Device, parent, "#{dev.inspect} should have a parent"
|
215
|
+
assert_equal path[-2], parent.port_number, "#{dev.inspect} should have a parent port number out of the port_path" if parent.port_number
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_wrap_sys_device
|
223
|
+
skip unless RUBY_PLATFORM =~ /linux/
|
224
|
+
d = usb.devices[0]
|
225
|
+
File.open(format("/dev/bus/usb/%03d/%03d", d.bus_number, d.device_address), "w+") do |io|
|
226
|
+
devh = usb.wrap_sys_device(io)
|
227
|
+
devh.kernel_driver_active?(0)
|
228
|
+
devh.close
|
229
|
+
|
230
|
+
usb.wrap_sys_device(io) do |devh|
|
231
|
+
devh.kernel_driver_active?(0)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_wrap_sys_device_failure
|
237
|
+
skip unless RUBY_PLATFORM =~ /linux/
|
238
|
+
d = usb.devices[0]
|
239
|
+
assert_raises(LIBUSB::ERROR_OTHER) do
|
240
|
+
File.open(format("/dev/bus/usb/%03d/%03d", d.bus_number, d.device_address), "r") do |io|
|
241
|
+
usb.wrap_sys_device(io).kernel_driver_active?(0)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
@@ -0,0 +1,118 @@
|
|
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
|
+
require "libusb/eventmachine"
|
19
|
+
require "eventmachine"
|
20
|
+
|
21
|
+
class TestLibusbEventMachine < Minitest::Test
|
22
|
+
include LIBUSB
|
23
|
+
BOMS_GET_MAX_LUN = 0xFE
|
24
|
+
|
25
|
+
attr_accessor :context
|
26
|
+
attr_accessor :device
|
27
|
+
attr_accessor :devh
|
28
|
+
attr_accessor :endpoint_in
|
29
|
+
attr_accessor :endpoint_out
|
30
|
+
|
31
|
+
def setup
|
32
|
+
@context = Context.new
|
33
|
+
@context.debug = 3
|
34
|
+
|
35
|
+
@device = context.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 ).last
|
36
|
+
skip "no mass storage device found" unless @device
|
37
|
+
|
38
|
+
@endpoint_in = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
|
39
|
+
@endpoint_out = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN == 0 }
|
40
|
+
@devh = @device.open
|
41
|
+
|
42
|
+
if RUBY_PLATFORM=~/linux/i && devh.kernel_driver_active?(0)
|
43
|
+
devh.detach_kernel_driver(0)
|
44
|
+
end
|
45
|
+
devh.claim_interface(0)
|
46
|
+
|
47
|
+
# clear any pending data
|
48
|
+
devh.clear_halt(endpoint_in)
|
49
|
+
end
|
50
|
+
|
51
|
+
def teardown
|
52
|
+
end
|
53
|
+
|
54
|
+
def em_run
|
55
|
+
EventMachine.run do
|
56
|
+
@context.eventmachine_register
|
57
|
+
|
58
|
+
EventMachine.add_shutdown_hook do
|
59
|
+
@devh.release_interface(0) if @devh
|
60
|
+
@devh.close if @devh
|
61
|
+
@context.eventmachine_unregister
|
62
|
+
end
|
63
|
+
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def test_bulk_transfer
|
70
|
+
em_run do
|
71
|
+
ticks = 0
|
72
|
+
tr = devh.eventmachine_bulk_transfer(
|
73
|
+
endpoint: @endpoint_in,
|
74
|
+
timeout: 1500,
|
75
|
+
dataIn: 123 )
|
76
|
+
# puts "started usb transfer #{tr}"
|
77
|
+
|
78
|
+
tr.callback do |data|
|
79
|
+
# puts "recved: #{data.inspect}"
|
80
|
+
|
81
|
+
assert false, "the bulk transfer shouldn't succeed"
|
82
|
+
EventMachine.stop
|
83
|
+
end
|
84
|
+
tr.errback do |text|
|
85
|
+
# puts "recv-err: #{text}"
|
86
|
+
assert true, "the bulk transfer should fail"
|
87
|
+
|
88
|
+
assert_operator ticks, :>=, 4
|
89
|
+
EventMachine.stop
|
90
|
+
end
|
91
|
+
|
92
|
+
EventMachine.add_periodic_timer(0.333) do
|
93
|
+
ticks += 1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_event_loop
|
99
|
+
em_run do
|
100
|
+
tr = devh.eventmachine_control_transfer(
|
101
|
+
bmRequestType: ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
102
|
+
bRequest: BOMS_GET_MAX_LUN,
|
103
|
+
wValue: 0, wIndex: 0, dataIn: 1 )
|
104
|
+
|
105
|
+
# puts "started usb transfer #{tr}"
|
106
|
+
tr.callback do |data|
|
107
|
+
# puts "recved: #{data.inspect}"
|
108
|
+
assert true, "the control transfer should succeed"
|
109
|
+
EventMachine.stop
|
110
|
+
end
|
111
|
+
tr.errback do |text|
|
112
|
+
# puts "recv-err: #{text}"
|
113
|
+
assert false, "the control transfer shouldn't fail"
|
114
|
+
EventMachine.stop
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,52 @@
|
|
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
|
+
# These tests should be started with valgrind to check for
|
17
|
+
# invalid memmory access.
|
18
|
+
|
19
|
+
require "minitest/autorun"
|
20
|
+
require "libusb"
|
21
|
+
|
22
|
+
class TestLibusbGc < Minitest::Test
|
23
|
+
include LIBUSB
|
24
|
+
|
25
|
+
def get_some_endpoint
|
26
|
+
Context.new.devices.each do |dev|
|
27
|
+
return dev.endpoints.last unless dev.endpoints.empty?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_descriptors
|
32
|
+
ep = get_some_endpoint
|
33
|
+
ps = ep.wMaxPacketSize
|
34
|
+
GC.start
|
35
|
+
assert_equal ps, ep.wMaxPacketSize, "GC should not free EndpointDescriptor"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_log_cb
|
39
|
+
LIBUSB.set_options OPTION_LOG_CB: proc{}, OPTION_LOG_LEVEL: LIBUSB::LOG_LEVEL_DEBUG
|
40
|
+
|
41
|
+
c = LIBUSB::Context.new OPTION_LOG_CB: proc{}, OPTION_NO_DEVICE_DISCOVERY: nil
|
42
|
+
GC.start
|
43
|
+
c.devices
|
44
|
+
c.set_log_cb(LIBUSB::LOG_CB_CONTEXT){}
|
45
|
+
c.devices
|
46
|
+
GC.start
|
47
|
+
c.devices
|
48
|
+
|
49
|
+
ensure
|
50
|
+
LIBUSB.set_options OPTION_LOG_CB: [nil], OPTION_LOG_LEVEL: LIBUSB::LOG_LEVEL_NONE
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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 TestLibusbHotplug < Minitest::Test
|
20
|
+
include LIBUSB
|
21
|
+
|
22
|
+
attr_reader :ctx
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@ctx = Context.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def teardown
|
29
|
+
# No need to release the LIBUSB::Context any longer.
|
30
|
+
# It is cleaned up by the GC.
|
31
|
+
# @ctx.exit
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_enumerate
|
35
|
+
devs = []
|
36
|
+
ctx.on_hotplug_event flags: HOTPLUG_ENUMERATE do |dev, event|
|
37
|
+
devs << dev
|
38
|
+
assert_equal :HOTPLUG_EVENT_DEVICE_ARRIVED, event
|
39
|
+
:repeat
|
40
|
+
end
|
41
|
+
# Not really necessary, but just to be sure that the callback was called:
|
42
|
+
ctx.handle_events 0
|
43
|
+
|
44
|
+
assert_equal ctx.devices.sort, devs.sort
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_enumerate_with_left
|
48
|
+
devs = []
|
49
|
+
ctx.on_hotplug_event flags: HOTPLUG_ENUMERATE, events: HOTPLUG_EVENT_DEVICE_LEFT do |dev, event|
|
50
|
+
devs << dev
|
51
|
+
assert_equal :HOTPLUG_EVENT_DEVICE_ARRIVED, event
|
52
|
+
:repeat
|
53
|
+
end
|
54
|
+
# Not really necessary, but just to be sure that the callback was called:
|
55
|
+
ctx.handle_events 0
|
56
|
+
|
57
|
+
assert_equal [], devs.sort, "Enumerate should not send any LEFT events"
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_deregister
|
61
|
+
handle1 = ctx.on_hotplug_event{ assert false, "Callback should not be called" }
|
62
|
+
handle2 = ctx.on_hotplug_event{ assert false, "Callback should not be called" }
|
63
|
+
handle1.deregister
|
64
|
+
handle2.deregister
|
65
|
+
ctx.handle_events 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_wrong_yieldreturn
|
69
|
+
ex = assert_raises(ArgumentError) do
|
70
|
+
ctx.on_hotplug_event flags: :HOTPLUG_ENUMERATE do |dev, event|
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_match(/:finish.*:repeat/, ex.to_s, "Should give a useful hint")
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_context
|
78
|
+
handle = ctx.on_hotplug_event do |dev, event|
|
79
|
+
end
|
80
|
+
assert_equal ctx, handle.context, "The callback handle should have it's context"
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_real_device_plugging_and_yieldreturn_and_gc_and_deregister
|
84
|
+
# This callback should be triggered once
|
85
|
+
devs = []
|
86
|
+
ctx.on_hotplug_event do |dev, event|
|
87
|
+
devs << [dev, event]
|
88
|
+
:finish
|
89
|
+
end
|
90
|
+
|
91
|
+
# This callback should be triggered twice
|
92
|
+
devs2 = []
|
93
|
+
ctx.on_hotplug_event do |dev, event|
|
94
|
+
devs2 << [dev, event]
|
95
|
+
puts format(" %p: %p", event, dev)
|
96
|
+
:repeat
|
97
|
+
end
|
98
|
+
|
99
|
+
# This callback should never be triggered
|
100
|
+
handle = ctx.on_hotplug_event{ assert false, "Deregistered callback should never be called" }
|
101
|
+
|
102
|
+
# GC shouldn't free any relevant callbacks or blocks
|
103
|
+
GC.start
|
104
|
+
|
105
|
+
print "\nPlease add and remove an USB device (2*5 sec): "
|
106
|
+
handle.deregister
|
107
|
+
ctx.handle_events 0
|
108
|
+
ctx.handle_events 5000
|
109
|
+
ctx.handle_events 5000
|
110
|
+
|
111
|
+
skip "no hotplug action taken" if devs.empty? && devs2.empty?
|
112
|
+
assert_equal 1, devs.length, "Should be deregistered after the first event"
|
113
|
+
assert_equal 2, devs2.length, "Should have received two events"
|
114
|
+
assert_operator devs2.map(&:last), :include?, :HOTPLUG_EVENT_DEVICE_ARRIVED, "Should have received ARRIVED"
|
115
|
+
assert_operator devs2.map(&:last), :include?, :HOTPLUG_EVENT_DEVICE_LEFT, "Should have received LEFT"
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_interrupt_event_handler
|
119
|
+
th = Thread.new do
|
120
|
+
ctx.handle_events 5000
|
121
|
+
end
|
122
|
+
|
123
|
+
sleep 0.1 # Workaround a bug in libusb-1,0.21
|
124
|
+
st = Time.now
|
125
|
+
ctx.interrupt_event_handler
|
126
|
+
th.join
|
127
|
+
assert_operator Time.now-st, :<, 5.0
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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 TestLibusbIsoTransfer < Minitest::Test
|
20
|
+
include LIBUSB
|
21
|
+
|
22
|
+
def setup
|
23
|
+
c = Context.new
|
24
|
+
begin
|
25
|
+
@dev = c.devices.first.open
|
26
|
+
rescue LIBUSB::ERROR_ACCESS
|
27
|
+
@dev = nil
|
28
|
+
skip "error opening device"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown
|
33
|
+
@dev.close if @dev
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_iso_transfer
|
37
|
+
tr = IsochronousTransfer.new 10, dev_handle: @dev
|
38
|
+
assert_equal 10, tr.num_packets, "number of packets should match"
|
39
|
+
|
40
|
+
tr.buffer = " "*130
|
41
|
+
tr.packet_lengths = 13
|
42
|
+
tr[7].length = 12
|
43
|
+
assert_equal 12, tr[7].length, "packet length should be set"
|
44
|
+
assert_equal 13, tr[8].length, "packet length should be set"
|
45
|
+
|
46
|
+
assert_raises(LIBUSB::ERROR_IO, "the randomly choosen device will probably not handle iso transfer") do
|
47
|
+
tr.submit!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_max_alt_packet_size
|
52
|
+
d = Context.new.devices[0]
|
53
|
+
size = d.max_alt_packet_size d.interfaces[0], d.settings[0], d.endpoints[0]
|
54
|
+
assert_operator 0, :<=, size
|
55
|
+
end
|
56
|
+
end
|