libusb 0.5.1-x64-mingw32 → 0.6.0-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -2
- data/Gemfile +2 -0
- data/History.md +12 -0
- data/README.md +25 -14
- data/Rakefile +62 -109
- data/appveyor.yml +23 -0
- data/lib/libusb/call.rb +14 -11
- data/lib/libusb/compat.rb +9 -9
- data/lib/libusb/context.rb +16 -1
- data/lib/libusb/dependencies.rb +7 -0
- data/lib/libusb/dev_handle.rb +13 -3
- data/lib/libusb/eventmachine.rb +4 -4
- data/lib/libusb/transfer.rb +71 -10
- data/lib/libusb/version_gem.rb +1 -1
- data/libusb.gemspec +7 -5
- data/test/test_libusb_bulk_stream_transfer.rb +1 -1
- data/test/test_libusb_descriptors.rb +4 -4
- data/test/test_libusb_event_machine.rb +7 -7
- data/test/test_libusb_hotplug.rb +15 -3
- data/test/test_libusb_iso_transfer.rb +1 -1
- data/test/test_libusb_mass_storage.rb +19 -19
- data/test/test_libusb_mass_storage2.rb +1 -1
- data/test/test_libusb_structs.rb +13 -0
- data/test/test_libusb_threads.rb +2 -2
- data/wireshark-usb-sniffer.png +0 -0
- metadata +15 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a20d98f43636caf12240a486b0e9c22bb190394b
|
4
|
+
data.tar.gz: c47aa11c776f146fb16fb5329586b2a96fcecc84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83426e897d09ae1a468d134a69a31385f9694dabba99fc36bcfb71c92563098c7276cf43a8b77e1b0dfad39695327df034858e21fa9671d2a2768b9070298381
|
7
|
+
data.tar.gz: 6401e3b895dae693a044ffb9b894e4fb1f19e5a1d5cccbbf190572c5731bb1cfbfa6e1010218910586f6177bc94d604a71789feac26c4d3954d7313af83dac01
|
data/.travis.yml
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
language: ruby
|
2
2
|
sudo: false
|
3
3
|
rvm:
|
4
|
-
- "1.8.7"
|
5
4
|
- "1.9.3"
|
6
5
|
- "2.0.0"
|
7
6
|
- "2.1"
|
8
7
|
- "2.2"
|
9
|
-
-
|
8
|
+
- "2.3.1"
|
9
|
+
- "2.3.1-clang"
|
10
|
+
- jruby-1.7.26
|
11
|
+
- jruby-9.1.5.0
|
10
12
|
- rbx
|
13
|
+
matrix:
|
14
|
+
allow_failures:
|
15
|
+
- rvm: rbx
|
16
|
+
- rvm: "2.3.1-clang"
|
11
17
|
script: bundle exec rake travis
|
data/Gemfile
CHANGED
data/History.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
0.6.0 / 2016-12-09
|
2
|
+
------------------
|
3
|
+
* Update bundled libusb version to 1.0.21.
|
4
|
+
* Set minimum Ruby version requirement to 1.9.3.
|
5
|
+
* Add binary gems for Linux in addition to Windows.
|
6
|
+
* Switch to mini_portile2 for (cross-) builing the libusb library.
|
7
|
+
* Add Context#interrupt_event_handler new in libusb-1.0.21
|
8
|
+
* Add support for persistent/zerocopy device memory for transfers.
|
9
|
+
It is new in libusb-1.0.21 and enabled by default for DevHandle#*_transfer methods.
|
10
|
+
* Raise a more meaningful exception in case of bulk stream transfers on too old libusb versions.
|
11
|
+
* Prefer the bundled libusb-dll over installed system library.
|
12
|
+
|
1
13
|
0.5.1 / 2015-09-29
|
2
14
|
------------------
|
3
15
|
* Add ability to force use of the system or builtin libusb-1.0 library.
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
<!-- -*- coding: utf-8 -*- -->
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/larskanis/libusb.svg)](https://travis-ci.org/larskanis/libusb)
|
4
|
+
[![Build Status](https://ci.appveyor.com/api/projects/status/mdfnfdwu4mil42o3?svg=true)](https://ci.appveyor.com/project/larskanis/libusb)
|
4
5
|
|
5
6
|
Access USB devices from Ruby
|
6
7
|
============================
|
@@ -23,15 +24,13 @@ Features
|
|
23
24
|
|
24
25
|
Synopsis
|
25
26
|
--------
|
26
|
-
See [the documentation](http://rubydoc.info/gems/libusb/frames) for a full API description.
|
27
|
-
|
28
27
|
```ruby
|
29
28
|
require "libusb"
|
30
29
|
|
31
30
|
usb = LIBUSB::Context.new
|
32
|
-
device = usb.devices(:
|
31
|
+
device = usb.devices(idVendor: 0x04b4, idProduct: 0x8613).first
|
33
32
|
device.open_interface(0) do |handle|
|
34
|
-
handle.control_transfer(:
|
33
|
+
handle.control_transfer(bmRequestType: 0x40, bRequest: 0xa0, wValue: 0xe600, wIndex: 0x0000, dataOut: 1.chr)
|
35
34
|
end
|
36
35
|
```
|
37
36
|
{LIBUSB::Context#devices} is used to get all or only particular devices.
|
@@ -55,18 +54,20 @@ Each {LIBUSB::Setting} specifies it's own set of communication endpoints.
|
|
55
54
|
Each {LIBUSB::Endpoint} specifies the type of transfer, direction, polling interval and
|
56
55
|
maximum packet size.
|
57
56
|
|
57
|
+
See [the documentation](http://rubydoc.info/gems/libusb/frames) for a full API description.
|
58
58
|
|
59
59
|
Prerequisites
|
60
60
|
-------------
|
61
61
|
|
62
|
-
* Linux,
|
63
|
-
* Optionally: [libusb](http://libusb.info)
|
62
|
+
* Linux, MacOS or Windows system with Ruby MRI 1.9/2.x, JRuby or recent version of Rubinius
|
63
|
+
* Optionally: [libusb](http://libusb.info) C-library version 1.0.8 or any newer version.
|
64
|
+
The system libusb library can be installed like so:
|
64
65
|
* Debian or Ubuntu:
|
65
66
|
|
66
67
|
```
|
67
68
|
$ sudo apt-get install libusb-1.0-0-dev
|
68
69
|
```
|
69
|
-
*
|
70
|
+
* MacOS: install with homebrew:
|
70
71
|
|
71
72
|
```
|
72
73
|
$ brew install libusb
|
@@ -83,7 +84,7 @@ Install
|
|
83
84
|
|
84
85
|
$ gem install libusb
|
85
86
|
|
86
|
-
While ```gem install``` the system is checked for a usable libusb
|
87
|
+
While ```gem install``` the system is checked for a usable libusb library installation.
|
87
88
|
If none could be found, a bundled libusb version is built and used, instead.
|
88
89
|
|
89
90
|
Latest code can be used in this way:
|
@@ -92,11 +93,21 @@ Latest code can be used in this way:
|
|
92
93
|
$ bundle
|
93
94
|
$ rake install_gem
|
94
95
|
|
96
|
+
Troubleshooting
|
97
|
+
------------------------
|
98
|
+
In order to implement a driver for a USB device, it's essential to have a look at the packets that are send to and received back from the USB device. [Wireshark](https://www.wireshark.org) has builtin capabilities to sniff USB traffic. On Linux you possibly need to load the usbmon kernel module before start:
|
99
|
+
```
|
100
|
+
sudo modprobe usbmon
|
101
|
+
```
|
102
|
+
On Windows it's possible to sniff USB, if the USB kernel driver was installed by the Wireshark setup.
|
103
|
+
|
104
|
+
![Wireshark](wireshark-usb-sniffer.png?raw=true "Wireshark sniffing USB packets")
|
105
|
+
|
95
106
|
Device hotplug support
|
96
107
|
----------------------
|
97
108
|
|
98
109
|
Support for device hotplugging can be used, if ```LIBUSB.has_capability?(:CAP_HAS_HOTPLUG)``` returns ```true```.
|
99
|
-
This requires libusb
|
110
|
+
This requires libusb-1.0.16 or newer on Linux or MacOS. Windows support is [still on the way](https://github.com/libusbx/libusbx/issues/9).
|
100
111
|
|
101
112
|
A hotplug event handler can be registered with {LIBUSB::Context#on_hotplug_event}.
|
102
113
|
You then need to call {LIBUSB::Context#handle_events} in order to receive any events.
|
@@ -109,21 +120,21 @@ Usage on Windows
|
|
109
120
|
|
110
121
|
In contrast to Linux, any access to an USB device by LIBUSB on Windows requires a proper driver
|
111
122
|
installed in the system. Fortunately creating such a driver is quite easy with
|
112
|
-
[Zadig](http://
|
123
|
+
[Zadig](http://zadig.akeo.ie/). Select the interesting USB device,
|
113
124
|
choose WinUSB driver and press "Install Driver". That's it. You may take the generated output directory
|
114
|
-
with it's INI-file and use it for driver
|
125
|
+
with it's INI-file and use it for driver installations on other 32 or 64 bit Windows
|
115
126
|
systems.
|
116
127
|
|
117
128
|
|
118
129
|
Cross compiling for Windows
|
119
130
|
---------------------------
|
120
131
|
|
121
|
-
Libusb-gem can be cross built for
|
132
|
+
Libusb-gem can be cross built for Windows and Linux operating systems, using the [rake-compiler-dock](https://github.com/larskanis/rake-compiler-dock) .
|
122
133
|
Just run:
|
123
134
|
|
124
|
-
$ rake gem:
|
135
|
+
$ rake gem:native
|
125
136
|
|
126
|
-
If everything works, there
|
137
|
+
If everything works, there are several platform specific gem files (like `libusb-VERSION-x64-mingw32.gem`) in the pkg
|
127
138
|
directory.
|
128
139
|
|
129
140
|
EventMachine integration
|
data/Rakefile
CHANGED
@@ -8,10 +8,11 @@ require 'uri'
|
|
8
8
|
require 'ostruct'
|
9
9
|
require 'rake/clean'
|
10
10
|
require 'rake_compiler_dock'
|
11
|
+
require_relative 'ext/libusb_recipe'
|
11
12
|
|
12
13
|
task :gem => :build
|
13
14
|
task :compile do
|
14
|
-
sh "ruby ext/extconf.rb"
|
15
|
+
sh "ruby ext/extconf.rb --disable-system-libusb"
|
15
16
|
end
|
16
17
|
|
17
18
|
task :test=>:compile do
|
@@ -24,110 +25,62 @@ task :travis=>:compile do
|
|
24
25
|
end
|
25
26
|
task :default => :test
|
26
27
|
|
27
|
-
task
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
STATIC_SOURCESDIR = COMPILE_HOME + 'sources'
|
33
|
-
|
34
|
-
# Fetch tarball from sourceforge
|
35
|
-
LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.20'
|
36
|
-
LIBUSB_SOURCE_URI = URI( "http://downloads.sourceforge.net/project/libusb/libusb-1.0/libusb-#{LIBUSB_VERSION}/libusb-#{LIBUSB_VERSION}.tar.bz2" )
|
37
|
-
LIBUSB_TARBALL = STATIC_SOURCESDIR + File.basename( LIBUSB_SOURCE_URI.path )
|
38
|
-
|
39
|
-
# Fetch tarball from git repo
|
40
|
-
# LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '295c9d1'
|
41
|
-
# LIBUSB_SOURCE_URI = URI( "http://git.libusb.org/?p=libusb.git;a=snapshot;h=#{LIBUSB_VERSION};sf=tbz2" )
|
42
|
-
# LIBUSB_TARBALL = STATIC_SOURCESDIR + "libusb-#{LIBUSB_VERSION}.tar.bz2"
|
28
|
+
task "release:tag" do
|
29
|
+
hfile = "History.md"
|
30
|
+
version = LIBUSB::VERSION
|
31
|
+
reldate = Time.now.strftime("%Y-%m-%d")
|
32
|
+
headline = '([^\w]*)(\d+\.\d+\.\d+)([^\w]+)([2Y][0Y][0-9Y][0-9Y]-[0-1M][0-9M]-[0-3D][0-9D])([^\w]*|$)'
|
43
33
|
|
44
|
-
|
45
|
-
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
34
|
+
hin = File.read(hfile)
|
35
|
+
hout = hin.sub(/#{headline}/) do
|
36
|
+
raise "#{hfile} isn't up-to-date for version #{version}" unless $2==version
|
37
|
+
$1 + $2 + $3 + reldate + $5
|
38
|
+
end
|
39
|
+
if hout != hin
|
40
|
+
Bundler.ui.confirm "Updating #{hfile} for release."
|
41
|
+
File.write(hfile, hout)
|
42
|
+
sh "git", "commit", hfile, "-m", "Update release date in #{hfile}"
|
43
|
+
end
|
53
44
|
|
54
|
-
|
55
|
-
|
45
|
+
Bundler.ui.confirm "Tag release with annotation:"
|
46
|
+
m = hout.match(/(?<annotation>#{headline}.*?)#{headline}/m) || raise("Unable to find release notes in #{hfile}")
|
47
|
+
Bundler.ui.info(m[:annotation].gsub(/^/, " "))
|
48
|
+
IO.popen(["git", "tag", "--file=-", version], "w") do |fd|
|
49
|
+
fd.write m[:annotation]
|
50
|
+
end
|
51
|
+
end
|
56
52
|
|
57
|
-
|
53
|
+
task "release:guard_clean" => "release:tag"
|
58
54
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
url = LIBUSB_SOURCE_URI
|
64
|
-
sh "wget '#{url}' -O #{LIBUSB_TARBALL}"
|
55
|
+
task "release:rubygem_push" => "gem:native" do
|
56
|
+
CrossLibraries.each do |ruby_platform, _|
|
57
|
+
gh = Bundler::GemHelper.new
|
58
|
+
gh.rubygem_push(gh.spec_path.gsub(".gem", "-#{ruby_platform}.gem"))
|
65
59
|
end
|
66
60
|
end
|
67
61
|
|
62
|
+
task 'gem:native' do
|
63
|
+
sh "bundle package"
|
64
|
+
RakeCompilerDock.sh <<-EOT
|
65
|
+
bundle --local &&
|
66
|
+
rake cross gem
|
67
|
+
EOT
|
68
|
+
end
|
68
69
|
|
69
70
|
class CrossLibrary < OpenStruct
|
70
71
|
include Rake::DSL
|
71
72
|
|
72
|
-
def initialize(ruby_platform, host_platform)
|
73
|
+
def initialize(ruby_platform, host_platform, libusb_dllname)
|
73
74
|
super()
|
74
75
|
|
75
|
-
self.ruby_platform
|
76
|
-
self.
|
77
|
-
|
78
|
-
|
79
|
-
self.
|
80
|
-
|
81
|
-
# Static libusb build vars
|
82
|
-
self.static_libusb_builddir = static_builddir + LIBUSB_TARBALL.basename(".tar.bz2")
|
83
|
-
self.libusb_configure = static_libusb_builddir + 'configure'
|
84
|
-
self.libusb_makefile = static_libusb_builddir + 'Makefile'
|
85
|
-
self.libusb_dll = static_libusb_builddir + 'libusb/.libs/libusb-1.0.dll'
|
86
|
-
|
87
|
-
#
|
88
|
-
# Static libusb build tasks
|
89
|
-
#
|
90
|
-
CLEAN.include static_libusb_builddir.to_s
|
91
|
-
|
92
|
-
directory static_libusb_builddir.to_s
|
76
|
+
self.ruby_platform = ruby_platform
|
77
|
+
self.recipe = LibusbRecipe.new
|
78
|
+
recipe.host = host_platform
|
79
|
+
recipe.configure_options << "--host=#{recipe.host}"
|
80
|
+
self.libusb_dll = Pathname.new(recipe.path) + libusb_dllname
|
93
81
|
|
94
|
-
|
95
|
-
|
96
|
-
sh 'tar', '-xjf', LIBUSB_TARBALL.to_s, '-C', static_libusb_builddir.parent.to_s
|
97
|
-
libusb_makefile.unlink if libusb_makefile.exist?
|
98
|
-
end
|
99
|
-
|
100
|
-
file libusb_configure => static_libusb_builddir do |t|
|
101
|
-
Dir.chdir( static_libusb_builddir ) do
|
102
|
-
sh "sh autogen.sh && make distclean"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
libusb_env = [
|
107
|
-
"CFLAGS='-fno-omit-frame-pointer'",
|
108
|
-
"LDFLAGS='-static-libgcc'",
|
109
|
-
"CC='#{host_platform}-gcc -static-libgcc'", # hack libtool, since it doesn't support -static-libgcc yet.
|
110
|
-
]
|
111
|
-
|
112
|
-
# generate the makefile in a clean build location
|
113
|
-
file libusb_makefile => libusb_configure do |t|
|
114
|
-
Dir.chdir( static_libusb_builddir ) do
|
115
|
-
options = [
|
116
|
-
"--target=#{host_platform}",
|
117
|
-
"--host=#{host_platform}",
|
118
|
-
"--build=#{ruby_build}",
|
119
|
-
]
|
120
|
-
|
121
|
-
configure_path = static_libusb_builddir + 'configure'
|
122
|
-
sh "env #{[libusb_env, configure_path.to_s, *options].join(" ")}"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# make libusb-1.0.dll
|
127
|
-
task libusb_dll => [ libusb_makefile ] do |t|
|
128
|
-
Dir.chdir( static_libusb_builddir ) do
|
129
|
-
sh 'make'
|
130
|
-
end
|
82
|
+
file libusb_dll do
|
83
|
+
recipe.cook
|
131
84
|
end
|
132
85
|
|
133
86
|
task "libusb_dll:#{ruby_platform}" => libusb_dll
|
@@ -137,9 +90,17 @@ class CrossLibrary < OpenStruct
|
|
137
90
|
spec = Gem::Specification::load("libusb.gemspec").dup
|
138
91
|
spec.platform = Gem::Platform.new(ruby_platform)
|
139
92
|
spec.extensions = []
|
93
|
+
|
94
|
+
# Remove files unnecessary for native gems
|
140
95
|
spec.files -= `git ls-files ext`.split("\n")
|
96
|
+
spec.files.reject!{|f| f.start_with?('ports') }
|
141
97
|
spec_text_files = spec.files.dup
|
142
|
-
|
98
|
+
|
99
|
+
# Add native libusb-dll
|
100
|
+
spec.files << "lib/#{libusb_dll.basename}"
|
101
|
+
|
102
|
+
# MiniPortile isn't required for native gems
|
103
|
+
spec.dependencies.reject!{|d| d.name=="mini_portile2" }
|
143
104
|
|
144
105
|
# Generate a package for this gem
|
145
106
|
pkg = Gem::PackageTask.new(spec) do |pkg|
|
@@ -161,32 +122,24 @@ class CrossLibrary < OpenStruct
|
|
161
122
|
end
|
162
123
|
|
163
124
|
# copy libusb.dll to pkg directory
|
164
|
-
f = "#{pkg.package_dir_path}/lib/#{
|
125
|
+
f = "#{pkg.package_dir_path}/lib/#{libusb_dll.basename}"
|
165
126
|
mkdir_p File.dirname(f)
|
166
127
|
rm_f f
|
167
|
-
safe_ln libusb_dll, f
|
128
|
+
safe_ln libusb_dll.realpath, f
|
168
129
|
end
|
169
130
|
|
170
|
-
file "lib/#{
|
131
|
+
file "lib/#{libusb_dll.basename}" => [libusb_dll]
|
171
132
|
end
|
172
133
|
end
|
173
134
|
end
|
174
135
|
|
175
136
|
CrossLibraries = [
|
176
|
-
['i386-mingw32', 'i686-w64-mingw32'],
|
177
|
-
['x64-mingw32', 'x86_64-w64-mingw32'],
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
desc "Download and update bundled libusb"
|
183
|
-
task :update_libusb => LIBUSB_TARBALL do
|
184
|
-
sh 'rm', '-r', (EXT_BUILDDIR + "libusb-*").to_s do end
|
185
|
-
sh 'git', 'rm', '-rfq', (EXT_BUILDDIR + "libusb-*").to_s do end
|
186
|
-
sh 'tar', '-xjf', LIBUSB_TARBALL.to_s, '-C', EXT_LIBUSB_BUILDDIR.parent.to_s
|
187
|
-
drops = %w[msvc].map{|f| (EXT_LIBUSB_BUILDDIR+f).to_s }
|
188
|
-
sh 'rm', '-r', '-f', *drops
|
189
|
-
sh 'git', 'add', EXT_LIBUSB_BUILDDIR.to_s
|
137
|
+
['i386-mingw32', 'i686-w64-mingw32', 'bin/libusb-1.0.dll'],
|
138
|
+
['x64-mingw32', 'x86_64-w64-mingw32', 'bin/libusb-1.0.dll'],
|
139
|
+
['x86-linux', 'i686-linux-gnu', 'lib/libusb-1.0.so'],
|
140
|
+
['x86_64-linux', 'x86_64-linux-gnu', 'lib/libusb-1.0.so'],
|
141
|
+
].each do |ruby_platform, host_platform, libusb_dll|
|
142
|
+
CrossLibrary.new ruby_platform, host_platform, libusb_dll
|
190
143
|
end
|
191
144
|
|
192
145
|
# vim: syntax=ruby
|
data/appveyor.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
init:
|
2
|
+
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
3
|
+
- SET PATH=C:\MinGW\msys\1.0\bin;%PATH%
|
4
|
+
- SET RAKEOPT=-rdevkit
|
5
|
+
install:
|
6
|
+
- ruby --version
|
7
|
+
- gem --version
|
8
|
+
- bundle install
|
9
|
+
build_script:
|
10
|
+
- bundle exec rake compile
|
11
|
+
test_script:
|
12
|
+
- bundle exec rake travis
|
13
|
+
environment:
|
14
|
+
matrix:
|
15
|
+
- ruby_version: "193"
|
16
|
+
- ruby_version: "200"
|
17
|
+
- ruby_version: "200-x64"
|
18
|
+
- ruby_version: "21"
|
19
|
+
- ruby_version: "21-x64"
|
20
|
+
- ruby_version: "22"
|
21
|
+
- ruby_version: "22-x64"
|
22
|
+
- ruby_version: "23"
|
23
|
+
- ruby_version: "23-x64"
|
data/lib/libusb/call.rb
CHANGED
@@ -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"
|
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, :
|
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, :
|
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, :
|
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, :
|
315
|
-
attach_function 'libusb_clear_halt', [:libusb_device_handle, :int], :int, :
|
316
|
-
attach_function 'libusb_reset_device', [:libusb_device_handle], :int, :
|
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, :
|
335
|
-
try_attach_function 'libusb_handle_events_completed', [:libusb_context, :pointer], :int, :
|
336
|
-
attach_function 'libusb_handle_events_timeout', [:libusb_context, :pointer], :int, :
|
337
|
-
try_attach_function 'libusb_handle_events_timeout_completed', [:libusb_context, :pointer, :pointer], :int, :
|
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
|
data/lib/libusb/compat.rb
CHANGED
@@ -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 :
|
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(:
|
317
|
-
:
|
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(:
|
323
|
-
:
|
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
|
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
|
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
|
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
|
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
|
data/lib/libusb/context.rb
CHANGED
@@ -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 :
|
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
|
data/lib/libusb/dev_handle.rb
CHANGED
@@ -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 :
|
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 :
|
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 :
|
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
|
data/lib/libusb/eventmachine.rb
CHANGED
@@ -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( :
|
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
|
-
# :
|
163
|
-
# :
|
164
|
-
# :
|
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
|
data/lib/libusb/transfer.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
#
|
292
|
+
# Available since libusb-1.0.19.
|
232
293
|
#
|
233
294
|
# @return [Fixnum] the stream id for the transfer
|
234
295
|
def stream_id
|
data/lib/libusb/version_gem.rb
CHANGED
data/libusb.gemspec
CHANGED
@@ -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.
|
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 :
|
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( :
|
165
|
-
devs2 += usb.devices( :
|
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( :
|
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( :
|
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
|
|
@@ -32,7 +32,7 @@ class TestLibusbEventMachine < Minitest::Test
|
|
32
32
|
@context = Context.new
|
33
33
|
@context.debug = 3
|
34
34
|
|
35
|
-
@device = context.devices( :
|
35
|
+
@device = context.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 ).last
|
36
36
|
skip "no mass storage device found" unless @device
|
37
37
|
|
38
38
|
@endpoint_in = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
|
@@ -70,9 +70,9 @@ class TestLibusbEventMachine < Minitest::Test
|
|
70
70
|
em_run do
|
71
71
|
ticks = 0
|
72
72
|
tr = devh.eventmachine_bulk_transfer(
|
73
|
-
:
|
74
|
-
:
|
75
|
-
:
|
73
|
+
endpoint: @endpoint_in,
|
74
|
+
timeout: 1500,
|
75
|
+
dataIn: 123 )
|
76
76
|
# puts "started usb transfer #{tr}"
|
77
77
|
|
78
78
|
tr.callback do |data|
|
@@ -98,9 +98,9 @@ class TestLibusbEventMachine < Minitest::Test
|
|
98
98
|
def test_event_loop
|
99
99
|
em_run do
|
100
100
|
tr = devh.eventmachine_control_transfer(
|
101
|
-
:
|
102
|
-
:
|
103
|
-
:
|
101
|
+
bmRequestType: ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
102
|
+
bRequest: BOMS_GET_MAX_LUN,
|
103
|
+
wValue: 0, wIndex: 0, dataIn: 1 )
|
104
104
|
|
105
105
|
# puts "started usb transfer #{tr}"
|
106
106
|
tr.callback do |data|
|
data/test/test_libusb_hotplug.rb
CHANGED
@@ -31,7 +31,7 @@ class TestLibusbHotplug < Minitest::Test
|
|
31
31
|
|
32
32
|
def test_enumerate
|
33
33
|
devs = []
|
34
|
-
ctx.on_hotplug_event :
|
34
|
+
ctx.on_hotplug_event flags: HOTPLUG_ENUMERATE do |dev, event|
|
35
35
|
devs << dev
|
36
36
|
assert_equal :HOTPLUG_EVENT_DEVICE_ARRIVED, event
|
37
37
|
:repeat
|
@@ -44,7 +44,7 @@ class TestLibusbHotplug < Minitest::Test
|
|
44
44
|
|
45
45
|
def test_enumerate_with_left
|
46
46
|
devs = []
|
47
|
-
ctx.on_hotplug_event :
|
47
|
+
ctx.on_hotplug_event flags: HOTPLUG_ENUMERATE, events: HOTPLUG_EVENT_DEVICE_LEFT do |dev, event|
|
48
48
|
devs << dev
|
49
49
|
assert_equal :HOTPLUG_EVENT_DEVICE_ARRIVED, event
|
50
50
|
:repeat
|
@@ -65,7 +65,7 @@ class TestLibusbHotplug < Minitest::Test
|
|
65
65
|
|
66
66
|
def test_wrong_yieldreturn
|
67
67
|
ex = assert_raises(ArgumentError) do
|
68
|
-
ctx.on_hotplug_event :
|
68
|
+
ctx.on_hotplug_event flags: :HOTPLUG_ENUMERATE do |dev, event|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -112,4 +112,16 @@ class TestLibusbHotplug < Minitest::Test
|
|
112
112
|
assert_operator devs2.map(&:last), :include?, :HOTPLUG_EVENT_DEVICE_ARRIVED, "Should have received ARRIVED"
|
113
113
|
assert_operator devs2.map(&:last), :include?, :HOTPLUG_EVENT_DEVICE_LEFT, "Should have received LEFT"
|
114
114
|
end
|
115
|
+
|
116
|
+
def test_interrupt_event_handler
|
117
|
+
th = Thread.new do
|
118
|
+
ctx.handle_events 5000
|
119
|
+
end
|
120
|
+
|
121
|
+
sleep 0.1 # Workaround a bug in libusb-1,0.21
|
122
|
+
st = Time.now
|
123
|
+
ctx.interrupt_event_handler
|
124
|
+
th.join
|
125
|
+
assert_operator Time.now-st, :<, 5.0
|
126
|
+
end
|
115
127
|
end
|
@@ -34,7 +34,7 @@ class TestLibusbIsoTransfer < Minitest::Test
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def test_iso_transfer
|
37
|
-
tr = IsochronousTransfer.new 10, :
|
37
|
+
tr = IsochronousTransfer.new 10, dev_handle: @dev
|
38
38
|
assert_equal 10, tr.num_packets, "number of packets should match"
|
39
39
|
|
40
40
|
tr.buffer = " "*130
|
@@ -40,7 +40,7 @@ class TestLibusbMassStorage < Minitest::Test
|
|
40
40
|
@usb.debug = 3
|
41
41
|
@asynchron = false
|
42
42
|
|
43
|
-
@device = usb.devices( :
|
43
|
+
@device = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 ).last
|
44
44
|
skip "no mass storage device found" unless @device
|
45
45
|
|
46
46
|
@endpoint_in = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
|
@@ -97,10 +97,10 @@ class TestLibusbMassStorage < Minitest::Test
|
|
97
97
|
cbw = ['USBC', expected_tag, data_length, direction, lun, cdb.length, cdb].pack('a*VVCCCa*')
|
98
98
|
cbw = cbw.ljust(31, "\0")
|
99
99
|
|
100
|
-
num_bytes = bulk_transfer(:
|
100
|
+
num_bytes = bulk_transfer(endpoint: endpoint_out, dataOut: cbw)
|
101
101
|
assert_equal 31, num_bytes, "31 bytes CBW should be sent"
|
102
102
|
|
103
|
-
recv = bulk_transfer(:
|
103
|
+
recv = bulk_transfer(endpoint: endpoint_in, dataIn: data_length)
|
104
104
|
|
105
105
|
get_mass_storage_status(expected_tag)
|
106
106
|
return recv
|
@@ -109,7 +109,7 @@ class TestLibusbMassStorage < Minitest::Test
|
|
109
109
|
def get_mass_storage_status(expected_tag)
|
110
110
|
retries = 5
|
111
111
|
buffer = begin
|
112
|
-
bulk_transfer(:
|
112
|
+
bulk_transfer(endpoint: endpoint_in, dataIn: 13)
|
113
113
|
rescue LIBUSB::ERROR_PIPE
|
114
114
|
if (retries-=1)>=0
|
115
115
|
dev.clear_halt(endpoint_in)
|
@@ -167,23 +167,23 @@ class TestLibusbMassStorage < Minitest::Test
|
|
167
167
|
|
168
168
|
def mass_storage_reset
|
169
169
|
res = control_transfer(
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:
|
170
|
+
bmRequestType: ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
171
|
+
bRequest: BOMS_RESET,
|
172
|
+
wValue: 0, wIndex: 0)
|
173
173
|
assert_equal 0, res, "BOMS_RESET response should be 0 byte"
|
174
174
|
|
175
175
|
res = control_transfer(
|
176
|
-
:
|
177
|
-
:
|
178
|
-
:
|
176
|
+
bmRequestType: ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
177
|
+
bRequest: BOMS_RESET,
|
178
|
+
wValue: 0, wIndex: 0, dataOut: '')
|
179
179
|
assert_equal 0, res, "BOMS_RESET response should be 0 byte"
|
180
180
|
end
|
181
181
|
|
182
182
|
def read_max_lun
|
183
183
|
res = control_transfer(
|
184
|
-
:
|
185
|
-
:
|
186
|
-
:
|
184
|
+
bmRequestType: ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
185
|
+
bRequest: BOMS_GET_MAX_LUN,
|
186
|
+
wValue: 0, wIndex: 0, dataIn: 1)
|
187
187
|
assert [0].pack("C")==res || [1].pack("C")==res, "BOMS_GET_MAX_LUN response is usually 0 or 1"
|
188
188
|
end
|
189
189
|
|
@@ -217,7 +217,7 @@ class TestLibusbMassStorage < Minitest::Test
|
|
217
217
|
end
|
218
218
|
assert_raises(LIBUSB::ERROR_TIMEOUT) do
|
219
219
|
begin
|
220
|
-
bulk_transfer(:
|
220
|
+
bulk_transfer(endpoint: endpoint_in, dataIn: 123)
|
221
221
|
rescue LIBUSB::ERROR_TIMEOUT => err
|
222
222
|
assert_kind_of String, err.transferred
|
223
223
|
raise
|
@@ -258,11 +258,11 @@ class TestLibusbMassStorage < Minitest::Test
|
|
258
258
|
end
|
259
259
|
|
260
260
|
def test_wrong_argument
|
261
|
-
assert_raises(ArgumentError){ dev.bulk_transfer(:
|
262
|
-
assert_raises(ArgumentError){ dev.interrupt_transfer(:
|
261
|
+
assert_raises(ArgumentError){ dev.bulk_transfer(endpoint: endpoint_in, dataOut: "data") }
|
262
|
+
assert_raises(ArgumentError){ dev.interrupt_transfer(endpoint: endpoint_in, dataOut: "data") }
|
263
263
|
assert_raises(ArgumentError){ dev.control_transfer(
|
264
|
-
:
|
265
|
-
:
|
266
|
-
:
|
264
|
+
bmRequestType: ENDPOINT_OUT|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
265
|
+
bRequest: BOMS_RESET,
|
266
|
+
wValue: 0, wIndex: 0, dataIn: 123) }
|
267
267
|
end
|
268
268
|
end
|
@@ -27,7 +27,7 @@ class TestLibusbMassStorage2 < Minitest::Test
|
|
27
27
|
def setup
|
28
28
|
@usb = Context.new
|
29
29
|
@usb.debug = 3
|
30
|
-
@device = usb.devices( :
|
30
|
+
@device = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 ).last
|
31
31
|
skip "no mass storage device found" unless @device
|
32
32
|
|
33
33
|
@interface = device.interfaces.first
|
data/test/test_libusb_structs.rb
CHANGED
@@ -42,4 +42,17 @@ class TestLibusbStructs < Minitest::Test
|
|
42
42
|
assert_equal false, s.completed?
|
43
43
|
assert_equal 0, s[:completed]
|
44
44
|
end
|
45
|
+
|
46
|
+
def test_Transfer
|
47
|
+
t = LIBUSB::InterruptTransfer.new allow_device_memory: true
|
48
|
+
assert_equal :TRANSFER_COMPLETED, t.status
|
49
|
+
assert_equal true, t.allow_device_memory
|
50
|
+
assert_equal nil, t.memory_type
|
51
|
+
|
52
|
+
t.alloc_buffer(10)
|
53
|
+
assert_equal :user_space, t.memory_type, "no device assigned -> should use memory from user space"
|
54
|
+
|
55
|
+
t.free_buffer
|
56
|
+
assert_equal nil, t.memory_type
|
57
|
+
end
|
45
58
|
end
|
data/test/test_libusb_threads.rb
CHANGED
@@ -34,7 +34,7 @@ class TestLibusbThreads < Minitest::Test
|
|
34
34
|
@usb = Context.new
|
35
35
|
@usb.debug = 3
|
36
36
|
|
37
|
-
@devices = usb.devices( :
|
37
|
+
@devices = usb.devices( bClass: CLASS_MASS_STORAGE, bSubClass: [0x06,0x01], bProtocol: 0x50 )
|
38
38
|
skip "less than two mass storage devices found" unless @devices.length >= 2
|
39
39
|
|
40
40
|
@devs = @devices.map do |device|
|
@@ -71,7 +71,7 @@ class TestLibusbThreads < Minitest::Test
|
|
71
71
|
1.times do
|
72
72
|
st = Time.now
|
73
73
|
assert_raises LIBUSB::ERROR_TIMEOUT do
|
74
|
-
dev.bulk_transfer(:endpoint
|
74
|
+
dev.bulk_transfer(endpoint: endpoint, dataIn: 123, timeout: 100)
|
75
75
|
end
|
76
76
|
assert_operator Time.now-st, :<, 5
|
77
77
|
dev.clear_halt(endpoint)
|
Binary file
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libusb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: x64-mingw32
|
6
6
|
authors:
|
7
7
|
- Lars Kanis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -56,16 +56,16 @@ dependencies:
|
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '1.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '1.0'
|
69
69
|
description: LIBUSB is a Ruby binding that gives Ruby programmers access to arbitrary
|
70
70
|
USB devices
|
71
71
|
email:
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- History.md
|
83
83
|
- README.md
|
84
84
|
- Rakefile
|
85
|
+
- appveyor.yml
|
85
86
|
- lib/libusb-1.0.dll
|
86
87
|
- lib/libusb.rb
|
87
88
|
- lib/libusb/bos.rb
|
@@ -90,6 +91,7 @@ files:
|
|
90
91
|
- lib/libusb/configuration.rb
|
91
92
|
- lib/libusb/constants.rb
|
92
93
|
- lib/libusb/context.rb
|
94
|
+
- lib/libusb/dependencies.rb
|
93
95
|
- lib/libusb/dev_handle.rb
|
94
96
|
- lib/libusb/device.rb
|
95
97
|
- lib/libusb/endpoint.rb
|
@@ -117,9 +119,10 @@ files:
|
|
117
119
|
- test/test_libusb_structs.rb
|
118
120
|
- test/test_libusb_threads.rb
|
119
121
|
- test/test_libusb_version.rb
|
122
|
+
- wireshark-usb-sniffer.png
|
120
123
|
homepage: http://github.com/larskanis/libusb
|
121
124
|
licenses:
|
122
|
-
- LGPL-3
|
125
|
+
- LGPL-3.0
|
123
126
|
metadata: {}
|
124
127
|
post_install_message:
|
125
128
|
rdoc_options:
|
@@ -132,15 +135,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
135
|
requirements:
|
133
136
|
- - ">="
|
134
137
|
- !ruby/object:Gem::Version
|
135
|
-
version:
|
138
|
+
version: 1.9.3
|
136
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
140
|
requirements:
|
138
141
|
- - ">="
|
139
142
|
- !ruby/object:Gem::Version
|
140
143
|
version: '0'
|
141
144
|
requirements: []
|
142
|
-
rubyforge_project:
|
143
|
-
rubygems_version: 2.
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 2.5.2
|
144
147
|
signing_key:
|
145
148
|
specification_version: 4
|
146
149
|
summary: Access USB devices from Ruby via libusb-1.0
|