libusb 0.3.3-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,278 @@
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 "test/unit"
23
+ require "libusb"
24
+
25
+ class TestLibusbMassStorage < Test::Unit::TestCase
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_raise(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_attach_kernel_driver
261
+ dev.release_interface(0)
262
+ if RUBY_PLATFORM=~/linux/i
263
+ dev.attach_kernel_driver(0)
264
+ assert dev.kernel_driver_active?(0), "kernel driver should be active again"
265
+ end
266
+ dev.close
267
+ @dev = nil
268
+ end
269
+
270
+ def test_wrong_argument
271
+ assert_raise(ArgumentError){ dev.bulk_transfer(:endpoint=>endpoint_in, :dataOut=>"data") }
272
+ assert_raise(ArgumentError){ dev.interrupt_transfer(:endpoint=>endpoint_in, :dataOut=>"data") }
273
+ assert_raise(ArgumentError){ dev.control_transfer(
274
+ :bmRequestType=>ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
275
+ :bRequest=>BOMS_RESET,
276
+ :wValue=>0, :wIndex=>0, :dataIn=>123) }
277
+ end
278
+ end
@@ -0,0 +1,73 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+ #
16
+
17
+ require "test/unit"
18
+ require "libusb"
19
+
20
+ class TestLibusbMassStorage2 < Test::Unit::TestCase
21
+ include LIBUSB
22
+
23
+ attr_accessor :usb
24
+ attr_accessor :device
25
+ attr_accessor :interface
26
+
27
+ def setup
28
+ @usb = Context.new
29
+ @usb.debug = 3
30
+ @device = usb.devices( :bClass=>CLASS_MASS_STORAGE, :bSubClass=>[0x06,0x01], :bProtocol=>0x50 ).last
31
+ skip "no mass storage device found" unless @device
32
+
33
+ @interface = device.interfaces.first
34
+
35
+ # Ensure kernel driver is detached
36
+ device.open do |dev|
37
+ if RUBY_PLATFORM=~/linux/i && dev.kernel_driver_active?(interface)
38
+ assert dev.kernel_driver_active?(0), "DevHandle#kernel_driver_active? may be called with an Interface instance or a Fixnum"
39
+ dev.detach_kernel_driver(interface)
40
+ end
41
+ end
42
+ end
43
+
44
+ def teardown
45
+ end
46
+
47
+ def test_open_with_block
48
+ device.open do |dev|
49
+ assert_kind_of DevHandle, dev
50
+ assert_kind_of String, dev.string_descriptor_ascii(1)
51
+ end
52
+ end
53
+
54
+ def test_claim_interface_with_block
55
+ res = device.open do |dev|
56
+ dev.claim_interface(interface) do |dev2|
57
+ assert_kind_of DevHandle, dev2
58
+ assert_kind_of String, dev2.string_descriptor_ascii(1)
59
+ 12345
60
+ end
61
+ end
62
+ assert_equal 12345, res, "Block versions should pass through the result"
63
+ end
64
+
65
+ def test_open_interface
66
+ res = device.open_interface(interface) do |dev|
67
+ assert_kind_of DevHandle, dev
68
+ assert_kind_of String, dev.string_descriptor_ascii(1)
69
+ 12345
70
+ end
71
+ assert_equal 12345, res, "Block versions should pass through the result"
72
+ end
73
+ end
@@ -0,0 +1,45 @@
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 "test/unit"
17
+ require "libusb"
18
+
19
+ class TestLibusbStructs < Test::Unit::TestCase
20
+ def test_struct_Timeval
21
+ s = LIBUSB::Call::Timeval.new
22
+ assert_equal 0, s.in_ms
23
+ s.in_ms = 12345678
24
+ assert_equal 12345, s[:tv_sec]
25
+ assert_equal 678000, s[:tv_usec]
26
+ assert_equal 12345678, s.in_ms
27
+
28
+ s.in_s = 1234.5678
29
+ assert_equal 1234, s[:tv_sec]
30
+ assert_equal 567800, s[:tv_usec]
31
+ assert_equal 1234.5678, s.in_s
32
+ end
33
+
34
+ def test_struct_CompletionFlag
35
+ s = LIBUSB::Context::CompletionFlag.new
36
+ assert_equal 0, s[:completed]
37
+ assert_equal false, s.completed?
38
+ s.completed = true
39
+ assert_equal 1, s[:completed]
40
+ assert_equal true, s.completed?
41
+ s.completed = false
42
+ assert_equal false, s.completed?
43
+ assert_equal 0, s[:completed]
44
+ end
45
+ end
@@ -0,0 +1,89 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+ #
16
+ # This test requires two connected, but not mounted mass storage device with
17
+ # read/write access allowed.
18
+
19
+ require "test/unit"
20
+ require "libusb"
21
+
22
+ class TestLibusbThreads < Test::Unit::TestCase
23
+ include LIBUSB
24
+
25
+ BOMS_GET_MAX_LUN = 0xFE
26
+
27
+ attr_accessor :usb
28
+ attr_accessor :devices
29
+ attr_accessor :devs
30
+ attr_accessor :endpoints_in
31
+ attr_accessor :endpoints_out
32
+
33
+ def setup
34
+ @usb = Context.new
35
+ @usb.debug = 3
36
+
37
+ @devices = usb.devices( :bClass=>CLASS_MASS_STORAGE, :bSubClass=>[0x06,0x01], :bProtocol=>0x50 )
38
+ skip "less than two mass storage devices found" unless @devices.length >= 2
39
+
40
+ @devs = @devices.map do |device|
41
+ dev = device.open
42
+ if RUBY_PLATFORM=~/linux/i && dev.kernel_driver_active?(0)
43
+ dev.detach_kernel_driver(0)
44
+ end
45
+ dev.claim_interface(0)
46
+ dev
47
+ end
48
+
49
+ @endpoints_in = {}
50
+ @endpoints_out = {}
51
+
52
+ @devs.each do |dev|
53
+ @endpoints_in[dev] = dev.device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
54
+ @endpoints_out[dev] = dev.device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN == 0 }
55
+ end
56
+
57
+ Thread.abort_on_exception = true
58
+ end
59
+
60
+ def teardown
61
+ if devs
62
+ devs.each do |dev|
63
+ dev.release_interface(0)
64
+ dev.close
65
+ end
66
+ end
67
+ end
68
+
69
+ def thread_worker(dev)
70
+ endpoint = endpoints_in[dev]
71
+ 1.times do
72
+ st = Time.now
73
+ assert_raise LIBUSB::ERROR_TIMEOUT do
74
+ dev.bulk_transfer(:endpoint=>endpoint, :dataIn=>123, :timeout=>100)
75
+ end
76
+ assert_operator Time.now-st, :<, 5
77
+ dev.clear_halt(endpoint)
78
+ end
79
+ end
80
+
81
+ def test_sync_api
82
+ threads = devs.map do |dev|
83
+ Thread.new do
84
+ thread_worker(dev)
85
+ end
86
+ end
87
+ threads.map(&:join)
88
+ end
89
+ end