libusb 0.6.4-x64-mingw32 → 0.7.0-x64-mingw32

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.
@@ -372,19 +372,22 @@ module LIBUSB
372
372
  # @yieldparam [String, Integer, LIBUSB::Error] result result of the transfer is yielded to the block,
373
373
  # when the asynchronous transfer has finished
374
374
  # @raise [ArgumentError, LIBUSB::Error] in case of failure
375
- def bulk_transfer(args={}, &block)
376
- timeout = args.delete(:timeout) || 1000
377
- endpoint = args.delete(:endpoint) || raise(ArgumentError, "no endpoint given")
375
+ def bulk_transfer(timeout: 1000,
376
+ endpoint:,
377
+ dataIn: nil,
378
+ dataOut: nil,
379
+ allow_device_memory: false,
380
+ &block)
381
+
378
382
  endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
379
383
  if endpoint&ENDPOINT_IN != 0
380
- dataIn = args.delete(:dataIn) || raise(ArgumentError, "no :dataIn given for bulk read")
384
+ dataIn || raise(ArgumentError, "no :dataIn given for bulk read")
381
385
  else
382
- dataOut = args.delete(:dataOut) || raise(ArgumentError, "no :dataOut given for bulk write")
386
+ dataOut || raise(ArgumentError, "no :dataOut given for bulk write")
383
387
  end
384
- raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
385
388
 
386
389
  # reuse transfer struct to speed up transfer
387
- @bulk_transfer ||= BulkTransfer.new dev_handle: self, allow_device_memory: true
390
+ @bulk_transfer ||= BulkTransfer.new dev_handle: self, allow_device_memory: allow_device_memory
388
391
  tr = @bulk_transfer
389
392
  tr.endpoint = endpoint
390
393
  tr.timeout = timeout
@@ -440,19 +443,21 @@ module LIBUSB
440
443
  # @yieldparam [String, Integer, LIBUSB::Error] result result of the transfer is yielded to the block,
441
444
  # when the asynchronous transfer has finished
442
445
  # @raise [ArgumentError, LIBUSB::Error] in case of failure
443
- def interrupt_transfer(args={}, &block)
444
- timeout = args.delete(:timeout) || 1000
445
- endpoint = args.delete(:endpoint) || raise(ArgumentError, "no endpoint given")
446
+ def interrupt_transfer(timeout: 1000,
447
+ endpoint:,
448
+ dataIn: nil,
449
+ dataOut: nil,
450
+ allow_device_memory: false,
451
+ &block)
446
452
  endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
447
453
  if endpoint&ENDPOINT_IN != 0
448
- dataIn = args.delete(:dataIn) || raise(ArgumentError, "no :dataIn given for interrupt read")
454
+ dataIn || raise(ArgumentError, "no :dataIn given for interrupt read")
449
455
  else
450
- dataOut = args.delete(:dataOut) || raise(ArgumentError, "no :dataOut given for interrupt write")
456
+ dataOut || raise(ArgumentError, "no :dataOut given for interrupt write")
451
457
  end
452
- raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
453
458
 
454
459
  # reuse transfer struct to speed up transfer
455
- @interrupt_transfer ||= InterruptTransfer.new dev_handle: self, allow_device_memory: true
460
+ @interrupt_transfer ||= InterruptTransfer.new dev_handle: self, allow_device_memory: allow_device_memory
456
461
  tr = @interrupt_transfer
457
462
  tr.endpoint = endpoint
458
463
  tr.timeout = timeout
@@ -497,22 +502,27 @@ module LIBUSB
497
502
  # @yieldparam [String, Integer, LIBUSB::Error] result result of the transfer is yielded to the block,
498
503
  # when the asynchronous transfer has finished
499
504
  # @raise [ArgumentError, LIBUSB::Error] in case of failure
500
- def control_transfer(args={}, &block)
501
- bmRequestType = args.delete(:bmRequestType) || raise(ArgumentError, "param :bmRequestType not given")
502
- bRequest = args.delete(:bRequest) || raise(ArgumentError, "param :bRequest not given")
503
- wValue = args.delete(:wValue) || raise(ArgumentError, "param :wValue not given")
504
- wIndex = args.delete(:wIndex) || raise(ArgumentError, "param :wIndex not given")
505
- timeout = args.delete(:timeout) || 1000
505
+ def control_transfer(bmRequestType:,
506
+ bRequest:,
507
+ wValue:,
508
+ wIndex:,
509
+ timeout: 1000,
510
+ dataIn: nil,
511
+ dataOut: nil,
512
+ allow_device_memory: false,
513
+ &block)
514
+
506
515
  if bmRequestType&ENDPOINT_IN != 0
