libusb 0.8.0-aarch64-mingw-ucrt

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.appveyor.yml +33 -0
  3. data/.github/workflows/ci.yml +185 -0
  4. data/.gitignore +9 -0
  5. data/.travis.yml +26 -0
  6. data/.yardopts +6 -0
  7. data/COPYING +165 -0
  8. data/Gemfile +20 -0
  9. data/History.md +225 -0
  10. data/README.md +184 -0
  11. data/Rakefile +82 -0
  12. data/lib/libusb/bos.rb +501 -0
  13. data/lib/libusb/call.rb +707 -0
  14. data/lib/libusb/compat.rb +376 -0
  15. data/lib/libusb/configuration.rb +154 -0
  16. data/lib/libusb/constants.rb +181 -0
  17. data/lib/libusb/context.rb +577 -0
  18. data/lib/libusb/context_reference.rb +43 -0
  19. data/lib/libusb/dependencies.rb +7 -0
  20. data/lib/libusb/dev_handle.rb +571 -0
  21. data/lib/libusb/device.rb +456 -0
  22. data/lib/libusb/endpoint.rb +195 -0
  23. data/lib/libusb/eventmachine.rb +203 -0
  24. data/lib/libusb/gem_helper.rb +152 -0
  25. data/lib/libusb/interface.rb +60 -0
  26. data/lib/libusb/libusb_recipe.rb +29 -0
  27. data/lib/libusb/setting.rb +132 -0
  28. data/lib/libusb/ss_companion.rb +72 -0
  29. data/lib/libusb/stdio.rb +25 -0
  30. data/lib/libusb/transfer.rb +418 -0
  31. data/lib/libusb/version_gem.rb +19 -0
  32. data/lib/libusb/version_struct.rb +63 -0
  33. data/lib/libusb-1.0.dll +0 -0
  34. data/lib/libusb.rb +146 -0
  35. data/libusb.gemspec +28 -0
  36. data/test/test_libusb.rb +42 -0
  37. data/test/test_libusb_bos.rb +162 -0
  38. data/test/test_libusb_bulk_stream_transfer.rb +61 -0
  39. data/test/test_libusb_compat.rb +78 -0
  40. data/test/test_libusb_compat_mass_storage.rb +81 -0
  41. data/test/test_libusb_context.rb +88 -0
  42. data/test/test_libusb_descriptors.rb +258 -0
  43. data/test/test_libusb_event_machine.rb +118 -0
  44. data/test/test_libusb_event_machine_eintr.rb +81 -0
  45. data/test/test_libusb_gc.rb +52 -0
  46. data/test/test_libusb_hotplug.rb +129 -0
  47. data/test/test_libusb_iso_transfer.rb +56 -0
  48. data/test/test_libusb_mass_storage.rb +268 -0
  49. data/test/test_libusb_mass_storage2.rb +96 -0
  50. data/test/test_libusb_structs.rb +87 -0
  51. data/test/test_libusb_threads.rb +89 -0
  52. data/wireshark-usb-sniffer.png +0 -0
  53. metadata +110 -0
