libusb 0.7.0-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.appveyor.yml +33 -0
  3. data/.github/workflows/ci.yml +185 -0
  4. data/.gitignore +9 -0
  5. data/.travis.yml +26 -0
  6. data/.yardopts +6 -0
  7. data/COPYING +165 -0
  8. data/Gemfile +19 -0
  9. data/History.md +193 -0
  10. data/README.md +184 -0
  11. data/Rakefile +79 -0
  12. data/lib/libusb/bos.rb +362 -0
  13. data/lib/libusb/call.rb +622 -0
  14. data/lib/libusb/compat.rb +376 -0
  15. data/lib/libusb/configuration.rb +154 -0
  16. data/lib/libusb/constants.rb +170 -0
  17. data/lib/libusb/context.rb +576 -0
  18. data/lib/libusb/context_reference.rb +38 -0
  19. data/lib/libusb/dependencies.rb +7 -0
  20. data/lib/libusb/dev_handle.rb +574 -0
  21. data/lib/libusb/device.rb +407 -0
  22. data/lib/libusb/endpoint.rb +195 -0
  23. data/lib/libusb/eventmachine.rb +187 -0
  24. data/lib/libusb/gem_helper.rb +151 -0
  25. data/lib/libusb/interface.rb +60 -0
  26. data/lib/libusb/libusb_recipe.rb +29 -0
  27. data/lib/libusb/setting.rb +132 -0
  28. data/lib/libusb/ss_companion.rb +72 -0
  29. data/lib/libusb/stdio.rb +25 -0
  30. data/lib/libusb/transfer.rb +418 -0
  31. data/lib/libusb/version_gem.rb +19 -0
  32. data/lib/libusb/version_struct.rb +63 -0
  33. data/lib/libusb-1.0.dll +0 -0
  34. data/lib/libusb.rb +146 -0
  35. data/libusb.gemspec +28 -0
  36. data/test/test_libusb.rb +42 -0
  37. data/test/test_libusb_bos.rb +140 -0
  38. data/test/test_libusb_bulk_stream_transfer.rb +61 -0
  39. data/test/test_libusb_compat.rb +78 -0
  40. data/test/test_libusb_compat_mass_storage.rb +81 -0
  41. data/test/test_libusb_context.rb +88 -0
  42. data/test/test_libusb_descriptors.rb +245 -0
  43. data/test/test_libusb_event_machine.rb +118 -0
  44. data/test/test_libusb_gc.rb +52 -0
  45. data/test/test_libusb_hotplug.rb +129 -0
  46. data/test/test_libusb_iso_transfer.rb +56 -0
  47. data/test/test_libusb_mass_storage.rb +268 -0
  48. data/test/test_libusb_mass_storage2.rb +96 -0
  49. data/test/test_libusb_structs.rb +87 -0
  50. data/test/test_libusb_threads.rb +89 -0
  51. data/wireshark-usb-sniffer.png +0 -0
  52. 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