507
- dataIn = args.delete(:dataIn) || 0
516
+ raise ArgumentError, "invalid param :dataOut" unless dataOut.nil?
517
+ dataIn ||= 0
508
518
  dataOut = ''
509
519
  else
510
- dataOut = args.delete(:dataOut) || ''
520
+ raise ArgumentError, "invalid param :dataIn" unless dataIn.nil?
521
+ dataOut ||= ''
511
522
  end
512
- raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
513
523
 
514
524
  # reuse transfer struct to speed up transfer
515
- @control_transfer ||= ControlTransfer.new dev_handle: self, allow_device_memory: true
525
+ @control_transfer ||= ControlTransfer.new dev_handle: self, allow_device_memory: allow_device_memory
516
526
  tr = @control_transfer
517
527
  tr.timeout = timeout
518
528
  if dataIn
data/lib/libusb/device.rb CHANGED
@@ -21,24 +21,27 @@ module LIBUSB
21
21
  # Devices of the system can be obtained with {Context#devices} .
22
22
  class Device
23
23
  include Comparable
24
+ include ContextReference
24
25
 
25
26
  # @return [Context] the context this device belongs to.
26
27
  attr_reader :context
27
28
 
28
29
  def initialize context, pDev
29
30
  @context = context
30
- def pDev.unref_device(id)
31
- Call.libusb_unref_device(self)
32
- end
33
- ObjectSpace.define_finalizer(self, pDev.method(:unref_device))
34
- Call.libusb_ref_device(pDev)
35
31
  @pDev = pDev
32
+ register_context(context.instance_variable_get(:@ctx), :libusb_unref_device)
33
+ Call.libusb_ref_device(pDev)
36
34
 
37
35
  @pDevDesc = Call::DeviceDescriptor.new
38
36
  res = Call.libusb_get_device_descriptor(@pDev, @pDevDesc)
39
37
  LIBUSB.raise_error res, "in libusb_get_device_descriptor" if res!=0
40
38
  end
41
39
 
40
+ # The pointer for ContextReference
41
+ private def pointer
42
+ @pDev
43
+ end
44
+
42
45
  # Open the device and obtain a device handle.
43
46
  #
44
47
  # A handle allows you to perform I/O on the device in question.
@@ -160,6 +163,44 @@ module LIBUSB
160
163
  res
161
164
  end
162
165
 
166
+ if Call.respond_to?(:libusb_get_max_alt_packet_size)
167
+
168
+ # Calculate the maximum packet size which a specific endpoint is capable of
169
+ # sending or receiving in the duration of 1 microframe
170
+ #
171
+ # Only the active configuration is examined. The calculation is based on the
172
+ # wMaxPacketSize field in the endpoint descriptor as described in section
173
+ # 9.6.6 in the USB 2.0 specifications.
174
+ #
175
+ # If acting on an isochronous or interrupt endpoint, this function will
176
+ # multiply the value found in bits 0:10 by the number of transactions per
177
+ # microframe (determined by bits 11:12). Otherwise, this function just
178
+ # returns the numeric value found in bits 0:10. For USB 3.0 device, it
179
+ # will attempts to retrieve the Endpoint Companion Descriptor to return
180
+ # wBytesPerInterval.
181
+ #
182
+ # This function is useful for setting up isochronous transfers, for example
183
+ # you might pass the return value from this function to
184
+ # +IsochronousTransfer.packet_lengths=+ in order to set the length field of every
185
+ # isochronous packet in a transfer.
186
+ #
187
+ # Available since libusb-1.0.27.
188
+ #
189
+ # @param [Interface, Fixnum] interface the interface or its bInterfaceNumber of the interface the endpoint belongs to
190
+ # @param [Setting, Fixnum] alternate_setting the alternate setting or its bAlternateSetting
191
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
192
+ # @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
193
+ # @see max_iso_packet_size
194
+ def max_alt_packet_size(interface, alternate_setting, endpoint)
195
+ interface = interface.bInterfaceNumber if interface.respond_to? :bInterfaceNumber
196
+ alternate_setting = alternate_setting.bAlternateSetting if alternate_setting.respond_to? :bAlternateSetting
197
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
198
+ res = Call.libusb_get_max_alt_packet_size(@pDev, interface, alternate_setting, endpoint)
199
+ LIBUSB.raise_error res, "in libusb_get_max_alt_packet_size" unless res>=0
200
+ res
201
+ end
202
+ end
203
+
163
204
  # Calculate the maximum packet size which a specific endpoint is capable is
