libusb 0.1.0

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.
@@ -0,0 +1,370 @@
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 file is for compatibility with ruby-usb and libusb-0.1.
17
+ #
18
+ # Please visit the project website at http://github.com/larskanis/libusb
19
+ # for support.
20
+
21
+ require 'libusb'
22
+ require 'forwardable'
23
+
24
+ # Compatibility layer for ruby-usb[http://www.a-k-r.org/ruby-usb/] (API based on libusb-0.1)
25
+ #
26
+ # This module provides some limited compatibility to ruby-usb.
27
+ #
28
+ # Usage example:
29
+ # begin
30
+ # require 'usb'
31
+ # rescue LoadError
32
+ # require 'libusb/compat'
33
+ # end
34
+ # p USB.devices => [#<USB::Device ...>]
35
+ #
36
+ # Known issues:
37
+ # * Exceptions are different between ruby-usb and libusb and they don't get converted
38
+ # * libusb-1.0 doesn't explicitly manage USB-buses, so only one Bus is used currently
39
+ module USB
40
+ DefaultContext = LIBUSB::Context.new
41
+
42
+ USB_CLASS_PER_INTERFACE = LIBUSB::CLASS_PER_INTERFACE
43
+ USB_CLASS_AUDIO = LIBUSB::CLASS_AUDIO
44
+ USB_CLASS_COMM = LIBUSB::CLASS_COMM
45
+ USB_CLASS_HID = LIBUSB::CLASS_HID
46
+ USB_CLASS_PRINTER = LIBUSB::CLASS_PRINTER
47
+ USB_CLASS_PTP = LIBUSB::CLASS_PTP
48
+ USB_CLASS_MASS_STORAGE = LIBUSB::CLASS_MASS_STORAGE
49
+ USB_CLASS_HUB = LIBUSB::CLASS_HUB
50
+ USB_CLASS_DATA = LIBUSB::CLASS_DATA
51
+ USB_CLASS_VENDOR_SPEC = LIBUSB::CLASS_VENDOR_SPEC
52
+
53
+ USB_DT_DEVICE = LIBUSB::DT_DEVICE
54
+ USB_DT_CONFIG = LIBUSB::DT_CONFIG
55
+ USB_DT_STRING = LIBUSB::DT_STRING
56
+ USB_DT_INTERFACE = LIBUSB::DT_INTERFACE
57
+ USB_DT_ENDPOINT = LIBUSB::DT_ENDPOINT
58
+ USB_DT_HID = LIBUSB::DT_HID
59
+ USB_DT_REPORT = LIBUSB::DT_REPORT
60
+ USB_DT_PHYSICAL = LIBUSB::DT_PHYSICAL
61
+ USB_DT_HUB = LIBUSB::DT_HUB
62
+ USB_DT_DEVICE_SIZE = LIBUSB::DT_DEVICE_SIZE
63
+ USB_DT_CONFIG_SIZE = LIBUSB::DT_CONFIG_SIZE
64
+ USB_DT_INTERFACE_SIZE = LIBUSB::DT_INTERFACE_SIZE
65
+ USB_DT_ENDPOINT_SIZE = LIBUSB::DT_ENDPOINT_SIZE
66
+ USB_DT_ENDPOINT_AUDIO_SIZE = LIBUSB::DT_ENDPOINT_AUDIO_SIZE
67
+ USB_DT_HUB_NONVAR_SIZE = LIBUSB::DT_HUB_NONVAR_SIZE
68
+
69
+ USB_ENDPOINT_ADDRESS_MASK = LIBUSB::ENDPOINT_ADDRESS_MASK
70
+ USB_ENDPOINT_DIR_MASK = LIBUSB::ENDPOINT_DIR_MASK
71
+ USB_ENDPOINT_IN = LIBUSB::ENDPOINT_IN
72
+ USB_ENDPOINT_OUT = LIBUSB::ENDPOINT_OUT
73
+
74
+ USB_ENDPOINT_TYPE_MASK = LIBUSB::TRANSFER_TYPE_MASK
75
+ USB_ENDPOINT_TYPE_CONTROL = LIBUSB::TRANSFER_TYPE_CONTROL
76
+ USB_ENDPOINT_TYPE_ISOCHRONOUS = LIBUSB::TRANSFER_TYPE_ISOCHRONOUS
77
+ USB_ENDPOINT_TYPE_BULK = LIBUSB::TRANSFER_TYPE_BULK
78
+ USB_ENDPOINT_TYPE_INTERRUPT = LIBUSB::TRANSFER_TYPE_INTERRUPT
79
+
80
+ USB_REQ_GET_STATUS = LIBUSB::REQUEST_GET_STATUS
81
+ USB_REQ_CLEAR_FEATURE = LIBUSB::REQUEST_CLEAR_FEATURE
82
+ USB_REQ_SET_FEATURE = LIBUSB::REQUEST_SET_FEATURE
83
+ USB_REQ_SET_ADDRESS = LIBUSB::REQUEST_SET_ADDRESS
84
+ USB_REQ_GET_DESCRIPTOR = LIBUSB::REQUEST_GET_DESCRIPTOR
85
+ USB_REQ_SET_DESCRIPTOR = LIBUSB::REQUEST_SET_DESCRIPTOR
86
+ USB_REQ_GET_CONFIGURATION = LIBUSB::REQUEST_GET_CONFIGURATION
87
+ USB_REQ_SET_CONFIGURATION = LIBUSB::REQUEST_SET_CONFIGURATION
88
+ USB_REQ_GET_INTERFACE = LIBUSB::REQUEST_GET_INTERFACE
89
+ USB_REQ_SET_INTERFACE = LIBUSB::REQUEST_SET_INTERFACE
90
+ USB_REQ_SYNCH_FRAME = LIBUSB::REQUEST_SYNCH_FRAME
91
+ USB_TYPE_STANDARD = LIBUSB::REQUEST_TYPE_STANDARD
92
+ USB_TYPE_CLASS = LIBUSB::REQUEST_TYPE_CLASS
93
+ USB_TYPE_VENDOR = LIBUSB::REQUEST_TYPE_VENDOR
94
+ USB_TYPE_RESERVED = LIBUSB::REQUEST_TYPE_RESERVED
95
+ USB_RECIP_DEVICE = LIBUSB::RECIPIENT_DEVICE
96
+ USB_RECIP_INTERFACE = LIBUSB::RECIPIENT_INTERFACE
97
+ USB_RECIP_ENDPOINT = LIBUSB::RECIPIENT_ENDPOINT
98
+ USB_RECIP_OTHER = LIBUSB::RECIPIENT_OTHER
99
+
100
+ HAS_GET_DRIVER_NP = RUBY_PLATFORM=~/mswin|mingw/ ? false : true
101
+ HAS_DETACH_KERNEL_DRIVER_NP = RUBY_PLATFORM=~/mswin|mingw/ ? false : true
102
+
103
+ # not defined by libusb-1.0, but typical values are:
104
+ USB_MAXENDPOINTS = 32
105
+ USB_MAXINTERFACES = 32
106
+ USB_MAXALTSETTING = 128
107
+ USB_MAXCONFIG = 8
108
+
109
+
110
+ def USB.busses
111
+ [DefaultBus]
112
+ end
113
+
114
+ def USB.devices; DefaultContext.devices.map{|c| Device.new(c) }; end
115
+ def USB.configurations() USB.devices.map {|d| d.configurations }.flatten end
116
+ def USB.interfaces() USB.configurations.map {|d| d.interfaces }.flatten end
117
+ def USB.settings() USB.interfaces.map {|d| d.settings }.flatten end
118
+ def USB.endpoints() USB.settings.map {|d| d.endpoints }.flatten end
119
+
120
+ def USB.find_bus(n)
121
+ DefaultBus
122
+ end
123
+
124
+ def USB.each_device_by_class(devclass, subclass=nil, protocol=nil)
125
+ devs = DefaultContext.devices :bClass=>devclass, :bSubClass=>subclass, :bProtocol=>protocol
126
+ devs.each do |dev|
127
+ yield Device.new(dev)
128
+ end
129
+ nil
130
+ end
131
+
132
+ class Bus
133
+ def initialize(context)
134
+ @ct = context
135
+ end
136
+ def devices
137
+ @ct.devices.map{|d| Device.new(d) }
138
+ end
139
+
140
+ def configurations() self.devices.map{|d| d.configurations }.flatten end
141
+ def interfaces() self.configurations.map {|d| d.interfaces }.flatten end
142
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
143
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
144
+
145
+ def find_device(n)
146
+ raise NotImplementedError
147
+ end
148
+ end
149
+
150
+ DefaultBus = Bus.new(DefaultContext)
151
+
152
+ def USB.dev_string(base_class, sub_class, protocol)
153
+ LIBUSB.dev_string(base_class, sub_class, protocol)
154
+ end
155
+
156
+ class Device
157
+ extend Forwardable
158
+ include Comparable
159
+
160
+ def initialize(dev)
161
+ @dev = dev
162
+ end
163
+
164
+ def_delegators :@dev, :bLength, :bDescriptorType, :bcdUSB, :bDeviceClass,
165
+ :bDeviceSubClass, :bDeviceProtocol, :bMaxPacketSize0, :idVendor, :idProduct,
166
+ :bcdDevice, :iManufacturer, :iProduct, :iSerialNumber, :bNumConfigurations,
167
+ :manufacturer, :product, :serial_number,
168
+ :inspect
169
+
170
+ def <=>(o)
171
+ @dev<=>o.instance_variable_get(:@dev)
172
+ end
173
+
174
+ def open
175
+ h = DevHandle.new(@dev.open)
176
+ if block_given?
177
+ begin
178
+ r = yield h
179
+ ensure
180
+ h.usb_close
181
+ end
182
+ else
183
+ h
184
+ end
185
+ end
186
+
187
+ def bus; DefaultBus; end
188
+ def configurations; @dev.configurations.map{|c| Configuration.new(c) }; end
189
+ def interfaces; @dev.interfaces.map{|c| Interface.new(c) }; end
190
+ def settings; @dev.settings.map{|c| Setting.new(c) }; end
191
+ def endpoints; @dev.endpoints.map{|c| Endpoint.new(c) }; end
192
+ end
193
+
194
+ class Configuration
195
+ extend Forwardable
196
+ include Comparable
197
+
198
+ def initialize(cd)
199
+ @cd = cd
200
+ end
201
+
202
+ def_delegators :@cd, :bLength, :bDescriptorType, :wTotalLength, :bNumInterfaces,
203
+ :bConfigurationValue, :iConfiguration, :bmAttributes, :maxPower,
204
+ :inspect
205
+
206
+ def <=>(o)
207
+ @cd<=>o.instance_variable_get(:@cd)
208
+ end
209
+
210
+ def bus; DefaultBus; end
211
+ def device() Device.new(@cd.device) end
212
+ def interfaces; @cd.interfaces.map{|c| Interface.new(c) }; end
213
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
214
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
215
+ end
216
+
217
+ class Interface
218
+ extend Forwardable
219
+ include Comparable
220
+
221
+ def initialize(i)
222
+ @i = i
223
+ end
224
+
225
+ def_delegators :@i, :inspect
226
+
227
+ def <=>(o)
228
+ @i<=>o.instance_variable_get(:@i)
229
+ end
230
+
231
+ def bus() self.configuration.device.bus end
232
+ def device() self.configuration.device end
233
+ def configuration; Configuration.new(@i.configuration); end
234
+ def settings; @i.alt_settings.map{|c| Setting.new(c) }; end
235
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
236
+ end
237
+
238
+ class Setting
239
+ extend Forwardable
240
+ include Comparable
241
+
242
+ def initialize(id)
243
+ @id = id
244
+ end
245
+
246
+ def_delegators :@id, :bLength, :bDescriptorType, :bInterfaceNumber, :bAlternateSetting,
247
+ :bNumEndpoints, :bInterfaceClass, :bInterfaceSubClass, :bInterfaceProtocol,
248
+ :iInterface, :inspect
249
+
250
+ def <=>(o)
251
+ @id<=>o.instance_variable_get(:@id)
252
+ end
253
+
254
+ def bus() self.interface.configuration.device.bus end
255
+ def device() self.interface.configuration.device end
256
+ def configuration() self.interface.configuration end
257
+ def interface; Interface.new(@id.interface); end
258
+ def endpoints() @id.endpoints.map {|d| Endpoint.new(d) }.flatten end
259
+ end
260
+
261
+ class Endpoint
262
+ extend Forwardable
263
+ include Comparable
264
+
265
+ def initialize(ep)
266
+ @ep = ep
267
+ end
268
+
269
+ def_delegators :@ep, :bLength, :bDescriptorType, :bEndpointAddress, :bmAttributes,
270
+ :wMaxPacketSize, :bInterval, :bRefresh, :bSynchAddress,
271
+ :inspect
272
+
273
+ def <=>(o)
274
+ @ep<=>o.instance_variable_get(:@ep)
275
+ end
276
+
277
+ def bus() self.setting.interface.configuration.device.bus end
278
+ def device() self.setting.interface.configuration.device end
279
+ def configuration() self.setting.interface.configuration end
280
+ def interface() self.setting.interface end
281
+ def setting; Setting.new(@ep.setting); end
282
+ end
283
+
284
+ class DevHandle
285
+ def initialize(dev)
286
+ @dev = dev
287
+ end
288
+
289
+ def usb_close; @dev.close; end
290
+ def usb_set_configuration(c); @dev.configuration=c; end
291
+ def usb_set_altinterface(c); @dev.set_interface_alt_setting=c; end
292
+ def usb_clear_halt(c); @dev.clear_halt(c); end
293
+ def usb_reset; @dev.reset_device; end
294
+ def usb_claim_interface(c); @dev.claim_interface(c); end
295
+ def usb_release_interface(c); @dev.release_interface(c); end
296
+ def usb_get_string(index, langid, buffer)
297
+ t = @dev.string_descriptor(index, langid)
298
+ buffer[0, t.length] = t
299
+ t.length
300
+ end
301
+ def usb_get_string_simple(index, buffer)
302
+ t = @dev.string_descriptor_ascii(index)
303
+ buffer[0, t.length] = t
304
+ t.length
305
+ end
306
+
307
+ def usb_control_msg(requesttype, request, value, index, bytes, timeout)
308
+ if requesttype&LIBUSB::ENDPOINT_IN != 0
309
+ # transfer direction in
310
+ res = @dev.control_transfer(:bmRequestType=>requesttype, :bRequest=>request,
311
+ :wValue=>value, :wIndex=>index, :dataIn=>bytes.bytesize, :timeout=>timeout)
312
+ bytes[0, res.bytesize] = res
313
+ res.bytesize
314
+ else
315
+ # transfer direction out
316
+ @dev.control_transfer(:bmRequestType=>requesttype, :bRequest=>request, :wValue=>value,
317
+ :wIndex=>index, :dataOut=>bytes, :timeout=>timeout)
318
+ end
319
+ end
320
+
321
+ def usb_bulk_write(endpoint, bytes, timeout)
322
+ @dev.bulk_transfer(:endpoint=>endpoint, :dataOut=>bytes, :timeout=>timeout)
323
+ end
324
+ def usb_bulk_read(endpoint, bytes, timeout)
325
+ res = @dev.bulk_transfer(:endpoint=>endpoint, :dataIn=>bytes.bytesize, :timeout=>timeout)
326
+ bytes[0, res.bytesize] = res
327
+ res.bytesize
328
+ end
329
+
330
+ def usb_interrupt_write(endpoint, bytes, timeout)
331
+ @dev.interrupt_transfer(:endpoint=>endpoint, :dataOut=>bytes, :timeout=>timeout)
332
+ end
333
+ def usb_interrupt_read(endpoint, bytes, timeout)
334
+ res = @dev.interrupt_transfer(:endpoint=>endpoint, :dataIn=>bytes.bytesize, :timeout=>timeout)
335
+ bytes[0, res.bytesize] = res
336
+ res.bytesize
337
+ end
338
+
339
+ # rb_define_method(rb_cUSB_DevHandle, "usb_get_descriptor", rusb_get_descriptor, 3);
340
+ # rb_define_method(rb_cUSB_DevHandle, "usb_get_descriptor_by_endpoint", rusb_get_descriptor_by_endpoint, 4);
341
+
342
+ if HAS_DETACH_KERNEL_DRIVER_NP
343
+ def usb_detach_kernel_driver_np(interface, dummy=nil)
344
+ @dev.detach_kernel_driver(interface)
345
+ end
346
+ end
347
+
348
+ if HAS_GET_DRIVER_NP
349
+ def usb_get_driver_np(interface, buffer)
350
+ if @dev.kernel_driver_active?(interface)
351
+ t = "unknown driver"
352
+ buffer[0, t.length] = t
353
+ else
354
+ raise Errno::ENODATA, "No data available"
355
+ end
356
+ nil
357
+ end
358
+ end
359
+
360
+ alias set_configuration usb_set_configuration
361
+ alias set_altinterface usb_set_altinterface
362
+ alias clear_halt usb_clear_halt
363
+ alias claim_interface usb_claim_interface
364
+ alias release_interface usb_release_interface
365
+
366
+ def get_string_simple(index)
367
+ @dev.string_descriptor_ascii(index)
368
+ end
369
+ end
370
+ end
@@ -0,0 +1,78 @@
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/compat"
18
+
19
+ class TestLibusbCompat < Test::Unit::TestCase
20
+ include USB
21
+
22
+ attr_accessor :usb
23
+
24
+ def test_find
25
+ devlist = USB.devices
26
+ assert_kind_of Array, devlist, "Bus#find should return an Array"
27
+ assert_kind_of Device, devlist.first, "Bus#find should return Devices"
28
+ devlist.each do |dev|
29
+ assert_match( /Device/, dev.inspect, "Device#inspect should work")
30
+ end
31
+ end
32
+
33
+ def test_constants
34
+ assert_equal 7, USB_CLASS_PRINTER, "Printer class id should be defined"
35
+ assert_equal 32, USB_TYPE_CLASS, "type class should be defined"
36
+ end
37
+
38
+ def test_descriptors
39
+ USB.devices.each do |dev|
40
+ assert_match(/Device/, dev.inspect, "Device#inspect should work")
41
+ dev.configurations.each do |config_desc|
42
+ assert_match(/Configuration/, config_desc.inspect, "Configuration#inspect should work")
43
+ assert dev.configurations.include?(config_desc), "Device#configurations should include this one"
44
+
45
+ config_desc.interfaces.each do |interface|
46
+ assert_match(/Interface/, interface.inspect, "Interface#inspect should work")
47
+
48
+ assert dev.interfaces.include?(interface), "Device#interfaces should include this one"
49
+ assert config_desc.interfaces.include?(interface), "Configuration#interfaces should include this one"
50
+
51
+ interface.settings.each do |if_desc|
52
+ assert_match(/Setting/, if_desc.inspect, "Setting#inspect should work")
53
+
54
+ assert dev.settings.include?(if_desc), "Device#settings should include this one"
55
+ assert config_desc.settings.include?(if_desc), "Configuration#settings should include this one"
56
+ assert interface.settings.include?(if_desc), "Interface#settings should include this one"
57
+
58
+ if_desc.endpoints.each do |ep|
59
+ assert_match(/Endpoint/, ep.inspect, "Endpoint#inspect should work")
60
+
61
+ assert dev.endpoints.include?(ep), "Device#endpoints should include this one"
62
+ assert config_desc.endpoints.include?(ep), "Configuration#endpoints should include this one"
63
+ assert interface.endpoints.include?(ep), "Interface#endpoints should include this one"
64
+ assert if_desc.endpoints.include?(ep), "Setting#endpoints should include this one"
65
+
66
+ assert_equal if_desc, ep.setting, "backref should be correct"
67
+ assert_equal interface, ep.interface, "backref should be correct"
68
+ assert_equal config_desc, ep.configuration, "backref should be correct"
69
+ assert_equal dev, ep.device, "backref should be correct"
70
+
71
+ assert_operator 0, :<, ep.wMaxPacketSize, "packet size should be > 0"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,81 @@
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/compat"
18
+
19
+ class TestLibusbCompat < Test::Unit::TestCase
20
+ include USB
21
+
22
+ attr_accessor :devh
23
+
24
+ BOMS_RESET = 0xFF
25
+ BOMS_GET_MAX_LUN = 0xFE
26
+
27
+ def setup
28
+ devs = []
29
+ USB.each_device_by_class(USB_CLASS_MASS_STORAGE, 0x01, 0x50){|dev| devs << dev }
30
+ USB.each_device_by_class(USB_CLASS_MASS_STORAGE, 0x06, 0x50){|dev| devs << dev }
31
+
32
+ dev = devs.last
33
+ abort "no mass storage device found" unless dev
34
+ devh = dev.open
35
+ if RUBY_PLATFORM=~/linux/i
36
+ data = " "*1000
37
+ begin
38
+ devh.usb_get_driver_np 0, data
39
+ rescue Errno::ENODATA
40
+ data = "nodata exception".ljust(1000, "\0")
41
+ end
42
+ assert_match(/\w+/, data, "There should be a driver or an exception")
43
+ begin
44
+ # second param is needed because of a bug in ruby-usb
45
+ devh.usb_detach_kernel_driver_np 0, 123
46
+ rescue RuntimeError => e
47
+ assert_match(/ERROR_NOT_FOUND/, e.to_s, "Raise proper exception, if no kernel driver is active")
48
+ end
49
+ end
50
+
51
+ endpoint_in = dev.endpoints.find{|ep| ep.bEndpointAddress&USB_ENDPOINT_IN != 0 }
52
+ endpoint_out = dev.endpoints.find{|ep| ep.bEndpointAddress&USB_ENDPOINT_IN == 0 }
53
+
54
+ devh.set_configuration 1
55
+ devh.set_configuration dev.configurations.first
56
+ devh.claim_interface dev.settings.first
57
+ devh.clear_halt(endpoint_in)
58
+ devh.clear_halt(endpoint_out.bEndpointAddress)
59
+ @devh = devh
60
+ end
61
+
62
+ def teardown
63
+ if devh
64
+ devh.release_interface 0
65
+ devh.usb_close
66
+ end
67
+ end
68
+
69
+ def test_mass_storage_reset
70
+ res = devh.usb_control_msg(USB_ENDPOINT_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
71
+ BOMS_RESET, 0, 0, "", 2000)
72
+ assert_equal 0, res, "BOMS_RESET response should be 0 byte"
73
+ end
74
+
75
+ def test_read_max_lun
76
+ bytes = [].pack('x1')
77
+ devh.usb_control_msg(USB_ENDPOINT_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
78
+ BOMS_GET_MAX_LUN, 0, 0, bytes, 100)
79
+ assert [0].pack("C")==bytes || [1].pack("C")==bytes, "BOMS_GET_MAX_LUN response is usually 0 or 1"
80
+ end
81
+ end