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.
- data/.autotest +23 -0
- data/.gemtest +0 -0
- data/COPYING +165 -0
- data/History.txt +15 -0
- data/Manifest.txt +15 -0
- data/README.rdoc +110 -0
- data/Rakefile +144 -0
- data/lib/libusb.rb +1523 -0
- data/lib/libusb/compat.rb +370 -0
- data/test/test_libusb_compat.rb +78 -0
- data/test/test_libusb_compat_mass_storage.rb +81 -0
- data/test/test_libusb_descriptors.rb +122 -0
- data/test/test_libusb_gc.rb +37 -0
- data/test/test_libusb_iso_transfer.rb +45 -0
- data/test/test_libusb_mass_storage.rb +271 -0
- metadata +106 -0
@@ -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
|