libusb 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -2
  3. data/Gemfile +2 -0
  4. data/History.md +12 -0
  5. data/README.md +25 -14
  6. data/Rakefile +64 -109
  7. data/appveyor.yml +23 -0
  8. data/ext/extconf.rb +10 -12
  9. data/ext/libusb_recipe.rb +29 -0
  10. data/lib/libusb/call.rb +14 -11
  11. data/lib/libusb/compat.rb +9 -9
  12. data/lib/libusb/context.rb +16 -1
  13. data/lib/libusb/dependencies.rb +7 -0
  14. data/lib/libusb/dev_handle.rb +13 -3
  15. data/lib/libusb/eventmachine.rb +4 -4
  16. data/lib/libusb/transfer.rb +71 -10
  17. data/lib/libusb/version_gem.rb +1 -1
  18. data/libusb.gemspec +7 -5
  19. data/ports/archives/libusb-1.0.21.tar.bz2 +0 -0
  20. data/test/test_libusb_bulk_stream_transfer.rb +1 -1
  21. data/test/test_libusb_descriptors.rb +4 -4
  22. data/test/test_libusb_event_machine.rb +7 -7
  23. data/test/test_libusb_hotplug.rb +15 -3
  24. data/test/test_libusb_iso_transfer.rb +1 -1
  25. data/test/test_libusb_mass_storage.rb +19 -19
  26. data/test/test_libusb_mass_storage2.rb +1 -1
  27. data/test/test_libusb_structs.rb +13 -0
  28. data/test/test_libusb_threads.rb +2 -2
  29. data/wireshark-usb-sniffer.png +0 -0
  30. metadata +32 -156
  31. checksums.yaml.gz.sig +0 -0
  32. data.tar.gz.sig +0 -0
  33. data/ext/libusb-1.0.20/AUTHORS +0 -89
  34. data/ext/libusb-1.0.20/COPYING +0 -504
  35. data/ext/libusb-1.0.20/ChangeLog +0 -227
  36. data/ext/libusb-1.0.20/INSTALL +0 -234
  37. data/ext/libusb-1.0.20/Makefile.am +0 -28
  38. data/ext/libusb-1.0.20/Makefile.in +0 -897
  39. data/ext/libusb-1.0.20/NEWS +0 -2
  40. data/ext/libusb-1.0.20/PORTING +0 -94
  41. data/ext/libusb-1.0.20/README +0 -29
  42. data/ext/libusb-1.0.20/TODO +0 -2
  43. data/ext/libusb-1.0.20/Xcode/common.xcconfig +0 -49
  44. data/ext/libusb-1.0.20/Xcode/config.h +0 -28
  45. data/ext/libusb-1.0.20/Xcode/debug.xcconfig +0 -29
  46. data/ext/libusb-1.0.20/Xcode/libusb.xcconfig +0 -21
  47. data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +0 -865
  48. data/ext/libusb-1.0.20/Xcode/libusb_debug.xcconfig +0 -21
  49. data/ext/libusb-1.0.20/Xcode/libusb_release.xcconfig +0 -21
  50. data/ext/libusb-1.0.20/Xcode/release.xcconfig +0 -30
  51. data/ext/libusb-1.0.20/aclocal.m4 +0 -1193
  52. data/ext/libusb-1.0.20/android/README +0 -114
  53. data/ext/libusb-1.0.20/android/config.h +0 -81
  54. data/ext/libusb-1.0.20/android/jni/Android.mk +0 -23
  55. data/ext/libusb-1.0.20/android/jni/Application.mk +0 -24
  56. data/ext/libusb-1.0.20/android/jni/examples.mk +0 -134
  57. data/ext/libusb-1.0.20/android/jni/libusb.mk +0 -54
  58. data/ext/libusb-1.0.20/android/jni/tests.mk +0 -56
  59. data/ext/libusb-1.0.20/compile +0 -347
  60. data/ext/libusb-1.0.20/config.guess +0 -1421
  61. data/ext/libusb-1.0.20/config.h.in +0 -155
  62. data/ext/libusb-1.0.20/config.sub +0 -1807
  63. data/ext/libusb-1.0.20/configure +0 -15466
  64. data/ext/libusb-1.0.20/configure.ac +0 -326
  65. data/ext/libusb-1.0.20/depcomp +0 -791
  66. data/ext/libusb-1.0.20/doc/Makefile.am +0 -9
  67. data/ext/libusb-1.0.20/doc/Makefile.in +0 -456
  68. data/ext/libusb-1.0.20/doc/doxygen.cfg.in +0 -2334
  69. data/ext/libusb-1.0.20/examples/Makefile.am +0 -19
  70. data/ext/libusb-1.0.20/examples/Makefile.in +0 -713
  71. data/ext/libusb-1.0.20/examples/dpfp.c +0 -506
  72. data/ext/libusb-1.0.20/examples/dpfp_threaded.c +0 -549
  73. data/ext/libusb-1.0.20/examples/ezusb.c +0 -831
  74. data/ext/libusb-1.0.20/examples/ezusb.h +0 -120
  75. data/ext/libusb-1.0.20/examples/fxload.c +0 -308
  76. data/ext/libusb-1.0.20/examples/getopt/getopt.c +0 -1060
  77. data/ext/libusb-1.0.20/examples/getopt/getopt.h +0 -180
  78. data/ext/libusb-1.0.20/examples/getopt/getopt1.c +0 -188
  79. data/ext/libusb-1.0.20/examples/hotplugtest.c +0 -122
  80. data/ext/libusb-1.0.20/examples/listdevs.c +0 -71
  81. data/ext/libusb-1.0.20/examples/sam3u_benchmark.c +0 -193
  82. data/ext/libusb-1.0.20/examples/xusb.c +0 -1130
  83. data/ext/libusb-1.0.20/install-sh +0 -501
  84. data/ext/libusb-1.0.20/libusb-1.0.pc.in +0 -11
  85. data/ext/libusb-1.0.20/libusb/Makefile.am +0 -90
  86. data/ext/libusb-1.0.20/libusb/Makefile.in +0 -1053
  87. data/ext/libusb-1.0.20/libusb/core.c +0 -2452
  88. data/ext/libusb-1.0.20/libusb/descriptor.c +0 -1201
  89. data/ext/libusb-1.0.20/libusb/hotplug.c +0 -344
  90. data/ext/libusb-1.0.20/libusb/hotplug.h +0 -90
  91. data/ext/libusb-1.0.20/libusb/io.c +0 -2760
  92. data/ext/libusb-1.0.20/libusb/libusb-1.0.def +0 -168
  93. data/ext/libusb-1.0.20/libusb/libusb-1.0.rc +0 -61
  94. data/ext/libusb-1.0.20/libusb/libusb.h +0 -1999
  95. data/ext/libusb-1.0.20/libusb/libusbi.h +0 -1102
  96. data/ext/libusb-1.0.20/libusb/os/darwin_usb.c +0 -1969
  97. data/ext/libusb-1.0.20/libusb/os/darwin_usb.h +0 -158
  98. data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +0 -5
  99. data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +0 -810
  100. data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +0 -1193
  101. data/ext/libusb-1.0.20/libusb/os/haiku/compile +0 -347
  102. data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +0 -1421
  103. data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +0 -1807
  104. data/ext/libusb-1.0.20/libusb/os/haiku/configure +0 -17579
  105. data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +0 -8
  106. data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +0 -791
  107. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +0 -378
  108. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +0 -112
  109. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +0 -550
  110. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +0 -255
  111. data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +0 -180
  112. data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +0 -501
  113. data/ext/libusb-1.0.20/libusb/os/haiku/ltmain.sh +0 -9655
  114. data/ext/libusb-1.0.20/libusb/os/haiku/m4/libtool.m4 +0 -7992
  115. data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltoptions.m4 +0 -384
  116. data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltsugar.m4 +0 -123
  117. data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltversion.m4 +0 -23
  118. data/ext/libusb-1.0.20/libusb/os/haiku/m4/lt~obsolete.m4 +0 -98
  119. data/ext/libusb-1.0.20/libusb/os/haiku/missing +0 -215
  120. data/ext/libusb-1.0.20/libusb/os/linux_netlink.c +0 -369
  121. data/ext/libusb-1.0.20/libusb/os/linux_udev.c +0 -306
  122. data/ext/libusb-1.0.20/libusb/os/linux_usbfs.c +0 -2692
  123. data/ext/libusb-1.0.20/libusb/os/linux_usbfs.h +0 -192
  124. data/ext/libusb-1.0.20/libusb/os/netbsd_usb.c +0 -674
  125. data/ext/libusb-1.0.20/libusb/os/openbsd_usb.c +0 -768
  126. data/ext/libusb-1.0.20/libusb/os/poll_posix.c +0 -53
  127. data/ext/libusb-1.0.20/libusb/os/poll_posix.h +0 -11
  128. data/ext/libusb-1.0.20/libusb/os/poll_windows.c +0 -728
  129. data/ext/libusb-1.0.20/libusb/os/poll_windows.h +0 -131
  130. data/ext/libusb-1.0.20/libusb/os/threads_posix.c +0 -82
  131. data/ext/libusb-1.0.20/libusb/os/threads_posix.h +0 -50
  132. data/ext/libusb-1.0.20/libusb/os/threads_windows.c +0 -214
  133. data/ext/libusb-1.0.20/libusb/os/threads_windows.h +0 -87
  134. data/ext/libusb-1.0.20/libusb/os/wince_usb.c +0 -869
  135. data/ext/libusb-1.0.20/libusb/os/wince_usb.h +0 -131
  136. data/ext/libusb-1.0.20/libusb/os/windows_common.h +0 -108
  137. data/ext/libusb-1.0.20/libusb/os/windows_usb.c +0 -4643
  138. data/ext/libusb-1.0.20/libusb/os/windows_usb.h +0 -973
  139. data/ext/libusb-1.0.20/libusb/strerror.c +0 -202
  140. data/ext/libusb-1.0.20/libusb/sync.c +0 -308
  141. data/ext/libusb-1.0.20/libusb/version.h +0 -18
  142. data/ext/libusb-1.0.20/libusb/version_nano.h +0 -1
  143. data/ext/libusb-1.0.20/ltmain.sh +0 -9655
  144. data/ext/libusb-1.0.20/m4/libtool.m4 +0 -7992
  145. data/ext/libusb-1.0.20/m4/ltoptions.m4 +0 -384
  146. data/ext/libusb-1.0.20/m4/ltsugar.m4 +0 -123
  147. data/ext/libusb-1.0.20/m4/ltversion.m4 +0 -23
  148. data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +0 -98
  149. data/ext/libusb-1.0.20/missing +0 -215
  150. data/ext/libusb-1.0.20/tests/Makefile.am +0 -6
  151. data/ext/libusb-1.0.20/tests/Makefile.in +0 -596
  152. data/ext/libusb-1.0.20/tests/libusb_testlib.h +0 -107
  153. data/ext/libusb-1.0.20/tests/stress.c +0 -160
  154. data/ext/libusb-1.0.20/tests/testlib.c +0 -277
  155. metadata.gz.sig +0 -0