164
205
  # sending or receiving in the duration of 1 microframe.
165
206
  #
@@ -179,6 +220,7 @@ module LIBUSB
179
220
  #
180
221
  # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
181
222
  # @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
223
+ # @see max_alt_packet_size
182
224
  def max_iso_packet_size(endpoint)
183
225
  endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
184
226
  res = Call.libusb_get_max_iso_packet_size(@pDev, endpoint)
@@ -310,7 +352,7 @@ module LIBUSB
310
352
  def manufacturer
311
353
  return @manufacturer if defined? @manufacturer
312
354
  @manufacturer = try_string_descriptor_ascii(self.iManufacturer)
313
- @manufacturer.strip! if @manufacturer
355
+ @manufacturer = @manufacturer.strip if @manufacturer
314
356
  @manufacturer
315
357
  end
316
358
 
@@ -319,7 +361,7 @@ module LIBUSB
319
361
  def product
320
362
  return @product if defined? @product
321
363
  @product = try_string_descriptor_ascii(self.iProduct)
322
- @product.strip! if @product
364
+ @product = @product.strip if @product
323
365
  @product
324
366
  end
325
367
 
@@ -328,7 +370,7 @@ module LIBUSB
328
370
  def serial_number
329
371
  return @serial_number if defined? @serial_number
330
372
  @serial_number = try_string_descriptor_ascii(self.iSerialNumber)
331
- @serial_number.strip! if @serial_number
373
+ @serial_number = @serial_number.strip if @serial_number
332
374
  @serial_number
333
375
  end
334
376
 
@@ -181,13 +181,14 @@ module LIBUSB
181
181
  # @return [SsCompanion]
182
182
  def ss_companion
183
183
  ep_comp = FFI::MemoryPointer.new :pointer
184
+ ctx = device.context.instance_variable_get(:@ctx)
184
185
  res = Call.libusb_get_ss_endpoint_companion_descriptor(
185
- device.context.instance_variable_get(:@ctx),
186
+ ctx,
186
187
  pointer,
187
188
  ep_comp
188
189
  )
189
190
  LIBUSB.raise_error res, "in libusb_get_ss_endpoint_companion_descriptor" if res!=0
190
- SsCompanion.new ep_comp.read_pointer
191
+ SsCompanion.new ctx, ep_comp.read_pointer
191
192
  end
192
193
  end
193
194
  end
@@ -62,6 +62,10 @@ class Context
62
62
  @eventmachine_attached_fds.each do |fd, watcher|
63
63
  watcher.detach
64
64
  end
65
+
66
+ # Deregister callbacks
67
+ on_pollfd_added
68
+ on_pollfd_removed
65
69
  end
66
70
 
67
71
  class EMPollfdHandler < EventMachine::Connection
@@ -118,7 +122,7 @@ class DevHandle
118
122
  include EM::Deferrable
119
123
 
120
124
  def initialize(opts, dev_handle, transfer_method)
121
- dev_handle.send(transfer_method, opts) do |res|
125
+ dev_handle.send(transfer_method, **opts) do |res|
122
126
  EM.next_tick do
123
127
  if res.kind_of?(LIBUSB::Error)
124
128
  fail res
@@ -134,7 +138,7 @@ class DevHandle
134
138
  #
135
139
  # @see Context#eventmachine_register
136
140
  # DevHandle#interrupt_transfer
137
- def eventmachine_interrupt_transfer(opts={})
141
+ def eventmachine_interrupt_transfer(**opts)
138
142
  eventmachine_transfer(opts, :interrupt_transfer)
139
143
  end
140
144
 
@@ -151,7 +155,7 @@ class DevHandle
151
155
  #
152
156
  # @see Context#eventmachine_register
153
157
  # DevHandle#bulk_transfer
154
- def eventmachine_bulk_transfer(opts={})
158
+ def eventmachine_bulk_transfer(**opts)
155
159
  eventmachine_transfer(opts, :bulk_transfer)
156
160
  end
157
161
 
@@ -171,7 +175,7 @@ class DevHandle
171
175
  #
172
176
  # @see Context#eventmachine_register
