libusb 0.6.3-x86-mingw32 → 0.7.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,7 +11,8 @@ module LIBUSB
11
11
  def initialize
12
12
  super("libusb", LIBUSB_VERSION)
13
13
  self.target = File.join(ROOT, "ports")
14
- self.files = [url: LIBUSB_SOURCE_URI, sha1: LIBUSB_SOURCE_SHA1]
14
+ self.files = [url: LIBUSB_SOURCE_URI, sha256: LIBUSB_SOURCE_SHA256]
15
+ self.patch_files = Dir[File.join(ROOT, "patches", self.name, self.version, "*.patch")].sort
15
16
  self.configure_options = []
16
17
  end
17
18
 
@@ -24,7 +25,5 @@ module LIBUSB
24
25
  self.activate
25
26
  self
26
27
  end
27
-
28
- public :files_hashs
29
28
  end
30
29
  end
@@ -19,13 +19,21 @@ module LIBUSB
19
19
  # A structure representing the superspeed endpoint companion descriptor.
20
20
  #
21
21
  # This descriptor is documented in section 9.6.7 of the USB 3.0 specification. All multiple-byte fields are represented in host-endian format.
22
- class SsCompanion < FFI::ManagedStruct
22
+ class SsCompanion < FFI::Struct
23
+ include ContextReference
24
+
23
25
  layout :bLength, :uint8,
24
26
  :bDescriptorType, :uint8,
25
27
  :bMaxBurst, :uint8,
26
28
  :bmAttributes, :uint8,
27
29
  :wBytesPerInterval, :uint16
28
30
 
31
+ def initialize(ctx, *args)
32
+ super(*args)
33
+
34
+ register_context(ctx, :libusb_free_ss_endpoint_companion_descriptor)
35
+ end
36
+
29
37
  # Size of this descriptor (in bytes)
30
38
  def bLength
31
39
  self[:bLength]
@@ -60,10 +68,5 @@ module LIBUSB
60
68
  def inspect
61
69
  "\#<#{self.class} burst: #{bMaxBurst} attrs: #{bmAttributes}>"
62
70
  end
63
-
64
- # @private
65
- def self.release(ptr)
66
- Call.libusb_free_ss_endpoint_companion_descriptor(ptr)
67
- end
68
71
  end
69
72
  end
@@ -28,25 +28,30 @@ module LIBUSB
28
28
  class ZeroCopyMemory < FFI::Pointer
29
29
  attr_reader :size
30
30
 
31
- def initialize(dev_handle, ptr, size)
32
- @dev_handle = dev_handle
31
+ def initialize(pDevhandle, ptr, size)
32
+ @pDevhandle = pDevhandle
33
33
  @size = size
34
34
  super(ptr)
35
35
  end
36
36
 
37
37
  def free(id=nil)
38
+ # puts format("libusb_dev_mem_free(%#x, %d)%s", address, @size||0, id ? " by GC" : '')
38
39
  return unless @size
39
- # puts format("libusb_dev_mem_free(%#x, %d)%s", address, @size, id ? " by GC" : '')
40
- res = Call.libusb_dev_mem_free( @dev_handle.pHandle, self, @size )
40
+ res = Call.libusb_dev_mem_free( @pDevhandle, self, @size )
41
41
  LIBUSB.raise_error res, "in libusb_dev_mem_free" if res!=0
42
42
  @size = nil
43
43
  end
44
44
  end
45
45
 
46
+ class << self
47
+ private :new
48
+ end
49
+
46
50
  def initialize(args={})
47
51
  @buffer = nil
48
52
  @completion_flag = Context::CompletionFlag.new
49
53
  @allow_device_memory = false
54
+ @dev_handle = nil
50
55
  args.each{|k,v| send("#{k}=", v) }
51
56
  end
52
57
  private :initialize
@@ -55,15 +60,29 @@ module LIBUSB
55
60
  def dev_handle=(dev)
56
61
  @dev_handle = dev
57
62
  @transfer[:dev_handle] = @dev_handle.pHandle
63
+ # Now that the transfer is bound to a DevHandle, it must be registered in the Context.
64
+ # This ensures that the Call::Transfer is freed before libusb_exit, avoiding warnings about still referenced devices.
65
+ ctx = dev.device.context.instance_variable_get(:@ctx)
66
+ @transfer.instance_variable_set(:@ctx, ctx.ref_context)
58
67
  end
59
68
 