data/lib/libusb/bos.rb ADDED
@@ -0,0 +1,501 @@
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 'libusb/call'
17
+
18
+ module LIBUSB
19
+ # A structure representing the Binary Device Object Store (BOS) descriptor.
20
+ # This descriptor is documented in section 9.6.2 of the USB 3.0 specification.
21
+ # All multiple-byte fields are represented in host-endian format.
22
+ class Bos < FFI::Struct
23
+
24
+ module GenericMethods
25
+ # @return [Integer] Size of this descriptor (in bytes)
26
+ def bLength
27
+ self[:bLength]
28
+ end
29
+
30
+ # @return [Integer] Descriptor type. Will have value LIBUSB::DT_DEVICE_CAPABILITY
31
+ # in this context.
32
+ def bDescriptorType
33
+ self[:bDescriptorType]
34
+ end
35
+
36
+ # @return [Integer] Device Capability type
37
+ def bDevCapabilityType
38
+ self[:bDevCapabilityType]
39
+ end
40
+
41
+ def inspect
42
+ "\#<#{self.class} cap: #{bDevCapabilityType} data: #{dev_capability_data.unpack1("H*")}>"
43
+ end
44
+
45
+ # @return [String] Device Capability data (bLength - 3 bytes)
46
+ def dev_capability_data
47
+ pointer.read_bytes(bLength - 3)
48
+ end
49
+ end
50
+
51
+ # A generic representation of a BOS Device Capability descriptor.
52
+ class DeviceCapability < FFI::Struct
53
+ include GenericMethods
54
+
55
+ layout :bLength, :uint8,
56
+ :bDescriptorType, :uint8,
57
+ :bDevCapabilityType, :uint8
58
+
59
+ def initialize( bos, *args)
60
+ # Avoid that the bos struct is GC'ed before this instance
61
+ @bos = bos
62
+ super(*args)
63
+ end
64
+ end
65
+
66
+ # A structure representing the USB 2.0 Extension descriptor
67
+ # This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification.
68
+ # All multiple-byte fields are represented in host-endian format.
69
+ class Usb20Extension < FFI::Struct
70
+ include GenericMethods
71
+ include ContextReference
72
+
73
+ layout :bLength, :uint8,
74
+ :bDescriptorType, :uint8,
75
+ :bDevCapabilityType, :uint8,
76
+ :bmAttributes, :uint32
77
+
78
+ def initialize(ctx, *args)
79
+ super(*args)
80
+
81
+ register_context(ctx, :libusb_free_usb_2_0_extension_descriptor)
82
+ end
83
+
84
+ # Bitmap encoding of supported device level features.
85
+ # A value of one in a bit location indicates a feature is
86
+ # supported; a value of zero indicates it is not supported.
87
+ # @see Call::Usb20ExtensionAttributes
88
+ def bmAttributes
89
+ self[:bmAttributes]
90
+ end
91
+
92
+ # @return [Boolean] Supports Link Power Management (LPM)
93
+ def bm_lpm_support?
94
+ (bmAttributes & BM_LPM_SUPPORT) != 0
95
+ end
96
+
97
+ def inspect
98
+ attrs = Call::Usb20ExtensionAttributes.to_h.map do |k, v|
99
+ (bmAttributes & v) ? k.to_s : nil
100
+ end
101
+ "\#<#{self.class} #{attrs.compact.join(",")}>"
102
+ end
103
+ end
104
+
105
+ # A structure representing the SuperSpeed USB Device Capability descriptor
106
+ # This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification.
107
+ # All multiple-byte fields are represented in host-endian format.
108
+ class SsUsbDeviceCapability < FFI::Struct
109
+ include GenericMethods
110
+ include ContextReference
111
+
112
+ layout :bLength, :uint8,
113
+ :bDescriptorType, :uint8,
114
+ :bDevCapabilityType, :uint8,
115
+ :bmAttributes, :uint8,
116
+ :wSpeedSupported, :uint16,
117
+ :bFunctionalitySupport, :uint8,
118
+ :bU1DevExitLat, :uint8,
119
+ :bU2DevExitLat, :uint16
120
+
121
+ def initialize(ctx, *args)
122
+ super(*args)
123
+
124
+ register_context(ctx, :libusb_free_ss_usb_device_capability_descriptor)
125
+ end
126
+
127
+ # Bitmap encoding of supported device level features.
128
+ # A value of one in a bit location indicates a feature is
129
+ # supported; a value of zero indicates it is not supported.
130
+ #
131
+ # @return [Integer]
132
+ # @see Call::SsUsbDeviceCapabilityAttributes
133
+ def bmAttributes
134
+ self[:bmAttributes]
135
+ end
136
+
137
+ # @return [Boolean] Supports Latency Tolerance Messages (LTM)
138
+ def bm_ltm_support?
139
+ (bmAttributes & BM_LTM_SUPPORT) != 0
140
+ end
141
+
142
+ def inspect
143
+ attrs = Call::SsUsbDeviceCapabilityAttributes.to_h.map do |k,v|
144
+ (bmAttributes & v) != 0 ? k.to_s : nil
145
+ end
146
+ "\#<#{self.class} #{attrs.compact.join(",")} #{supported_speeds.join(",")}>"
147
+ end
148
+
149
+ # Bitmap encoding of the speed supported by this device when
150
+ # operating in SuperSpeed mode.
151
+ #
152
+ # @return [Integer]
153
+ # @see Call::SupportedSpeeds
154
+ def wSpeedSupported
155
+ self[:wSpeedSupported]
156
+ end
157
+
158
+ # @return [Array<Symbol>] speeds supported by this device when
159
+ # operating in SuperSpeed mode {Call::SupportedSpeeds}
160
+ def supported_speeds
161
+ speeds = Call::SupportedSpeeds.to_h.map do |k,v|
162
+ (wSpeedSupported & v) != 0 ? k : nil
163
+ end
164
+ speeds.compact
165
+ end
166
+
167
+ # The lowest speed at which all the functionality supported
168
+ # by the device is available to the user. For example if the
169
+ # device supports all its functionality when connected at
170
+ # full speed and above then it sets this value to 1.
171
+ #
172
+ # * 0 - low speed
173
+ # * 1 - full speed
174
+ # * 2 - high speed
175
+ # * 3 - super speed
176
+ #
177
+ # @return [Integer]
178
+ def bFunctionalitySupport
179
+ self[:bFunctionalitySupport]
180
+ end
181
+
182
+ # @return [Integer] U1 Device Exit Latency.
183
+ def bU1DevExitLat
184
+ self[:bU1DevExitLat]
185
+ end
186
+
187
+ # @return [Integer] U2 Device Exit Latency.
188
+ def bU2DevExitLat
189
+ self[:bU2DevExitLat]
190
+ end
191
+ end
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
+
324
+ # A structure representing the Container ID descriptor.
325
+ # This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
326
+ # All multiple-byte fields, except UUIDs, are represented in host-endian format.
327
+ class ContainerId < FFI::Struct
328
+ include GenericMethods
329
+ include ContextReference
330
+
331
+ layout :bLength, :uint8,
332
+ :bDescriptorType, :uint8,
333
+ :bDevCapabilityType, :uint8,
334
+ :bReserved, :uint8,
335
+ :ContainerID, [:uint8, 16]
336
+
337
+ def initialize(ctx, *args)
338
+ super(*args)
339
+
340
+ register_context(ctx, :libusb_free_container_id_descriptor)
341
+ end
342
+
343
+ # Reserved field
344
+ def bReserved
345
+ self[:bReserved]
346
+ end
347
+
348
+ # @return [String] 128 bit UUID
349
+ def container_id
350
+ self[:ContainerID].to_ptr.read_bytes(16)
351
+ end
352
+
353
+ def inspect
354
+ "\#<#{self.class} #{container_id.unpack1("H*")}>"
355
+ end
356
+ end
357
+
358
+
359
+ # A structure representing a Platform descriptor.
360
+ # This descriptor is documented in section 9.6.2.4 of the USB 3.2 specification.
361
+ class PlatformDescriptor < FFI::Struct
362
+ include GenericMethods
363
+ include ContextReference
364
+
365
+ layout :bLength, :uint8,
366
+ :bDescriptorType, :uint8,
367
+ # Capability type. Will have value
368
+ # libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
369
+ # LIBUSB_BT_CONTAINER_ID in this context.
370
+ :bDevCapabilityType, :uint8,
371
+ # Reserved field
372
+ :bReserved, :uint8,
373
+ # 128 bit UUID
374
+ :PlatformCapabilityUUID, [:uint8, 16],
375
+ # Capability data (bLength - 20)
376
+ :CapabilityData, [:uint8, 0]
377
+
378
+ def initialize(ctx, *args)
379
+ super(*args)
380
+
381
+ register_context(ctx, :libusb_free_platform_descriptor)
382
+ end
383
+
384
+ # Reserved field
385
+ def bReserved
386
+ self[:bReserved]
387
+ end
388
+
389
+ # @return [String] 128 bit UUID
390
+ def platformCapabilityUUID
391
+ self[:PlatformCapabilityUUID].to_ptr.read_bytes(16)
392
+ end
393
+
394
+ # This is a variable-length field containing data associated with the platform specific capability.
395
+ # This field may be zero bytes in length.
396
+ # @return [String]
397
+ def capabilityData
398
+ self[:CapabilityData].to_ptr.read_bytes(bLength - 20)
399
+ end
400
+
401
+ def inspect
402
+ "\#<#{self.class} #{platformCapabilityUUID.unpack1("H*")} (#{capabilityData.unpack1("H*")})>"
403
+ end
404
+ end
405
+
406
+ include ContextReference
407
+
408
+ def initialize(ctx, *args)
409
+ @ctx = ctx
410
+ super(*args)
411
+
412
+ register_context(ctx, :libusb_free_bos_descriptor)
413
+ end
414
+
415
+ layout :bLength, :uint8,
416
+ :bDescriptorType, :uint8,
417
+ :wTotalLength, :uint16,
418
+ :bNumDeviceCaps, :uint8,
419
+ :dev_capability, [:pointer, 0]
420
+
421
+ # @return [Integer] Size of this descriptor (in bytes)
422
+ def bLength
423
+ self[:bLength]
424
+ end
425
+
426
+ # @return [Integer] Descriptor type. Will have value LIBUSB::DT_BOS LIBUSB_DT_BOS
427
+ # in this context.
428
+ def bDescriptorType
429
+ self[:bDescriptorType]
430
+ end
431
+
432
+ # @return [Integer] Length of this descriptor and all of its sub descriptors
433
+ def wTotalLength
434
+ self[:wTotalLength]
435
+ end
436
+
437
+ # @return [Integer] The number of separate device capability descriptors in
438
+ # the BOS
439
+ def bNumDeviceCaps
440
+ self[:bNumDeviceCaps]
441
+ end
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
+
451
+ # bNumDeviceCap Device Capability Descriptors
452
+ #
453
+ # @return [Array<Bos::DeviceCapability, Bos::Usb20Extension, Bos::SsUsbDeviceCapability, Bos::ContainerId>]
454
+ def device_capabilities
455
+ caps = []
456
+ # Capabilities are appended to the bos header
457
+ ptr = pointer + offset_of(:dev_capability)
458
+ bNumDeviceCaps.times do
459
+ cap = DeviceCapability.new self, ptr.read_pointer
460
+ cap = case cap.bDevCapabilityType
461
+ when LIBUSB::BT_WIRELESS_USB_DEVICE_CAPABILITY
462
+ # no struct defined in libusb -> use generic DeviceCapability
463
+ cap
464
+ when LIBUSB::BT_USB_2_0_EXTENSION
465
+ wrap_device_capability(cap, :libusb_get_usb_2_0_extension_descriptor, Usb20Extension)
466
+ when LIBUSB::BT_SS_USB_DEVICE_CAPABILITY
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)
470
+ when LIBUSB::BT_CONTAINER_ID
471
+ wrap_device_capability(cap, :libusb_get_container_id_descriptor, ContainerId)
472
+ when LIBUSB::BT_PLATFORM_DESCRIPTOR
473
+ wrap_device_capability(cap, :libusb_get_platform_descriptor, PlatformDescriptor)
474
+ else
475
+ # unknown capability -> use generic DeviceCapability
476
+ cap
477
+ end
478
+ ptr += FFI.type_size(:pointer)
479
+ caps << cap
480
+ end
481
+ caps
482
+ end
483
+
484
+ # @return [Array<Symbol>] Types of Capabilities
485
+ #
486
+ # @see Call::BosTypes
487
+ def device_capability_types
488
+ # Capabilities are appended to the bos header
489
+ ptr = pointer + offset_of(:dev_capability)
490
+ bNumDeviceCaps.times.map do
491
+ cap = DeviceCapability.new self, ptr.read_pointer
492
+ ptr += FFI.type_size(:pointer)
493
+ Call::BosTypes.find cap.bDevCapabilityType
494
+ end
495
+ end
496
+
497
+ def inspect
498
+ "\#<#{self.class} #{device_capability_types.join(", ")}>"
499
+ end
500
+ end
501
+ end