libusb 0.7.0-x64-mingw-ucrt
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.
- checksums.yaml +7 -0
- data/.appveyor.yml +33 -0
- data/.github/workflows/ci.yml +185 -0
- data/.gitignore +9 -0
- data/.travis.yml +26 -0
- data/.yardopts +6 -0
- data/COPYING +165 -0
- data/Gemfile +19 -0
- data/History.md +193 -0
- data/README.md +184 -0
- data/Rakefile +79 -0
- data/lib/libusb/bos.rb +362 -0
- data/lib/libusb/call.rb +622 -0
- data/lib/libusb/compat.rb +376 -0
- data/lib/libusb/configuration.rb +154 -0
- data/lib/libusb/constants.rb +170 -0
- data/lib/libusb/context.rb +576 -0
- data/lib/libusb/context_reference.rb +38 -0
- data/lib/libusb/dependencies.rb +7 -0
- data/lib/libusb/dev_handle.rb +574 -0
- data/lib/libusb/device.rb +407 -0
- data/lib/libusb/endpoint.rb +195 -0
- data/lib/libusb/eventmachine.rb +187 -0
- data/lib/libusb/gem_helper.rb +151 -0
- data/lib/libusb/interface.rb +60 -0
- data/lib/libusb/libusb_recipe.rb +29 -0
- data/lib/libusb/setting.rb +132 -0
- data/lib/libusb/ss_companion.rb +72 -0
- data/lib/libusb/stdio.rb +25 -0
- data/lib/libusb/transfer.rb +418 -0
- data/lib/libusb/version_gem.rb +19 -0
- data/lib/libusb/version_struct.rb +63 -0
- data/lib/libusb-1.0.dll +0 -0
- data/lib/libusb.rb +146 -0
- data/libusb.gemspec +28 -0
- data/test/test_libusb.rb +42 -0
- data/test/test_libusb_bos.rb +140 -0
- data/test/test_libusb_bulk_stream_transfer.rb +61 -0
- data/test/test_libusb_compat.rb +78 -0
- data/test/test_libusb_compat_mass_storage.rb +81 -0
- data/test/test_libusb_context.rb +88 -0
- data/test/test_libusb_descriptors.rb +245 -0
- data/test/test_libusb_event_machine.rb +118 -0
- data/test/test_libusb_gc.rb +52 -0
- data/test/test_libusb_hotplug.rb +129 -0
- data/test/test_libusb_iso_transfer.rb +56 -0
- data/test/test_libusb_mass_storage.rb +268 -0
- data/test/test_libusb_mass_storage2.rb +96 -0
- data/test/test_libusb_structs.rb +87 -0
- data/test/test_libusb_threads.rb +89 -0
- data/wireshark-usb-sniffer.png +0 -0
- metadata +112 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'libusb'
|
17
|
+
require 'eventmachine'
|
18
|
+
|
19
|
+
module LIBUSB
|
20
|
+
class Context
|
21
|
+
# Register libusb's file descriptors and timeouts to EventMachine.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# require 'libusb/eventmachine'
|
25
|
+
# context = LIBUSB::Context.new
|
26
|
+
# EventMachine.run do
|
27
|
+
# context.eventmachine_register
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @see
|
31
|
+
# DevHandle#eventmachine_bulk_transfer
|
32
|
+
# DevHandle#eventmachine_control_transfer
|
33
|
+
# DevHandle#eventmachine_interrupt_transfer
|
34
|
+
def eventmachine_register
|
35
|
+
@eventmachine_attached_fds = {}
|
36
|
+
@eventmachine_timer = nil
|
37
|
+
|
38
|
+
pollfds = self.pollfds
|
39
|
+
if pollfds
|
40
|
+
pollfds.each do |pollfd|
|
41
|
+
eventmachine_add_pollfd(pollfd)
|
42
|
+
end
|
43
|
+
|
44
|
+
self.on_pollfd_added do |pollfd|
|
45
|
+
eventmachine_add_pollfd(pollfd)
|
46
|
+
end
|
47
|
+
|
48
|
+
self.on_pollfd_removed do |pollfd|
|
49
|
+
eventmachine_rm_pollfd(pollfd)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
# Libusb pollfd API is not available on this platform.
|
53
|
+
# Use simple polling timer, instead:
|
54
|
+
EventMachine.add_periodic_timer(0.01) do
|
55
|
+
@eventmachine_timer = self.handle_events 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def eventmachine_unregister
|
61
|
+
@eventmachine_timer.cancel if @eventmachine_timer
|
62
|
+
@eventmachine_attached_fds.each do |fd, watcher|
|
63
|
+
watcher.detach
|
64
|
+
end
|
65
|
+
|
66
|
+
# Deregister callbacks
|
67
|
+
on_pollfd_added
|
68
|
+
on_pollfd_removed
|
69
|
+
end
|
70
|
+
|
71
|
+
class EMPollfdHandler < EventMachine::Connection
|
72
|
+
def initialize
|
73
|
+
@callbacks = []
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_need_handle_events(&block)
|
78
|
+
@callbacks << block
|
79
|
+
end
|
80
|
+
|
81
|
+
def need_handle_events
|
82
|
+
@callbacks.each do |cb|
|
83
|
+
cb.call
|
84
|
+
end
|
85
|
+
end
|
86
|
+
alias notify_readable need_handle_events
|
87
|
+
alias notify_writable need_handle_events
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def eventmachine_add_pollfd(pollfd)
|
92
|
+
conn = EventMachine.watch(pollfd.io, EMPollfdHandler)
|
93
|
+
conn.notify_readable = pollfd.pollin?
|
94
|
+
conn.notify_writable = pollfd.pollout?
|
95
|
+
cb = proc do
|
96
|
+
if @eventmachine_timer
|
97
|
+
@eventmachine_timer.cancel
|
98
|
+
@eventmachine_timer = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
self.handle_events 0
|
102
|
+
timeout = self.next_timeout
|
103
|
+
# puts "libusb new timeout: #{timeout.inspect}"
|
104
|
+
if timeout
|
105
|
+
@eventmachine_timer = EventMachine.add_timer(timeout, &cb)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
conn.on_need_handle_events(&cb)
|
109
|
+
|
110
|
+
@eventmachine_attached_fds[pollfd.fd] = conn
|
111
|
+
# puts "libusb pollfd added: #{pollfd.inspect}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def eventmachine_rm_pollfd(pollfd)
|
115
|
+
@eventmachine_attached_fds[pollfd.fd].detach
|
116
|
+
# puts "libusb pollfd removed: #{pollfd.inspect}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class DevHandle
|
121
|
+
class EMTransfer
|
122
|
+
include EM::Deferrable
|
123
|
+
|
124
|
+
def initialize(opts, dev_handle, transfer_method)
|
125
|
+
dev_handle.send(transfer_method, **opts) do |res|
|
126
|
+
EM.next_tick do
|
127
|
+
if res.kind_of?(LIBUSB::Error)
|
128
|
+
fail res
|
129
|
+
else
|
130
|
+
succeed res
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Execute an eventmachine driven USB interrupt transfer.
|
138
|
+
#
|
139
|
+
# @see Context#eventmachine_register
|
140
|
+
# DevHandle#interrupt_transfer
|
141
|
+
def eventmachine_interrupt_transfer(**opts)
|
142
|
+
eventmachine_transfer(opts, :interrupt_transfer)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Execute an eventmachine driven USB bulk transfer.
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# tr = devh.eventmachine_bulk_transfer( endpoint: 0x02, dataOut: "data" )
|
149
|
+
# tr.callback do |data|
|
150
|
+
# puts "sent: #{data.inspect}"
|
151
|
+
# end
|
152
|
+
# tr.errback do |ex|
|
153
|
+
# puts "send-err: #{ex}"
|
154
|
+
# end
|
155
|
+
#
|
156
|
+
# @see Context#eventmachine_register
|
157
|
+
# DevHandle#bulk_transfer
|
158
|
+
def eventmachine_bulk_transfer(**opts)
|
159
|
+
eventmachine_transfer(opts, :bulk_transfer)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Execute an eventmachine driven USB control transfer.
|
163
|
+
#
|
164
|
+
# @example
|
165
|
+
# tr = devh.eventmachine_control_transfer(
|
166
|
+
# bmRequestType: ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
167
|
+
# bRequest: 0x01,
|
168
|
+
# wValue: 0, wIndex: 0, dataIn: 1 )
|
169
|
+
# tr.callback do |data|
|
170
|
+
# puts "recved: #{data.inspect}"
|
171
|
+
# end
|
172
|
+
# tr.errback do |ex|
|
173
|
+
# puts "recv-err: #{ex}"
|
174
|
+
# end
|
175
|
+
#
|
176
|
+
# @see Context#eventmachine_register
|
177
|
+
# DevHandle#control_transfer
|
178
|
+
def eventmachine_control_transfer(**opts)
|
179
|
+
eventmachine_transfer(opts, :control_transfer)
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
def eventmachine_transfer(opts, method)
|
184
|
+
EMTransfer.new opts, self, method
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,151 @@
|
|
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 "bundler/gem_helper"
|
17
|
+
|
18
|
+
module LIBUSB
|
19
|
+
class GemHelper < Bundler::GemHelper
|
20
|
+
attr_accessor :cross_platforms
|
21
|
+
|
22
|
+
def install
|
23
|
+
super
|
24
|
+
|
25
|
+
task "release:guard_clean" => ["release:update_history"]
|
26
|
+
|
27
|
+
task "release:update_history" do
|
28
|
+
update_history
|
29
|
+
end
|
30
|
+
|
31
|
+
task "release:rubygem_push" => ["gem:native"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def hfile
|
35
|
+
"History.md"
|
36
|
+
end
|
37
|
+
|
38
|
+
def headline
|
39
|
+
'([^\w]*)(\d+\.\d+\.\d+)([^\w]+)([2Y][0Y][0-9Y][0-9Y]-[0-1M][0-9M]-[0-3D][0-9D])([^\w]*|$)'
|
40
|
+
end
|
41
|
+
|
42
|
+
def reldate
|
43
|
+
Time.now.strftime("%Y-%m-%d")
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_history
|
47
|
+
hin = File.read(hfile)
|
48
|
+
hout = hin.sub(/#{headline}/) do
|
49
|
+
raise "#{hfile} isn't up-to-date for version #{version}" unless $2==version.to_s
|
50
|
+
$1 + $2 + $3 + reldate + $5
|
51
|
+
end
|
52
|
+
if hout != hin
|
53
|
+
Bundler.ui.confirm "Updating #{hfile} for release."
|
54
|
+
File.write(hfile, hout)
|
55
|
+
Rake::FileUtilsExt.sh "git", "commit", hfile, "-m", "Update release date in #{hfile}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def tag_version
|
60
|
+
Bundler.ui.confirm "Tag release with annotation:"
|
61
|
+
m = File.read(hfile).match(/(?<annotation>#{headline}.*?)#{headline}/m) || raise("Unable to find release notes in #{hfile}")
|
62
|
+
Bundler.ui.info(m[:annotation].gsub(/^/, " "))
|
63
|
+
IO.popen(["git", "tag", "--file=-", version_tag], "w") do |fd|
|
64
|
+
fd.write m[:annotation]
|
65
|
+
end
|
66
|
+
yield if block_given?
|
67
|
+
rescue
|
68
|
+
Bundler.ui.error "Untagging #{version_tag} due to error."
|
69
|
+
sh "git tag -d #{version_tag}"
|
70
|
+
raise
|
71
|
+
end
|
72
|
+
|
73
|
+
def rubygem_push(path)
|
74
|
+
cross_platforms.each do |ruby_platform|
|
75
|
+
super(path.gsub(/\.gem\z/, "-#{ruby_platform}.gem"))
|
76
|
+
end
|
77
|
+
super(path)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
class CrossLibrary < OpenStruct
|
83
|
+
include Rake::DSL
|
84
|
+
|
85
|
+
def initialize(ruby_platform, host_platform, libusb_dllname)
|
86
|
+
super()
|
87
|
+
|
88
|
+
self.ruby_platform = ruby_platform
|
89
|
+
self.recipe = LIBUSB::LibusbRecipe.new
|
90
|
+
recipe.host = ruby_platform
|
91
|
+
recipe.configure_options << "--host=#{host_platform}"
|
92
|
+
recipe.configure_options << "CC=#{host_platform}-gcc -static-libgcc" if recipe.host =~ /mingw/
|
93
|
+
self.libusb_dll = Pathname.new(recipe.path) + libusb_dllname
|
94
|
+
|
95
|
+
file libusb_dll do
|
96
|
+
recipe.cook
|
97
|
+
end
|
98
|
+
|
99
|
+
task "libusb_dll:#{ruby_platform}" => libusb_dll
|
100
|
+
|
101
|
+
desc 'Cross compile libusb for all targets'
|
102
|
+
task :cross => "cross:#{ruby_platform}"
|
103
|
+
|
104
|
+
desc "Cross compile libusb for #{ruby_platform}"
|
105
|
+
task "cross:#{ruby_platform}" => [ "libusb_dll:#{ruby_platform}" ] do |t|
|
106
|
+
spec = Gem::Specification::load("libusb.gemspec").dup
|
107
|
+
spec.platform = Gem::Platform.new(ruby_platform)
|
108
|
+
spec.extensions = []
|
109
|
+
|
110
|
+
# Remove files unnecessary for native gems
|
111
|
+
spec.files -= `git ls-files ext`.split("\n")
|
112
|
+
spec.files.reject!{|f| f.start_with?('ports') }
|
113
|
+
spec_text_files = spec.files.dup
|
114
|
+
|
115
|
+
# Add native libusb-dll
|
116
|
+
spec.files << "lib/#{libusb_dll.basename}"
|
117
|
+
|
118
|
+
# MiniPortile isn't required for native gems
|
119
|
+
spec.dependencies.reject!{|d| d.name=="mini_portile2" }
|
120
|
+
|
121
|
+
# Generate a package for this gem
|
122
|
+
pkg = Gem::PackageTask.new(spec) do |pkg|
|
123
|
+
pkg.need_zip = false
|
124
|
+
pkg.need_tar = false
|
125
|
+
# Do not copy any files per PackageTask, because
|
126
|
+
# we need the files from the platform specific directory
|
127
|
+
pkg.package_files.clear
|
128
|
+
end
|
129
|
+
|
130
|
+
# copy files of the gem to pkg directory
|
131
|
+
file pkg.package_dir_path => spec_text_files do
|
132
|
+
spec_text_files.each do |fn|
|
133
|
+
f = File.join(pkg.package_dir_path, fn)
|
134
|
+
fdir = File.dirname(f)
|
135
|
+
mkdir_p(fdir) if !File.exist?(fdir)
|
136
|
+
rm_f f
|
137
|
+
safe_ln(fn, f)
|
138
|
+
end
|
139
|
+
|
140
|
+
# copy libusb.dll to pkg directory
|
141
|
+
f = "#{pkg.package_dir_path}/lib/#{libusb_dll.basename}"
|
142
|
+
mkdir_p File.dirname(f)
|
143
|
+
rm_f f
|
144
|
+
safe_ln libusb_dll.realpath, f
|
145
|
+
end
|
146
|
+
|
147
|
+
file "lib/#{libusb_dll.basename}" => [libusb_dll]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'libusb/call'
|
17
|
+
|
18
|
+
module LIBUSB
|
19
|
+
class Interface < FFI::Struct
|
20
|
+
include Comparable
|
21
|
+
|
22
|
+
layout :altsetting, :pointer,
|
23
|
+
:num_altsetting, :int
|
24
|
+
|
25
|
+
# Number of this interface.
|
26
|
+
def bInterfaceNumber
|
27
|
+
settings.first.bInterfaceNumber
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(configuration, *args)
|
31
|
+
@configuration = configuration
|
32
|
+
super(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Configuration] the configuration this interface belongs to.
|
36
|
+
attr_reader :configuration
|
37
|
+
|
38
|
+
def alt_settings
|
39
|
+
ifs = []
|
40
|
+
self[:num_altsetting].times do |i|
|
41
|
+
ifs << Setting.new(self, self[:altsetting] + i*Setting.size)
|
42
|
+
end
|
43
|
+
return ifs
|
44
|
+
end
|
45
|
+
alias settings alt_settings
|
46
|
+
|
47
|
+
def inspect
|
48
|
+
"\#<#{self.class} #{bInterfaceNumber}>"
|
49
|
+
end
|
50
|
+
|
51
|
+
# The {Device} this Interface belongs to.
|
52
|
+
def device() self.configuration.device end
|
53
|
+
# Return all endpoints of all alternative settings as Array of {Endpoint}s.
|
54
|
+
def endpoints() self.alt_settings.map {|d| d.endpoints }.flatten end
|
55
|
+
|
56
|
+
def <=>(o)
|
57
|
+
configuration<=>o.configuration
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'dependencies'
|
2
|
+
require 'rubygems'
|
3
|
+
# Keep the version constraint in sync with libusb.gemspec
|
4
|
+
gem "mini_portile2", LIBUSB::MINI_PORTILE_VERSION
|
5
|
+
require "mini_portile2"
|
6
|
+
|
7
|
+
module LIBUSB
|
8
|
+
class LibusbRecipe < MiniPortile
|
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, sha256: LIBUSB_SOURCE_SHA256]
|
15
|
+
self.patch_files = Dir[File.join(ROOT, "patches", self.name, self.version, "*.patch")].sort
|
16
|
+
self.configure_options = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def cook_and_activate
|
20
|
+
checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{self.host}.installed")
|
21
|
+
unless File.exist?(checkpoint)
|
22
|
+
self.cook
|
23
|
+
FileUtils.touch checkpoint
|
24
|
+
end
|
25
|
+
self.activate
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'libusb/call'
|
17
|
+
|
18
|
+
module LIBUSB
|
19
|
+
class Setting < FFI::Struct
|
20
|
+
include Comparable
|
21
|
+
|
22
|
+
layout :bLength, :uint8,
|
23
|
+
:bDescriptorType, :uint8,
|
24
|
+
:bInterfaceNumber, :uint8,
|
25
|
+
:bAlternateSetting, :uint8,
|
26
|
+
:bNumEndpoints, :uint8,
|
27
|
+
:bInterfaceClass, :uint8,
|
28
|
+
:bInterfaceSubClass, :uint8,
|
29
|
+
:bInterfaceProtocol, :uint8,
|
30
|
+
:iInterface, :uint8,
|
31
|
+
:endpoint, :pointer,
|
32
|
+
:extra, :pointer,
|
33
|
+
:extra_length, :int
|
34
|
+
|
35
|
+
# Size of this descriptor (in bytes).
|
36
|
+
def bLength
|
37
|
+
self[:bLength]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Descriptor type (0x04)
|
41
|
+
def bDescriptorType
|
42
|
+
self[:bDescriptorType]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Number of the interface this setting belongs to.
|
46
|
+
def bInterfaceNumber
|
47
|
+
self[:bInterfaceNumber]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Value used to select this alternate setting for this interface.
|
51
|
+
def bAlternateSetting
|
52
|
+
self[:bAlternateSetting]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Number of endpoints used by this interface (excluding the control endpoint).
|
56
|
+
def bNumEndpoints
|
57
|
+
self[:bNumEndpoints]
|
58
|
+
end
|
59
|
+
|
60
|
+
# USB-IF class code for this interface.
|
61
|
+
def bInterfaceClass
|
62
|
+
self[:bInterfaceClass]
|
63
|
+
end
|
64
|
+
|
65
|
+
# USB-IF subclass code for this interface, qualified by the {Setting#bInterfaceClass} value.
|
66
|
+
def bInterfaceSubClass
|
67
|
+
self[:bInterfaceSubClass]
|
68
|
+
end
|
69
|
+
|
70
|
+
# USB-IF protocol code for this interface, qualified by the {Setting#bInterfaceClass} and {Setting#bInterfaceSubClass} values.
|
71
|
+
def bInterfaceProtocol
|
72
|
+
self[:bInterfaceProtocol]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Index of string descriptor describing this interface.
|
76
|
+
def iInterface
|
77
|
+
self[:iInterface]
|
78
|
+
end
|
79
|
+
|
80
|
+
# Extra descriptors.
|
81
|
+
#
|
82
|
+
# @return [String]
|
83
|
+
def extra
|
84
|
+
return if self[:extra].null?
|
85
|
+
self[:extra].read_string(self[:extra_length])
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(interface, *args)
|
89
|
+
@interface = interface
|
90
|
+
super(*args)
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Interface] the interface this setting belongs to.
|
94
|
+
attr_reader :interface
|
95
|
+
|
96
|
+
def endpoints
|
97
|
+
ifs = []
|
98
|
+
self[:bNumEndpoints].times do |i|
|
99
|
+
ifs << Endpoint.new(self, self[:endpoint] + i*Endpoint.size)
|
100
|
+
end
|
101
|
+
return ifs
|
102
|
+
end
|
103
|
+
|
104
|
+
def inspect
|
105
|
+
attrs = []
|
106
|
+
attrs << self.bAlternateSetting.to_s
|
107
|
+
devclass = LIBUSB.dev_string(self.bInterfaceClass, self.bInterfaceSubClass, self.bInterfaceProtocol)
|
108
|
+
attrs << devclass
|
109
|
+
desc = self.description
|
110
|
+
attrs << desc if desc != '?'
|
111
|
+
"\#<#{self.class} #{attrs.join(' ')}>"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return name of this interface as String.
|
115
|
+
def description
|
116
|
+
return @description if defined? @description
|
117
|
+
@description = device.try_string_descriptor_ascii(self.iInterface)
|
118
|
+
end
|
119
|
+
|
120
|
+
# The {Device} this Setting belongs to.
|
121
|
+
def device() self.interface.configuration.device end
|
122
|
+
# The {Configuration} this Setting belongs to.
|
123
|
+
def configuration() self.interface.configuration end
|
124
|
+
|
125
|
+
def <=>(o)
|
126
|
+
t = interface<=>o.interface
|
127
|
+
t = bInterfaceNumber<=>o.bInterfaceNumber if t==0
|
128
|
+
t = bAlternateSetting<=>o.bAlternateSetting if t==0
|
129
|
+
t
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# This file is part of Libusb for Ruby.
|
2
|
+
#
|
3
|
+
# Libusb for Ruby is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# Libusb for Ruby is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public License
|
14
|
+
# along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'libusb/call'
|
17
|
+
|
18
|
+
module LIBUSB
|
19
|
+
# A structure representing the superspeed endpoint companion descriptor.
|
20
|
+
#
|
21
|
+
# This descriptor is documented in section 9.6.7 of the USB 3.0 specification. All multiple-byte fields are represented in host-endian format.
|
22
|
+
class SsCompanion < FFI::Struct
|
23
|
+
include ContextReference
|
24
|
+
|
25
|
+
layout :bLength, :uint8,
|
26
|
+
:bDescriptorType, :uint8,
|
27
|
+
:bMaxBurst, :uint8,
|
28
|
+
:bmAttributes, :uint8,
|
29
|
+
:wBytesPerInterval, :uint16
|
30
|
+
|
31
|
+
def initialize(ctx, *args)
|
32
|
+
super(*args)
|
33
|
+
|
34
|
+
register_context(ctx, :libusb_free_ss_endpoint_companion_descriptor)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Size of this descriptor (in bytes)
|
38
|
+
def bLength
|
39
|
+
self[:bLength]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Descriptor type.
|
43
|
+
#
|
44
|
+
# Will have value LIBUSB::DT_SS_ENDPOINT_COMPANION in this context.
|
45
|
+
def bDescriptorType
|
46
|
+
self[:bDescriptorType]
|
47
|
+
end
|
48
|
+
|
49
|
+
# The maximum number of packets the endpoint can send or recieve as part of a burst.
|
50
|
+
def bMaxBurst
|
51
|
+
self[:bMaxBurst]
|
52
|
+
end
|
53
|
+
|
54
|
+
# In bulk EP: bits 4:0 represents the maximum number of streams the EP supports.
|
55
|
+
#
|
56
|
+
# In isochronous EP: bits 1:0 represents the Mult - a zero based value that determines the maximum number of packets within a service interval
|
57
|
+
def bmAttributes
|
58
|
+
self[:bmAttributes]
|
59
|
+
end
|
60
|
+
|
61
|
+
# The total number of bytes this EP will transfer every service interval.
|
62
|
+
#
|
63
|
+
# valid only for periodic EPs.
|
64
|
+
def wBytesPerInterval
|
65
|
+
self[:wBytesPerInterval]
|
66
|
+
end
|
67
|
+
|
68
|
+
def inspect
|
69
|
+
"\#<#{self.class} burst: #{bMaxBurst} attrs: #{bmAttributes}>"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/libusb/stdio.rb
ADDED
@@ -0,0 +1,25 @@
|
|
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
|
+
module Stdio
|
21
|
+
extend FFI::Library
|
22
|
+
ffi_lib FFI::Platform::LIBC
|
23
|
+
attach_function :free, [ :pointer ], :void
|
24
|
+
end
|
25
|
+
end
|