60
- # Timeout for this transfer in millseconds.
69
+ # The handle for the device to communicate with.
70
+ attr_reader :dev_handle
71
+
72
+ # Set timeout for this transfer in millseconds.
61
73
  #
62
74
  # A value of 0 indicates no timeout.
63
75
  def timeout=(value)
64
76
  @transfer[:timeout] = value
65
77
  end
66
78
 
79
+ # Get timeout for this transfer in millseconds.
80
+ #
81
+ # A value of 0 indicates no timeout.
82
+ def timeout
83
+ @transfer[:timeout]
84
+ end
85
+
67
86
  # Set the address of a valid endpoint to communicate with.
68
87
  def endpoint=(endpoint)
69
88
  endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
@@ -148,7 +167,7 @@ module LIBUSB
148
167
  ptr = Call.libusb_dev_mem_alloc( @dev_handle.pHandle, len )
149
168
  # puts format("libusb_dev_mem_alloc(%d) => %#x", len, ptr.address)
150
169
  unless ptr.null?
151
- buffer = ZeroCopyMemory.new(@dev_handle, ptr, len)
170
+ buffer = ZeroCopyMemory.new(@dev_handle.pHandle, ptr, len)
152
171
  ObjectSpace.define_finalizer(self, buffer.method(:free))
153
172
  end
154
173
  end
@@ -225,6 +244,8 @@ module LIBUSB
225
244
  #
226
245
  # Inspect {#status} to check for transfer errors.
227
246
  def submit_and_wait
247
+ raise ArgumentError, "#{self.class}#dev_handle not set" unless @dev_handle
248
+
228
249
  @completion_flag.completed = false
229
250
  submit! do |tr2|
230
251
  @completion_flag.completed = true
@@ -235,7 +256,7 @@ module LIBUSB
235
256
  @dev_handle.device.context.handle_events nil, @completion_flag
236
257
  rescue ERROR_INTERRUPTED
237
258
  next
238
- rescue LIBUSB::Error
259
+ rescue Exception
239
260
  cancel!
240
261
  until @completion_flag.completed?
241
262
  @dev_handle.device.context.handle_events nil, @completion_flag
@@ -256,6 +277,10 @@ module LIBUSB
256
277
  end
257
278
 
258
279
  class BulkTransfer < Transfer
280
+ def self.new(*)
281
+ super
282
+ end
283
+
259
284
  def initialize(args={})
260
285
  @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
261
286
  @transfer[:type] = TRANSFER_TYPE_BULK
@@ -272,6 +297,10 @@ module LIBUSB
272
297
  #
273
298
  # Available since libusb-1.0.19.
274
299
  class BulkStreamTransfer < Transfer
300
+ def self.new(*)
301
+ super
302
+ end
303
+
275
304
  def initialize(args={})
276
305
  @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
277
306
  @transfer[:type] = TRANSFER_TYPE_BULK_STREAM
@@ -299,6 +328,10 @@ module LIBUSB
299
328
  end
300
329
 
301
330
  class ControlTransfer < Transfer
331
+ def self.new(*)
332
+ super
333
+ end
334
+
302
335
  def initialize(args={})
303
336
  @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
304
337
  @transfer[:type] = TRANSFER_TYPE_CONTROL
@@ -308,6 +341,10 @@ module LIBUSB
308
341
  end
309
342
 
310
343
  class InterruptTransfer < Transfer
344
+ def self.new(*)
345
+ super
346
+ end
347
+
311
348
  def initialize(args={})
312
349
  @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
313
350
  @transfer[:type] = TRANSFER_TYPE_INTERRUPT
@@ -339,6 +376,10 @@ module LIBUSB
339
376
  end
340
377
 
341
378
  class IsochronousTransfer < Transfer
379
+ def self.new(*)
380
+ super
381
+ end
382
+
342
383
  def initialize(num_packets, args={})
343
384
  @ptr = Call.libusb_alloc_transfer(num_packets)
344
385
  @transfer = Call::Transfer.new @ptr
@@ -15,5 +15,5 @@
15
15
 
16
16
  module LIBUSB
17
17
  # Library version of libusb for Ruby
18
- VERSION = "0.6.3"
18
+ VERSION = "0.7.0"
19
19
  end
data/lib/libusb-1.0.dll CHANGED
Binary file
data/lib/libusb.rb CHANGED
@@ -20,6 +20,7 @@ module LIBUSB
20
20
  autoload :VERSION, 'libusb/version_gem'
