libusb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|