libusb 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/History.md +17 -1
- data/Rakefile +1 -2
- data/ext/extconf.rb +1 -0
- data/lib/libusb/bos.rb +153 -14
- data/lib/libusb/call.rb +86 -1
- data/lib/libusb/constants.rb +11 -0
- data/lib/libusb/context.rb +5 -6
- data/lib/libusb/context_reference.rb +5 -0
- data/lib/libusb/dependencies.rb +2 -2
- data/lib/libusb/dev_handle.rb +18 -21
- data/lib/libusb/device.rb +54 -5
- data/lib/libusb/eventmachine.rb +18 -2
- data/lib/libusb/gem_helper.rb +1 -0
- data/lib/libusb/transfer.rb +3 -3
- data/lib/libusb/version_gem.rb +1 -1
- data/ports/archives/libusb-1.0.30.tar.bz2 +0 -0
- data/test/test_libusb_bos.rb +27 -5
- data/test/test_libusb_descriptors.rb +13 -0
- data/test/test_libusb_event_machine_eintr.rb +81 -0
- metadata +5 -7
- data/ports/archives/libusb-1.0.27.tar.bz2 +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 81987d2e99821ceff5acf54c463c28b83fcb586aa401d3c90d23af4777bde459
|
|
4
|
+
data.tar.gz: 9921b3deb351982884c2848313721d786fe1e4bcf5e4db2dcff37cda297ec05a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39ab11140cb2d68b5540337fb7d5c27743956cd479576002f194ac5f2b89d67711819fee84932f76090cb877cb11034294721f56031b4578fb717a722ebf0184
|
|
7
|
+
data.tar.gz: c11df155a20a7cfbeeae72bb313c79ea47b1d5fb3a6c94869e294ba261f7a995901553aafc943719ffd13db31e5d592c32c6a08ce53b887d3382788de9a83434
|
data/Gemfile
CHANGED
|
@@ -10,8 +10,9 @@ end
|
|
|
10
10
|
|
|
11
11
|
gem 'rake-compiler-dock', '~> 1.1'
|
|
12
12
|
gem 'rake-compiler', '~> 1.0'
|
|
13
|
-
gem 'bundler', '>= 1', '<
|
|
13
|
+
gem 'bundler', '>= 1', '< 5.a'
|
|
14
14
|
gem 'yard', '~> 0.6', '>= 0.9.36'
|
|
15
|
+
gem 'ostruct', '~> 0.1'
|
|
15
16
|
|
|
16
17
|
# For some reason this is required in addition to the gemspec
|
|
17
18
|
# when 'bundle config force_ruby_platform true' is active:
|
data/History.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
0.8.0 / 2026-08-02
|
|
2
|
+
------------------
|
|
3
|
+
|
|
4
|
+
Added:
|
|
5
|
+
* Add LIBUSB::SsplusUsbDeviceCapability introduced in libusb-1.0.28. #53
|
|
6
|
+
* Add LIBUSB::Device#device_string and prefer it in Device#inspect. #54
|
|
7
|
+
This retrievs product string, manufacturer and serial number from the OS without opening the device.
|
|
8
|
+
* Enable hotplug support on Windows introduced in libusb-1.0.30.
|
|
9
|
+
* Add LIBUSB::Device#get_session_data introduced in libusb-1.0.30. #54
|
|
10
|
+
|
|
11
|
+
Changed:
|
|
12
|
+
* Don't kill the EventMachine reactor on LIBUSB_ERROR_INTERRUPTED. #52
|
|
13
|
+
* Improve yard docs.
|
|
14
|
+
* Update builtin libusb to 1.0.30
|
|
15
|
+
|
|
16
|
+
|
|
1
17
|
0.7.2 / 2024-10-23
|
|
2
18
|
------------------
|
|
3
19
|
|
|
@@ -150,7 +166,7 @@ Deprecated:
|
|
|
150
166
|
* Build bundled libusbx sources in case libusb-1.0.so can not be loaded from the system
|
|
151
167
|
* Replace Hoe with Bundler
|
|
152
168
|
* Add timeout and completion_flag to Context#handle_events
|
|
153
|
-
* Add asynchronous DevHandle#{control|interrupt|bulk}_transfer method variants
|
|
169
|
+
* Add asynchronous `DevHandle#{control|interrupt|bulk}_transfer` method variants
|
|
154
170
|
* Add the ability to retrieve the data already transfered when it comes to an exception
|
|
155
171
|
* Add notification API for libusb's file describtors for event driven USB transfers
|
|
156
172
|
* Add experimental integration to EventMachine
|
data/Rakefile
CHANGED
|
@@ -5,7 +5,6 @@ require 'bundler/gem_helper'
|
|
|
5
5
|
require 'rubygems/package_task'
|
|
6
6
|
require 'pathname'
|
|
7
7
|
require 'uri'
|
|
8
|
-
require 'ostruct'
|
|
9
8
|
require 'rake/clean'
|
|
10
9
|
require_relative 'lib/libusb/libusb_recipe'
|
|
11
10
|
require_relative 'lib/libusb/gem_helper'
|
|
@@ -39,7 +38,7 @@ task :gemfile_libusb_gem do
|
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
task :test do
|
|
42
|
-
sh "ruby -w -W2 -I
|
|
41
|
+
sh "ruby -w -W2 -I. -Ilib -e \"#{Dir["test/test_*.rb"].map{|f| "require '#{f}';"}.join}\" -- -v"
|
|
43
42
|
end
|
|
44
43
|
task :default => :test
|
|
45
44
|
|
data/ext/extconf.rb
CHANGED
|
@@ -70,6 +70,7 @@ def build_bundled_libusb(have_udev)
|
|
|
70
70
|
|
|
71
71
|
require_relative '../lib/libusb/libusb_recipe'
|
|
72
72
|
recipe = LIBUSB::LibusbRecipe.new
|
|
73
|
+
recipe.configure_options << "--enable-windows-hotplug"
|
|
73
74
|
recipe.configure_options << "--disable-udev" unless have_udev
|
|
74
75
|
recipe.cook_and_activate
|
|
75
76
|
recipe.path
|
data/lib/libusb/bos.rb
CHANGED
|
@@ -169,10 +169,11 @@ module LIBUSB
|
|
|
169
169
|
# device supports all its functionality when connected at
|
|
170
170
|
# full speed and above then it sets this value to 1.
|
|
171
171
|
#
|
|
172
|
-
# 0 - low speed
|
|
173
|
-
# 1 - full speed
|
|
174
|
-
# 2 - high speed
|
|
175
|
-
# 3 - super speed
|
|
172
|
+
# * 0 - low speed
|
|
173
|
+
# * 1 - full speed
|
|
174
|
+
# * 2 - high speed
|
|
175
|
+
# * 3 - super speed
|
|
176
|
+
#
|
|
176
177
|
# @return [Integer]
|
|
177
178
|
def bFunctionalitySupport
|
|
178
179
|
self[:bFunctionalitySupport]
|
|
@@ -189,6 +190,137 @@ module LIBUSB
|
|
|
189
190
|
end
|
|
190
191
|
end
|
|
191
192
|
|
|
193
|
+
# A structure representing a SuperSpeedPlus descriptor attribute
|
|
194
|
+
#
|
|
195
|
+
# @see SsplusUsbDeviceCapability
|
|
196
|
+
class SsplusSublinkAttribute < FFI::Struct
|
|
197
|
+
|
|
198
|
+
layout :ssid, :uint8,
|
|
199
|
+
:exponent, Call::SuperspeedplusSublinkAttributeExponent,
|
|
200
|
+
:type, Call::SuperspeedplusSublinkAttributeSublinkType,
|
|
201
|
+
:direction, Call::SuperspeedplusSublinkAttributeSublinkDirection,
|
|
202
|
+
:protocol, Call::SuperspeedplusSublinkAttributeLinkProtocol,
|
|
203
|
+
:mantissa, :uint16
|
|
204
|
+
|
|
205
|
+
# Sublink Speed Attribute ID (SSID).
|
|
206
|
+
#
|
|
207
|
+
# This field is an ID that uniquely identifies the speed of this sublink.
|
|
208
|
+
def ssid
|
|
209
|
+
self[:ssid]
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# This field defines the base 10 exponent times 3, that shall be applied to the mantissa.
|
|
213
|
+
# @see Call::SuperspeedplusSublinkAttributeExponent
|
|
214
|
+
def exponent
|
|
215
|
+
self[:exponent]
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# This field identifies whether the Sublink Speed Attribute defines a symmetric or asymmetric bit rate.
|
|
219
|
+
# @see Call::SuperspeedplusSublinkAttributeSublinkType
|
|
220
|
+
def type
|
|
221
|
+
self[:type]
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# This field indicates if this Sublink Speed Attribute defines the receive or transmit bit rate.
|
|
225
|
+
# @see Call::SuperspeedplusSublinkAttributeSublinkDirection
|
|
226
|
+
def direction
|
|
227
|
+
self[:direction]
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# This field identifies the protocol supported by the link.
|
|
231
|
+
# @see Call::SuperspeedplusSublinkAttributeLinkProtocol
|
|
232
|
+
def protocol
|
|
233
|
+
self[:protocol]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# This field defines the mantissa that shall be applied to the exponent when calculating the maximum bit rate.
|
|
237
|
+
def mantissa
|
|
238
|
+
self[:mantissa]
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def to_s_human_readable
|
|
242
|
+
exponents = {
|
|
243
|
+
SSPLUS_ATTR_EXP_BPS: " ",
|
|
244
|
+
SSPLUS_ATTR_EXP_KBS: "K",
|
|
245
|
+
SSPLUS_ATTR_EXP_MBS: "M",
|
|
246
|
+
SSPLUS_ATTR_EXP_GBS: "G",
|
|
247
|
+
}
|
|
248
|
+
format("id=%u speed=%u%sbs %s %s SuperSpeed%s",
|
|
249
|
+
ssid,
|
|
250
|
+
mantissa,
|
|
251
|
+
exponents[exponent],
|
|
252
|
+
type == :SSPLUS_ATTR_TYPE_ASYM ? "Asym" : "Sym",
|
|
253
|
+
direction == :SSPLUS_ATTR_DIR_TX ? "TX" : "RX",
|
|
254
|
+
protocol == :SSPLUS_ATTR_PROT_SSPLUS ? "+": "" )
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def inspect
|
|
258
|
+
"\#<#{self.class} #{to_s_human_readable}>"
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# A structure representing the SuperSpeedPlus descriptor
|
|
263
|
+
# This descriptor is documented in section 9.6.2.5 of the USB 3.1 specification.
|
|
264
|
+
class SsplusUsbDeviceCapability < FFI::Struct
|
|
265
|
+
include ContextReference
|
|
266
|
+
|
|
267
|
+
layout :numSublinkSpeedAttributes, :uint8,
|
|
268
|
+
:numSublinkSpeedIDs, :uint8,
|
|
269
|
+
:ssid, :uint8,
|
|
270
|
+
:minRxLaneCount, :uint8,
|
|
271
|
+
:minTxLaneCount, :uint8,
|
|
272
|
+
:sublinkSpeedAttributes, [SsplusSublinkAttribute, 0]
|
|
273
|
+
|
|
274
|
+
def initialize(ctx, *args)
|
|
275
|
+
super(*args)
|
|
276
|
+
|
|
277
|
+
register_context(ctx, :libusb_free_ssplus_usb_device_capability_descriptor)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def inspect
|
|
281
|
+
attrs = %i[ numSublinkSpeedAttributes numSublinkSpeedIDs ssid minRxLaneCount minTxLaneCount ].map do |key|
|
|
282
|
+
"#{key}: #{self.send(key).inspect}"
|
|
283
|
+
end
|
|
284
|
+
"\#<#{self.class} #{attrs.join(", ")}>"
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Sublink Speed Attribute Count
|
|
288
|
+
def numSublinkSpeedAttributes
|
|
289
|
+
self[:numSublinkSpeedAttributes]
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Sublink Speed ID Count
|
|
293
|
+
def numSublinkSpeedIDs
|
|
294
|
+
self[:numSublinkSpeedIDs]
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Unique ID to indicates the minimum lane speed
|
|
298
|
+
def ssid
|
|
299
|
+
self[:ssid]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# This field indicates the minimum receive lane count.
|
|
303
|
+
def minRxLaneCount
|
|
304
|
+
self[:minRxLaneCount]
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# This field indicates the minimum transmit lane count
|
|
308
|
+
def minTxLaneCount
|
|
309
|
+
self[:minTxLaneCount]
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# Returns an Array of SublinkSpeedAttributes
|
|
313
|
+
#
|
|
314
|
+
# The array size equals {numSublinkSpeedAttributes}.
|
|
315
|
+
#
|
|
316
|
+
# @return [Array<SsplusSublinkAttribute>]
|
|
317
|
+
def sublinkSpeedAttributes
|
|
318
|
+
self[:numSublinkSpeedAttributes].times.map do |idx|
|
|
319
|
+
self[:sublinkSpeedAttributes][idx]
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
192
324
|
# A structure representing the Container ID descriptor.
|
|
193
325
|
# This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
|
|
194
326
|
# All multiple-byte fields, except UUIDs, are represented in host-endian format.
|
|
@@ -308,33 +440,40 @@ module LIBUSB
|
|
|
308
440
|
self[:bNumDeviceCaps]
|
|
309
441
|
end
|
|
310
442
|
|
|
443
|
+
private def wrap_device_capability(cap, func, struct)
|
|
444
|
+
if Call.respond_to?(func)
|
|
445
|
+
pp_ext = FFI::MemoryPointer.new :pointer
|
|
446
|
+
res = Call.send(func, @ctx, cap.pointer, pp_ext)
|
|
447
|
+
struct.new(@ctx, pp_ext.read_pointer) if res==0
|
|
448
|
+
end || cap
|
|
449
|
+
end
|
|
450
|
+
|
|
311
451
|
# bNumDeviceCap Device Capability Descriptors
|
|
312
452
|
#
|
|
313
453
|
# @return [Array<Bos::DeviceCapability, Bos::Usb20Extension, Bos::SsUsbDeviceCapability, Bos::ContainerId>]
|
|
314
454
|
def device_capabilities
|
|
315
|
-
pp_ext = FFI::MemoryPointer.new :pointer
|
|
316
455
|
caps = []
|
|
317
456
|
# Capabilities are appended to the bos header
|
|
318
457
|
ptr = pointer + offset_of(:dev_capability)
|
|
319
458
|
bNumDeviceCaps.times do
|
|
320
459
|
cap = DeviceCapability.new self, ptr.read_pointer
|
|
321
|
-
case cap.bDevCapabilityType
|
|
460
|
+
cap = case cap.bDevCapabilityType
|
|
322
461
|
when LIBUSB::BT_WIRELESS_USB_DEVICE_CAPABILITY
|
|
323
462
|
# no struct defined in libusb -> use generic DeviceCapability
|
|
463
|
+
cap
|
|
324
464
|
when LIBUSB::BT_USB_2_0_EXTENSION
|
|
325
|
-
|
|
326
|
-
cap = Usb20Extension.new(@ctx, pp_ext.read_pointer) if res==0
|
|
465
|
+
wrap_device_capability(cap, :libusb_get_usb_2_0_extension_descriptor, Usb20Extension)
|
|
327
466
|
when LIBUSB::BT_SS_USB_DEVICE_CAPABILITY
|
|
328
|
-
|
|
329
|
-
|
|
467
|
+
wrap_device_capability(cap, :libusb_get_ss_usb_device_capability_descriptor, SsUsbDeviceCapability)
|
|
468
|
+
when LIBUSB::BT_SUPERSPEED_PLUS_CAPABILITY
|
|
469
|
+
wrap_device_capability(cap, :libusb_get_ssplus_usb_device_capability_descriptor, SsplusUsbDeviceCapability)
|
|
330
470
|
when LIBUSB::BT_CONTAINER_ID
|
|
331
|
-
|
|
332
|
-
cap = ContainerId.new(@ctx, pp_ext.read_pointer) if res==0
|
|
471
|
+
wrap_device_capability(cap, :libusb_get_container_id_descriptor, ContainerId)
|
|
333
472
|
when LIBUSB::BT_PLATFORM_DESCRIPTOR
|
|
334
|
-
|
|
335
|
-
cap = PlatformDescriptor.new(@ctx, pp_ext.read_pointer) if res==0
|
|
473
|
+
wrap_device_capability(cap, :libusb_get_platform_descriptor, PlatformDescriptor)
|
|
336
474
|
else
|
|
337
475
|
# unknown capability -> use generic DeviceCapability
|
|
476
|
+
cap
|
|
338
477
|
end
|
|
339
478
|
ptr += FFI.type_size(:pointer)
|
|
340
479
|
caps << cap
|
data/lib/libusb/call.rb
CHANGED
|
@@ -224,6 +224,39 @@ module LIBUSB
|
|
|
224
224
|
:BM_LTM_SUPPORT, 2,
|
|
225
225
|
]
|
|
226
226
|
|
|
227
|
+
|
|
228
|
+
# enum used in SsplusSublinkAttribute
|
|
229
|
+
SuperspeedplusSublinkAttributeSublinkType = enum :libusb_superspeedplus_sublink_attribute_sublink_type, [
|
|
230
|
+
:SSPLUS_ATTR_TYPE_SYM, 0,
|
|
231
|
+
:SSPLUS_ATTR_TYPE_ASYM, 1,
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
# enum used in SsplusSublinkAttribute
|
|
235
|
+
SuperspeedplusSublinkAttributeSublinkDirection = enum :libusb_superspeedplus_sublink_attribute_sublink_direction, [
|
|
236
|
+
:SSPLUS_ATTR_DIR_RX, 0,
|
|
237
|
+
:SSPLUS_ATTR_DIR_TX, 1,
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
# enum used in SsplusSublinkAttribute
|
|
241
|
+
#
|
|
242
|
+
# This field defines the base 10 exponent times 3, that shall be applied to the mantissa.
|
|
243
|
+
# * Bit = Bits per second
|
|
244
|
+
# * Kb = Kbps
|
|
245
|
+
# * Mb = Mbps
|
|
246
|
+
# * Gb = Gbps
|
|
247
|
+
SuperspeedplusSublinkAttributeExponent = enum :libusb_superspeedplus_sublink_attribute_exponent, [
|
|
248
|
+
:SSPLUS_ATTR_EXP_BPS, 0,
|
|
249
|
+
:SSPLUS_ATTR_EXP_KBS, 1,
|
|
250
|
+
:SSPLUS_ATTR_EXP_MBS, 2,
|
|
251
|
+
:SSPLUS_ATTR_EXP_GBS, 3,
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
# enum used in SsplusSublinkAttribute
|
|
255
|
+
SuperspeedplusSublinkAttributeLinkProtocol = enum :libusb_superspeedplus_sublink_attribute_link_protocol, [
|
|
256
|
+
:SSPLUS_ATTR_PROT_SS, 0,
|
|
257
|
+
:SSPLUS_ATTR_PROT_SSPLUS, 1,
|
|
258
|
+
]
|
|
259
|
+
|
|
227
260
|
# USB capability types
|
|
228
261
|
#
|
|
229
262
|
# @see Bos::DeviceCapability
|
|
@@ -237,7 +270,7 @@ module LIBUSB
|
|
|
237
270
|
:BT_BATTERY_INFO_CAPABILITY, 0x07, # Provides information on each battery supported by the device
|
|
238
271
|
:BT_PD_CONSUMER_PORT_CAPABILITY, 0x08, # The consumer characteristics of a port on the device
|
|
239
272
|
:BT_PD_PROVIDER_PORT_CAPABILITY, 0x09, # The provider characteristics of a port on the device
|
|
240
|
-
:
|
|
273
|
+
:BT_SUPERSPEED_PLUS_CAPABILITY, 0x0A, # Defines the set of SuperSpeed Plus USB specific device level capabilities
|
|
241
274
|
:BT_PRECISION_TIME_MEASUREMENT, 0x0B, # Precision Time Measurement (PTM) Capability Descriptor
|
|
242
275
|
:BT_Wireless_USB_Ext, 0x0C, # Defines the set of Wireless USB 1.1-specific device level capabilities
|
|
243
276
|
:BT_BILLBOARD, 0x0D, # Billboard capability
|
|
@@ -268,6 +301,14 @@ module LIBUSB
|
|
|
268
301
|
:HOTPLUG_ENUMERATE, 1,
|
|
269
302
|
]
|
|
270
303
|
|
|
304
|
+
# The device string type.
|
|
305
|
+
DeviceStringType = enum :libusb_device_string_type, [
|
|
306
|
+
:DEVICE_STRING_MANUFACTURER,
|
|
307
|
+
:DEVICE_STRING_PRODUCT,
|
|
308
|
+
:DEVICE_STRING_SERIAL_NUMBER,
|
|
309
|
+
:DEVICE_STRING_COUNT # The total number of string types.
|
|
310
|
+
]
|
|
311
|
+
|
|
271
312
|
# Log message levels.
|
|
272
313
|
#
|
|
273
314
|
# - :LOG_LEVEL_NONE (0) : no messages ever printed by the library (default)
|
|
@@ -459,6 +500,8 @@ module LIBUSB
|
|
|
459
500
|
try_attach_function 'libusb_free_usb_2_0_extension_descriptor', [:pointer], :void
|
|
460
501
|
try_attach_function 'libusb_get_ss_usb_device_capability_descriptor', [:libusb_context, :pointer, :pointer], :int
|
|
461
502
|
try_attach_function 'libusb_free_ss_usb_device_capability_descriptor', [:pointer], :void
|
|
503
|
+
try_attach_function 'libusb_get_ssplus_usb_device_capability_descriptor', [:libusb_context, :pointer, :pointer], :int
|
|
504
|
+
try_attach_function 'libusb_free_ssplus_usb_device_capability_descriptor', [:pointer], :void
|
|
462
505
|
try_attach_function 'libusb_get_container_id_descriptor', [:libusb_context, :pointer, :pointer], :int
|
|
463
506
|
try_attach_function 'libusb_free_container_id_descriptor', [:pointer], :void
|
|
464
507
|
try_attach_function 'libusb_get_platform_descriptor', [:libusb_context, :pointer, :pointer], :int
|
|
@@ -521,6 +564,46 @@ module LIBUSB
|
|
|
521
564
|
:pointer, :pointer], :int
|
|
522
565
|
try_attach_function 'libusb_hotplug_deregister_callback', [:libusb_context, :libusb_hotplug_callback_handle], :void
|
|
523
566
|
|
|
567
|
+
# Retrieve a device string without needing to open the device.
|
|
568
|
+
#
|
|
569
|
+
# Since version v1.0.30 \ref LIBUSB_API_VERSION >= 0x0100010C
|
|
570
|
+
#
|
|
571
|
+
# \param dev the target device
|
|
572
|
+
# \param string_type the string type to retrieve
|
|
573
|
+
# \param data the data buffer for the UTF-8 encoded string.
|
|
574
|
+
# \param length the size of the data buffer in bytes.
|
|
575
|
+
# USB string descriptors cannot be longer than
|
|
576
|
+
# LIBUSB_DEVICE_STRING_BYTES_MAX.
|
|
577
|
+
# \returns a negative error code or
|
|
578
|
+
# the actual string length in bytes including the null terminator.
|
|
579
|
+
# \see libusb_get_string_descriptor()
|
|
580
|
+
# \see libusb_get_string_descriptor_ascii()
|
|
581
|
+
#
|
|
582
|
+
# This function works when the device is still closed since it relies
|
|
583
|
+
# on the operating system to provide the string. The operating system
|
|
584
|
+
# normally reads and caches the common string descriptors during
|
|
585
|
+
# USB enumeration.
|
|
586
|
+
#
|
|
587
|
+
# Since the USB string descriptor could be processed by the OS,
|
|
588
|
+
# this function returns a UTF-8 encoded string.
|
|
589
|
+
#
|
|
590
|
+
# The string will be returned untranslated or in the default OS language
|
|
591
|
+
# when supported by the OS and USB device.
|
|
592
|
+
#
|
|
593
|
+
# One way to call this function is using a buffer on the stack:
|
|
594
|
+
#
|
|
595
|
+
# char buffer[LIBUSB_DEVICE_STRING_BYTES_MAX];
|
|
596
|
+
# int ret = libusb_get_device_string(dev, LIBUSB_DEVICE_STRING_SERIAL_NUMBER, buffer, sizeof(buffer));
|
|
597
|
+
# if (ret < 0) {
|
|
598
|
+
# // handle error
|
|
599
|
+
# }
|
|
600
|
+
#
|
|
601
|
+
# This function is commonly used to get the serial number to allow
|
|
602
|
+
# for device selection before opening the selected device.
|
|
603
|
+
try_attach_function 'libusb_get_device_string', [:libusb_device, DeviceStringType, :pointer, :int], :int
|
|
604
|
+
|
|
605
|
+
try_attach_function 'libusb_get_session_data', [:libusb_device], :ulong
|
|
606
|
+
|
|
524
607
|
class IsoPacketDescriptor < FFI::Struct
|
|
525
608
|
layout :length, :uint,
|
|
526
609
|
:actual_length, :uint,
|
|
@@ -554,6 +637,8 @@ module LIBUSB
|
|
|
554
637
|
super
|
|
555
638
|
|
|
556
639
|
ptr = pointer
|
|
640
|
+
# @private
|
|
641
|
+
# called by GC
|
|
557
642
|
def ptr.free_struct(id)
|
|
558
643
|
Call.libusb_free_transfer(self)
|
|
559
644
|
return unless @ctx
|
data/lib/libusb/constants.rb
CHANGED
|
@@ -36,6 +36,7 @@ module LIBUSB
|
|
|
36
36
|
Call::LogLevels,
|
|
37
37
|
Call::LogCbMode,
|
|
38
38
|
Call::Options,
|
|
39
|
+
Call::DeviceStringType,
|
|
39
40
|
].each do |enum|
|
|
40
41
|
enum.to_h.each{|k,v| const_set(k,v) }
|
|
41
42
|
end
|
|
@@ -92,6 +93,16 @@ module LIBUSB
|
|
|
92
93
|
# Wildcard matching for hotplug events.
|
|
93
94
|
HOTPLUG_MATCH_ANY = -1
|
|
94
95
|
|
|
96
|
+
# The maximum length for a device string descriptor in UTF-8.
|
|
97
|
+
#
|
|
98
|
+
# 255 max descriptor length with 2 byte header
|
|
99
|
+
# => 253 bytes UTF-16LE, no null termination (USB 2.0 9.6.7)
|
|
100
|
+
# => 126.5 codepoints
|
|
101
|
+
# => 126 * 3 + 1
|
|
102
|
+
# => 382 bytes
|
|
103
|
+
#
|
|
104
|
+
# Stay with 256 * 2/3 = 384 to be safe.
|
|
105
|
+
DEVICE_STRING_BYTES_MAX = 384
|
|
95
106
|
|
|
96
107
|
# http://www.usb.org/developers/defined_class
|
|
97
108
|
# @private
|
data/lib/libusb/context.rb
CHANGED
|
@@ -523,14 +523,13 @@ module LIBUSB
|
|
|
523
523
|
#
|
|
524
524
|
# Since libusb version 1.0.16.
|
|
525
525
|
#
|
|
526
|
-
# @param [
|
|
527
|
-
# @option args [Fixnum,Symbol] :events bitwise or of events that will trigger this callback.
|
|
526
|
+
# @param [Fixnum,Symbol] events bitwise or of events that will trigger this callback.
|
|
528
527
|
# Default is +LIBUSB::HOTPLUG_EVENT_DEVICE_ARRIVED|LIBUSB::HOTPLUG_EVENT_DEVICE_LEFT+ .
|
|
529
528
|
# See {Call::HotplugEvents HotplugEvents}
|
|
530
|
-
# @
|
|
531
|
-
# @
|
|
532
|
-
# @
|
|
533
|
-
# @
|
|
529
|
+
# @param [Fixnum,Symbol] flags hotplug callback flags. Default is 0. See {Call::HotplugFlags HotplugFlags}
|
|
530
|
+
# @param [Fixnum] vendor_id the vendor id to match. Default is {HOTPLUG_MATCH_ANY}.
|
|
531
|
+
# @param [Fixnum] product_id the product id to match. Default is {HOTPLUG_MATCH_ANY}.
|
|
532
|
+
# @param [Fixnum] dev_class the device class to match. Default is {HOTPLUG_MATCH_ANY}.
|
|
534
533
|
# @return [HotplugCallback] The handle to the registered callback.
|
|
535
534
|
#
|
|
536
535
|
# @yieldparam [Device] device the attached or removed {Device} is yielded to the block
|
|
@@ -17,16 +17,21 @@ module LIBUSB
|
|
|
17
17
|
module ContextReference
|
|
18
18
|
def register_context(ctx, free_sym)
|
|
19
19
|
ptr = pointer
|
|
20
|
+
|
|
21
|
+
# @private
|
|
22
|
+
# called by GC or #free
|
|
20
23
|
def ptr.free_struct(id)
|
|
21
24
|
return unless @ctx
|
|
22
25
|
Call.send(@free_sym, self)
|
|
23
26
|
@ctx.unref_context
|
|
24
27
|
end
|
|
28
|
+
|
|
25
29
|
ptr.instance_variable_set(:@free_sym, free_sym)
|
|
26
30
|
ptr.instance_variable_set(:@ctx, ctx.ref_context)
|
|
27
31
|
ObjectSpace.define_finalizer(self, ptr.method(:free_struct))
|
|
28
32
|
end
|
|
29
33
|
|
|
34
|
+
# Free the struct manually
|
|
30
35
|
def free
|
|
31
36
|
ptr = pointer
|
|
32
37
|
ptr.free_struct nil
|
data/lib/libusb/dependencies.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module LIBUSB
|
|
2
|
-
LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.
|
|
2
|
+
LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.30'
|
|
3
3
|
LIBUSB_SOURCE_URI = "https://github.com/libusb/libusb/releases/download/v#{LIBUSB_VERSION}/libusb-#{LIBUSB_VERSION}.tar.bz2"
|
|
4
|
-
LIBUSB_SOURCE_SHA256 = '
|
|
4
|
+
LIBUSB_SOURCE_SHA256 = 'fea36f34f9156400209595e300840767ab1a385ede1dc7ee893015aea9c6dbaf'
|
|
5
5
|
|
|
6
6
|
MINI_PORTILE_VERSION = '~> 2.1'
|
|
7
7
|
end
|
data/lib/libusb/dev_handle.rb
CHANGED
|
@@ -194,7 +194,7 @@ module LIBUSB
|
|
|
194
194
|
|
|
195
195
|
if Call.respond_to?(:libusb_alloc_streams)
|
|
196
196
|
|
|
197
|
-
# @method alloc_streams
|
|
197
|
+
# @method alloc_streams(num_streams, endpoints)
|
|
198
198
|
#
|
|
199
199
|
# Allocate up to num_streams usb bulk streams on the specified endpoints. This
|
|
200
200
|
# function takes an array of endpoints rather then a single endpoint because
|
|
@@ -222,7 +222,7 @@ module LIBUSB
|
|
|
222
222
|
res
|
|
223
223
|
end
|
|
224
224
|
|
|
225
|
-
# @method free_streams
|
|
225
|
+
# @method free_streams(endpoints)
|
|
226
226
|
#
|
|
227
227
|
# Free usb bulk streams allocated with {alloc_streams}
|
|
228
228
|
#
|
|
@@ -286,7 +286,7 @@ module LIBUSB
|
|
|
286
286
|
# @private
|
|
287
287
|
if Call.respond_to?(:libusb_set_auto_detach_kernel_driver)
|
|
288
288
|
|
|
289
|
-
# @method auto_detach_kernel_driver=
|
|
289
|
+
# @method auto_detach_kernel_driver=(enable)
|
|
290
290
|
# Enable/disable libusb's automatic kernel driver detachment.
|
|
291
291
|
#
|
|
292
292
|
# When this is enabled libusb will automatically detach the kernel driver on an
|
|
@@ -358,11 +358,10 @@ module LIBUSB
|
|
|
358
358
|
# transferred; do not assume that timeout conditions indicate a complete lack of
|
|
359
359
|
# I/O.
|
|
360
360
|
#
|
|
361
|
-
# @param [
|
|
362
|
-
# @
|
|
363
|
-
# @
|
|
364
|
-
# @
|
|
365
|
-
# @option args [Fixnum] :timeout timeout (in millseconds) that this function should wait before giving
|
|
361
|
+
# @param [Endpoint, Fixnum] endpoint the (address of a) valid endpoint to communicate with
|
|
362
|
+
# @param [String] dataOut the data to send with an outgoing transfer
|
|
363
|
+
# @param [Fixnum] dataIn the number of bytes expected to receive with an ingoing transfer
|
|
364
|
+
# @param [Fixnum] timeout timeout (in millseconds) that this function should wait before giving
|
|
366
365
|
# up due to no response being received. For an unlimited timeout, use value 0. Defaults to 1000 ms.
|
|
367
366
|
#
|
|
368
367
|
# @return [Fixnum] Number of bytes sent for an outgoing transfer
|
|
@@ -429,11 +428,10 @@ module LIBUSB
|
|
|
429
428
|
#
|
|
430
429
|
# The default endpoint bInterval value is used as the polling interval.
|
|
431
430
|
#
|
|
432
|
-
# @param [
|
|
433
|
-
# @
|
|
434
|
-
# @
|
|
435
|
-
# @
|
|
436
|
-
# @option args [Fixnum] :timeout timeout (in millseconds) that this function should wait before giving
|
|
431
|
+
# @param [Endpoint, Fixnum] endpoint the (address of a) valid endpoint to communicate with
|
|
432
|
+
# @param [String] dataOut the data to send with an outgoing transfer
|
|
433
|
+
# @param [Fixnum] dataIn the number of bytes expected to receive with an ingoing transfer
|
|
434
|
+
# @param [Fixnum] timeout timeout (in millseconds) that this function should wait before giving
|
|
437
435
|
# up due to no response being received. For an unlimited timeout, use value 0. Defaults to 1000 ms.
|
|
438
436
|
#
|
|
439
437
|
# @return [Fixnum] Number of bytes sent for an outgoing transfer
|
|
@@ -483,16 +481,15 @@ module LIBUSB
|
|
|
483
481
|
# The direction of the transfer is inferred from the +:bmRequestType+ field of the
|
|
484
482
|
# setup packet.
|
|
485
483
|
#
|
|
486
|
-
# @param [
|
|
487
|
-
# @
|
|
488
|
-
# @
|
|
489
|
-
# @
|
|
490
|
-
# @
|
|
491
|
-
# @option args [String] :dataOut the data to send with an outgoing transfer, it
|
|
484
|
+
# @param [Fixnum] bmRequestType the request type field for the setup packet
|
|
485
|
+
# @param [Fixnum] bRequest the request field for the setup packet
|
|
486
|
+
# @param [Fixnum] wValue the value field for the setup packet
|
|
487
|
+
# @param [Fixnum] wIndex the index field for the setup packet
|
|
488
|
+
# @param [String] dataOut the data to send with an outgoing transfer, it
|
|
492
489
|
# is appended to the setup packet
|
|
493
|
-
# @
|
|
490
|
+
# @param [Fixnum] dataIn the number of bytes expected to receive with an ingoing transfer
|
|
494
491
|
# (excluding setup packet)
|
|
495
|
-
# @
|
|
492
|
+
# @param [Fixnum] timeout timeout (in millseconds) that this function should wait before giving
|
|
496
493
|
# up due to no response being received. For an unlimited timeout, use value 0. Defaults to 1000 ms.
|
|
497
494
|
#
|
|
498
495
|
# @return [Fixnum] Number of bytes sent (excluding setup packet) for outgoing transfer
|
data/lib/libusb/device.rb
CHANGED
|
@@ -319,6 +319,51 @@ module LIBUSB
|
|
|
319
319
|
@pDevDesc[:bNumConfigurations]
|
|
320
320
|
end
|
|
321
321
|
|
|
322
|
+
if Call.respond_to?(:libusb_get_device_string)
|
|
323
|
+
# Retrieve the device description strings without opening the device.
|
|
324
|
+
# So permissions for open aren't necessary.
|
|
325
|
+
#
|
|
326
|
+
# This function works when the device is still closed since it relies
|
|
327
|
+
# on the operating system to provide the string. The operating system
|
|
328
|
+
# normally reads and caches the common string descriptors during
|
|
329
|
+
# USB enumeration.
|
|
330
|
+
#
|
|
331
|
+
# Since the USB string descriptor could be processed by the OS,
|
|
332
|
+
# this function returns a UTF-8 encoded string.
|
|
333
|
+
#
|
|
334
|
+
# The string will be returned untranslated or in the default OS language
|
|
335
|
+
# when supported by the OS and USB device.
|
|
336
|
+
#
|
|
337
|
+
# @param [Symbol, Integer] string_type One of {Call::DeviceStringType}
|
|
338
|
+
#
|
|
339
|
+
# Available since libusb-1.0.30
|
|
340
|
+
#
|
|
341
|
+
def device_string(string_type)
|
|
342
|
+
buffer = FFI::MemoryPointer.new(DEVICE_STRING_BYTES_MAX)
|
|
343
|
+
res = Call.libusb_get_device_string(@pDev, string_type, buffer, buffer.size)
|
|
344
|
+
LIBUSB.raise_error res, "in libusb_get_device_string" if res<0
|
|
345
|
+
buffer.read_bytes(res)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
if Call.respond_to?(:libusb_get_session_data)
|
|
350
|
+
# Returns the backend-specific identifier of the underlying system device tree
|
|
351
|
+
# node. Can be used to find the corresponding system device and directly query
|
|
352
|
+
# it (or access it otherwise) when and if necessary.
|
|
353
|
+
#
|
|
354
|
+
# Relevant backends:
|
|
355
|
+
# - Darwin: IOKit `sessionID`
|
|
356
|
+
# - Windows WinUSB: `DEVINST`
|
|
357
|
+
# - Linux, BSD: `busnum << 8 | devnum`
|
|
358
|
+
#
|
|
359
|
+
# Since version 1.0.30, \ref LIBUSB_API_VERSION >= 0x0100010C
|
|
360
|
+
#
|
|
361
|
+
# \param dev a device (must not be null)
|
|
362
|
+
# \returns the backend-specific device identifier
|
|
363
|
+
def get_session_data
|
|
364
|
+
Call.libusb_get_session_data(@pDev)
|
|
365
|
+
end
|
|
366
|
+
end
|
|
322
367
|
|
|
323
368
|
def inspect
|
|
324
369
|
attrs = []
|
|
@@ -339,9 +384,13 @@ module LIBUSB
|
|
|
339
384
|
"\#<#{self.class} #{attrs.join(' ')}>"
|
|
340
385
|
end
|
|
341
386
|
|
|
342
|
-
def try_string_descriptor_ascii(i)
|
|
387
|
+
def try_string_descriptor_ascii(i, enum=nil)
|
|
343
388
|
begin
|
|
344
|
-
|
|
389
|
+
if enum && respond_to?(:device_string)
|
|
390
|
+
device_string(enum)
|
|
391
|
+
else
|
|
392
|
+
open{|h| h.string_descriptor_ascii(i) }
|
|
393
|
+
end
|
|
345
394
|
rescue
|
|
346
395
|
"?"
|
|
347
396
|
end
|
|
@@ -351,7 +400,7 @@ module LIBUSB
|
|
|
351
400
|
# @return String
|
|
352
401
|
def manufacturer
|
|
353
402
|
return @manufacturer if defined? @manufacturer
|
|
354
|
-
@manufacturer = try_string_descriptor_ascii(self.iManufacturer)
|
|
403
|
+
@manufacturer = try_string_descriptor_ascii(self.iManufacturer, DEVICE_STRING_MANUFACTURER)
|
|
355
404
|
@manufacturer = @manufacturer.strip if @manufacturer
|
|
356
405
|
@manufacturer
|
|
357
406
|
end
|
|
@@ -360,7 +409,7 @@ module LIBUSB
|
|
|
360
409
|
# @return String
|
|
361
410
|
def product
|
|
362
411
|
return @product if defined? @product
|
|
363
|
-
@product = try_string_descriptor_ascii(self.iProduct)
|
|
412
|
+
@product = try_string_descriptor_ascii(self.iProduct, DEVICE_STRING_PRODUCT)
|
|
364
413
|
@product = @product.strip if @product
|
|
365
414
|
@product
|
|
366
415
|
end
|
|
@@ -369,7 +418,7 @@ module LIBUSB
|
|
|
369
418
|
# @return String
|
|
370
419
|
def serial_number
|
|
371
420
|
return @serial_number if defined? @serial_number
|
|
372
|
-
@serial_number = try_string_descriptor_ascii(self.iSerialNumber)
|
|
421
|
+
@serial_number = try_string_descriptor_ascii(self.iSerialNumber, DEVICE_STRING_SERIAL_NUMBER)
|
|
373
422
|
@serial_number = @serial_number.strip if @serial_number
|
|
374
423
|
@serial_number
|
|
375
424
|
end
|
data/lib/libusb/eventmachine.rb
CHANGED
|
@@ -52,7 +52,12 @@ class Context
|
|
|
52
52
|
# Libusb pollfd API is not available on this platform.
|
|
53
53
|
# Use simple polling timer, instead:
|
|
54
54
|
EventMachine.add_periodic_timer(0.01) do
|
|
55
|
-
|
|
55
|
+
begin
|
|
56
|
+
@eventmachine_timer = self.handle_events 0
|
|
57
|
+
rescue ERROR_INTERRUPTED
|
|
58
|
+
# Interrupted by a signal; nothing was handled. The next tick of this
|
|
59
|
+
# periodic timer retries. See the pollfd callback below.
|
|
60
|
+
end
|
|
56
61
|
end
|
|
57
62
|
end
|
|
58
63
|
end
|
|
@@ -98,7 +103,18 @@ class Context
|
|
|
98
103
|
@eventmachine_timer = nil
|
|
99
104
|
end
|
|
100
105
|
|
|
101
|
-
|
|
106
|
+
begin
|
|
107
|
+
self.handle_events 0
|
|
108
|
+
rescue ERROR_INTERRUPTED
|
|
109
|
+
# poll() was interrupted by a signal, so no events were handled. This
|
|
110
|
+
# is transient and retryable: the descriptor stays watched and the next
|
|
111
|
+
# readable/writable event re-enters this callback. Without this rescue
|
|
112
|
+
# the exception unwinds out of EventMachine.run and takes the whole
|
|
113
|
+
# reactor (and typically the process) down. Same handling as the
|
|
114
|
+
# synchronous transfer path in transfer.rb.
|
|
115
|
+
next
|
|
116
|
+
end
|
|
117
|
+
|
|
102
118
|
timeout = self.next_timeout
|
|
103
119
|
# puts "libusb new timeout: #{timeout.inspect}"
|
|
104
120
|
if timeout
|
data/lib/libusb/gem_helper.rb
CHANGED
data/lib/libusb/transfer.rb
CHANGED
|
@@ -311,9 +311,9 @@ module LIBUSB
|
|
|
311
311
|
# Set a transfers bulk stream id.
|
|
312
312
|
#
|
|
313
313
|
# @param [Fixnum] stream_id the stream id to set
|
|
314
|
-
def stream_id=(
|
|
315
|
-
Call.libusb_transfer_set_stream_id(@transfer,
|
|
316
|
-
|
|
314
|
+
def stream_id=(stream_id)
|
|
315
|
+
Call.libusb_transfer_set_stream_id(@transfer, stream_id)
|
|
316
|
+
stream_id
|
|
317
317
|
end
|
|
318
318
|
|
|
319
319
|
# Get a transfers bulk stream id.
|
data/lib/libusb/version_gem.rb
CHANGED
|
Binary file
|
data/test/test_libusb_bos.rb
CHANGED
|
@@ -62,7 +62,7 @@ class TestLibusbBos < Minitest::Test
|
|
|
62
62
|
:BT_BATTERY_INFO_CAPABILITY,
|
|
63
63
|
:BT_PD_CONSUMER_PORT_CAPABILITY,
|
|
64
64
|
:BT_PD_PROVIDER_PORT_CAPABILITY,
|
|
65
|
-
:
|
|
65
|
+
:BT_SUPERSPEED_PLUS_CAPABILITY,
|
|
66
66
|
:BT_PRECISION_TIME_MEASUREMENT,
|
|
67
67
|
:BT_Wireless_USB_Ext,
|
|
68
68
|
:BT_BILLBOARD,
|
|
@@ -77,11 +77,14 @@ class TestLibusbBos < Minitest::Test
|
|
|
77
77
|
caps.each do |cap|
|
|
78
78
|
did_cap = true
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
unless cap.is_a?(Bos::SsplusUsbDeviceCapability)
|
|
81
|
+
assert_operator 4, :<=, cap.bLength
|
|
82
|
+
assert_equal LIBUSB::DT_DEVICE_CAPABILITY, cap.bDescriptorType
|
|
83
|
+
assert_kind_of String, cap.dev_capability_data, "should provide binary capability data"
|
|
84
|
+
assert_operator 1, :<=, cap.dev_capability_data.length, "dev_capability_data should be at least one byte"
|
|
85
|
+
end
|
|
83
86
|
assert_kind_of String, cap.inspect, "should respond to inspect"
|
|
84
|
-
|
|
87
|
+
assert_match(/\#<#{cap.class}/, cap.inspect, "inspect contains the class name")
|
|
85
88
|
|
|
86
89
|
case cap
|
|
87
90
|
when Bos::DeviceCapability
|
|
@@ -102,6 +105,25 @@ class TestLibusbBos < Minitest::Test
|
|
|
102
105
|
assert_operator 0, :<=, cap.bU1DevExitLat
|
|
103
106
|
assert_operator 0, :<=, cap.bU2DevExitLat
|
|
104
107
|
|
|
108
|
+
when Bos::SsplusUsbDeviceCapability
|
|
109
|
+
assert_kind_of Array, cap.sublinkSpeedAttributes
|
|
110
|
+
assert_equal cap.numSublinkSpeedAttributes, cap.sublinkSpeedAttributes.size
|
|
111
|
+
assert_operator 1, :<=, cap.numSublinkSpeedIDs
|
|
112
|
+
assert_operator 1, :<=, cap.numSublinkSpeedAttributes
|
|
113
|
+
assert_kind_of Integer, cap.ssid
|
|
114
|
+
assert_operator 0, :<=, cap.minRxLaneCount
|
|
115
|
+
assert_operator 0, :<=, cap.minTxLaneCount
|
|
116
|
+
|
|
117
|
+
sl = cap.sublinkSpeedAttributes[0]
|
|
118
|
+
assert_match(/id=.* SuperSpeed/, sl.to_s_human_readable)
|
|
119
|
+
assert_kind_of String, sl.inspect, "should respond to inspect"
|
|
120
|
+
assert_kind_of Integer, sl.ssid
|
|
121
|
+
assert_kind_of Symbol, sl.exponent
|
|
122
|
+
assert_kind_of Symbol, sl.type
|
|
123
|
+
assert_kind_of Symbol, sl.direction
|
|
124
|
+
assert_kind_of Symbol, sl.protocol
|
|
125
|
+
assert_operator 1, :<=, sl.mantissa
|
|
126
|
+
|
|
105
127
|
when Bos::ContainerId
|
|
106
128
|
assert_equal 4, cap.bDevCapabilityType
|
|
107
129
|
assert_operator 0, :<=, cap.bReserved
|
|
@@ -45,6 +45,10 @@ class TestLibusbDescriptors < Minitest::Test
|
|
|
45
45
|
assert_kind_of Integer, dev.iSerialNumber
|
|
46
46
|
assert_kind_of Integer, dev.bNumConfigurations
|
|
47
47
|
|
|
48
|
+
assert_kind_of String, dev.manufacturer
|
|
49
|
+
assert_kind_of String, dev.product
|
|
50
|
+
assert_kind_of String, dev.serial_number
|
|
51
|
+
|
|
48
52
|
dev.configurations.each do |config_desc|
|
|
49
53
|
assert_match(/Configuration/, config_desc.inspect, "ConfigDescriptor#inspect should work")
|
|
50
54
|
assert dev.configurations.include?(config_desc), "Device#configurations should include this one"
|
|
@@ -242,4 +246,13 @@ class TestLibusbDescriptors < Minitest::Test
|
|
|
242
246
|
end
|
|
243
247
|
end
|
|
244
248
|
end
|
|
249
|
+
|
|
250
|
+
def test_get_session_data
|
|
251
|
+
skip "libusb version older than 1.0.30" if Gem::Version.new(LIBUSB.version) < Gem::Version.new("1.0.30")
|
|
252
|
+
|
|
253
|
+
usb.devices.each do |dev|
|
|
254
|
+
assert_kind_of Integer, dev.get_session_data
|
|
255
|
+
refute_equal 0, dev.get_session_data
|
|
256
|
+
end
|
|
257
|
+
end
|
|
245
258
|
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 "minitest/autorun"
|
|
17
|
+
require "libusb"
|
|
18
|
+
require "libusb/eventmachine"
|
|
19
|
+
require "eventmachine"
|
|
20
|
+
|
|
21
|
+
# LIBUSB_ERROR_INTERRUPTED means poll() was interrupted by a signal and no
|
|
22
|
+
# events were handled. It is transient and retryable, but Context#handle_events
|
|
23
|
+
# raises on it like any other negative return, and the EventMachine integration
|
|
24
|
+
# used to call handle_events unrescued -- so a signal arriving at the wrong
|
|
25
|
+
# moment unwound out of EventMachine.run and killed the reactor.
|
|
26
|
+
#
|
|
27
|
+
# These tests need no USB device: they drive the registered callback directly.
|
|
28
|
+
class TestLibusbEventMachineEintr < Minitest::Test
|
|
29
|
+
include LIBUSB
|
|
30
|
+
|
|
31
|
+
def setup
|
|
32
|
+
@context = Context.new
|
|
33
|
+
skip "libusb pollfd API not available on this platform" unless @context.pollfds&.any?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The callback the pollfd handler invokes must swallow ERROR_INTERRUPTED and
|
|
37
|
+
# leave the reactor running.
|
|
38
|
+
def test_pollfd_callback_survives_eintr
|
|
39
|
+
interrupts = 0
|
|
40
|
+
@context.define_singleton_method(:handle_events) do |*|
|
|
41
|
+
interrupts += 1
|
|
42
|
+
raise LIBUSB::ERROR_INTERRUPTED
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
assert dispatch_pollfd_events, "reactor must stay up after ERROR_INTERRUPTED"
|
|
46
|
+
assert_operator interrupts, :>=, 1, "handle_events should have been called"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Only ERROR_INTERRUPTED is transient. Every other libusb error must still
|
|
50
|
+
# propagate, so a real fault is not silently swallowed.
|
|
51
|
+
def test_pollfd_callback_still_raises_other_errors
|
|
52
|
+
@context.define_singleton_method(:handle_events) do |*|
|
|
53
|
+
raise LIBUSB::ERROR_NO_DEVICE
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
assert_raises(LIBUSB::ERROR_NO_DEVICE) { dispatch_pollfd_events }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Run the reactor, register libusb's pollfds with it and invoke the resulting
|
|
62
|
+
# callbacks exactly as EMPollfdHandler#notify_readable does. Returns whether
|
|
63
|
+
# the reactor was still running once they had been dispatched.
|
|
64
|
+
def dispatch_pollfd_events
|
|
65
|
+
reactor_alive = false
|
|
66
|
+
|
|
67
|
+
EventMachine.run do
|
|
68
|
+
@context.eventmachine_register
|
|
69
|
+
|
|
70
|
+
begin
|
|
71
|
+
@context.instance_variable_get(:@eventmachine_attached_fds).each_value(&:need_handle_events)
|
|
72
|
+
reactor_alive = EventMachine.reactor_running?
|
|
73
|
+
ensure
|
|
74
|
+
@context.eventmachine_unregister
|
|
75
|
+
EventMachine.stop
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
reactor_alive
|
|
80
|
+
end
|
|
81
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libusb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lars Kanis
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: ffi
|
|
@@ -81,7 +80,7 @@ files:
|
|
|
81
80
|
- lib/libusb/version_gem.rb
|
|
82
81
|
- lib/libusb/version_struct.rb
|
|
83
82
|
- libusb.gemspec
|
|
84
|
-
- ports/archives/libusb-1.0.
|
|
83
|
+
- ports/archives/libusb-1.0.30.tar.bz2
|
|
85
84
|
- test/test_libusb.rb
|
|
86
85
|
- test/test_libusb_bos.rb
|
|
87
86
|
- test/test_libusb_bulk_stream_transfer.rb
|
|
@@ -90,6 +89,7 @@ files:
|
|
|
90
89
|
- test/test_libusb_context.rb
|
|
91
90
|
- test/test_libusb_descriptors.rb
|
|
92
91
|
- test/test_libusb_event_machine.rb
|
|
92
|
+
- test/test_libusb_event_machine_eintr.rb
|
|
93
93
|
- test/test_libusb_gc.rb
|
|
94
94
|
- test/test_libusb_hotplug.rb
|
|
95
95
|
- test/test_libusb_iso_transfer.rb
|
|
@@ -103,7 +103,6 @@ licenses:
|
|
|
103
103
|
- LGPL-3.0
|
|
104
104
|
metadata:
|
|
105
105
|
yard.run: yri
|
|
106
|
-
post_install_message:
|
|
107
106
|
rdoc_options:
|
|
108
107
|
- "--main"
|
|
109
108
|
- README.md
|
|
@@ -121,8 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
121
120
|
- !ruby/object:Gem::Version
|
|
122
121
|
version: '0'
|
|
123
122
|
requirements: []
|
|
124
|
-
rubygems_version:
|
|
125
|
-
signing_key:
|
|
123
|
+
rubygems_version: 4.1.0.dev
|
|
126
124
|
specification_version: 4
|
|
127
125
|
summary: Access USB devices from Ruby via libusb-1.0
|
|
128
126
|
test_files: []
|
|
Binary file
|