@@ -0,0 +1,29 @@
1
+ require_relative '../lib/libusb/dependencies'
2
+ require 'rubygems'
3
+ # NOTE: Keep this version constraint in sync with libusb.gemspec
4
+ gem "mini_portile2", LIBUSB::MINI_PORTILE_VERSION
5
+ require "mini_portile2"
6
+
7
+ class LibusbRecipe < MiniPortile
8
+ include LIBUSB
9
+ ROOT = File.expand_path('../..', __FILE__)
10
+
11
+ def initialize
12
+ super("libusb", LIBUSB_VERSION)
13
+ self.target = File.join(ROOT, "ports")
14
+ self.files = [url: LIBUSB_SOURCE_URI, sha1: LIBUSB_SOURCE_SHA1]
15
+ self.configure_options = []
16
+ end
17
+
18
+ def cook_and_activate
19
+ checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{self.host}.installed")
20
+ unless File.exist?(checkpoint)
21
+ self.cook
22
+ FileUtils.touch checkpoint
23
+ end
24
+ self.activate
25
+ self
26
+ end
27
+
28
+ public :files_hashs
29
+ end
@@ -28,7 +28,7 @@ module LIBUSB
28
28
  prefix = FFI::Platform::LIBPREFIX.empty? ? 'lib' : FFI::Platform::LIBPREFIX
