libusb 0.6.0-x86-linux

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +17 -0
  4. data/.yardopts +6 -0
  5. data/COPYING +165 -0
  6. data/Gemfile +11 -0
  7. data/History.md +124 -0
  8. data/README.md +159 -0
  9. data/Rakefile +145 -0
  10. data/appveyor.yml +23 -0
  11. data/lib/libusb.rb +58 -0
  12. data/lib/libusb/bos.rb +306 -0
  13. data/lib/libusb/call.rb +446 -0
  14. data/lib/libusb/compat.rb +376 -0
  15. data/lib/libusb/configuration.rb +155 -0
  16. data/lib/libusb/constants.rb +160 -0
  17. data/lib/libusb/context.rb +426 -0
  18. data/lib/libusb/dependencies.rb +7 -0
  19. data/lib/libusb/dev_handle.rb +564 -0
  20. data/lib/libusb/device.rb +365 -0
  21. data/lib/libusb/endpoint.rb +194 -0
  22. data/lib/libusb/eventmachine.rb +183 -0
  23. data/lib/libusb/interface.rb +60 -0
  24. data/lib/libusb/setting.rb +132 -0
  25. data/lib/libusb/ss_companion.rb +69 -0
  26. data/lib/libusb/stdio.rb +25 -0
  27. data/lib/libusb/transfer.rb +377 -0
  28. data/lib/libusb/version_gem.rb +19 -0
  29. data/lib/libusb/version_struct.rb +63 -0
  30. data/libusb.gemspec +30 -0
  31. data/test/test_libusb_bos.rb +118 -0
  32. data/test/test_libusb_bulk_stream_transfer.rb +50 -0
  33. data/test/test_libusb_capability.rb +23 -0
  34. data/test/test_libusb_compat.rb +78 -0
  35. data/test/test_libusb_compat_mass_storage.rb +81 -0
  36. data/test/test_libusb_descriptors.rb +212 -0
  37. data/test/test_libusb_event_machine.rb +118 -0
  38. data/test/test_libusb_gc.rb +37 -0
  39. data/test/test_libusb_hotplug.rb +127 -0
  40. data/test/test_libusb_iso_transfer.rb +50 -0
  41. data/test/test_libusb_mass_storage.rb +268 -0
  42. data/test/test_libusb_mass_storage2.rb +96 -0
  43. data/test/test_libusb_structs.rb +58 -0
  44. data/test/test_libusb_threads.rb +89 -0
  45. data/test/test_libusb_version.rb +40 -0
  46. data/wireshark-usb-sniffer.png +0 -0
  47. metadata +150 -0
