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.
- checksums.yaml +4 -4
- data/.appveyor.yml +33 -0
- data/.github/workflows/ci.yml +185 -0
- data/.gitignore +1 -0
- data/.travis.yml +12 -7
- data/Gemfile +4 -1
- data/History.md +38 -0
- data/README.md +29 -4
- data/Rakefile +41 -12
- data/lib/libusb/bos.rb +85 -29
- data/lib/libusb/call.rb +132 -16
- data/lib/libusb/configuration.rb +3 -4
- data/lib/libusb/constants.rb +4 -0
- data/lib/libusb/context.rb +176 -35
- data/lib/libusb/context_reference.rb +38 -0
- data/lib/libusb/dependencies.rb +2 -2
- data/lib/libusb/dev_handle.rb +34 -24
- data/lib/libusb/device.rb +50 -8
- data/lib/libusb/endpoint.rb +3 -2
- data/lib/libusb/eventmachine.rb +8 -4
- data/lib/libusb/gem_helper.rb +9 -6
- data/lib/libusb/libusb_recipe.rb +2 -3
- data/lib/libusb/ss_companion.rb +9 -6
- data/lib/libusb/transfer.rb +10 -6
- data/lib/libusb/version_gem.rb +1 -1
- data/lib/libusb-1.0.dll +0 -0
- data/lib/libusb.rb +106 -18
- data/libusb.gemspec +1 -5
- data/test/test_libusb_bos.rb +22 -0
- data/test/test_libusb_bulk_stream_transfer.rb +23 -12
- data/test/test_libusb_context.rb +47 -0
- data/test/test_libusb_descriptors.rb +44 -11
- data/test/test_libusb_gc.rb +15 -0
- data/test/test_libusb_hotplug.rb +3 -1
- data/test/test_libusb_iso_transfer.rb +6 -0
- data/test/test_libusb_mass_storage.rb +6 -6
- metadata +7 -62
- data/appveyor.yml +0 -36
data/lib/libusb/dev_handle.rb
CHANGED
@@ -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(
|
376
|
-
|
377
|
-
|
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
|
384
|
+
dataIn || raise(ArgumentError, "no :dataIn given for bulk read")
|
381
385
|
else
|
382
|
-
dataOut
|
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:
|
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(
|
444
|
-
|
445
|
-
|
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
|
454
|
+
dataIn || raise(ArgumentError, "no :dataIn given for interrupt read")
|
449
455
|
else
|
450
|
-
dataOut
|
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:
|
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(
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
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
|
-
|
516
|
+
raise ArgumentError, "invalid param :dataOut" unless dataOut.nil?
|
517
|
+
dataIn ||= 0
|
508
518
|
dataOut = ''
|
509
519
|
else
|
510
|
-
|
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:
|
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
|
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
|
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
|
373
|
+
@serial_number = @serial_number.strip if @serial_number
|
332
374
|
@serial_number
|
333
375
|
end
|
334
376
|
|
data/lib/libusb/endpoint.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/libusb/eventmachine.rb
CHANGED
@@ -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
|
|
data/lib/libusb/gem_helper.rb
CHANGED
@@ -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
|
-
|
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 =
|
91
|
-
recipe.configure_options << "--host=#{
|
92
|
-
recipe.configure_options << "CC=#{
|
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
|
102
|
-
task :cross =>
|
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 = []
|
data/lib/libusb/libusb_recipe.rb
CHANGED
@@ -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,
|
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
|
data/lib/libusb/ss_companion.rb
CHANGED
@@ -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::
|
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
|
data/lib/libusb/transfer.rb
CHANGED
@@ -28,16 +28,16 @@ module LIBUSB
|
|
28
28
|
class ZeroCopyMemory < FFI::Pointer
|
29
29
|
attr_reader :size
|
30
30
|
|
31
|
-
def initialize(
|
32
|
-
@
|
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
|
-
|
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
|
259
|
+
rescue Exception
|
256
260
|
cancel!
|
257
261
|
until @completion_flag.completed?
|
258
262
|
@dev_handle.device.context.handle_events nil, @completion_flag
|
data/lib/libusb/version_gem.rb
CHANGED
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
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(">=
|
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
|
data/test/test_libusb_bos.rb
CHANGED
@@ -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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
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
|