21
21
  autoload :Version, 'libusb/version_struct'
22
22
  autoload :Configuration, 'libusb/configuration'
23
+ autoload :ContextReference, 'libusb/context_reference'
23
24
  autoload :DevHandle, 'libusb/dev_handle'
24
25
  autoload :Device, 'libusb/device'
25
26
  autoload :Endpoint, 'libusb/endpoint'
@@ -32,27 +33,114 @@ module LIBUSB
32
33
  autoload klass, 'libusb/transfer'
33
34
  end
34
35
 
35
- if Call.respond_to?(:libusb_get_version)
36
- # Get version of the underlying libusb library.
37
- # Available since libusb-1.0.10.
38
- # @return [Version] version object
39
- def self.version
40
- Version.new(Call.libusb_get_version)
36
+ class << self
37
+ if Call.respond_to?(:libusb_get_version)
38
+ # Get version of the underlying libusb library.
39
+ # Available since libusb-1.0.10.
40
+ # @return [Version] version object
41
+ def version
42
+ Version.new(Call.libusb_get_version)
43
+ end
44
+ end
45
+
46
+ if Call.respond_to?(:libusb_has_capability)
47
+ # Check at runtime if the loaded library has a given capability.
48
+ # Available since libusb-1.0.9.
49
+ # @param [Symbol] capability the {Call::Capabilities Capabilities} symbol to check for
50
+ # @return [Boolean] +true+ if the running library has the capability, +false+ otherwise
51
+ def has_capability?(capability)
52
+ r = Call.libusb_has_capability(capability)
53
+ return r != 0
54
+ end
55
+ else
56
+ def has_capability?(capability)
57
+ false
58
+ end
59
+ end
60
+
61
+ private def expect_option_args(exp, is)
62
+ raise ArgumentError, "wrong number of arguments (given #{is+1}, expected #{exp+1})" if is != exp
41
63
  end
42
- end
43
64
 
44
- if Call.respond_to?(:libusb_has_capability)
45
- # Check at runtime if the loaded library has a given capability.
46
- # Available since libusb-1.0.9.
47
- # @param [Symbol] capability the {Call::Capabilities Capabilities} symbol to check for
48
- # @return [Boolean] +true+ if the running library has the capability, +false+ otherwise
49
- def self.has_capability?(capability)
50
- r = Call.libusb_has_capability(capability)
51
- return r != 0
65
+ private def wrap_log_cb(block, mode)
66
+ if block
67
+ cb_proc = proc do |p_ctx, lev, str|
68
+ ctx = case p_ctx
69
+ when FFI::Pointer::NULL then nil
70
+ else p_ctx.to_i
71
+ end
72
+ block.call(ctx, lev, str)
73
+ end
74
+ end
75
+
76
+ # Avoid garbage collection of the proc, since only the function pointer is given to libusb
77
+ if Call::LogCbMode.to_native(mode, nil) & LOG_CB_GLOBAL != 0
78
+ @log_cb_global_proc = cb_proc
79
+ end
80
+ if Call::LogCbMode.to_native(mode, nil) & LOG_CB_CONTEXT != 0
81
+ @log_cb_context_proc = cb_proc
82
+ end
83
+ cb_proc
84
+ end
85
+
86
+ private def option_args_to_ffi(option, args, ctx)
87
+ case option
88
+ when :OPTION_LOG_LEVEL, LIBUSB::OPTION_LOG_LEVEL
89
+ expect_option_args(1, args.length)
90
+ [:libusb_log_level, args[0]]
91
+ when :OPTION_USE_USBDK, LIBUSB::OPTION_USE_USBDK
92
+ expect_option_args(0, args.length)
93
+ []
94
+ when :OPTION_NO_DEVICE_DISCOVERY, LIBUSB::OPTION_NO_DEVICE_DISCOVERY
95
+ expect_option_args(0, args.length)
96
+ []
97
+ when :OPTION_LOG_CB, LIBUSB::OPTION_LOG_CB
98
+ expect_option_args(1, args.length)
99
+ cb_proc = ctx.send(:wrap_log_cb, args[0], LOG_CB_CONTEXT)
100
+ [:libusb_log_cb, cb_proc]
101
+ else
102
+ raise ArgumentError, "unknown option #{option.inspect}"
103
+ end
52
104
  end
