libusb 0.7.0-x64-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 (52) 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 +19 -0
  9. data/History.md +193 -0
  10. data/README.md +184 -0
  11. data/Rakefile +79 -0
  12. data/lib/libusb/bos.rb +362 -0
  13. data/lib/libusb/call.rb +622 -0
  14. data/lib/libusb/compat.rb +376 -0
  15. data/lib/libusb/configuration.rb +154 -0
  16. data/lib/libusb/constants.rb +170 -0
  17. data/lib/libusb/context.rb +576 -0
  18. data/lib/libusb/context_reference.rb +38 -0
  19. data/lib/libusb/dependencies.rb +7 -0
  20. data/lib/libusb/dev_handle.rb +574 -0
  21. data/lib/libusb/device.rb +407 -0
  22. data/lib/libusb/endpoint.rb +195 -0
  23. data/lib/libusb/eventmachine.rb +187 -0
  24. data/lib/libusb/gem_helper.rb +151 -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 +140 -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 +245 -0
  43. data/test/test_libusb_event_machine.rb +118 -0
  44. data/test/test_libusb_gc.rb +52 -0
  45. data/test/test_libusb_hotplug.rb +129 -0
  46. data/test/test_libusb_iso_transfer.rb +56 -0
  47. data/test/test_libusb_mass_storage.rb +268 -0
  48. data/test/test_libusb_mass_storage2.rb +96 -0
  49. data/test/test_libusb_structs.rb +87 -0
  50. data/test/test_libusb_threads.rb +89 -0
  51. data/wireshark-usb-sniffer.png +0 -0
  52. metadata +112 -0