173
177
  # DevHandle#control_transfer
174
- def eventmachine_control_transfer(opts={})
178
+ def eventmachine_control_transfer(**opts)
175
179
  eventmachine_transfer(opts, :control_transfer)
176
180
  end
177
181
 
@@ -66,7 +66,7 @@ module LIBUSB
66
66
  yield if block_given?
67
67
  rescue
68
68
  Bundler.ui.error "Untagging #{version_tag} due to error."
69
- sh_with_code "git tag -d #{version_tag}"
69
+ sh "git tag -d #{version_tag}"
70
70
  raise
71
71
  end
72
72
 
@@ -87,9 +87,9 @@ module LIBUSB
87
87
 
88
88
  self.ruby_platform = ruby_platform
89
89
  self.recipe = LIBUSB::LibusbRecipe.new
90
- recipe.host = host_platform
91
- recipe.configure_options << "--host=#{recipe.host}"
92
- recipe.configure_options << "CC=#{recipe.host}-gcc -static-libgcc" if recipe.host =~ /mingw/
90
+ recipe.host = ruby_platform
91
+ recipe.configure_options << "--host=#{host_platform}"
92
+ recipe.configure_options << "CC=#{host_platform}-gcc -static-libgcc" if recipe.host =~ /mingw/
93
93
  self.libusb_dll = Pathname.new(recipe.path) + libusb_dllname
94
94
 
95
95
  file libusb_dll do
@@ -98,8 +98,11 @@ module LIBUSB
98
98
 
99
99
  task "libusb_dll:#{ruby_platform}" => libusb_dll
100
100
 
101
- desc 'Cross compile libusb for win32'
102
- task :cross => [ "libusb_dll:#{ruby_platform}" ] do |t|
101
+ desc 'Cross compile libusb for all targets'
102
+ task :cross => "cross:#{ruby_platform}"
103
+
104
+ desc "Cross compile libusb for #{ruby_platform}"
105
+ task "cross:#{ruby_platform}" => [ "libusb_dll:#{ruby_platform}" ] do |t|
103
106
  spec = Gem::Specification::load("libusb.gemspec").dup
104
107
  spec.platform = Gem::Platform.new(ruby_platform)
105
108
  spec.extensions = []
@@ -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,16 +28,16 @@ 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
@@ -60,6 +60,10 @@ module LIBUSB
60
60
  def dev_handle=(dev)
61
61
  @dev_handle = dev
62
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)
63
67
  end
64
68
 
65
69
  # The handle for the device to communicate with.
@@ -163,7 +167,7 @@ module LIBUSB
163
167
  ptr = Call.libusb_dev_mem_alloc( @dev_handle.pHandle, len )
164
168
  # puts format("libusb_dev_mem_alloc(%d) => %#x", len, ptr.address)
165
169
  unless ptr.null?
166
- buffer = ZeroCopyMemory.new(@dev_handle, ptr, len)
170
+ buffer = ZeroCopyMemory.new(@dev_handle.pHandle, ptr, len)
167
171
  ObjectSpace.define_finalizer(self, buffer.method(:free))
168
172
  end
169
173
  end
@@ -252,7 +256,7 @@ module LIBUSB
252
256
  @dev_handle.device.context.handle_events nil, @completion_flag
253
257
  rescue ERROR_INTERRUPTED
254
258
  next
255
- rescue LIBUSB::Error
259
+ rescue Exception
256
260
  cancel!
257
261
  until @completion_flag.completed?
258
262
  @dev_handle.device.context.handle_events nil, @completion_flag
@@ -15,5 +15,5 @@
15
15
 
16
16
  module LIBUSB
17
17
  # Library version of libusb for Ruby
18
- VERSION = "0.6.4"
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
@@ -22,11 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.extensions = ['ext/extconf.rb']
23
23
  s.metadata["yard.run"] = "yri"
24
24
 
25
- s.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
25
+ s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
26
26
  s.add_runtime_dependency 'ffi', '~> 1.0'
27
27
  s.add_runtime_dependency 'mini_portile2', LIBUSB::MINI_PORTILE_VERSION
28
- s.add_development_dependency 'rake-compiler', '~> 1.0'
29
- s.add_development_dependency 'rake-compiler-dock', '~> 0.2'
30
- s.add_development_dependency 'bundler', '~> 1.0'
31
- s.add_development_dependency 'yard', '~> 0.6'
32
28
  end
@@ -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