53
- else
54
- def self.has_capability?(capability)
55
- false
105
+
106
+ if Call.respond_to?(:libusb_set_option)
107
+ # Set an default option in the libusb library.
108
+ #
109
+ # Use this function to configure a specific option within the library.
110
+ # See {Call::Options option list}.
111
+ #
112
+ # Some options require one or more arguments to be provided.
113
+ # Consult each option's documentation for specific requirements.
114
+ #
115
+ # The option will be added to a list of default options that will be applied to all subsequently created contexts.
116
+ #
117
+ # Available since libusb-1.0.22, LIBUSB_API_VERSION >= 0x01000106
118
+ #
119
+ # @param [Symbol, Fixnum] option
120
+ # @param args Zero or more arguments depending on +option+
121
+ #
122
+ # Available since libusb-1.0.22
123
+ def set_option(option, *args)
124
+ ffi_args = option_args_to_ffi(option, args, self)
125
+ res = Call.libusb_set_option(nil, option, *ffi_args)
126
+ LIBUSB.raise_error res, "in libusb_set_option" if res<0
127
+ end
128
+
129
+ # Convenience function to set default options in the libusb library.
130
+ #
131
+ # Use this function to configure any number of options within the library.
132
+ # It takes a Hash the same way as given to {Context.initialize}.
133
+ # See also {Call::Options option list}.
134
+ #
135
+ # Available since libusb-1.0.22, LIBUSB_API_VERSION >= 0x01000106
136
+ #
137
+ # @param [Hash{Call::Options => Object}] options Option hash
138
+ # @see set_option
139
+ def set_options(options={})
140
+ options.each do |k, v|
141
+ set_option(k, *Array(v))
142
+ end
143
+ end
56
144
  end
57
145
  end
58
146
  end
data/libusb.gemspec CHANGED
@@ -20,11 +20,9 @@ Gem::Specification.new do |s|
20
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
21
  s.require_paths = ["lib"]
22
22
  s.extensions = ['ext/extconf.rb']
23
+ s.metadata["yard.run"] = "yri"
23
24
 
24
- s.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
25
+ s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
25
26
  s.add_runtime_dependency 'ffi', '~> 1.0'
26
27
  s.add_runtime_dependency 'mini_portile2', LIBUSB::MINI_PORTILE_VERSION
27
- s.add_development_dependency 'rake-compiler', '~> 1.0'
28
- s.add_development_dependency 'rake-compiler-dock', '~> 0.2'
29
- s.add_development_dependency 'bundler', '~> 1.0'
30
28
  end
@@ -16,22 +16,24 @@
16
16
  require "minitest/autorun"
17
17
  require "libusb"
18
18
 
19
- class TestLibusbVersion < Minitest::Test
20
- def setup
21
- @v = LIBUSB.version
19
+ class TestLibusb < Minitest::Test
20
+ def test_has_capability
21
+ assert LIBUSB.has_capability?(:CAP_HAS_CAPABILITY)
22
22
  end
23
23
 
24
24
  def test_version_parts
25
- assert_operator @v.major, :>=, 0
26
- assert_operator @v.minor, :>=, 0
27
- assert_operator @v.micro, :>=, 0
28
- assert_operator @v.nano, :>=, 0
29
- assert_kind_of String, @v.rc
25
+ v = LIBUSB.version
26
+ assert_operator v.major, :>=, 0
27
+ assert_operator v.minor, :>=, 0
28
+ assert_operator v.micro, :>=, 0
29
+ assert_operator v.nano, :>=, 0
30
+ assert_kind_of String, v.rc
30
31
  end
31
32
 
32
33
  def test_version_string
