libusb 0.6.0-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +17 -0
  4. data/.yardopts +6 -0
  5. data/COPYING +165 -0
  6. data/Gemfile +11 -0
  7. data/History.md +124 -0
  8. data/README.md +159 -0
  9. data/Rakefile +145 -0
  10. data/appveyor.yml +23 -0
  11. data/lib/libusb.rb +58 -0
  12. data/lib/libusb/bos.rb +306 -0
  13. data/lib/libusb/call.rb +446 -0
  14. data/lib/libusb/compat.rb +376 -0
  15. data/lib/libusb/configuration.rb +155 -0
  16. data/lib/libusb/constants.rb +160 -0
  17. data/lib/libusb/context.rb +426 -0
  18. data/lib/libusb/dependencies.rb +7 -0
  19. data/lib/libusb/dev_handle.rb +564 -0
  20. data/lib/libusb/device.rb +365 -0
  21. data/lib/libusb/endpoint.rb +194 -0
  22. data/lib/libusb/eventmachine.rb +183 -0
  23. data/lib/libusb/interface.rb +60 -0
  24. data/lib/libusb/setting.rb +132 -0
  25. data/lib/libusb/ss_companion.rb +69 -0
  26. data/lib/libusb/stdio.rb +25 -0
  27. data/lib/libusb/transfer.rb +377 -0
  28. data/lib/libusb/version_gem.rb +19 -0
  29. data/lib/libusb/version_struct.rb +63 -0
  30. data/libusb.gemspec +30 -0
  31. data/test/test_libusb_bos.rb +118 -0
  32. data/test/test_libusb_bulk_stream_transfer.rb +50 -0
  33. data/test/test_libusb_capability.rb +23 -0
  34. data/test/test_libusb_compat.rb +78 -0
  35. data/test/test_libusb_compat_mass_storage.rb +81 -0
  36. data/test/test_libusb_descriptors.rb +212 -0
  37. data/test/test_libusb_event_machine.rb +118 -0
  38. data/test/test_libusb_gc.rb +37 -0
  39. data/test/test_libusb_hotplug.rb +127 -0
  40. data/test/test_libusb_iso_transfer.rb +50 -0
  41. data/test/test_libusb_mass_storage.rb +268 -0
  42. data/test/test_libusb_mass_storage2.rb +96 -0
  43. data/test/test_libusb_structs.rb +58 -0
  44. data/test/test_libusb_threads.rb +89 -0
  45. data/test/test_libusb_version.rb +40 -0
  46. data/wireshark-usb-sniffer.png +0 -0
  47. metadata +150 -0
@@ -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,37 @@
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
+ end
@@ -0,0 +1,127 @@
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
+ @ctx.exit
30
+ end
31
+
32
+ def test_enumerate
33
+ devs = []
34
+ ctx.on_hotplug_event flags: HOTPLUG_ENUMERATE do |dev, event|
35
+ devs << dev
36
+ assert_equal :HOTPLUG_EVENT_DEVICE_ARRIVED, event
37
+ :repeat
38
+ end
39
+ # Not really necessary, but just to be sure that the callback was called:
40
+ ctx.handle_events 0
41
+
42
+ assert_equal ctx.devices.sort, devs.sort
43
+ end
44
+
45
+ def test_enumerate_with_left
46
+ devs = []
47
+ ctx.on_hotplug_event flags: HOTPLUG_ENUMERATE, events: HOTPLUG_EVENT_DEVICE_LEFT do |dev, event|
48
+ devs << dev
49
+ assert_equal :HOTPLUG_EVENT_DEVICE_ARRIVED, event
50
+ :repeat
51
+ end
52
+ # Not really necessary, but just to be sure that the callback was called:
53
+ ctx.handle_events 0
54
+
55
+ assert_equal [], devs.sort, "Enumerate should not send any LEFT events"
56
+ end
57
+
58
+ def test_deregister
59
+ handle1 = ctx.on_hotplug_event{ assert false, "Callback should not be called" }
60
+ handle2 = ctx.on_hotplug_event{ assert false, "Callback should not be called" }
61
+ handle1.deregister
62
+ handle2.deregister
63
+ ctx.handle_events 0
64
+ end
65
+
66
+ def test_wrong_yieldreturn
67
+ ex = assert_raises(ArgumentError) do
68
+ ctx.on_hotplug_event flags: :HOTPLUG_ENUMERATE do |dev, event|
69
+ end
70
+ end
71
+
72
+ assert_match(/:finish.*:repeat/, ex.to_s, "Should give a useful hint")
73
+ end
74
+
75
+ def test_context
76
+ handle = ctx.on_hotplug_event do |dev, event|
77
+ end
78
+ assert_equal ctx, handle.context, "The callback handle should have it's context"
79
+ end
80
+
81
+ def test_real_device_plugging_and_yieldreturn_and_gc_and_deregister
82
+ # This callback should be triggered once
83
+ devs = []
84
+ ctx.on_hotplug_event do |dev, event|
85
+ devs << [dev, event]
86
+ :finish
87
+ end
88
+
89
+ # This callback should be triggered twice
90
+ devs2 = []
91
+ ctx.on_hotplug_event do |dev, event|
92
+ devs2 << [dev, event]
93
+ puts format(" %p: %p", event, dev)
94
+ :repeat
95
+ end
96
+
97
+ # This callback should never be triggered
98
+ handle = ctx.on_hotplug_event{ assert false, "Deregistered callback should never be called" }
99
+
100
+ # GC shouldn't free any relevant callbacks or blocks
101
+ GC.start
102
+
103
+ print "\nPlease add and remove an USB device (2*5 sec): "
104
+ handle.deregister
105
+ ctx.handle_events 0
106
+ ctx.handle_events 5000
107
+ ctx.handle_events 5000
108
+
109
+ skip "no hotplug action taken" if devs.empty? && devs2.empty?
110
+ assert_equal 1, devs.length, "Should be deregistered after the first event"
111
+ assert_equal 2, devs2.length, "Should have received two events"
112
+ assert_operator devs2.map(&:last), :include?, :HOTPLUG_EVENT_DEVICE_ARRIVED, "Should have received ARRIVED"
113
+ assert_operator devs2.map(&:last), :include?, :HOTPLUG_EVENT_DEVICE_LEFT, "Should have received LEFT"
114
+ end
115
+
116
+ def test_interrupt_event_handler
117
+ th = Thread.new do
118
+ ctx.handle_events 5000
119
+ end
120
+
121
+ sleep 0.1 # Workaround a bug in libusb-1,0.21
122
+ st = Time.now
123
+ ctx.interrupt_event_handler
124
+ th.join
125
+ assert_operator Time.now-st, :<, 5.0
126
+ end
127
+ end
@@ -0,0 +1,50 @@
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
+ end
@@ -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