29
29
  bundled_dll = File.join(root_path, "lib/#{prefix}usb-1.0.#{ext}")
30
30
  bundled_dll_cygwin = File.join(root_path, "bin/#{prefix}usb-1.0.#{ext}")
31
- ffi_lib(["#{prefix}usb-1.0", bundled_dll, bundled_dll_cygwin])
31
+ ffi_lib([bundled_dll, bundled_dll_cygwin, "#{prefix}usb-1.0"])
32
32
 
33
33
  ClassCodes = enum :libusb_class_code, [
34
34
  :CLASS_PER_INTERFACE, 0,
@@ -292,7 +292,7 @@ module LIBUSB
292
292
  try_attach_function 'libusb_get_ss_endpoint_companion_descriptor', [:pointer, :pointer, :pointer], :int
293
293
  try_attach_function 'libusb_free_ss_endpoint_companion_descriptor', [:pointer], :void
294
294
 
295
- try_attach_function 'libusb_get_bos_descriptor', [:libusb_device_handle, :pointer], :int, :blocking=>true
295
+ try_attach_function 'libusb_get_bos_descriptor', [:libusb_device_handle, :pointer], :int, blocking: true
296
296
  try_attach_function 'libusb_free_bos_descriptor', [:pointer], :void
297
297
  try_attach_function 'libusb_get_usb_2_0_extension_descriptor', [:libusb_context, :pointer, :pointer], :int
298
298
  try_attach_function 'libusb_free_usb_2_0_extension_descriptor', [:pointer], :void
@@ -305,17 +305,19 @@ module LIBUSB
305
305
  attach_function 'libusb_close', [:pointer], :void
306
306
  attach_function 'libusb_get_device', [:libusb_device_handle], :pointer
307
307
 
308
- attach_function 'libusb_set_configuration', [:libusb_device_handle, :int], :int, :blocking=>true
308
+ attach_function 'libusb_set_configuration', [:libusb_device_handle, :int], :int, blocking: true
309
309
  attach_function 'libusb_claim_interface', [:libusb_device_handle, :int], :int
310
- attach_function 'libusb_release_interface', [:libusb_device_handle, :int], :int, :blocking=>true
310
+ attach_function 'libusb_release_interface', [:libusb_device_handle, :int], :int, blocking: true
311
311
 
312
312
  attach_function 'libusb_open_device_with_vid_pid', [:pointer, :int, :int], :pointer
313
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
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
317
  try_attach_function 'libusb_alloc_streams', [:libusb_device_handle, :uint32, :pointer, :int], :int
318
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
319
321
 
320
322
  attach_function 'libusb_kernel_driver_active', [:libusb_device_handle, :int], :int
321
323
  attach_function 'libusb_detach_kernel_driver', [:libusb_device_handle, :int], :int
@@ -331,10 +333,11 @@ module LIBUSB
331
333
  try_attach_function 'libusb_transfer_set_stream_id', [:libusb_transfer, :uint32], :void
332
334
  try_attach_function 'libusb_transfer_get_stream_id', [:libusb_transfer], :uint32
333
335
 
334
- attach_function 'libusb_handle_events', [:libusb_context], :int, :blocking=>true
335
- try_attach_function 'libusb_handle_events_completed', [:libusb_context, :pointer], :int, :blocking=>true
336
- attach_function 'libusb_handle_events_timeout', [:libusb_context, :pointer], :int, :blocking=>true
337
- try_attach_function 'libusb_handle_events_timeout_completed', [:libusb_context, :pointer, :pointer], :int, :blocking=>true
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
338
341
 
339
342
  callback :libusb_pollfd_added_cb, [:int, :short, :pointer], :void
340
343
  callback :libusb_pollfd_removed_cb, [:int, :pointer], :void
@@ -130,7 +130,7 @@ module USB
130
130
  end
131
131
 
132
132
  def USB.each_device_by_class(devclass, subclass=nil, protocol=nil)
133
- devs = default_context.devices :bClass=>devclass, :bSubClass=>subclass, :bProtocol=>protocol
133
+ devs = default_context.devices bClass: devclass, bSubClass: subclass, bProtocol: protocol
134
134
  devs.each do |dev|
135
135
  yield Device.new(dev)
136
136
  end
@@ -313,31 +313,31 @@ module USB
313
313
  def usb_control_msg(requesttype, request, value, index, bytes, timeout)
314
314
  if requesttype&LIBUSB::ENDPOINT_IN != 0
315
315
  # transfer direction in
316
- res = @dev.control_transfer(:bmRequestType=>requesttype, :bRequest=>request,
317
- :wValue=>value, :wIndex=>index, :dataIn=>bytes.bytesize, :timeout=>timeout)
316
+ res = @dev.control_transfer(bmRequestType: requesttype, bRequest: request,
317
+ wValue: value, wIndex: index, dataIn: bytes.bytesize, timeout: timeout)
318
318
  bytes[0, res.bytesize] = res
319
319
  res.bytesize
320
320
  else
321
321
  # transfer direction out
322
- @dev.control_transfer(:bmRequestType=>requesttype, :bRequest=>request, :wValue=>value,
323
- :wIndex=>index, :dataOut=>bytes, :timeout=>timeout)
322
+ @dev.control_transfer(bmRequestType: requesttype, bRequest: request, wValue: value,
323
+ wIndex: index, dataOut: bytes, timeout: timeout)
324
324
  end
325
325
  end
326
326
 
327
327
  def usb_bulk_write(endpoint, bytes, timeout)
328
- @dev.bulk_transfer(:endpoint=>endpoint, :dataOut=>bytes, :timeout=>timeout)
328
+ @dev.bulk_transfer(endpoint: endpoint, dataOut: bytes, timeout: timeout)
329
329
  end
330
330
  def usb_bulk_read(endpoint, bytes, timeout)
331
- res = @dev.bulk_transfer(:endpoint=>endpoint, :dataIn=>bytes.bytesize, :timeout=>timeout)
331
+ res = @dev.bulk_transfer(endpoint: endpoint, dataIn: bytes.bytesize, timeout: timeout)
332
332
  bytes[0, res.bytesize] = res
333
333
  res.bytesize
334
334
  end
335
335
 
336
336
  def usb_interrupt_write(endpoint, bytes, timeout)
337
- @dev.interrupt_transfer(:endpoint=>endpoint, :dataOut=>bytes, :timeout=>timeout)
337
+ @dev.interrupt_transfer(endpoint: endpoint, dataOut: bytes, timeout: timeout)
338
338
  end
339
339
  def usb_interrupt_read(endpoint, bytes, timeout)
340
- res = @dev.interrupt_transfer(:endpoint=>endpoint, :dataIn=>bytes.bytesize, :timeout=>timeout)
340
+ res = @dev.interrupt_transfer(endpoint: endpoint, dataIn: bytes.bytesize, timeout: timeout)
341
341
  bytes[0, res.bytesize] = res
342
342
  res.bytesize
343
343
  end
@@ -181,6 +181,8 @@ module LIBUSB
181
181
  # @param [Integer, nil] timeout the maximum time (in millseconds) to block waiting for
182
182
  # events, or 0 for non-blocking mode
183
183
  # @param [Context::CompletionFlag, nil] completion_flag CompletionFlag to check
184
+ #
185
+ # @see interrupt_event_handler
184
186
  def handle_events(timeout=nil, completion_flag=nil)
185
187
  if completion_flag && !completion_flag.is_a?(Context::CompletionFlag)
186
188
  raise ArgumentError, "completion_flag is not a CompletionFlag"
@@ -203,6 +205,19 @@ module LIBUSB
203
205
  LIBUSB.raise_error res, "in libusb_handle_events" if res<0
204
206
  end
205
207
 
208
+ if Call.respond_to?(:libusb_interrupt_event_handler)
209
+ # Interrupt any active thread that is handling events.
210
+ #
211
+ # This is mainly useful for interrupting a dedicated event handling thread when an application wishes to call {Context#exit}.
212
+ #
213
+ # Available since libusb-1.0.21.
214
+ #
215
+ # @see handle_events
216
+ def interrupt_event_handler
217
+ Call.libusb_interrupt_event_handler(@ctx)
218
+ end
219
+ end
220
+
206
221
  # Obtain a list of devices currently attached to the USB system, optionally matching certain criteria.
207
222
  #
208
223
  # @param [Hash] filter_hash A number of criteria can be defined in key-value pairs.
@@ -218,7 +233,7 @@ module LIBUSB
218
233
  #
219
234
  # @example
220
235
  # # Return all devices of vendor 0x0ab1 where idProduct is 3 or 4:
221
- # context.device :idVendor=>0x0ab1, :idProduct=>[0x0003, 0x0004]
236
+ # context.device idVendor: 0x0ab1, idProduct: [0x0003, 0x0004]
222
237
  #
223
238
  # @return [Array<LIBUSB::Device>]
224
239
  def devices(filter_hash={})
@@ -0,0 +1,7 @@
1
+ module LIBUSB
2
+ LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.21'
3
+ LIBUSB_SOURCE_URI = "https://github.com/libusb/libusb/releases/download/v#{LIBUSB_VERSION}/libusb-#{LIBUSB_VERSION}.tar.bz2"
4
+ LIBUSB_SOURCE_SHA1 = '54d71841542eb1a6f0b0420878a4d5434efe8d28'
5
+
6
+ MINI_PORTILE_VERSION = '~> 2.1'
7
+ end
@@ -41,6 +41,9 @@ module LIBUSB
41
41
  #
42
42
  # This is a non-blocking function; no requests are sent over the bus.
43
43
  def close
44
+ @bulk_transfer.free_buffer if @bulk_transfer
45
+ @interrupt_transfer.free_buffer if @interrupt_transfer
46
+ @control_transfer.free_buffer if @control_transfer
44
47
  Call.libusb_close(@pHandle)
45
48
  end
46
49
 
@@ -235,6 +238,13 @@ module LIBUSB
235
238
  LIBUSB.raise_error res, "in libusb_free_streams" unless res>=0
236
239
  nil
237
240
  end
241
+
242
+ else
243
+
244
+ def alloc_streams(num_streams, endpoints)
245
+ raise NotImplementedError, "libusb-1.0.19+ is required for bulk stream transfers"
246
+ end
247
+
238
248
  end
239
249
 
240
250
  # Determine if a kernel driver is active on an interface.
@@ -374,7 +384,7 @@ module LIBUSB
374
384
  raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
375
385
 
376
386
  # reuse transfer struct to speed up transfer
377
- @bulk_transfer ||= BulkTransfer.new :dev_handle => self
387
+ @bulk_transfer ||= BulkTransfer.new dev_handle: self, allow_device_memory: true
378
388
  tr = @bulk_transfer
379
389
  tr.endpoint = endpoint
380
390
  tr.timeout = timeout
@@ -442,7 +452,7 @@ module LIBUSB
442
452
  raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
443
453
 
444
454
  # reuse transfer struct to speed up transfer
445
- @interrupt_transfer ||= InterruptTransfer.new :dev_handle => self
455
+ @interrupt_transfer ||= InterruptTransfer.new dev_handle: self, allow_device_memory: true
446
456
  tr = @interrupt_transfer
447
457
  tr.endpoint = endpoint
448
458
  tr.timeout = timeout
@@ -502,7 +512,7 @@ module LIBUSB
502
512
  raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
503
513
 
504
514
  # reuse transfer struct to speed up transfer
505
- @control_transfer ||= ControlTransfer.new :dev_handle => self
515
+ @control_transfer ||= ControlTransfer.new dev_handle: self, allow_device_memory: true
506
516
  tr = @control_transfer
507
517
  tr.timeout = timeout
508
518
  if dataIn
@@ -141,7 +141,7 @@ class DevHandle
141
141
  # Execute an eventmachine driven USB bulk transfer.
142
142
  #
143
143
  # @example
144
- # tr = devh.eventmachine_bulk_transfer( :endpoint => 0x02, :dataOut => "data" )
144
+ # tr = devh.eventmachine_bulk_transfer( endpoint: 0x02, dataOut: "data" )
145
145
  # tr.callback do |data|
146
146
  # puts "sent: #{data.inspect}"
147
147
  # end
@@ -159,9 +159,9 @@ class DevHandle
159
159
  #
160
160
  # @example
161
161
  # tr = devh.eventmachine_control_transfer(
162
- # :bmRequestType=>ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
163
- # :bRequest=>0x01,
164
- # :wValue=>0, :wIndex=>0, :dataIn=>1 )
162
+ # bmRequestType: ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
163
+ # bRequest: 0x01,
164
+ # wValue: 0, wIndex: 0, dataIn: 1 )
165
165
  # tr.callback do |data|
166
166
  # puts "recved: #{data.inspect}"
167
167
  # end
@@ -25,10 +25,29 @@ module LIBUSB
25
25
  # Using {Transfer} derived classes directly, however, is needed for isochronous transfers and
26
26
  # allows a more advanced buffer management.
27
27
  class Transfer
28
+ class ZeroCopyMemory < FFI::Pointer
29
+ attr_reader :size
30
+
31
+ def initialize(dev_handle, ptr, size)
32
+ @dev_handle = dev_handle
33
+ @size = size
34
+ super(ptr)
35
+ end
36
+
37
+ def free(id=nil)
38
+ return unless @size
39
+ # puts format("libusb_dev_mem_free(%#x, %d)%s", address, @size, id ? " by GC" : '')
40
+ res = Call.libusb_dev_mem_free( @dev_handle.pHandle, self, @size )
41
+ LIBUSB.raise_error res, "in libusb_dev_mem_free" if res!=0
42
+ @size = nil
43
+ end
44
+ end
45
+
28
46
  def initialize(args={})
29
- args.each{|k,v| send("#{k}=", v) }
30
47
  @buffer = nil
31
48
  @completion_flag = Context::CompletionFlag.new
49
+ @allow_device_memory = false
50
+ args.each{|k,v| send("#{k}=", v) }
32
51
  end
33
52
  private :initialize
34
53
 
@@ -52,11 +71,9 @@ module LIBUSB
52
71
  end
53
72
 
54
73
  # Set output data that should be sent.
74
+ # @see #allow_device_memory
55
75
  def buffer=(data)
56
- if !@buffer || data.bytesize>@buffer.size
57
- free_buffer
58
- @buffer = FFI::MemoryPointer.new(data.bytesize, 1, false)
59
- end
76
+ ensure_enough_buffer(data.bytesize)
60
77
  @buffer.put_bytes(0, data)
61
78
  @transfer[:buffer] = @buffer
62
79
  @transfer[:length] = data.bytesize
@@ -81,11 +98,9 @@ module LIBUSB
81
98
  #
82
99
  # @param [Fixnum] len Number of bytes to allocate
83
100
  # @param [String, nil] data some data to initialize the buffer with
101
+ # @see #allow_device_memory
84
102
  def alloc_buffer(len, data=nil)
85
- if !@buffer || len>@buffer.size
86
- free_buffer
87
- @buffer = FFI::MemoryPointer.new(len, 1, false)
88
- end
103
+ ensure_enough_buffer(len)
89
104
  @buffer.put_bytes(0, data) if data
90
105
  @transfer[:buffer] = @buffer
91
106
  @transfer[:length] = len
@@ -96,6 +111,52 @@ module LIBUSB
96
111
  @transfer[:actual_length]
97
112
  end
98
113
 
114
+ # Try to use persistent device memory.
115
+ #
116
+ # If enabled, attempts to allocate a block of persistent DMA memory suitable for transfers against the given device.
117
+ # The memory is allocated by {#alloc_buffer} or {#buffer=}.
118
+ # If unsuccessful, ordinary user space memory will be used.
119
+ #
120
+ # Using this memory instead of regular memory means that the host controller can use DMA directly into the buffer to increase performance, and also that transfers can no longer fail due to kernel memory fragmentation.
121
+ #
122
+ # It requires libusb-1.0.21 and Linux-4.6 to be effective, but it can safely be enabled on other systems.
123
+ #
124
+ # Note that this type of memory is bound to the {#dev_handle=}.
125
+ # So even if the {DevHandle} is closed, the memory is still accessable and the device is locked.
126
+ # It is free'd by the garbage collector eventually, but in order to close the device deterministic, it is required to call {#free_buffer} on all {Transfer}s which use persistent device memory.
127
+ #
128
+ # @see #free_buffer
129
+ # @see #memory_type
130
+ attr_accessor :allow_device_memory
131
+
132
+ # @return +:device_memory+ - If persistent device memory is allocated.
133
+ # @return +:user_space+ - If user space memory is allocated.
134
+ # @return +nil+ - If no memory is allocated.
135
+ def memory_type
136
+ case @buffer
137
+ when ZeroCopyMemory then :device_memory
138
+ when FFI::MemoryPointer then :user_space
139
+ else nil
140
+ end
141
+ end
142
+
143
+ def ensure_enough_buffer(len)
144
+ if !@buffer || len>@buffer.size
145
+ free_buffer
146
+ # Try to use zero-copy-memory and fallback to FFI-memory if not available
147
+ if @allow_device_memory && @dev_handle && Call.respond_to?(:libusb_dev_mem_alloc)
148
+ ptr = Call.libusb_dev_mem_alloc( @dev_handle.pHandle, len )
149
+ # puts format("libusb_dev_mem_alloc(%d) => %#x", len, ptr.address)
150
+ unless ptr.null?
151
+ buffer = ZeroCopyMemory.new(@dev_handle, ptr, len)
152
+ ObjectSpace.define_finalizer(self, buffer.method(:free))
153
+ end
154
+ end
155
+ @buffer = buffer || FFI::MemoryPointer.new(len, 1, false)
156
+ end
157
+ end
158
+ private :ensure_enough_buffer
159
+
99
160
  # Retrieve the data actually transferred.
100
161
  #
101
162
  # @param [Fixnum] offset optional offset of the retrieved data in the buffer.
@@ -228,7 +289,7 @@ module LIBUSB
228
289
 
229
290
  # Get a transfers bulk stream id.
230
291
  #
231
- # Since version 1.0.19.
292
+ # Available since libusb-1.0.19.
232
293
  #
233
294
  # @return [Fixnum] the stream id for the transfer
234
295
  def stream_id
@@ -15,5 +15,5 @@
15
15
 
16
16
  module LIBUSB
17
17
  # Library version of libusb for Ruby
18
- VERSION = "0.5.1"
18
+ VERSION = "0.6.0"
19
19
  end
@@ -1,6 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
3
  require "libusb/version_gem"
4
+ require "libusb/dependencies"
4
5
 
5
6
  Gem::Specification.new do |s|
6
7
  s.name = "libusb"
@@ -10,19 +11,20 @@ Gem::Specification.new do |s|
10
11
  s.homepage = "http://github.com/larskanis/libusb"
11
12
  s.summary = %q{Access USB devices from Ruby via libusb-1.0}
12
13
  s.description = %q{LIBUSB is a Ruby binding that gives Ruby programmers access to arbitrary USB devices}
13
- s.licenses = ['LGPL-3']
14
+ s.licenses = ['LGPL-3.0']
14
15
  s.rdoc_options = %w[--main README.md --charset=UTF-8]
15
16
 
16
- s.rubyforge_project = "libusb"
17
-
18
17
  s.files = `git ls-files`.split("\n")
18
+ s.files << "ports/archives/libusb-#{LIBUSB::LIBUSB_VERSION}.tar.bz2"
19
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
21
  s.require_paths = ["lib"]
22
22
  s.extensions = ['ext/extconf.rb']
23
23
 
24
- s.add_runtime_dependency 'ffi', '>= 1.0'
24
+ s.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
25
+ s.add_runtime_dependency 'ffi', '~> 1.0'
26
+ s.add_runtime_dependency 'mini_portile2', LIBUSB::MINI_PORTILE_VERSION
25
27
  s.add_development_dependency 'rake-compiler', '~> 0.9'
26
28
  s.add_development_dependency 'rake-compiler-dock', '~> 0.2'
27
- s.add_development_dependency 'bundler'
29
+ s.add_development_dependency 'bundler', '~> 1.0'
28
30
  end
@@ -44,7 +44,7 @@ class TestLibusbBulkStreamTransfer < Minitest::Test
44
44
  end
45
45
 
46
46
  def test_bulk_stream_transfer
47
- tr = BulkStreamTransfer.new :dev_handle=>@dev, :stream_id=>123, :buffer=>' '*100
47
+ tr = BulkStreamTransfer.new dev_handle: @dev, stream_id: 123, buffer: ' '*100
48
48
  assert_equal 123, tr.stream_id, "stream_id should match"
49
49
  end
50
50
  end
@@ -161,11 +161,11 @@ class TestLibusbDescriptors < Minitest::Test
161
161
  end
162
162
  end
163
163
 
164
- devs2 = usb.devices( :bClass=>CLASS_MASS_STORAGE, :bSubClass=>0x01, :bProtocol=>0x50 )
165
- devs2 += usb.devices( :bClass=>CLASS_MASS_STORAGE, :bSubClass=>0x06, :bProtocol=>0x50 )
164
+ devs2 = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: 0x01, bProtocol: 0x50 )
165
+ devs2 += usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: 0x06, bProtocol: 0x50 )
166
166
  assert_equal devs1.sort, devs2.sort, "devices and devices with filter should deliver the same device"
167
167
 
168
- devs3 = usb.devices( :bClass=>[CLASS_MASS_STORAGE], :bSubClass=>[0x01,0x06], :bProtocol=>[0x50] )
168
+ devs3 = usb.devices( bClass: [CLASS_MASS_STORAGE], bSubClass: [0x01,0x06], bProtocol: [0x50] )
169
169
  assert_equal devs1.sort, devs3.sort, "devices and devices with array-filter should deliver the same device"
170
170
  end
171
171
 
@@ -179,7 +179,7 @@ class TestLibusbDescriptors < Minitest::Test
179
179
  end
180
180
  end
181
181
 
182
- devs2 = usb.devices( :bClass=>CLASS_HUB )
182
+ devs2 = usb.devices( bClass: CLASS_HUB )
183
183
  assert_equal devs1.sort, devs2.sort, "devices and devices with filter should deliver the same device"
184
184
  end
185
185