@@ -0,0 +1,365 @@
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
+
25
+ # @return [Context] the context this device belongs to.
26
+ attr_reader :context
27
+
28
+ def initialize context, pDev
29
+ @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
+ @pDev = pDev
36
+
37
+ @pDevDesc = Call::DeviceDescriptor.new
38
+ res = Call.libusb_get_device_descriptor(@pDev, @pDevDesc)
39
+ LIBUSB.raise_error res, "in libusb_get_device_descriptor" if res!=0
40
+ end
41
+
42
+ # Open the device and obtain a device handle.
43
+ #
44
+ # A handle allows you to perform I/O on the device in question.
45
+ # This is a non-blocking function; no requests are sent over the bus.
46
+ #
47
+ # If called with a block, the handle is passed to the block
48
+ # and is closed when the block has finished.
49
+ #
50
+ # You need proper device access:
51
+ # * Linux: read+write permissions to <tt>/dev/bus/usb/<bus>/<dev></tt>
52
+ # * Windows: by installing a WinUSB-driver for the device (see {file:README.rdoc#Usage_on_Windows} )
53
+ #
54
+ # @return [DevHandle] Handle to the device.
55
+ def open
56
+ ppHandle = FFI::MemoryPointer.new :pointer
57
+ res = Call.libusb_open(@pDev, ppHandle)
58
+ LIBUSB.raise_error res, "in libusb_open" if res!=0
59
+ handle = DevHandle.new self, ppHandle.read_pointer
60
+ return handle unless block_given?
61
+ begin
62
+ yield handle
63
+ ensure
64
+ handle.close
65
+ end
66
+ end
67
+
68
+ # Open the device and claim an interface.
69
+ #
70
+ # This is a convenience method to {Device#open} and {DevHandle#claim_interface}.
71
+ # Must be called with a block. When the block has finished, the interface
72
+ # will be released and the device will be closed.
73
+ #
74
+ # @param [Interface, Fixnum] interface the interface or it's bInterfaceNumber you wish to claim
75
+ def open_interface(interface)
76
+ open do |dev|
77
+ dev.claim_interface(interface) do
78
+ yield dev
79
+ end
80
+ end
81
+ end
82
+
83
+ # Get the number of the bus that a device is connected to.
84
+ def bus_number
85
+ Call.libusb_get_bus_number(@pDev)
86
+ end
87
+
88
+ # Get the address of the device on the bus it is connected to.
89
+ def device_address
90
+ Call.libusb_get_device_address(@pDev)
91
+ end
92
+
93
+ if Call.respond_to?(:libusb_get_port_number)
94
+ # Get the number of the port that a device is connected to.
95
+ # Available since libusb-1.0.12.
96
+ #
97
+ # @return [Fixnum, nil] the port number (+nil+ if not available)
98
+ # @see #port_numbers
99
+ def port_number
100
+ r = Call.libusb_get_port_number(@pDev)
101
+ r==0 ? nil : r
102
+ end
103
+
104
+ # Get the the parent from the specified device [EXPERIMENTAL].
105
+ # Available since libusb-1.0.12.
106
+ #
107
+ # @return [Device, nil] the device parent or +nil+ if not available
108
+ # @see #port_numbers
109
+ def parent
110
+ pppDevs = FFI::MemoryPointer.new :pointer
111
+ Call.libusb_get_device_list(@context.instance_variable_get(:@ctx), pppDevs)
112
+ ppDevs = pppDevs.read_pointer
113
+ pParent = Call.libusb_get_parent(@pDev)
114
+ parent = pParent.null? ? nil : Device.new(@context, pParent)
115
+ Call.libusb_free_device_list(ppDevs, 1)
116
+ parent
117
+ end
118
+
119
+ # Get the list of all port numbers from root for the specified device.
120
+ # Available since libusb-1.0.12.
121
+ #
122
+ # @return [Array<Fixnum>]
123
+ # @see #parent
124
+ # @see #port_number
125
+ def port_numbers
126
+ # As per the USB 3.0 specs, the current maximum limit for the depth is 7.
127
+ path_len = 7
128
+ pPath = FFI::MemoryPointer.new :pointer, path_len
129
+
130
+ l = if Call.respond_to?(:libusb_get_port_numbers)
131
+ Call.libusb_get_port_numbers(@pDev, pPath, path_len)
132
+ else
133
+ Call.libusb_get_port_path(@context.instance_variable_get(:@ctx), @pDev, pPath, path_len)
134
+ end
135
+ pPath.read_array_of_uint8(l)
136
+ end
137
+ alias port_path port_numbers
138
+ end
139
+
140
+ if Call.respond_to?(:libusb_get_device_speed)
141
+ # Get the negotiated connection speed for a device.
142
+ # Available since libusb-1.0.9.
143
+ #
144
+ # @return [Symbol] a {Call::Speeds Speeds} symbol, where +:SPEED_UNKNOWN+ means that
145
+ # the OS doesn't know or doesn't support returning the negotiated speed.
146
+ def device_speed
147
+ Call.libusb_get_device_speed(@pDev)
148
+ end
149
+ end
150
+
151
+ # Convenience function to retrieve the wMaxPacketSize value for a
152
+ # particular endpoint in the active device configuration.
153
+ #
154
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
155
+ # @return [Fixnum] the wMaxPacketSize value
156
+ def max_packet_size(endpoint)
157
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
158
+ res = Call.libusb_get_max_packet_size(@pDev, endpoint)
159
+ LIBUSB.raise_error res, "in libusb_get_max_packet_size" unless res>=0
160
+ res
161
+ end
162
+
163
+ # Calculate the maximum packet size which a specific endpoint is capable is
164
+ # sending or receiving in the duration of 1 microframe.
165
+ #
166
+ # Only the active configution is examined. The calculation is based on the
167
+ # wMaxPacketSize field in the endpoint descriptor as described in section 9.6.6
168
+ # in the USB 2.0 specifications.
169
+ #
170
+ # If acting on an isochronous or interrupt endpoint, this function will
171
+ # multiply the value found in bits 0:10 by the number of transactions per
172
+ # microframe (determined by bits 11:12). Otherwise, this function just returns
173
+ # the numeric value found in bits 0:10.
174
+ #
175
+ # This function is useful for setting up isochronous transfers, for example
176
+ # you might use the return value from this function to call
177
+ # IsoPacket#alloc_buffer in order to set the length field
178
+ # of an isochronous packet in a transfer.
179
+ #
180
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
181
+ # @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
182
+ def max_iso_packet_size(endpoint)
183
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
184
+ res = Call.libusb_get_max_iso_packet_size(@pDev, endpoint)
185
+ LIBUSB.raise_error res, "in libusb_get_max_iso_packet_size" unless res>=0
186
+ res
187
+ end
188
+
189
+ # Obtain a config descriptor of the device.
190
+ #
191
+ # @param [Fixnum] index number of the config descriptor
192
+ # @return Configuration
193
+ def config_descriptor(index)
194
+ ppConfig = FFI::MemoryPointer.new :pointer
195
+ res = Call.libusb_get_config_descriptor(@pDev, index, ppConfig)
196
+ LIBUSB.raise_error res, "in libusb_get_config_descriptor" if res!=0
197
+ pConfig = ppConfig.read_pointer
198
+ config = Configuration.new(self, pConfig)
199
+ config
200
+ end
201
+
202
+ # Size of the Descriptor in Bytes (18 bytes)
203
+ def bLength
204
+ @pDevDesc[:bLength]
205
+ end
206
+
207
+ # Device Descriptor (0x01)
208
+ def bDescriptorType
209
+ @pDevDesc[:bDescriptorType]
210
+ end
211
+
212
+ # USB specification release number which device complies too
213
+ #
214
+ # @return [Integer] in binary-coded decimal
215
+ def bcdUSB
216
+ @pDevDesc[:bcdUSB]
217
+ end
218
+
219
+ # USB-IF class code for the device (Assigned by USB Org)
220
+ #
221
+ # * If equal to 0x00, each interface specifies it's own class code
222
+ # * If equal to 0xFF, the class code is vendor specified
223
+ # * Otherwise field is valid Class Code
224
+ def bDeviceClass
225
+ @pDevDesc[:bDeviceClass]
226
+ end
227
+
228
+ # USB-IF subclass code for the device, qualified by the {Device#bDeviceClass}
229
+ # value (Assigned by USB Org)
230
+ def bDeviceSubClass
231
+ @pDevDesc[:bDeviceSubClass]
232
+ end
233
+
234
+ # USB-IF protocol code for the device, qualified by the {Device#bDeviceClass}
235
+ # and {Device#bDeviceSubClass} values (Assigned by USB Org)
236
+ def bDeviceProtocol
237
+ @pDevDesc[:bDeviceProtocol]
238
+ end
239
+
240
+ # Maximum Packet Size for Endpoint 0. Valid Sizes are 8, 16, 32, 64
241
+ def bMaxPacketSize0
242
+ @pDevDesc[:bMaxPacketSize0]
243
+ end
244
+
245
+ # USB-IF vendor ID (Assigned by USB Org)
246
+ def idVendor
247
+ @pDevDesc[:idVendor]
248
+ end
249
+
250
+ # USB-IF product ID (Assigned by Manufacturer)
251
+ def idProduct
252
+ @pDevDesc[:idProduct]
253
+ end
254
+
255
+ # Device release number in binary-coded decimal.
256
+ def bcdDevice
257
+ @pDevDesc[:bcdDevice]
258
+ end
259
+
260
+ # Index of string descriptor describing manufacturer.
261
+ def iManufacturer
262
+ @pDevDesc[:iManufacturer]
263
+ end
264
+
265
+ # Index of string descriptor describing product.
266
+ def iProduct
267
+ @pDevDesc[:iProduct]
268
+ end
269
+
270
+ # Index of string descriptor containing device serial number.
271
+ def iSerialNumber
272
+ @pDevDesc[:iSerialNumber]
273
+ end
274
+
275
+ # Number of Possible Configurations
276
+ def bNumConfigurations
277
+ @pDevDesc[:bNumConfigurations]
278
+ end
279
+
280
+
281
+ def inspect
282
+ attrs = []
283
+ attrs << "#{self.bus_number}/#{self.device_address}"
284
+ attrs << ("%04x:%04x" % [self.idVendor, self.idProduct])
285
+ attrs << self.manufacturer
286
+ attrs << self.product
287
+ attrs << self.serial_number
288
+ if self.bDeviceClass == LIBUSB::CLASS_PER_INTERFACE
289
+ devclass = self.settings.map {|i|
290
+ LIBUSB.dev_string(i.bInterfaceClass, i.bInterfaceSubClass, i.bInterfaceProtocol)
291
+ }.join(", ")
292
+ else
293
+ devclass = LIBUSB.dev_string(self.bDeviceClass, self.bDeviceSubClass, self.bDeviceProtocol)
294
+ end
295
+ attrs << "(#{devclass})"
296
+ attrs.compact!
297
+ "\#<#{self.class} #{attrs.join(' ')}>"
298
+ end
299
+
300
+ def try_string_descriptor_ascii(i)
301
+ begin
302
+ open{|h| h.string_descriptor_ascii(i) }
303
+ rescue
304
+ "?"
305
+ end
306
+ end
307
+
308
+ # Return manufacturer of the device
309
+ # @return String
310
+ def manufacturer
311
+ return @manufacturer if defined? @manufacturer
312
+ @manufacturer = try_string_descriptor_ascii(self.iManufacturer)
313
+ @manufacturer.strip! if @manufacturer
314
+ @manufacturer
315
+ end
316
+
317
+ # Return product name of the device.
318
+ # @return String
319
+ def product
320
+ return @product if defined? @product
321
+ @product = try_string_descriptor_ascii(self.iProduct)
322
+ @product.strip! if @product
323
+ @product
324
+ end
325
+
326
+ # Return serial number of the device.
327
+ # @return String
328
+ def serial_number
329
+ return @serial_number if defined? @serial_number
330
+ @serial_number = try_string_descriptor_ascii(self.iSerialNumber)
331
+ @serial_number.strip! if @serial_number
332
+ @serial_number
333
+ end
334
+
335
+ # Return configurations of the device.
336
+ # @return [Array<Configuration>]
337
+ def configurations
338
+ configs = []
339
+ bNumConfigurations.times do |config_index|
340
+ begin
341
+ configs << config_descriptor(config_index)
342
+ rescue RuntimeError
343
+ # On Windows some devices don't return it's configuration.
344
+ end
345
+ end
346
+ configs
347
+ end
348
+
349
+ # Return all interfaces of this device.
350
+ # @return [Array<Interface>]
351
+ def interfaces() self.configurations.map {|d| d.interfaces }.flatten end
352
+ # Return all interface decriptions of this device.
353
+ # @return [Array<Setting>]
354
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
355
+ # Return all endpoints of all interfaces of this device.
356
+ # @return [Array<Endpoint>]
357
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
358
+
359
+ def <=>(o)
360
+ t = bus_number<=>o.bus_number
361
+ t = device_address<=>o.device_address if t==0
362
+ t
363
+ end
364
+ end
365
+ end
@@ -0,0 +1,194 @@
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
+ res = Call.libusb_get_ss_endpoint_companion_descriptor(
185
+ device.context.instance_variable_get(:@ctx),
186
+ pointer,
187
+ ep_comp
188
+ )
189
+ LIBUSB.raise_error res, "in libusb_get_ss_endpoint_companion_descriptor" if res!=0
190
+ SsCompanion.new ep_comp.read_pointer
191
+ end
192
+ end
193
+ end
194
+ end