33
- assert_match(/^\d+\.\d+\.\d+/, @v.to_s)
34
- assert_match(/^#<LIBUSB::Version \d+\.\d+\.\d+/, @v.inspect)
34
+ v = LIBUSB.version
35
+ assert_match(/^\d+\.\d+\.\d+/, v.to_s)
36
+ assert_match(/^#<LIBUSB::Version \d+\.\d+\.\d+/, v.inspect)
35
37
  end
36
38
 
37
39
  def test_gem_version_string
@@ -53,6 +53,23 @@ class TestLibusbBos < Minitest::Test
53
53
  :BT_USB_2_0_EXTENSION,
54
54
  :BT_SS_USB_DEVICE_CAPABILITY,
55
55
  :BT_CONTAINER_ID,
56
+ :BT_WIRELESS_USB_DEVICE_CAPABILITY,
57
+ :BT_USB_2_0_EXTENSION,
58
+ :BT_SS_USB_DEVICE_CAPABILITY,
59
+ :BT_CONTAINER_ID,
60
+ :BT_PLATFORM_DESCRIPTOR,
61
+ :BT_POWER_DELIVERY_CAPABILITY,
62
+ :BT_BATTERY_INFO_CAPABILITY,
63
+ :BT_PD_CONSUMER_PORT_CAPABILITY,
64
+ :BT_PD_PROVIDER_PORT_CAPABILITY,
65
+ :BT_SUPERSPEED_PLUS,
66
+ :BT_PRECISION_TIME_MEASUREMENT,
67
+ :BT_Wireless_USB_Ext,
68
+ :BT_BILLBOARD,
69
+ :BT_AUTHENTICATION,
70
+ :BT_BILLBOARD_EX,
71
+ :BT_CONFIGURATION_SUMMARY,
72
+ :BT_FWStatus_Capability,
56
73
  ], :include?, cap_type
57
74
  end
58
75
 
@@ -90,6 +107,11 @@ class TestLibusbBos < Minitest::Test
90
107
  assert_operator 0, :<=, cap.bReserved
91
108
  assert_operator 16, :==, cap.container_id.bytesize, "container_id should be 16 bytes long"
92
109
 
110
+ when Bos::PlatformDescriptor
111
+ assert_operator 0, :<=, cap.bReserved
112
+ assert_operator 16, :==, cap.platformCapabilityUUID.bytesize, "container_id should be 16 bytes long"
113
+ assert_kind_of String, cap.capabilityData
114
+
93
115
  else
94
116
  refute true, "invalid device capability class"
95
117
  end
@@ -21,11 +21,18 @@ class TestLibusbBulkStreamTransfer < Minitest::Test
21
21
 
22
22
  def setup
23
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"
24
+ c.devices.each do |dev|
25
+ if [:SPEED_SUPER, :SPEED_SUPER_PLUS].include?(dev.device_speed)
26
+ dev.endpoints.each do |ep|
27
+ if ep.transfer_type == :bulk
28
+ ss = ep.ss_companion
29
+ if ss.bmAttributes & 0x1f > 0
30
+ @dev = dev.open
31
+ break
32
+ end
33
+ end
34
+ end
35
+ end
29
36
  end
30
37
  end
31
38
 
@@ -34,17 +41,21 @@ class TestLibusbBulkStreamTransfer < Minitest::Test
34
41
  end
35
42
 
36
43
  def test_alloc_streams
37
- assert_raises(ERROR_NOT_SUPPORTED, "TODO: test with a OS that supports bulk streams and against a real device") do
38
- nr_allocated = @dev.alloc_streams( 2, @dev.device.endpoints )
39
- end
44
+ skip "no device found with bulk stream support" unless @dev
40
45
 
41
- assert_raises(ERROR_NOT_SUPPORTED) do
42
- @dev.free_streams( [0x01,0x82] )
43
- end
46
+ nr_allocated = @dev.alloc_streams( 2, @dev.device.endpoints )
47
+ assert_equal 2, nr_allocated
48
+
49
+ # TODO: test with a OS that supports bulk streams and against a real device
50
+
51
+ @dev.free_streams( [0x01,0x82] )
44
52
  end
45
53
 
46
54
  def test_bulk_stream_transfer
47
- tr = BulkStreamTransfer.new dev_handle: @dev, stream_id: 123, buffer: ' '*100
55
+ c = Context.new
56
+ dev = c.devices.first.open
57
+ tr = BulkStreamTransfer.new dev_handle: dev, stream_id: 123, buffer: ' '*100
48
58
  assert_equal 123, tr.stream_id, "stream_id should match"
59
+ dev.close
49
60
  end
50
61
  end
@@ -0,0 +1,88 @@
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 TestLibusbContext < Minitest::Test
20
+ def setup
21
+ @c = LIBUSB::Context.new
22
+ end
23
+
24
+ def teardown
25
+ @c.exit if @c
26
+ end
27
+
28
+ def test_set_option
29
+ @c.set_option LIBUSB::OPTION_LOG_LEVEL, LIBUSB::LOG_LEVEL_NONE
30
+ @c.set_option LIBUSB::OPTION_LOG_LEVEL, LIBUSB::LOG_LEVEL_ERROR
31
+ @c.set_option LIBUSB::OPTION_LOG_LEVEL, LIBUSB::LOG_LEVEL_WARNING
32
+ @c.set_option LIBUSB::OPTION_LOG_LEVEL, LIBUSB::LOG_LEVEL_INFO
33
+ @c.set_option LIBUSB::OPTION_LOG_LEVEL, LIBUSB::LOG_LEVEL_DEBUG
34
+ @c.set_option :OPTION_LOG_LEVEL, :LOG_LEVEL_NONE
35
+ end
36
+
37
+ def test_set_debug
38
+ @c.debug = 4
39
+ @c.debug = 0
40
+ end
41
+
42
+ def test_left_references
43
+ @test_devs = @c.devices
44
+ assert_raises(LIBUSB::RemainingReferencesError) do
45
+ @c.exit
46
+ end
47
+ @c = nil
48
+ end
49
+
50
+ def test_double_exit
51
+ @c.exit
52
+ end
53
+
54
+ def test_log_callback
55
+ skip "only supported on Linux" unless RUBY_PLATFORM=~/linux/
56
+ skip "libusb version older than 1.0.27" if Gem::Version.new(LIBUSB.version) < Gem::Version.new("1.0.27")
57
+
58
+ LIBUSB.set_options OPTION_LOG_CB: [nil], OPTION_LOG_LEVEL: LIBUSB::LOG_LEVEL_NONE
59
+ begin
60
+ called = Hash.new { |h, k| h[k] = [] }
61
+ LIBUSB.set_options OPTION_LOG_CB: proc{|*a| called[:global] << a }, OPTION_LOG_LEVEL: LIBUSB::LOG_LEVEL_DEBUG
62
+
63
+ c = LIBUSB::Context.new OPTION_LOG_CB: proc{|*a| called[:ctx1] << a }, OPTION_NO_DEVICE_DISCOVERY: nil
64
+ c.devices
65
+ c.set_log_cb(LIBUSB::LOG_CB_CONTEXT){|*a| called[:ctx2] << a }
66
+ c.devices
67
+
68
+ #pp called
69
+ assert_nil called[:global][0][0]
70
+ assert_equal :LOG_LEVEL_DEBUG, called[:global][0][1], called[:global][0][2]
71
+ assert_match(/libusb_init_context/, called[:global].join)
72
+ assert_match(/no device discovery/, called[:global].join)
73
+
74
+ assert_operator called[:ctx1].size, :>, called[:ctx2].size
75
+ assert_equal c, called[:ctx1][-1][0]
76
+ assert_equal :LOG_LEVEL_DEBUG, called[:ctx1][-1][1]
77
+ assert_match(/libusb_get_device_list/, called[:ctx1][-1][2])
78
+ assert_match(/no device discovery/, called[:ctx1].join)
79
+
80
+ assert_equal c, called[:ctx2][-1][0]
81
+ assert_equal :LOG_LEVEL_DEBUG, called[:ctx2][-1][1]
82
+ assert_match(/libusb_get_device_list/, called[:ctx2][-1][2])
83
+
84
+ ensure
85
+ LIBUSB.set_options OPTION_LOG_CB: [nil], OPTION_LOG_LEVEL: LIBUSB::LOG_LEVEL_NONE
86
+ end
87
+ end
88
+ end
@@ -119,7 +119,7 @@ class TestLibusbDescriptors < Minitest::Test
119
119
 
120
120
  usb.devices.each do |dev|
121
121
  dev.endpoints.each do |ep|
122
- if dev.device_speed == :SPEED_SUPER
122
+ if [:SPEED_SUPER, :SPEED_SUPER_PLUS].include?(dev.device_speed)
123
123
  ss = ep.ss_companion
124
124
  assert_match(/SsCompanion/, ss.inspect, "SsCompanion#inspect should work")
125
125
 
@@ -172,14 +172,19 @@ class TestLibusbDescriptors < Minitest::Test
172
172
  def test_device_filter_hubs
173
173
  devs1 = []
174
174
  usb.devices.each do |dev|
175
- dev.settings.each do |if_desc|
176
- if if_desc.bInterfaceClass == CLASS_HUB
177
- devs1 << dev
175
+ if dev.bDeviceClass==CLASS_PER_INTERFACE
176
+ dev.settings.each do |if_desc|
177
+ if if_desc.bInterfaceClass==CLASS_HUB
178
+ devs1 << dev
179
+ end
178
180
  end
181
+ else
182
+ devs1 << dev if dev.bDeviceClass == CLASS_HUB
179
183
  end
180
184
  end
181
185
 
182
186
  devs2 = usb.devices( bClass: CLASS_HUB )
187
+
183
188
  assert_equal devs1.sort, devs2.sort, "devices and devices with filter should deliver the same device"
184
189
  end
185
190
 
@@ -189,11 +194,11 @@ class TestLibusbDescriptors < Minitest::Test
189
194
  if ep
190
195
  assert_operator dev.max_packet_size(ep), :>, 0, "#{dev.inspect} should have a usable packet size"
191
196
  assert_operator dev.max_packet_size(ep.bEndpointAddress), :>, 0, "#{dev.inspect} should have a usable packet size"
192
- assert_operator dev.max_iso_packet_size(ep), :>, 0, "#{dev.inspect} should have a usable iso packet size"
193
- assert_operator dev.max_iso_packet_size(ep.bEndpointAddress), :>, 0, "#{dev.inspect} should have a usable iso packet size"
197
+ assert_operator dev.max_iso_packet_size(ep), :>=, 0, "#{dev.inspect} should have a usable iso packet size"
198
+ assert_operator dev.max_iso_packet_size(ep.bEndpointAddress), :>=, 0, "#{dev.inspect} should have a usable iso packet size"
194
199
  assert_operator dev.bus_number, :>=, 0, "#{dev.inspect} should have a bus_number"
195
200
  assert_operator dev.device_address, :>=, 0, "#{dev.inspect} should have a device_address"
196
- assert_operator([:SPEED_UNKNOWN, :SPEED_LOW, :SPEED_FULL, :SPEED_HIGH, :SPEED_SUPER], :include?, dev.device_speed, "#{dev.inspect} should have a device_speed")
201
+ assert_operator([:SPEED_UNKNOWN, :SPEED_LOW, :SPEED_FULL, :SPEED_HIGH, :SPEED_SUPER, :SPEED_SUPER_PLUS], :include?, dev.device_speed, "#{dev.inspect} should have a device_speed")
197
202
  path = dev.port_numbers
198
203
  assert_kind_of Array, path, "#{dev.inspect} should have port_numbers"
199
204
  path = dev.port_path
@@ -201,12 +206,40 @@ class TestLibusbDescriptors < Minitest::Test
201
206
  path.each do |port|
202
207
  assert_operator port, :>, 0, "#{dev.inspect} should have proper port_path entries"
203
208
  end
204
- assert_equal path[-1], dev.port_number, "#{dev.inspect} should have a port number out of the port_path"
205
- if parent=dev.parent
206
- assert_kind_of Device, parent, "#{dev.inspect} should have a parent"
207
- assert_equal path[-2], parent.port_number, "#{dev.inspect} should have a parent port number out of the port_path"
209
+ if path.empty?
210
+ assert_nil dev.port_number
211
+ else
212
+ assert_equal path[-1], dev.port_number, "#{dev.inspect} should have a port number out of the port_path"
213
+ if parent=dev.parent
214
+ assert_kind_of Device, parent, "#{dev.inspect} should have a parent"
215
+ assert_equal path[-2], parent.port_number, "#{dev.inspect} should have a parent port number out of the port_path" if parent.port_number
216
+ end
208
217
  end
209
218
  end
210
219
  end
211
220
  end
221
+
222
+ def test_wrap_sys_device
223
+ skip unless RUBY_PLATFORM =~ /linux/
224
+ d = usb.devices[0]
225
+ File.open(format("/dev/bus/usb/%03d/%03d", d.bus_number, d.device_address), "w+") do |io|
226
+ devh = usb.wrap_sys_device(io)
227
+ devh.kernel_driver_active?(0)
228
+ devh.close
229
+
230
+ usb.wrap_sys_device(io) do |devh|
231
+ devh.kernel_driver_active?(0)
232
+ end
233
+ end
234
+ end
235
+
236
+ def test_wrap_sys_device_failure
237
+ skip unless RUBY_PLATFORM =~ /linux/
238
+ d = usb.devices[0]
239
+ assert_raises(LIBUSB::ERROR_OTHER) do
240
+ File.open(format("/dev/bus/usb/%03d/%03d", d.bus_number, d.device_address), "r") do |io|
241
+ usb.wrap_sys_device(io).kernel_driver_active?(0)
242
+ end
243
+ end
244
+ end
212
245
  end