libusb 0.6.0-x86-linux

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.
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