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,446 @@
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 'rubygems'
17
+ require 'ffi'
18
+
19
+ module LIBUSB
20
+ # C level interface - for internal use only
21
+ #
22
+ # All enum codes are available as constants in {LIBUSB} namespace.
23
+ module Call
24
+ extend FFI::Library
25
+
26
+ root_path = File.expand_path("../../..", __FILE__)
27
+ ext = FFI::Platform::LIBSUFFIX
28
+ prefix = FFI::Platform::LIBPREFIX.empty? ? 'lib' : FFI::Platform::LIBPREFIX
29
+ bundled_dll = File.join(root_path, "lib/#{prefix}usb-1.0.#{ext}")
30
+ bundled_dll_cygwin = File.join(root_path, "bin/#{prefix}usb-1.0.#{ext}")
31
+ ffi_lib([bundled_dll, bundled_dll_cygwin, "#{prefix}usb-1.0"])
32
+
33
+ ClassCodes = enum :libusb_class_code, [
34
+ :CLASS_PER_INTERFACE, 0,
35
+ :CLASS_AUDIO, 1,
36
+ :CLASS_COMM, 2,
37
+ :CLASS_HID, 3,
38
+ :CLASS_PRINTER, 7,
39
+ :CLASS_PTP, 6,
40
+ :CLASS_MASS_STORAGE, 8,
41
+ :CLASS_HUB, 9,
42
+ :CLASS_DATA, 10,
43
+ :CLASS_WIRELESS, 0xe0,
44
+ :CLASS_APPLICATION, 0xfe,
45
+ :CLASS_VENDOR_SPEC, 0xff
46
+ ]
47
+
48
+ Errors = enum :libusb_error, [
49
+ :SUCCESS, 0,
50
+ :ERROR_IO, -1,
51
+ :ERROR_INVALID_PARAM, -2,
52
+ :ERROR_ACCESS, -3,
53
+ :ERROR_NO_DEVICE, -4,
54
+ :ERROR_NOT_FOUND, -5,
55
+ :ERROR_BUSY, -6,
56
+ :ERROR_TIMEOUT, -7,
57
+ :ERROR_OVERFLOW, -8,
58
+ :ERROR_PIPE, -9,
59
+ :ERROR_INTERRUPTED, -10,
60
+ :ERROR_NO_MEM, -11,
61
+ :ERROR_NOT_SUPPORTED, -12,
62
+ :ERROR_OTHER, -99,
63
+ ]
64
+
65
+ # Transfer status codes
66
+ TransferStatus = enum :libusb_transfer_status, [
67
+ :TRANSFER_COMPLETED,
68
+ :TRANSFER_ERROR,
69
+ :TRANSFER_TIMED_OUT,
70
+ :TRANSFER_CANCELLED,
71
+ :TRANSFER_STALL,
72
+ :TRANSFER_NO_DEVICE,
73
+ :TRANSFER_OVERFLOW,
74
+ ]
75
+
76
+ # libusb_transfer.flags values
77
+ TransferFlags = enum :libusb_transfer_flags, [
78
+ :TRANSFER_SHORT_NOT_OK, 1 << 0,
79
+ :TRANSFER_FREE_BUFFER, 1 << 1,
80
+ :TRANSFER_FREE_TRANSFER, 1 << 2,
81
+ :TRANSFER_ADD_ZERO_PACKET, 1 << 3,
82
+ ]
83
+
84
+ # Values for {Endpoint#transfer_type}.
85
+ TransferTypes = enum :libusb_transfer_type, [
86
+ # Control endpoint
87
+ :TRANSFER_TYPE_CONTROL, 0,
88
+ # Isochronous endpoint
89
+ :TRANSFER_TYPE_ISOCHRONOUS, 1,
90
+ # Bulk endpoint
91
+ :TRANSFER_TYPE_BULK, 2,
92
+ # Interrupt endpoint
93
+ :TRANSFER_TYPE_INTERRUPT, 3,
94
+ # Stream endpoint
95
+ :TRANSFER_TYPE_BULK_STREAM, 4,
96
+ ]
97
+
98
+ StandardRequests = enum :libusb_standard_request, [
99
+ :REQUEST_GET_STATUS, 0x00,
100
+ :REQUEST_CLEAR_FEATURE, 0x01,
101
+ :REQUEST_SET_FEATURE, 0x03,
102
+ :REQUEST_SET_ADDRESS, 0x05,
103
+ :REQUEST_GET_DESCRIPTOR, 0x06,
104
+ :REQUEST_SET_DESCRIPTOR, 0x07,
105
+ :REQUEST_GET_CONFIGURATION, 0x08,
106
+ :REQUEST_SET_CONFIGURATION, 0x09,
107
+ :REQUEST_GET_INTERFACE, 0x0A,
108
+ :REQUEST_SET_INTERFACE, 0x0B,
109
+ :REQUEST_SYNCH_FRAME, 0x0C,
110
+ ]
111
+
112
+ EndpointDirections = enum :libusb_endpoint_direction, [
113
+ :ENDPOINT_IN, 0x80,
114
+ :ENDPOINT_OUT, 0x00,
115
+ ]
116
+
117
+ DescriptorTypes = enum :libusb_descriptor_type, [
118
+ # Device descriptor. See {Device}
119
+ :DT_DEVICE, 0x01,
120
+ # Configuration descriptor. See {Configuration}
121
+ :DT_CONFIG, 0x02,
122
+ # String descriptor
123
+ :DT_STRING, 0x03,
124
+ # Interface descriptor. See {Interface}
125
+ :DT_INTERFACE, 0x04,
126
+ # Endpoint descriptor. See {Endpoint}
127
+ :DT_ENDPOINT, 0x05,
128
+ # BOS descriptor
129
+ :DT_BOS, 0x0f,
130
+ # Device Capability descriptor
131
+ :DT_DEVICE_CAPABILITY, 0x10,
132
+ # HID descriptor
133
+ :DT_HID, 0x21,
134
+ # HID report descriptor
135
+ :DT_REPORT, 0x22,
136
+ # Physical descriptor
137
+ :DT_PHYSICAL, 0x23,
138
+ # Hub descriptor
139
+ :DT_HUB, 0x29,
140
+ # SuperSpeed Hub descriptor
141
+ :DT_SUPERSPEED_HUB, 0x2a,
142
+ # SuperSpeed Endpoint Companion descriptor
143
+ :DT_SS_ENDPOINT_COMPANION, 0x30,
144
+ ]
145
+
146
+ RequestTypes = enum :libusb_request_type, [
147
+ :REQUEST_TYPE_STANDARD, (0x00 << 5),
148
+ :REQUEST_TYPE_CLASS, (0x01 << 5),
149
+ :REQUEST_TYPE_VENDOR, (0x02 << 5),
150
+ :REQUEST_TYPE_RESERVED, (0x03 << 5),
151
+ ]
152
+
153
+ RequestRecipients = enum :libusb_request_recipient, [
154
+ :RECIPIENT_DEVICE, 0x00,
155
+ :RECIPIENT_INTERFACE, 0x01,
156
+ :RECIPIENT_ENDPOINT, 0x02,
157
+ :RECIPIENT_OTHER, 0x03,
158
+ ]
159
+
160
+ IsoSyncTypes = enum :libusb_iso_sync_type, [
161
+ :ISO_SYNC_TYPE_NONE, 0,
162
+ :ISO_SYNC_TYPE_ASYNC, 1,
163
+ :ISO_SYNC_TYPE_ADAPTIVE, 2,
164
+ :ISO_SYNC_TYPE_SYNC, 3,
165
+ ]
166
+
167
+ Speeds = enum :libusb_speed, [
168
+ :SPEED_UNKNOWN, 0,
169
+ :SPEED_LOW, 1,
170
+ :SPEED_FULL, 2,
171
+ :SPEED_HIGH, 3,
172
+ :SPEED_SUPER, 4,
173
+ ]
174
+
175
+ # Supported speeds (wSpeedSupported) bitfield. Indicates what
176
+ # speeds the device supports.
177
+ SupportedSpeeds = enum :libusb_supported_speed, [
178
+ # Low speed operation supported (1.5MBit/s).
179
+ :LOW_SPEED_OPERATION, 1,
180
+ # Full speed operation supported (12MBit/s).
181
+ :FULL_SPEED_OPERATION, 2,
182
+ # High speed operation supported (480MBit/s).
183
+ :HIGH_SPEED_OPERATION, 4,
184
+ # Superspeed operation supported (5000MBit/s).
185
+ :SUPER_SPEED_OPERATION, 8,
186
+ ]
187
+
188
+ Capabilities = enum :libusb_capability, [
189
+ :CAP_HAS_CAPABILITY, 0x0000,
190
+ # Hotplug support is available on this platform.
191
+ :CAP_HAS_HOTPLUG, 0x0001,
192
+ # The library can access HID devices without requiring user intervention.
193
+ # Note that before being able to actually access an HID device, you may
194
+ # still have to call additional libusb functions such as
195
+ # {DevHandle#detach_kernel_driver}.
196
+ :CAP_HAS_HID_ACCESS, 0x0100,
197
+ # The library supports detaching of the default USB driver, using
198
+ # {DevHandle#detach_kernel_driver}, if one is set by the OS kernel.
199
+ :CAP_SUPPORTS_DETACH_KERNEL_DRIVER, 0x0101,
200
+ ]
201
+
202
+ # Masks for the bits of the
203
+ # {Bos::Usb20Extension#bmAttributes} field
204
+ # of the USB 2.0 Extension descriptor.
205
+ Usb20ExtensionAttributes = enum :libusb_usb_2_0_extension_attributes, [
206
+ # Supports Link Power Management (LPM)
207
+ :BM_LPM_SUPPORT, 2,
208
+ ]
209
+
210
+ # Masks for the bits of the
211
+ # {Bos::SsUsbDeviceCapability#bmAttributes} field
212
+ # field of the SuperSpeed USB Device Capability descriptor.
213
+ SsUsbDeviceCapabilityAttributes = enum :libusb_ss_usb_device_capability_attributes, [
214
+ # Supports Latency Tolerance Messages (LTM)
215
+ :BM_LTM_SUPPORT, 2,
216
+ ]
217
+
218
+ # USB capability types
219
+ #
220
+ # @see Bos::DeviceCapability
221
+ BosTypes = enum :libusb_bos_type, [
222
+ # Wireless USB device capability
223
+ :BT_WIRELESS_USB_DEVICE_CAPABILITY, 1,
224
+ # USB 2.0 extensions
225
+ :BT_USB_2_0_EXTENSION, 2,
226
+ # SuperSpeed USB device capability
227
+ :BT_SS_USB_DEVICE_CAPABILITY, 3,
228
+ # Container ID type
229
+ :BT_CONTAINER_ID, 4,
230
+ ]
231
+
232
+ # Since libusb version 1.0.16.
233
+ #
234
+ # Hotplug events
235
+ HotplugEvents = enum :libusb_hotplug_event, [
236
+ # A device has been plugged in and is ready to use.
237
+ :HOTPLUG_EVENT_DEVICE_ARRIVED, 0x01,
238
+
239
+ # A device has left and is no longer available.
240
+ # It is the user's responsibility to call libusb_close on any handle associated with a disconnected device.
241
+ # It is safe to call libusb_get_device_descriptor on a device that has left.
242
+ :HOTPLUG_EVENT_DEVICE_LEFT, 0x02,
243
+ ]
244
+
245
+ # Since libusb version 1.0.16.
246
+ #
247
+ # Flags for hotplug events */
248
+ HotplugFlags = enum :libusb_hotplug_flag, [
249
+ # Arm the callback and fire it for all matching currently attached devices.
250
+ :HOTPLUG_ENUMERATE, 1,
251
+ ]
252
+
253
+ typedef :pointer, :libusb_context
254
+ typedef :pointer, :libusb_device
255
+ typedef :pointer, :libusb_device_handle
256
+ typedef :pointer, :libusb_transfer
257
+ typedef :int, :libusb_hotplug_callback_handle
258
+
259
+ def self.try_attach_function(method, *args)
260
+ if ffi_libraries.find{|lib| lib.find_function(method) }
261
+ attach_function method, *args
262
+ end
263
+ end
264
+
265
+ try_attach_function 'libusb_get_version', [], :pointer
266
+
267
+ attach_function 'libusb_init', [ :pointer ], :int
268
+ attach_function 'libusb_exit', [ :pointer ], :void
269
+ attach_function 'libusb_set_debug', [:pointer, :int], :void
270
+ try_attach_function 'libusb_has_capability', [:libusb_capability], :int
271
+
272
+ attach_function 'libusb_get_device_list', [:pointer, :pointer], :ssize_t
273
+ attach_function 'libusb_free_device_list', [:pointer, :int], :void
274
+ attach_function 'libusb_ref_device', [:pointer], :pointer
275
+ attach_function 'libusb_unref_device', [:pointer], :void
276
+
277
+ attach_function 'libusb_get_device_descriptor', [:pointer, :pointer], :int
278
+ attach_function 'libusb_get_active_config_descriptor', [:pointer, :pointer], :int
279
+ attach_function 'libusb_get_config_descriptor', [:pointer, :uint8, :pointer], :int
280
+ attach_function 'libusb_get_config_descriptor_by_value', [:pointer, :uint8, :pointer], :int
281
+ attach_function 'libusb_free_config_descriptor', [:pointer], :void
282
+ attach_function 'libusb_get_bus_number', [:pointer], :uint8
283
+ try_attach_function 'libusb_get_port_number', [:pointer], :uint8
284
+ try_attach_function 'libusb_get_parent', [:pointer], :pointer
285
+ try_attach_function 'libusb_get_port_path', [:pointer, :pointer, :pointer, :uint8], :uint8
286
+ try_attach_function 'libusb_get_port_numbers', [:pointer, :pointer, :uint8], :uint8
287
+ attach_function 'libusb_get_device_address', [:pointer], :uint8
288
+ try_attach_function 'libusb_get_device_speed', [:pointer], :libusb_speed
289
+ attach_function 'libusb_get_max_packet_size', [:pointer, :uint8], :int
290
+ attach_function 'libusb_get_max_iso_packet_size', [:pointer, :uint8], :int
291
+
292
+ try_attach_function 'libusb_get_ss_endpoint_companion_descriptor', [:pointer, :pointer, :pointer], :int
293
+ try_attach_function 'libusb_free_ss_endpoint_companion_descriptor', [:pointer], :void
294
+
295
+ try_attach_function 'libusb_get_bos_descriptor', [:libusb_device_handle, :pointer], :int, blocking: true
296
+ try_attach_function 'libusb_free_bos_descriptor', [:pointer], :void
297
+ try_attach_function 'libusb_get_usb_2_0_extension_descriptor', [:libusb_context, :pointer, :pointer], :int
298
+ try_attach_function 'libusb_free_usb_2_0_extension_descriptor', [:pointer], :void
299
+ try_attach_function 'libusb_get_ss_usb_device_capability_descriptor', [:libusb_context, :pointer, :pointer], :int
300
+ try_attach_function 'libusb_free_ss_usb_device_capability_descriptor', [:pointer], :void
301
+ try_attach_function 'libusb_get_container_id_descriptor', [:libusb_context, :pointer, :pointer], :int
302
+ try_attach_function 'libusb_free_container_id_descriptor', [:pointer], :void
303
+
304
+ attach_function 'libusb_open', [:pointer, :pointer], :int
305
+ attach_function 'libusb_close', [:pointer], :void
306
+ attach_function 'libusb_get_device', [:libusb_device_handle], :pointer
307
+
308
+ attach_function 'libusb_set_configuration', [:libusb_device_handle, :int], :int, blocking: true
309
+ attach_function 'libusb_claim_interface', [:libusb_device_handle, :int], :int
310
+ attach_function 'libusb_release_interface', [:libusb_device_handle, :int], :int, blocking: true
311
+
312
+ attach_function 'libusb_open_device_with_vid_pid', [:pointer, :int, :int], :pointer
313
+
314
+ attach_function 'libusb_set_interface_alt_setting', [:libusb_device_handle, :int, :int], :int, blocking: true
315
+ attach_function 'libusb_clear_halt', [:libusb_device_handle, :int], :int, blocking: true
316
+ attach_function 'libusb_reset_device', [:libusb_device_handle], :int, blocking: true
317
+ try_attach_function 'libusb_alloc_streams', [:libusb_device_handle, :uint32, :pointer, :int], :int
318
+ try_attach_function 'libusb_free_streams', [:libusb_device_handle, :pointer, :int], :int
319
+ try_attach_function 'libusb_dev_mem_alloc', [:libusb_device_handle, :size_t], :pointer
320
+ try_attach_function 'libusb_dev_mem_free', [:libusb_device_handle, :pointer, :size_t], :int
321
+
322
+ attach_function 'libusb_kernel_driver_active', [:libusb_device_handle, :int], :int
323
+ attach_function 'libusb_detach_kernel_driver', [:libusb_device_handle, :int], :int
324
+ attach_function 'libusb_attach_kernel_driver', [:libusb_device_handle, :int], :int
325
+ try_attach_function 'libusb_set_auto_detach_kernel_driver', [:libusb_device_handle, :int], :int
326
+
327
+ attach_function 'libusb_get_string_descriptor_ascii', [:pointer, :uint8, :pointer, :int], :int
328
+
329
+ attach_function 'libusb_alloc_transfer', [:int], :pointer
330
+ attach_function 'libusb_submit_transfer', [:pointer], :int
331
+ attach_function 'libusb_cancel_transfer', [:pointer], :int
332
+ attach_function 'libusb_free_transfer', [:pointer], :void
333
+ try_attach_function 'libusb_transfer_set_stream_id', [:libusb_transfer, :uint32], :void
334
+ try_attach_function 'libusb_transfer_get_stream_id', [:libusb_transfer], :uint32
335
+
336
+ attach_function 'libusb_handle_events', [:libusb_context], :int, blocking: true
337
+ try_attach_function 'libusb_handle_events_completed', [:libusb_context, :pointer], :int, blocking: true
338
+ attach_function 'libusb_handle_events_timeout', [:libusb_context, :pointer], :int, blocking: true
339
+ try_attach_function 'libusb_handle_events_timeout_completed', [:libusb_context, :pointer, :pointer], :int, blocking: true
340
+ try_attach_function 'libusb_interrupt_event_handler', [:libusb_context], :void
341
+
342
+ callback :libusb_pollfd_added_cb, [:int, :short, :pointer], :void
343
+ callback :libusb_pollfd_removed_cb, [:int, :pointer], :void
344
+
345
+ attach_function 'libusb_get_pollfds', [:libusb_context], :pointer
346
+ attach_function 'libusb_get_next_timeout', [:libusb_context, :pointer], :int
347
+ attach_function 'libusb_set_pollfd_notifiers', [:libusb_context, :libusb_pollfd_added_cb, :libusb_pollfd_removed_cb, :pointer], :void
348
+ try_attach_function 'libusb_free_pollfds', [:pointer], :void
349
+
350
+ callback :libusb_transfer_cb_fn, [:pointer], :void
351
+
352
+ callback :libusb_hotplug_callback_fn, [:libusb_context, :libusb_device, :libusb_hotplug_event, :pointer], :int
353
+ try_attach_function 'libusb_hotplug_register_callback', [
354
+ :libusb_context, :libusb_hotplug_event, :libusb_hotplug_flag,
355
+ :int, :int, :int, :libusb_hotplug_callback_fn,
356
+ :pointer, :pointer], :int
357
+ try_attach_function 'libusb_hotplug_deregister_callback', [:libusb_context, :libusb_hotplug_callback_handle], :void
358
+
359
+ class IsoPacketDescriptor < FFI::Struct
360
+ layout :length, :uint,
361
+ :actual_length, :uint,
362
+ :status, :libusb_transfer_status
363
+ end
364
+
365
+ # Setup packet for control transfers.
366
+ class ControlSetup < FFI::Struct
367
+ layout :bmRequestType, :uint8,
368
+ :bRequest, :uint8,
369
+ :wValue, :uint16,
370
+ :wIndex, :uint16,
371
+ :wLength, :uint16
372
+ end
373
+
374
+ class Transfer < FFI::ManagedStruct
375
+ layout :dev_handle, :libusb_device_handle,
376
+ :flags, :uint8,
377
+ :endpoint, :uchar,
378
+ :type, :uchar,
379
+ :timeout, :uint,
380
+ :status, :libusb_transfer_status,
381
+ :length, :int,
382
+ :actual_length, :int,
383
+ :callback, :libusb_transfer_cb_fn,
384
+ :user_data, :pointer,
385
+ :buffer, :pointer,
386
+ :num_iso_packets, :int
387
+
388
+ def self.release(ptr)
389
+ Call.libusb_free_transfer(ptr)
390
+ end
391
+ end
392
+
393
+ class DeviceDescriptor < FFI::Struct
394
+ include Comparable
395
+
396
+ layout :bLength, :uint8,
397
+ :bDescriptorType, :uint8,
398
+ :bcdUSB, :uint16,
399
+ :bDeviceClass, :uint8,
400
+ :bDeviceSubClass, :uint8,
401
+ :bDeviceProtocol, :uint8,
402
+ :bMaxPacketSize0, :uint8,
403
+ :idVendor, :uint16,
404
+ :idProduct, :uint16,
405
+ :bcdDevice, :uint16,
406
+ :iManufacturer, :uint8,
407
+ :iProduct, :uint8,
408
+ :iSerialNumber, :uint8,
409
+ :bNumConfigurations, :uint8
410
+ end
411
+
412
+ class Timeval < FFI::Struct
413
+ layout :tv_sec, :long,
414
+ :tv_usec, :long
415
+
416
+ # set timeval to the number of milliseconds
417
+ # @param [Fixnum] value
418
+ def in_ms=(value)
419
+ self[:tv_sec], self[:tv_usec] = (value*1000).divmod(1000000)
420
+ end
421
+
422
+ # get the number of milliseconds in timeval
423
+ # @return [Fixnum]
424
+ def in_ms
425
+ self[:tv_sec]*1000 + self[:tv_usec]/1000
426
+ end
427
+
428
+ # set timeval to the number of seconds
429
+ # @param [Numeric] value
430
+ def in_s=(value)
431
+ self[:tv_sec], self[:tv_usec] = (value*1000000).divmod(1000000)
432
+ end
433
+
434
+ # get the number of seconds in timeval
435
+ # @return [Float]
436
+ def in_s
437
+ self[:tv_sec] + self[:tv_usec]/1000000.0
438
+ end
439
+ end
440
+
441
+ class Pollfd < FFI::Struct
442
+ layout :fd, :int,
443
+ :events, :short
444
+ end
445
+ end
446
+ end
@@ -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