libusb 0.7.0-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
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,376 @@
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
+ # This file is for compatibility with ruby-usb and libusb-0.1.
17
+ #
18
+ # Please visit the project website at http://github.com/larskanis/libusb
19
+ # for support.
20
+
21
+ require 'libusb'
22
+ require 'forwardable'
23
+
24
+ # Compatibility layer for ruby-usb[http://www.a-k-r.org/ruby-usb/] (API based on libusb-0.1)
25
+ #
26
+ # This module provides some limited compatibility to ruby-usb.
27
+ #
28
+ # Usage example:
29
+ # begin
30
+ # require 'usb'
31
+ # rescue LoadError
32
+ # require 'libusb/compat'
33
+ # end
34
+ # p USB.devices => [#<USB::Device ...>]
35
+ #
36
+ # Known issues:
37
+ # * Exceptions are different between ruby-usb and libusb and they don't get converted
38
+ # * libusb-1.0 doesn't explicitly manage USB-buses, so only one Bus is used currently
39
+ module USB
40
+ @default_context = nil
41
+ def self.default_context
42
+ @default_context ||= LIBUSB::Context.new
43
+ end
44
+
45
+ @default_bus = nil
46
+ def self.default_bus
47
+ @default_bus ||= Bus.new(default_context)
48
+ end
49
+
50
+ USB_CLASS_PER_INTERFACE = LIBUSB::CLASS_PER_INTERFACE
51
+ USB_CLASS_AUDIO = LIBUSB::CLASS_AUDIO
52
+ USB_CLASS_COMM = LIBUSB::CLASS_COMM
53
+ USB_CLASS_HID = LIBUSB::CLASS_HID
54
+ USB_CLASS_PRINTER = LIBUSB::CLASS_PRINTER
55
+ USB_CLASS_PTP = LIBUSB::CLASS_PTP
56
+ USB_CLASS_MASS_STORAGE = LIBUSB::CLASS_MASS_STORAGE
57
+ USB_CLASS_HUB = LIBUSB::CLASS_HUB
58
+ USB_CLASS_DATA = LIBUSB::CLASS_DATA
59
+ USB_CLASS_VENDOR_SPEC = LIBUSB::CLASS_VENDOR_SPEC
60
+
61
+ USB_DT_DEVICE = LIBUSB::DT_DEVICE
62
+ USB_DT_CONFIG = LIBUSB::DT_CONFIG
63
+ USB_DT_STRING = LIBUSB::DT_STRING
64
+ USB_DT_INTERFACE = LIBUSB::DT_INTERFACE
65
+ USB_DT_ENDPOINT = LIBUSB::DT_ENDPOINT
66
+ USB_DT_HID = LIBUSB::DT_HID
67
+ USB_DT_REPORT = LIBUSB::DT_REPORT
68
+ USB_DT_PHYSICAL = LIBUSB::DT_PHYSICAL
69
+ USB_DT_HUB = LIBUSB::DT_HUB
70
+ USB_DT_DEVICE_SIZE = LIBUSB::DT_DEVICE_SIZE
71
+ USB_DT_CONFIG_SIZE = LIBUSB::DT_CONFIG_SIZE
72
+ USB_DT_INTERFACE_SIZE = LIBUSB::DT_INTERFACE_SIZE
73
+ USB_DT_ENDPOINT_SIZE = LIBUSB::DT_ENDPOINT_SIZE
74
+ USB_DT_ENDPOINT_AUDIO_SIZE = LIBUSB::DT_ENDPOINT_AUDIO_SIZE
75
+ USB_DT_HUB_NONVAR_SIZE = LIBUSB::DT_HUB_NONVAR_SIZE
76
+
77
+ USB_ENDPOINT_ADDRESS_MASK = LIBUSB::ENDPOINT_ADDRESS_MASK
78
+ USB_ENDPOINT_DIR_MASK = LIBUSB::ENDPOINT_DIR_MASK
79
+ USB_ENDPOINT_IN = LIBUSB::ENDPOINT_IN
80
+ USB_ENDPOINT_OUT = LIBUSB::ENDPOINT_OUT
81
+
82
+ USB_ENDPOINT_TYPE_MASK = LIBUSB::TRANSFER_TYPE_MASK
83
+ USB_ENDPOINT_TYPE_CONTROL = LIBUSB::TRANSFER_TYPE_CONTROL
84
+ USB_ENDPOINT_TYPE_ISOCHRONOUS = LIBUSB::TRANSFER_TYPE_ISOCHRONOUS
85
+ USB_ENDPOINT_TYPE_BULK = LIBUSB::TRANSFER_TYPE_BULK
86
+ USB_ENDPOINT_TYPE_INTERRUPT = LIBUSB::TRANSFER_TYPE_INTERRUPT
87
+
88
+ USB_REQ_GET_STATUS = LIBUSB::REQUEST_GET_STATUS
89
+ USB_REQ_CLEAR_FEATURE = LIBUSB::REQUEST_CLEAR_FEATURE
90
+ USB_REQ_SET_FEATURE = LIBUSB::REQUEST_SET_FEATURE
91
+ USB_REQ_SET_ADDRESS = LIBUSB::REQUEST_SET_ADDRESS
92
+ USB_REQ_GET_DESCRIPTOR = LIBUSB::REQUEST_GET_DESCRIPTOR
93
+ USB_REQ_SET_DESCRIPTOR = LIBUSB::REQUEST_SET_DESCRIPTOR
94
+ USB_REQ_GET_CONFIGURATION = LIBUSB::REQUEST_GET_CONFIGURATION
95
+ USB_REQ_SET_CONFIGURATION = LIBUSB::REQUEST_SET_CONFIGURATION
96
+ USB_REQ_GET_INTERFACE = LIBUSB::REQUEST_GET_INTERFACE
97
+ USB_REQ_SET_INTERFACE = LIBUSB::REQUEST_SET_INTERFACE
98
+ USB_REQ_SYNCH_FRAME = LIBUSB::REQUEST_SYNCH_FRAME
99
+ USB_TYPE_STANDARD = LIBUSB::REQUEST_TYPE_STANDARD
100
+ USB_TYPE_CLASS = LIBUSB::REQUEST_TYPE_CLASS
101
+ USB_TYPE_VENDOR = LIBUSB::REQUEST_TYPE_VENDOR
102
+ USB_TYPE_RESERVED = LIBUSB::REQUEST_TYPE_RESERVED
103
+ USB_RECIP_DEVICE = LIBUSB::RECIPIENT_DEVICE
104
+ USB_RECIP_INTERFACE = LIBUSB::RECIPIENT_INTERFACE
105
+ USB_RECIP_ENDPOINT = LIBUSB::RECIPIENT_ENDPOINT
106
+ USB_RECIP_OTHER = LIBUSB::RECIPIENT_OTHER
107
+
108
+ HAS_GET_DRIVER_NP = !FFI::Platform.windows?
109
+ HAS_DETACH_KERNEL_DRIVER_NP = !FFI::Platform.windows?
110
+
111
+ # not defined by libusb-1.0, but typical values are:
112
+ USB_MAXENDPOINTS = 32
113
+ USB_MAXINTERFACES = 32
114
+ USB_MAXALTSETTING = 128
115
+ USB_MAXCONFIG = 8
116
+
117
+
118
+ def USB.busses
119
+ [default_bus]
120
+ end
121
+
122
+ def USB.devices; default_context.devices.map{|c| Device.new(c) }; end
123
+ def USB.configurations() USB.devices.map {|d| d.configurations }.flatten end
124
+ def USB.interfaces() USB.configurations.map {|d| d.interfaces }.flatten end
125
+ def USB.settings() USB.interfaces.map {|d| d.settings }.flatten end
126
+ def USB.endpoints() USB.settings.map {|d| d.endpoints }.flatten end
127
+
128
+ def USB.find_bus(n)
129
+ default_bus
130
+ end
131
+
132
+ def USB.each_device_by_class(devclass, subclass=nil, protocol=nil)
133
+ devs = default_context.devices bClass: devclass, bSubClass: subclass, bProtocol: protocol
134
+ devs.each do |dev|
135
+ yield Device.new(dev)
136
+ end
137
+ nil
138
+ end
139
+
140
+ class Bus
141
+ def initialize(context)
142
+ @ct = context
143
+ end
144
+ def devices
145
+ @ct.devices.map{|d| Device.new(d) }
146
+ end
147
+
148
+ def configurations() self.devices.map{|d| d.configurations }.flatten end
149
+ def interfaces() self.configurations.map {|d| d.interfaces }.flatten end
150
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
151
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
152
+
153
+ def find_device(n)
154
+ raise NotImplementedError
155
+ end
156
+ end
157
+
158
+ def USB.dev_string(base_class, sub_class, protocol)
159
+ LIBUSB.dev_string(base_class, sub_class, protocol)
160
+ end
161
+
162
+ class Device
163
+ extend Forwardable
164
+ include Comparable
165
+
166
+ def initialize(dev)
167
+ @dev = dev
168
+ end
169
+
170
+ def_delegators :@dev, :bLength, :bDescriptorType, :bcdUSB, :bDeviceClass,
171
+ :bDeviceSubClass, :bDeviceProtocol, :bMaxPacketSize0, :idVendor, :idProduct,
172
+ :bcdDevice, :iManufacturer, :iProduct, :iSerialNumber, :bNumConfigurations,
173
+ :manufacturer, :product, :serial_number,
174
+ :inspect
175
+
176
+ def <=>(o)
177
+ @dev<=>o.instance_variable_get(:@dev)
178
+ end
179
+
180
+ def open
181
+ h = DevHandle.new(@dev.open)
182
+ if block_given?
183
+ begin
184
+ yield h
185
+ ensure
186
+ h.usb_close
187
+ end
188
+ else
189
+ h
190
+ end
191
+ end
192
+
193
+ def bus; default_bus; end
194
+ def configurations; @dev.configurations.map{|c| Configuration.new(c) }; end
195
+ def interfaces; @dev.interfaces.map{|c| Interface.new(c) }; end
196
+ def settings; @dev.settings.map{|c| Setting.new(c) }; end
197
+ def endpoints; @dev.endpoints.map{|c| Endpoint.new(c) }; end
198
+ end
199
+
200
+ class Configuration
201
+ extend Forwardable
202
+ include Comparable
203
+
204
+ def initialize(cd)
205
+ @cd = cd
206
+ end
207
+
208
+ def_delegators :@cd, :bLength, :bDescriptorType, :wTotalLength, :bNumInterfaces,
209
+ :bConfigurationValue, :iConfiguration, :bmAttributes, :bMaxPower,
210
+ :inspect
211
+
212
+ def <=>(o)
213
+ @cd<=>o.instance_variable_get(:@cd)
214
+ end
215
+
216
+ def bus; default_bus; end
217
+ def device() Device.new(@cd.device) end
218
+ def interfaces; @cd.interfaces.map{|c| Interface.new(c) }; end
219
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
220
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
221
+ end
222
+
223
+ class Interface
224
+ extend Forwardable
225
+ include Comparable
226
+
227
+ def initialize(i)
228
+ @i = i
229
+ end
230
+
231
+ def_delegators :@i, :inspect
232
+
233
+ def <=>(o)
234
+ @i<=>o.instance_variable_get(:@i)
235
+ end
236
+
237
+ def bus() self.configuration.device.bus end
238
+ def device() self.configuration.device end
239
+ def configuration; Configuration.new(@i.configuration); end
240
+ def settings; @i.alt_settings.map{|c| Setting.new(c) }; end
241
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
242
+ end
243
+
244
+ class Setting
245
+ extend Forwardable
246
+ include Comparable
247
+
248
+ def initialize(id)
249
+ @id = id
250
+ end
251
+
252
+ def_delegators :@id, :bLength, :bDescriptorType, :bInterfaceNumber, :bAlternateSetting,
253
+ :bNumEndpoints, :bInterfaceClass, :bInterfaceSubClass, :bInterfaceProtocol,
254
+ :iInterface, :inspect
255
+
256
+ def <=>(o)
257
+ @id<=>o.instance_variable_get(:@id)
258
+ end
259
+
260
+ def bus() self.interface.configuration.device.bus end
261
+ def device() self.interface.configuration.device end
262
+ def configuration() self.interface.configuration end
263
+ def interface; Interface.new(@id.interface); end
264
+ def endpoints() @id.endpoints.map {|d| Endpoint.new(d) }.flatten end
265
+ end
266
+
267
+ class Endpoint
268
+ extend Forwardable
269
+ include Comparable
270
+
271
+ def initialize(ep)
272
+ @ep = ep
273
+ end
274
+
275
+ def_delegators :@ep, :bLength, :bDescriptorType, :bEndpointAddress, :bmAttributes,
276
+ :wMaxPacketSize, :bInterval, :bRefresh, :bSynchAddress,
277
+ :inspect
278
+
279
+ def <=>(o)
280
+ @ep<=>o.instance_variable_get(:@ep)
281
+ end
282
+
283
+ def bus() self.setting.interface.configuration.device.bus end
284
+ def device() self.setting.interface.configuration.device end
285
+ def configuration() self.setting.interface.configuration end
286
+ def interface() self.setting.interface end
287
+ def setting; Setting.new(@ep.setting); end
288
+ end
289
+
290
+ class DevHandle
291
+ def initialize(dev)
292
+ @dev = dev
293
+ end
294
+
295
+ def usb_close; @dev.close; end
296
+ def usb_set_configuration(c); @dev.configuration=c; end
297
+ def usb_set_altinterface(c); @dev.set_interface_alt_setting=c; end
298
+ def usb_clear_halt(c); @dev.clear_halt(c); end
299
+ def usb_reset; @dev.reset_device; end
300
+ def usb_claim_interface(c); @dev.claim_interface(c); end
301
+ def usb_release_interface(c); @dev.release_interface(c); end
302
+ def usb_get_string(index, langid, buffer)
303
+ t = @dev.string_descriptor(index, langid)
304
+ buffer[0, t.length] = t
305
+ t.length
306
+ end
307
+ def usb_get_string_simple(index, buffer)
308
+ t = @dev.string_descriptor_ascii(index)
309
+ buffer[0, t.length] = t
310
+ t.length
311
+ end
312
+
313
+ def usb_control_msg(requesttype, request, value, index, bytes, timeout)
314
+ if requesttype&LIBUSB::ENDPOINT_IN != 0
315
+ # transfer direction in
316
+ res = @dev.control_transfer(bmRequestType: requesttype, bRequest: request,
317
+ wValue: value, wIndex: index, dataIn: bytes.bytesize, timeout: timeout)
318
+ bytes[0, res.bytesize] = res
319
+ res.bytesize
320
+ else
321
+ # transfer direction out
322
+ @dev.control_transfer(bmRequestType: requesttype, bRequest: request, wValue: value,
323
+ wIndex: index, dataOut: bytes, timeout: timeout)
324
+ end
325
+ end
326
+
327
+ def usb_bulk_write(endpoint, bytes, timeout)
328
+ @dev.bulk_transfer(endpoint: endpoint, dataOut: bytes, timeout: timeout)
329
+ end
330
+ def usb_bulk_read(endpoint, bytes, timeout)
331
+ res = @dev.bulk_transfer(endpoint: endpoint, dataIn: bytes.bytesize, timeout: timeout)
332
+ bytes[0, res.bytesize] = res
333
+ res.bytesize
334
+ end
335
+
336
+ def usb_interrupt_write(endpoint, bytes, timeout)
337
+ @dev.interrupt_transfer(endpoint: endpoint, dataOut: bytes, timeout: timeout)
338
+ end
339
+ def usb_interrupt_read(endpoint, bytes, timeout)
340
+ res = @dev.interrupt_transfer(endpoint: endpoint, dataIn: bytes.bytesize, timeout: timeout)
341
+ bytes[0, res.bytesize] = res
342
+ res.bytesize
343
+ end
344
+
345
+ # rb_define_method(rb_cUSB_DevHandle, "usb_get_descriptor", rusb_get_descriptor, 3);
346
+ # rb_define_method(rb_cUSB_DevHandle, "usb_get_descriptor_by_endpoint", rusb_get_descriptor_by_endpoint, 4);
347
+
348
+ if HAS_DETACH_KERNEL_DRIVER_NP
349
+ def usb_detach_kernel_driver_np(interface, dummy=nil)
350
+ @dev.detach_kernel_driver(interface)
351
+ end
352
+ end
353
+
354
+ if HAS_GET_DRIVER_NP
355
+ def usb_get_driver_np(interface, buffer)
356
+ if @dev.kernel_driver_active?(interface)
357
+ t = "unknown driver"
358
+ buffer[0, t.length] = t
359
+ else
360
+ raise Errno::ENODATA, "No data available"
361
+ end
362
+ nil
363
+ end
364
+ end
365
+
366
+ alias set_configuration usb_set_configuration
367
+ alias set_altinterface usb_set_altinterface
368
+ alias clear_halt usb_clear_halt
369
+ alias claim_interface usb_claim_interface
370
+ alias release_interface usb_release_interface
371
+
372
+ def get_string_simple(index)
373
+ @dev.string_descriptor_ascii(index)
374
+ end
375
+ end
376
+ end
@@ -0,0 +1,154 @@
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 Configuration < FFI::Struct
20
+ include Comparable
21
+ include ContextReference
22
+
23
+ layout :bLength, :uint8,
24
+ :bDescriptorType, :uint8,
25
+ :wTotalLength, :uint16,
26
+ :bNumInterfaces, :uint8,
27
+ :bConfigurationValue, :uint8,
28
+ :iConfiguration, :uint8,
29
+ :bmAttributes, :uint8,
30
+ :bMaxPower, :uint8,
31
+ :interface, :pointer,
32
+ :extra, :pointer,
33
+ :extra_length, :int
34
+
35
+ # Size of this descriptor (in bytes).
36
+ def bLength
37
+ self[:bLength]
38
+ end
39
+
40
+ # Descriptor type (0x02)
41
+ def bDescriptorType
42
+ self[:bDescriptorType]
43
+ end
44
+
45
+ # Total length of data returned for this configuration.
46
+ def wTotalLength
47
+ self[:wTotalLength]
48
+ end
49
+
50
+ # Number of interfaces supported by this configuration.
51
+ def bNumInterfaces
52
+ self[:bNumInterfaces]
53
+ end
54
+
55
+ # Identifier value for this configuration.
56
+ def bConfigurationValue
57
+ self[:bConfigurationValue]
58
+ end
59
+
60
+ # Index of string descriptor describing this configuration.
61
+ def iConfiguration
62
+ self[:iConfiguration]
63
+ end
64
+
65
+ # Configuration characteristics.
66
+ #
67
+ # * Bit 7: Reserved, set to 1. (USB 1.0 Bus Powered)
68
+ # * Bit 6: Self Powered
69
+ # * Bit 5: Remote Wakeup
70
+ # * Bit 4..0: Reserved, set to 0.
71
+ #
72
+ # @return [Integer]
73
+ #
74
+ # @see #self_powered?
75
+ # @see #remote_wakeup?
76
+ def bmAttributes
77
+ self[:bmAttributes]
78
+ end
79
+
80
+ # @return [Boolean]
81
+ def self_powered?
82
+ bmAttributes & 0b1000000 != 0
83
+ end
84
+
85
+ # @return [Boolean]
86
+ def remote_wakeup?
87
+ bmAttributes & 0b100000 != 0
88
+ end
89
+
90
+ # Maximum power consumption of the USB device from this bus in this configuration when the device is fully opreation.
91
+ #
92
+ # @return [Integer] Maximum Power Consumption in 2mA units
93
+ def bMaxPower
94
+ self[:bMaxPower]
95
+ end
96
+
97
+ # @deprecated Use {#bMaxPower} instead.
98
+ alias maxPower bMaxPower
99
+
100
+
101
+ # Extra descriptors.
102
+ #
103
+ # @return [String]
104
+ def extra
105
+ return if self[:extra].null?
106
+ self[:extra].read_string(self[:extra_length])
107
+ end
108
+
109
+ def initialize(device, *args)
110
+ @device = device
111
+ super(*args)
112
+
113
+ register_context(device.context.instance_variable_get(:@ctx), :libusb_free_config_descriptor)
114
+ end
115
+
116
+ # @return [Device] the device this configuration belongs to.
117
+ attr_reader :device
118
+
119
+ def interfaces
120
+ ifs = []
121
+ self[:bNumInterfaces].times do |i|
122
+ ifs << Interface.new(self, self[:interface] + i*Interface.size)
123
+ end
124
+ return ifs
125
+ end
126
+
127
+ def inspect
128
+ attrs = []
129
+ attrs << self.bConfigurationValue.to_s
130
+ attrs << "SelfPowered" if self_powered?
131
+ attrs << "RemoteWakeup" if remote_wakeup?
132
+ desc = self.description
133
+ attrs << desc if desc != '?'
134
+ "\#<#{self.class} #{attrs.join(' ')}>"
135
+ end
136
+
137
+ # Return name of this configuration as String.
138
+ def description
139
+ return @description if defined? @description
140
+ @description = device.try_string_descriptor_ascii(self.iConfiguration)
141
+ end
142
+
143
+ # Return all interface decriptions of the configuration as Array of {Setting}s.
144
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
145
+ # Return all endpoints of all interfaces of the configuration as Array of {Endpoint}s.
146
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
147
+
148
+ def <=>(o)
149
+ t = device<=>o.device
150
+ t = bConfigurationValue<=>o.bConfigurationValue if t==0
151
+ t
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,170 @@
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
+ [
20
+ Call::ClassCodes,
21
+ Call::TransferTypes,
22
+ Call::StandardRequests,
23
+ Call::RequestTypes,
24
+ Call::DescriptorTypes,
25
+ Call::EndpointDirections,
26
+ Call::RequestRecipients,
27
+ Call::IsoSyncTypes,
28
+ Call::Speeds,
29
+ Call::Capabilities,
30
+ Call::SupportedSpeeds,
31
+ Call::Usb20ExtensionAttributes,
32
+ Call::SsUsbDeviceCapabilityAttributes,
33
+ Call::BosTypes,
34
+ Call::HotplugEvents,
35
+ Call::HotplugFlags,
36
+ Call::LogLevels,
37
+ Call::LogCbMode,
38
+ Call::Options,
39
+ ].each do |enum|
40
+ enum.to_h.each{|k,v| const_set(k,v) }
41
+ end
42
+
43
+ # Base class of libusb errors
44
+ class Error < RuntimeError
45
+ # The data already transferred before the exception was raised
46
+ # @return [Fixnum] Number of bytes sent for an outgoing transfer
47
+ # @return [String] Received data for an ingoing transfer
48
+ attr_reader :transferred
49
+
50
+ def initialize(msg=nil, transferred=nil)
51
+ super(msg)
52
+ @transferred = transferred
53
+ end
54
+ end
55
+
56
+ class RemainingReferencesError < Error
57
+ end
58
+
59
+ # @private
60
+ ErrorClassForResult = {}
61
+
62
+ # define an exception class for each error code
63
+ Call::Errors.to_h.each do |k,v|
64
+ klass = Class.new(Error)
65
+ klass.send(:define_method, :code){ v }
66
+ const_set(k, klass)
67
+ ErrorClassForResult[v] = klass
68
+ end
69
+
70
+ def self.raise_error(res, text)
71
+ klass = ErrorClassForResult[res]
72
+ raise klass, "#{klass} #{text}"
73
+ end
74
+
75
+ CONTROL_SETUP_SIZE = 8
76
+ DT_DEVICE_SIZE = 18
77
+ DT_CONFIG_SIZE = 9
78
+ DT_INTERFACE_SIZE = 9
79
+ DT_ENDPOINT_SIZE = 7
80
+ DT_ENDPOINT_AUDIO_SIZE = 9 # Audio extension
81
+ DT_HUB_NONVAR_SIZE = 7
82
+
83
+ ENDPOINT_ADDRESS_MASK = 0x0f # in bEndpointAddress
84
+ ENDPOINT_DIR_MASK = 0x80
85
+ TRANSFER_TYPE_MASK = 0x03 # in bmAttributes
86
+ ISO_SYNC_TYPE_MASK = 0x0C
87
+ ISO_USAGE_TYPE_MASK = 0x30
88
+
89
+ POLLIN = 1
90
+ POLLOUT = 4
91
+
92
+ # Wildcard matching for hotplug events.
93
+ HOTPLUG_MATCH_ANY = -1
94
+
95
+
96
+ # http://www.usb.org/developers/defined_class
97
+ # @private
98
+ CLASS_CODES = [
99
+ [0x01, nil, nil, "Audio"],
100
+ [0x02, nil, nil, "Comm"],
101
+ [0x03, nil, nil, "HID"],
102
+ [0x05, nil, nil, "Physical"],
103
+ [0x06, 0x01, 0x01, "StillImaging"],
104
+ [0x06, nil, nil, "Image"],
105
+ [0x07, nil, nil, "Printer"],
106
+ [0x08, 0x01, nil, "MassStorage RBC Bulk-Only"],
107
+ [0x08, 0x02, 0x50, "MassStorage ATAPI Bulk-Only"],
108
+ [0x08, 0x03, 0x50, "MassStorage QIC-157 Bulk-Only"],
109
+ [0x08, 0x04, nil, "MassStorage UFI"],
110
+ [0x08, 0x05, 0x50, "MassStorage SFF-8070i Bulk-Only"],
111
+ [0x08, 0x06, 0x50, "MassStorage SCSI Bulk-Only"],
112
+ [0x08, nil, nil, "MassStorage"],
113
+ [0x09, 0x00, 0x00, "Full speed Hub"],
114
+ [0x09, 0x00, 0x01, "Hi-speed Hub with single TT"],
115
+ [0x09, 0x00, 0x02, "Hi-speed Hub with multiple TTs"],
116
+ [0x09, nil, nil, "Hub"],
117
+ [0x0a, nil, nil, "CDC"],
118
+ [0x0b, nil, nil, "SmartCard"],
119
+ [0x0d, 0x00, 0x00, "ContentSecurity"],
120
+ [0x0e, nil, nil, "Video"],
121
+ [0xdc, 0x01, 0x01, "Diagnostic USB2"],
122
+ [0xdc, nil, nil, "Diagnostic"],
123
+ [0xe0, 0x01, 0x01, "Bluetooth"],
124
+ [0xe0, 0x01, 0x02, "UWB"],
125
+ [0xe0, 0x01, 0x03, "RemoteNDIS"],
126
+ [0xe0, 0x02, 0x01, "Host Wire Adapter Control/Data"],
127
+ [0xe0, 0x02, 0x02, "Device Wire Adapter Control/Data"],
128
+ [0xe0, 0x02, 0x03, "Device Wire Adapter Isochronous"],
129
+ [0xe0, nil, nil, "Wireless Controller"],
130
+ [0xef, 0x01, 0x01, "Active Sync"],
131
+ [0xef, 0x01, 0x02, "Palm Sync"],
132
+ [0xef, 0x02, 0x01, "Interface Association Descriptor"],
133
+ [0xef, 0x02, 0x02, "Wire Adapter Multifunction Peripheral"],
134
+ [0xef, 0x03, 0x01, "Cable Based Association Framework"],
135
+ [0xef, nil, nil, "Miscellaneous"],
136
+ [0xfe, 0x01, 0x01, "Device Firmware Upgrade"],
137
+ [0xfe, 0x02, 0x00, "IRDA Bridge"],
138
+ [0xfe, 0x03, 0x00, "USB Test and Measurement"],
139
+ [0xfe, 0x03, 0x01, "USB Test and Measurement (USBTMC USB488)"],
140
+ [0xfe, nil, nil, "Application Specific"],
141
+ [0xff, nil, nil, "Vendor specific"],
142
+ ]
143
+ # @private
144
+ CLASS_CODES_HASH1 = {}
145
+ # @private
146
+ CLASS_CODES_HASH2 = {}
147
+ # @private
148
+ CLASS_CODES_HASH3 = {}
149
+ CLASS_CODES.each {|base_class, sub_class, protocol, desc|
150
+ if protocol
151
+ CLASS_CODES_HASH3[[base_class, sub_class, protocol]] = desc
152
+ elsif sub_class
153
+ CLASS_CODES_HASH2[[base_class, sub_class]] = desc
154
+ else
155
+ CLASS_CODES_HASH1[base_class] = desc
156
+ end
157
+ }
158
+
159
+ def self.dev_string(base_class, sub_class, protocol)
160
+ if desc = CLASS_CODES_HASH3[[base_class, sub_class, protocol]]
161
+ desc
162
+ elsif desc = CLASS_CODES_HASH2[[base_class, sub_class]]
163
+ desc + " (%02x)" % [protocol]
164
+ elsif desc = CLASS_CODES_HASH1[base_class]
165
+ desc + " (%02x,%02x)" % [sub_class, protocol]
166
+ else
167
+ "Unknown(%02x,%02x,%02x)" % [base_class, sub_class, protocol]
168
+ end
169
+ end
170
+ end