@@ -0,0 +1,407 @@
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
+ # Class representing a USB device detected on the system.
20
+ #
21
+ # Devices of the system can be obtained with {Context#devices} .
22
+ class Device
23
+ include Comparable
24
+ include ContextReference
25
+
26
+ # @return [Context] the context this device belongs to.
27
+ attr_reader :context
28
+
29
+ def initialize context, pDev
30
+ @context = context
31
+ @pDev = pDev
32
+ register_context(context.instance_variable_get(:@ctx), :libusb_unref_device)
33
+ Call.libusb_ref_device(pDev)
34
+
35
+ @pDevDesc = Call::DeviceDescriptor.new
36
+ res = Call.libusb_get_device_descriptor(@pDev, @pDevDesc)
37
+ LIBUSB.raise_error res, "in libusb_get_device_descriptor" if res!=0
38
+ end
39
+
40
+ # The pointer for ContextReference
41
+ private def pointer
42
+ @pDev
43
+ end
44
+
45
+ # Open the device and obtain a device handle.
46
+ #
47
+ # A handle allows you to perform I/O on the device in question.
48
+ # This is a non-blocking function; no requests are sent over the bus.
49
+ #
50
+ # If called with a block, the handle is passed to the block
51
+ # and is closed when the block has finished.
52
+ #
53
+ # You need proper device access:
54
+ # * Linux: read+write permissions to <tt>/dev/bus/usb/<bus>/<dev></tt>
55
+ # * Windows: by installing a WinUSB-driver for the device (see {file:README.rdoc#Usage_on_Windows} )
56
+ #
57
+ # @return [DevHandle] Handle to the device.
58
+ def open
59
+ ppHandle = FFI::MemoryPointer.new :pointer
60
+ res = Call.libusb_open(@pDev, ppHandle)
61
+ LIBUSB.raise_error res, "in libusb_open" if res!=0
62
+ handle = DevHandle.new self, ppHandle.read_pointer
63
+ return handle unless block_given?
64
+ begin
65
+ yield handle
66
+ ensure
67
+ handle.close
68
+ end
69
+ end
70
+
71
+ # Open the device and claim an interface.
72
+ #
73
+ # This is a convenience method to {Device#open} and {DevHandle#claim_interface}.
74
+ # Must be called with a block. When the block has finished, the interface
75
+ # will be released and the device will be closed.
76
+ #
77
+ # @param [Interface, Fixnum] interface the interface or it's bInterfaceNumber you wish to claim
78
+ def open_interface(interface)
79
+ open do |dev|
80
+ dev.claim_interface(interface) do
81
+ yield dev
82
+ end
83
+ end
84
+ end
85
+
86
+ # Get the number of the bus that a device is connected to.
87
+ def bus_number
88
+ Call.libusb_get_bus_number(@pDev)
89
+ end
90
+
91
+ # Get the address of the device on the bus it is connected to.
92
+ def device_address
93
+ Call.libusb_get_device_address(@pDev)
94
+ end
95
+
96
+ if Call.respond_to?(:libusb_get_port_number)
97
+ # Get the number of the port that a device is connected to.
98
+ # Available since libusb-1.0.12.
99
+ #
100
+ # @return [Fixnum, nil] the port number (+nil+ if not available)
101
+ # @see #port_numbers
102
+ def port_number
103
+ r = Call.libusb_get_port_number(@pDev)
104
+ r==0 ? nil : r
105
+ end
106
+
107
+ # Get the the parent from the specified device [EXPERIMENTAL].
108
+ # Available since libusb-1.0.12.
109
+ #
110
+ # @return [Device, nil] the device parent or +nil+ if not available
111
+ # @see #port_numbers
112
+ def parent
113
+ pppDevs = FFI::MemoryPointer.new :pointer
114
+ Call.libusb_get_device_list(@context.instance_variable_get(:@ctx), pppDevs)
115
+ ppDevs = pppDevs.read_pointer
116
+ pParent = Call.libusb_get_parent(@pDev)
117
+ parent = pParent.null? ? nil : Device.new(@context, pParent)
118
+ Call.libusb_free_device_list(ppDevs, 1)
119
+ parent
120
+ end
121
+
122
+ # Get the list of all port numbers from root for the specified device.
123
+ # Available since libusb-1.0.12.
124
+ #
125
+ # @return [Array<Fixnum>]
126
+ # @see #parent
127
+ # @see #port_number
128
+ def port_numbers
129
+ # As per the USB 3.0 specs, the current maximum limit for the depth is 7.
130
+ path_len = 7
131
+ pPath = FFI::MemoryPointer.new :pointer, path_len
132
+
133
+ l = if Call.respond_to?(:libusb_get_port_numbers)
134
+ Call.libusb_get_port_numbers(@pDev, pPath, path_len)
135
+ else
136
+ Call.libusb_get_port_path(@context.instance_variable_get(:@ctx), @pDev, pPath, path_len)
137
+ end
138
+ pPath.read_array_of_uint8(l)
139
+ end
140
+ alias port_path port_numbers
141
+ end
142
+
143
+ if Call.respond_to?(:libusb_get_device_speed)
144
+ # Get the negotiated connection speed for a device.
145
+ # Available since libusb-1.0.9.
146
+ #
147
+ # @return [Symbol] a {Call::Speeds Speeds} symbol, where +:SPEED_UNKNOWN+ means that
148
+ # the OS doesn't know or doesn't support returning the negotiated speed.
149
+ def device_speed
150
+ Call.libusb_get_device_speed(@pDev)
151
+ end
152
+ end
153
+
154
+ # Convenience function to retrieve the wMaxPacketSize value for a
155
+ # particular endpoint in the active device configuration.
156
+ #
157
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
158
+ # @return [Fixnum] the wMaxPacketSize value
159
+ def max_packet_size(endpoint)
160
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
161
+ res = Call.libusb_get_max_packet_size(@pDev, endpoint)
162
+ LIBUSB.raise_error res, "in libusb_get_max_packet_size" unless res>=0
163
+ res
164
+ end
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
+
204
+ # Calculate the maximum packet size which a specific endpoint is capable is
205
+ # sending or receiving in the duration of 1 microframe.
206
+ #
207
+ # Only the active configution is examined. The calculation is based on the
208
+ # wMaxPacketSize field in the endpoint descriptor as described in section 9.6.6
209
+ # in the USB 2.0 specifications.
210
+ #
211
+ # If acting on an isochronous or interrupt endpoint, this function will
212
+ # multiply the value found in bits 0:10 by the number of transactions per
213
+ # microframe (determined by bits 11:12). Otherwise, this function just returns
214
+ # the numeric value found in bits 0:10.
215
+ #
216
+ # This function is useful for setting up isochronous transfers, for example
217
+ # you might use the return value from this function to call
218
+ # IsoPacket#alloc_buffer in order to set the length field
219
+ # of an isochronous packet in a transfer.
220
+ #
221
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
222
+ # @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
223
+ # @see max_alt_packet_size
224
+ def max_iso_packet_size(endpoint)
225
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
226
+ res = Call.libusb_get_max_iso_packet_size(@pDev, endpoint)
227
+ LIBUSB.raise_error res, "in libusb_get_max_iso_packet_size" unless res>=0
228
+ res
229
+ end
230
+
231
+ # Obtain a config descriptor of the device.
232
+ #
233
+ # @param [Fixnum] index number of the config descriptor
234
+ # @return Configuration
235
+ def config_descriptor(index)
236
+ ppConfig = FFI::MemoryPointer.new :pointer
237
+ res = Call.libusb_get_config_descriptor(@pDev, index, ppConfig)
238
+ LIBUSB.raise_error res, "in libusb_get_config_descriptor" if res!=0
239
+ pConfig = ppConfig.read_pointer
240
+ config = Configuration.new(self, pConfig)
241
+ config
242
+ end
243
+
244
+ # Size of the Descriptor in Bytes (18 bytes)
245
+ def bLength
246
+ @pDevDesc[:bLength]
247
+ end
248
+
249
+ # Device Descriptor (0x01)
250
+ def bDescriptorType
251
+ @pDevDesc[:bDescriptorType]
252
+ end
253
+
254
+ # USB specification release number which device complies too
255
+ #
256
+ # @return [Integer] in binary-coded decimal
257
+ def bcdUSB
258
+ @pDevDesc[:bcdUSB]
259
+ end
260
+
261
+ # USB-IF class code for the device (Assigned by USB Org)
262
+ #
263
+ # * If equal to 0x00, each interface specifies it's own class code
264
+ # * If equal to 0xFF, the class code is vendor specified
265
+ # * Otherwise field is valid Class Code
266
+ def bDeviceClass
267
+ @pDevDesc[:bDeviceClass]
268
+ end
269
+
270
+ # USB-IF subclass code for the device, qualified by the {Device#bDeviceClass}
271
+ # value (Assigned by USB Org)
272
+ def bDeviceSubClass
273
+ @pDevDesc[:bDeviceSubClass]
274
+ end
275
+
276
+ # USB-IF protocol code for the device, qualified by the {Device#bDeviceClass}
277
+ # and {Device#bDeviceSubClass} values (Assigned by USB Org)
278
+ def bDeviceProtocol
279
+ @pDevDesc[:bDeviceProtocol]
280
+ end
281
+
282
+ # Maximum Packet Size for Endpoint 0. Valid Sizes are 8, 16, 32, 64
283
+ def bMaxPacketSize0
284
+ @pDevDesc[:bMaxPacketSize0]
285
+ end
286
+
287
+ # USB-IF vendor ID (Assigned by USB Org)
288
+ def idVendor
289
+ @pDevDesc[:idVendor]
290
+ end
291
+
292
+ # USB-IF product ID (Assigned by Manufacturer)
293
+ def idProduct
294
+ @pDevDesc[:idProduct]
295
+ end
296
+
297
+ # Device release number in binary-coded decimal.
298
+ def bcdDevice
299
+ @pDevDesc[:bcdDevice]
300
+ end
301
+
302
+ # Index of string descriptor describing manufacturer.
303
+ def iManufacturer
304
+ @pDevDesc[:iManufacturer]
305
+ end
306
+
307
+ # Index of string descriptor describing product.
308
+ def iProduct
309
+ @pDevDesc[:iProduct]
310
+ end
311
+
312
+ # Index of string descriptor containing device serial number.
313
+ def iSerialNumber
314
+ @pDevDesc[:iSerialNumber]
315
+ end
316
+
317
+ # Number of Possible Configurations
318
+ def bNumConfigurations
319
+ @pDevDesc[:bNumConfigurations]
320
+ end
321
+
322
+
323
+ def inspect
324
+ attrs = []
325
+ attrs << "#{self.bus_number}/#{self.device_address}"
326
+ attrs << ("%04x:%04x" % [self.idVendor, self.idProduct])
327
+ attrs << self.manufacturer
328
+ attrs << self.product
329
+ attrs << self.serial_number
330
+ if self.bDeviceClass == LIBUSB::CLASS_PER_INTERFACE
331
+ devclass = self.settings.map {|i|
332
+ LIBUSB.dev_string(i.bInterfaceClass, i.bInterfaceSubClass, i.bInterfaceProtocol)
333
+ }.join(", ")
334
+ else
335
+ devclass = LIBUSB.dev_string(self.bDeviceClass, self.bDeviceSubClass, self.bDeviceProtocol)
336
+ end
337
+ attrs << "(#{devclass})"
338
+ attrs.compact!
339
+ "\#<#{self.class} #{attrs.join(' ')}>"
340
+ end
341
+
342
+ def try_string_descriptor_ascii(i)
343
+ begin
344
+ open{|h| h.string_descriptor_ascii(i) }
345
+ rescue
346
+ "?"
347
+ end
348
+ end
349
+
350
+ # Return manufacturer of the device
351
+ # @return String
352
+ def manufacturer
353
+ return @manufacturer if defined? @manufacturer
354
+ @manufacturer = try_string_descriptor_ascii(self.iManufacturer)
355
+ @manufacturer = @manufacturer.strip if @manufacturer
356
+ @manufacturer
357
+ end
358
+
359
+ # Return product name of the device.
360
+ # @return String
361
+ def product
362
+ return @product if defined? @product
363
+ @product = try_string_descriptor_ascii(self.iProduct)
364
+ @product = @product.strip if @product
365
+ @product
366
+ end
367
+
368
+ # Return serial number of the device.
369
+ # @return String
370
+ def serial_number
371
+ return @serial_number if defined? @serial_number
372
+ @serial_number = try_string_descriptor_ascii(self.iSerialNumber)
373
+ @serial_number = @serial_number.strip if @serial_number
374
+ @serial_number
375
+ end
376
+
377
+ # Return configurations of the device.
378
+ # @return [Array<Configuration>]
379
+ def configurations
380
+ configs = []
381
+ bNumConfigurations.times do |config_index|
382
+ begin
383
+ configs << config_descriptor(config_index)
384
+ rescue RuntimeError
385
+ # On Windows some devices don't return it's configuration.
386
+ end
387
+ end
388
+ configs
389
+ end
390
+
391
+ # Return all interfaces of this device.
392
+ # @return [Array<Interface>]
393
+ def interfaces() self.configurations.map {|d| d.interfaces }.flatten end
394
+ # Return all interface decriptions of this device.
395
+ # @return [Array<Setting>]
396
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
397
+ # Return all endpoints of all interfaces of this device.
398
+ # @return [Array<Endpoint>]
399
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
400
+
401
+ def <=>(o)
402
+ t = bus_number<=>o.bus_number
403
+ t = device_address<=>o.device_address if t==0
404
+ t
405
+ end
406
+ end
407
+ end
@@ -0,0 +1,195 @@
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
+ class Endpoint < FFI::Struct
20
+ include Comparable
21
+
22
+ layout :bLength, :uint8,
23
+ :bDescriptorType, :uint8,
24
+ :bEndpointAddress, :uint8,
25
+ :bmAttributes, :uint8,
26
+ :wMaxPacketSize, :uint16,
27
+ :bInterval, :uint8,
28
+ :bRefresh, :uint8,
29
+ :bSynchAddress, :uint8,
30
+ :extra, :pointer,
31
+ :extra_length, :int
32
+
33
+ # Size of Descriptor in Bytes (7 bytes)
34
+ def bLength
35
+ self[:bLength]
36
+ end
37
+
38
+ # Descriptor type (0x05)
39
+ def bDescriptorType
40
+ self[:bDescriptorType]
41
+ end
42
+
43
+ # The address of the endpoint described by this descriptor.
44
+ #
45
+ # * Bits 0..3: Endpoint Number.
46
+ # * Bits 4..6: Reserved. Set to Zero
47
+ # * Bits 7: Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
48
+ #
49
+ # @return [Integer]
50
+ #
51
+ # @see #endpoint_number
52
+ # @see #direction
53
+ def bEndpointAddress
54
+ self[:bEndpointAddress]
55
+ end
56
+
57
+ # @return [Integer]
58
+ def endpoint_number
59
+ bEndpointAddress & 0b1111
60
+ end
61
+
62
+ # @return [Symbol] Either +:in+ or +:out+
63
+ def direction
64
+ bEndpointAddress & ENDPOINT_IN == 0 ? :out : :in
65
+ end
66
+
67
+ # Attributes which apply to the endpoint when it is configured using the {Configuration#bConfigurationValue}.
68
+ #
69
+ # * Bits 1..0: Transfer Type
70
+ # * 00 = Control
71
+ # * 01 = Isochronous
72
+ # * 10 = Bulk
73
+ # * 11 = Interrupt
74
+ # * Bits 7..2: are reserved. If Isochronous endpoint,
75
+ # * Bits 3..2: Synchronisation Type (Iso Mode)
76
+ # * 00 = No Synchonisation
77
+ # * 01 = Asynchronous
78
+ # * 10 = Adaptive
79
+ # * 11 = Synchronous
80
+ # * Bits 5..4: Usage Type (Iso Mode)
81
+ # * 00 = Data Endpoint
82
+ # * 01 = Feedback Endpoint
83
+ # * 10 = Explicit Feedback Data Endpoint
84
+ # * 11 = Reserved
85
+ #
86
+ # @return [Integer]
87
+ #
88
+ # @see #transfer_type
89
+ # @see #usage_type
90
+ # @see #synchronization_type
91
+ def bmAttributes
92
+ self[:bmAttributes]
93
+ end
94
+
95
+ TransferTypes = [:control, :isochronous, :bulk, :interrupt]
96
+ # @return [Symbol] One of {TransferTypes}
97
+ def transfer_type
98
+ TransferTypes[bmAttributes & 0b11]
99
+ end
100
+
101
+ SynchronizationTypes = [:no_synchronization, :asynchronous, :adaptive, :synchronous]
102
+ # @return [Symbol] One of {SynchronizationTypes}
103
+ def synchronization_type
104
+ return unless transfer_type == :isochronous
105
+ SynchronizationTypes[(bmAttributes & 0b1100) >> 2]
106
+ end
107
+
108
+ UsageTypes = [:data, :feedback, :implicit_feedback, :unknown]
109
+ # @return [Symbol] One of {UsageTypes}
110
+ def usage_type
111
+ return unless transfer_type == :isochronous
112
+ UsageTypes[(bmAttributes & 0b110000) >> 4]
113
+ end
114
+
115
+ # Maximum Packet Size this endpoint is capable of sending or receiving
116
+ def wMaxPacketSize
117
+ self[:wMaxPacketSize]
118
+ end
119
+
120
+ # Interval for polling endpoint data transfers. Value in frame counts.
121
+ # Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field
122
+ # may range from 1 to 255 for interrupt endpoints.
123
+ #
124
+ # The interval is respected by the kernel driver, so user mode processes
125
+ # using libusb don't need to care about it.
126
+ def bInterval
127
+ self[:bInterval]
128
+ end
129
+
130
+ # For audio devices only: the rate at which synchronization feedback is provided.
131
+ def bRefresh
132
+ self[:bRefresh]
133
+ end
134
+
135
+ # For audio devices only: the address if the synch endpoint.
136
+ def bSynchAddress
137
+ self[:bSynchAddress]
138
+ end
139
+
140
+ # Extra descriptors.
141
+ #
142
+ # @return [String]
143
+ def extra
144
+ return if self[:extra].null?
145
+ self[:extra].read_string(self[:extra_length])
146
+ end
147
+
148
+ def initialize(setting, *args)
149
+ @setting = setting
150
+ super(*args)
151
+ end
152
+
153
+ # @return [Setting] the setting this endpoint belongs to.
154
+ attr_reader :setting
155
+
156
+ def inspect
157
+ type = [transfer_type, synchronization_type, usage_type].compact
158
+ "\#<#{self.class} #{endpoint_number} #{direction} #{type.join(" ")}>"
159
+ end
160
+
161
+ # The {Device} this Endpoint belongs to.
162
+ def device() self.setting.interface.configuration.device end
163
+ # The {Configuration} this Endpoint belongs to.
164
+ def configuration() self.setting.interface.configuration end
165
+ # The {Interface} this Endpoint belongs to.
166
+ def interface() self.setting.interface end
167
+
168
+ def <=>(o)
169
+ t = setting<=>o.setting
170
+ t = bEndpointAddress<=>o.bEndpointAddress if t==0
171
+ t
172
+ end
173
+
174
+ if Call.respond_to?(:libusb_get_ss_endpoint_companion_descriptor)
175
+
176
+ # @method ss_companion
177
+ # Get the endpoints superspeed endpoint companion descriptor (if any).
178
+ #
179
+ # Since libusb version 1.0.16.
180
+ #
181
+ # @return [SsCompanion]
182
+ def ss_companion
183
+ ep_comp = FFI::MemoryPointer.new :pointer
184
+ ctx = device.context.instance_variable_get(:@ctx)
185
+ res = Call.libusb_get_ss_endpoint_companion_descriptor(
186
+ ctx,
187
+ pointer,
188
+ ep_comp
189
+ )
190
+ LIBUSB.raise_error res, "in libusb_get_ss_endpoint_companion_descriptor" if res!=0
191
+ SsCompanion.new ctx, ep_comp.read_pointer
192
+ end
193
+ end
194
+ end
195
+ end