libusb 0.2.2-x86-mingw32 → 0.3.0-x86-mingw32
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.
- data/.gitignore +8 -0
- data/.travis.yml +10 -0
- data/.yardopts +6 -1
- data/Gemfile +16 -0
- data/{History.txt → History.md} +28 -16
- data/README.md +144 -0
- data/Rakefile +28 -24
- data/ext/extconf.rb +33 -0
- data/lib/libusb.rb +2 -3
- data/lib/libusb/call.rb +49 -7
- data/lib/libusb/compat.rb +15 -9
- data/lib/libusb/configuration.rb +15 -3
- data/lib/libusb/constants.rb +19 -6
- data/lib/libusb/context.rb +181 -3
- data/lib/libusb/dev_handle.rb +91 -40
- data/lib/libusb/endpoint.rb +41 -14
- data/lib/libusb/eventmachine.rb +183 -0
- data/lib/libusb/transfer.rb +21 -8
- data/lib/libusb/version_gem.rb +19 -0
- data/lib/libusb/{version.rb → version_struct.rb} +0 -0
- data/libusb.gemspec +31 -0
- data/test/test_libusb_compat.rb +1 -1
- data/test/test_libusb_compat_mass_storage.rb +2 -2
- data/test/test_libusb_descriptors.rb +1 -1
- data/test/test_libusb_event_machine.rb +118 -0
- data/test/test_libusb_iso_transfer.rb +6 -1
- data/test/test_libusb_mass_storage.rb +9 -3
- data/test/test_libusb_mass_storage2.rb +1 -1
- data/test/test_libusb_structs.rb +45 -0
- data/test/test_libusb_threads.rb +89 -0
- data/test/test_libusb_version.rb +4 -0
- metadata +44 -44
- data/.autotest +0 -23
- data/.gemtest +0 -0
- data/Manifest.txt +0 -3
- data/README.rdoc +0 -115
- data/test/test_libusb_keyboard.rb +0 -50
data/lib/libusb/endpoint.rb
CHANGED
@@ -47,18 +47,31 @@ module LIBUSB
|
|
47
47
|
# * Bits 7: Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
|
48
48
|
#
|
49
49
|
# @return [Integer]
|
50
|
+
#
|
51
|
+
# @see #endpoint_number
|
52
|
+
# @see #direction
|
50
53
|
def bEndpointAddress
|
51
54
|
self[:bEndpointAddress]
|
52
55
|
end
|
53
56
|
|
57
|
+
# @return [Integer]
|
58
|
+
def endpoint_number
|
59
|
+
bEndpointAddress & 0b1111
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Symbol] Either +:in+ or +:out+
|
63
|
+
def direction
|
64
|
+
bEndpointAddress & ENDPOINT_IN == 0 ? :out : :in
|
65
|
+
end
|
66
|
+
|
54
67
|
# Attributes which apply to the endpoint when it is configured using the {Configuration#bConfigurationValue}.
|
55
68
|
#
|
56
|
-
# * Bits 0
|
69
|
+
# * Bits 1..0: Transfer Type
|
57
70
|
# * 00 = Control
|
58
71
|
# * 01 = Isochronous
|
59
72
|
# * 10 = Bulk
|
60
73
|
# * 11 = Interrupt
|
61
|
-
# * Bits 2
|
74
|
+
# * Bits 7..2: are reserved. If Isochronous endpoint,
|
62
75
|
# * Bits 3..2: Synchronisation Type (Iso Mode)
|
63
76
|
# * 00 = No Synchonisation
|
64
77
|
# * 01 = Asynchronous
|
@@ -71,10 +84,34 @@ module LIBUSB
|
|
71
84
|
# * 11 = Reserved
|
72
85
|
#
|
73
86
|
# @return [Integer]
|
87
|
+
#
|
88
|
+
# @see #transfer_type
|
89
|
+
# @see #usage_type
|
90
|
+
# @see #synchronization_type
|
74
91
|
def bmAttributes
|
75
92
|
self[:bmAttributes]
|
76
93
|
end
|
77
94
|
|
95
|
+
TransferTypes = [:control, :isochronous, :bulk, :interrupt]
|
96
|
+
# @return [Symbol] One of {TransferTypes}
|
97
|
+
def transfer_type
|
98
|
+
TransferTypes[bmAttributes & 0b11]
|
99
|
+
end
|
100
|
+
|
101
|
+
SynchronizationTypes = [:no_synchronization, :asynchronous, :adaptive, :synchronous]
|
102
|
+
# @return [Symbol] One of {SynchronizationTypes}
|
103
|
+
def synchronization_type
|
104
|
+
return unless transfer_type == :isochronous
|
105
|
+
SynchronizationTypes[(bmAttributes & 0b1100) >> 2]
|
106
|
+
end
|
107
|
+
|
108
|
+
UsageTypes = [:data, :feedback, :implicit_feedback, :unknown]
|
109
|
+
# @return [Symbol] One of {UsageTypes}
|
110
|
+
def usage_type
|
111
|
+
return unless transfer_type == :isochronous
|
112
|
+
UsageTypes[(bmAttributes & 0b110000) >> 4]
|
113
|
+
end
|
114
|
+
|
78
115
|
# Maximum Packet Size this endpoint is capable of sending or receiving
|
79
116
|
def wMaxPacketSize
|
80
117
|
self[:wMaxPacketSize]
|
@@ -117,18 +154,8 @@ module LIBUSB
|
|
117
154
|
attr_reader :setting
|
118
155
|
|
119
156
|
def inspect
|
120
|
-
|
121
|
-
|
122
|
-
inout = (endpoint_address & 0b10000000) == 0 ? "OUT" : "IN "
|
123
|
-
bits = self.bmAttributes
|
124
|
-
transfer_type = %w[Control Isochronous Bulk Interrupt][0b11 & bits]
|
125
|
-
type = [transfer_type]
|
126
|
-
if transfer_type == 'Isochronous'
|
127
|
-
synchronization_type = %w[NoSynchronization Asynchronous Adaptive Synchronous][(0b1100 & bits) >> 2]
|
128
|
-
usage_type = %w[Data Feedback ImplicitFeedback ?][(0b110000 & bits) >> 4]
|
129
|
-
type << synchronization_type << usage_type
|
130
|
-
end
|
131
|
-
"\#<#{self.class} #{num} #{inout} #{type.join(" ")}>"
|
157
|
+
type = [transfer_type, synchronization_type, usage_type].compact
|
158
|
+
"\#<#{self.class} #{endpoint_number} #{direction} #{type.join(" ")}>"
|
132
159
|
end
|
133
160
|
|
134
161
|
# The {Device} this Endpoint belongs to.
|
@@ -0,0 +1,183 @@
|
|
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
|
+
end
|
66
|
+
|
67
|
+
class EMPollfdHandler < EventMachine::Connection
|
68
|
+
def initialize
|
69
|
+
@callbacks = []
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_need_handle_events(&block)
|
74
|
+
@callbacks << block
|
75
|
+
end
|
76
|
+
|
77
|
+
def need_handle_events
|
78
|
+
@callbacks.each do |cb|
|
79
|
+
cb.call
|
80
|
+
end
|
81
|
+
end
|
82
|
+
alias notify_readable need_handle_events
|
83
|
+
alias notify_writable need_handle_events
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
def eventmachine_add_pollfd(pollfd)
|
88
|
+
conn = EventMachine.watch(pollfd.io, EMPollfdHandler)
|
89
|
+
conn.notify_readable = pollfd.pollin?
|
90
|
+
conn.notify_writable = pollfd.pollout?
|
91
|
+
cb = proc do
|
92
|
+
if @eventmachine_timer
|
93
|
+
@eventmachine_timer.cancel
|
94
|
+
@eventmachine_timer = nil
|
95
|
+
end
|
96
|
+
|
97
|
+
self.handle_events 0
|
98
|
+
timeout = self.next_timeout
|
99
|
+
# puts "libusb new timeout: #{timeout.inspect}"
|
100
|
+
if timeout
|
101
|
+
@eventmachine_timer = EventMachine.add_timer(timeout, &cb)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
conn.on_need_handle_events(&cb)
|
105
|
+
|
106
|
+
@eventmachine_attached_fds[pollfd.fd] = conn
|
107
|
+
# puts "libusb pollfd added: #{pollfd.inspect}"
|
108
|
+
end
|
109
|
+
|
110
|
+
def eventmachine_rm_pollfd(pollfd)
|
111
|
+
@eventmachine_attached_fds[pollfd.fd].detach
|
112
|
+
# puts "libusb pollfd removed: #{pollfd.inspect}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class DevHandle
|
117
|
+
class EMTransfer
|
118
|
+
include EM::Deferrable
|
119
|
+
|
120
|
+
def initialize(opts, dev_handle, transfer_method)
|
121
|
+
dev_handle.send(transfer_method, opts) do |res|
|
122
|
+
EM.next_tick do
|
123
|
+
if res.kind_of?(LIBUSB::Error)
|
124
|
+
fail res
|
125
|
+
else
|
126
|
+
succeed res
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Execute an eventmachine driven USB interrupt transfer.
|
134
|
+
#
|
135
|
+
# @see Context#eventmachine_register
|
136
|
+
# DevHandle#interrupt_transfer
|
137
|
+
def eventmachine_interrupt_transfer(opts={})
|
138
|
+
eventmachine_transfer(opts, :interrupt_transfer)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Execute an eventmachine driven USB bulk transfer.
|
142
|
+
#
|
143
|
+
# @example
|
144
|
+
# tr = devh.eventmachine_bulk_transfer( :endpoint => 0x02, :dataOut => "data" )
|
145
|
+
# tr.callback do |data|
|
146
|
+
# puts "sent: #{data.inspect}"
|
147
|
+
# end
|
148
|
+
# tr.errback do |ex|
|
149
|
+
# puts "send-err: #{ex}"
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# @see Context#eventmachine_register
|
153
|
+
# DevHandle#bulk_transfer
|
154
|
+
def eventmachine_bulk_transfer(opts={})
|
155
|
+
eventmachine_transfer(opts, :bulk_transfer)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Execute an eventmachine driven USB control transfer.
|
159
|
+
#
|
160
|
+
# @example
|
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 )
|
165
|
+
# tr.callback do |data|
|
166
|
+
# puts "recved: #{data.inspect}"
|
167
|
+
# end
|
168
|
+
# tr.errback do |ex|
|
169
|
+
# puts "recv-err: #{ex}"
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# @see Context#eventmachine_register
|
173
|
+
# DevHandle#control_transfer
|
174
|
+
def eventmachine_control_transfer(opts={})
|
175
|
+
eventmachine_transfer(opts, :control_transfer)
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
def eventmachine_transfer(opts, method)
|
180
|
+
EMTransfer.new opts, self, method
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/lib/libusb/transfer.rb
CHANGED
@@ -19,10 +19,16 @@ module LIBUSB
|
|
19
19
|
# Abstract base class for USB transfers. Use
|
20
20
|
# {ControlTransfer}, {BulkTransfer}, {InterruptTransfer}, {IsochronousTransfer}
|
21
21
|
# to do transfers.
|
22
|
+
#
|
23
|
+
# There are convenience methods for {DevHandle#bulk_transfer}, {DevHandle#control_transfer}
|
24
|
+
# and {DevHandle#interrupt_transfer}, that fit for most use cases.
|
25
|
+
# Using {Transfer} derived classes directly, however, is needed for isochronous transfers and
|
26
|
+
# allows a more advanced buffer management.
|
22
27
|
class Transfer
|
23
28
|
def initialize(args={})
|
24
29
|
args.each{|k,v| send("#{k}=", v) }
|
25
30
|
@buffer = nil
|
31
|
+
@completion_flag = Context::CompletionFlag.new
|
26
32
|
end
|
27
33
|
private :initialize
|
28
34
|
|
@@ -156,26 +162,33 @@ module LIBUSB
|
|
156
162
|
|
157
163
|
# Submit the transfer and wait until the transfer completes or fails.
|
158
164
|
#
|
159
|
-
#
|
160
|
-
def submit_and_wait
|
161
|
-
completed = false
|
165
|
+
# Inspect {#status} to check for transfer errors.
|
166
|
+
def submit_and_wait
|
167
|
+
@completion_flag.completed = false
|
162
168
|
submit! do |tr2|
|
163
|
-
completed = true
|
169
|
+
@completion_flag.completed = true
|
164
170
|
end
|
165
171
|
|
166
|
-
until completed
|
172
|
+
until @completion_flag.completed?
|
167
173
|
begin
|
168
|
-
@dev_handle.device.context.handle_events
|
174
|
+
@dev_handle.device.context.handle_events nil, @completion_flag
|
169
175
|
rescue ERROR_INTERRUPTED
|
170
176
|
next
|
171
177
|
rescue LIBUSB::Error
|
172
178
|
cancel!
|
173
|
-
until completed
|
174
|
-
@dev_handle.device.context.handle_events
|
179
|
+
until @completion_flag.completed?
|
180
|
+
@dev_handle.device.context.handle_events nil, @completion_flag
|
175
181
|
end
|
176
182
|
raise
|
177
183
|
end
|
178
184
|
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Submit the transfer and wait until the transfer completes or fails.
|
188
|
+
#
|
189
|
+
# A proper {LIBUSB::Error} is raised, in case the transfer did not complete.
|
190
|
+
def submit_and_wait!
|
191
|
+
submit_and_wait
|
179
192
|
|
180
193
|
raise( TransferStatusToError[status] || ERROR_OTHER, "error #{status}") unless status==:TRANSFER_COMPLETED
|
181
194
|
end
|
@@ -0,0 +1,19 @@
|
|
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
|
+
module LIBUSB
|
17
|
+
# Library version of libusb for Ruby
|
18
|
+
VERSION = "0.3.0"
|
19
|
+
end
|
File without changes
|
data/libusb.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "libusb/version_gem"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "libusb"
|
7
|
+
s.version = LIBUSB::VERSION
|
8
|
+
s.authors = ["Lars Kanis"]
|
9
|
+
s.email = ["lars@greiz-reinsdorf.de"]
|
10
|
+
s.homepage = "http://github.com/larskanis/libusb"
|
11
|
+
s.summary = %q{Access USB devices from Ruby via libusb-1.0}
|
12
|
+
s.description = %q{LIBUSB is a Ruby binding that gives Ruby programmers access to arbitrary USB devices}
|
13
|
+
s.rdoc_options = %w[--main README.md --charset=UTF-8]
|
14
|
+
|
15
|
+
s.rubyforge_project = "libusb"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.extensions = ['ext/extconf.rb']
|
22
|
+
|
23
|
+
# travis currently runs a slightly older version of rbx,
|
24
|
+
# that needs a special ffi version.
|
25
|
+
unless ENV['TRAVIS'] && defined?(RUBY_ENGINE) && RUBY_ENGINE=='rbx'
|
26
|
+
s.add_runtime_dependency 'ffi', '>= 1.0'
|
27
|
+
end
|
28
|
+
|
29
|
+
s.add_development_dependency 'rake-compiler', '>= 0.6'
|
30
|
+
s.add_development_dependency 'bundler'
|
31
|
+
end
|
data/test/test_libusb_compat.rb
CHANGED
@@ -68,7 +68,7 @@ class TestLibusbCompat < Test::Unit::TestCase
|
|
68
68
|
assert_equal config_desc, ep.configuration, "backref should be correct"
|
69
69
|
assert_equal dev, ep.device, "backref should be correct"
|
70
70
|
|
71
|
-
assert_operator 0,
|
71
|
+
assert_operator 0, :<=, ep.wMaxPacketSize, "packet size should be > 0"
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -16,7 +16,7 @@
|
|
16
16
|
require "test/unit"
|
17
17
|
require "libusb/compat"
|
18
18
|
|
19
|
-
class
|
19
|
+
class TestLibusbCompatMassStorage < Test::Unit::TestCase
|
20
20
|
include USB
|
21
21
|
|
22
22
|
attr_accessor :devh
|
@@ -30,7 +30,7 @@ class TestLibusbCompat < Test::Unit::TestCase
|
|
30
30
|
USB.each_device_by_class(USB_CLASS_MASS_STORAGE, 0x06, 0x50){|dev| devs << dev }
|
31
31
|
|
32
32
|
dev = devs.last
|
33
|
-
|
33
|
+
skip "no mass storage device found" unless dev
|
34
34
|
devh = dev.open
|
35
35
|
if RUBY_PLATFORM=~/linux/i
|
36
36
|
data = " "*1000
|
@@ -101,7 +101,7 @@ class TestLibusbDescriptors < Test::Unit::TestCase
|
|
101
101
|
assert_equal 5, ep.bDescriptorType
|
102
102
|
assert_kind_of Integer, ep.bEndpointAddress
|
103
103
|
assert_kind_of Integer, ep.bmAttributes
|
104
|
-
assert_operator 0,
|
104
|
+
assert_operator 0, :<=, ep.wMaxPacketSize, "packet size should be > 0"
|
105
105
|
assert_kind_of Integer, ep.bInterval
|
106
106
|
assert_kind_of Integer, ep.bRefresh
|
107
107
|
assert_kind_of Integer, ep.bSynchAddress
|
@@ -0,0 +1,118 @@
|
|
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 "test/unit"
|
17
|
+
require "libusb"
|
18
|
+
require "libusb/eventmachine"
|
19
|
+
require "eventmachine"
|
20
|
+
|
21
|
+
class TestLibusbEventMachine < Test::Unit::TestCase
|
22
|
+
include LIBUSB
|
23
|
+
BOMS_GET_MAX_LUN = 0xFE
|
24
|
+
|
25
|
+
attr_accessor :context
|
26
|
+
attr_accessor :device
|
27
|
+
attr_accessor :devh
|
28
|
+
attr_accessor :endpoint_in
|
29
|
+
attr_accessor :endpoint_out
|
30
|
+
|
31
|
+
def setup
|
32
|
+
@context = Context.new
|
33
|
+
@context.debug = 3
|
34
|
+
|
35
|
+
@device = context.devices( :bClass=>CLASS_MASS_STORAGE, :bSubClass=>[0x06,0x01], :bProtocol=>0x50 ).last
|
36
|
+
skip "no mass storage device found" unless @device
|
37
|
+
|
38
|
+
@endpoint_in = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN != 0 }
|
39
|
+
@endpoint_out = @device.endpoints.find{|ep| ep.bEndpointAddress&ENDPOINT_IN == 0 }
|
40
|
+
@devh = @device.open
|
41
|
+
|
42
|
+
if RUBY_PLATFORM=~/linux/i && devh.kernel_driver_active?(0)
|
43
|
+
devh.detach_kernel_driver(0)
|
44
|
+
end
|
45
|
+
devh.claim_interface(0)
|
46
|
+
|
47
|
+
# clear any pending data
|
48
|
+
devh.clear_halt(endpoint_in)
|
49
|
+
end
|
50
|
+
|
51
|
+
def teardown
|
52
|
+
end
|
53
|
+
|
54
|
+
def em_run
|
55
|
+
EventMachine.run do
|
56
|
+
@context.eventmachine_register
|
57
|
+
|
58
|
+
EventMachine.add_shutdown_hook do
|
59
|
+
@devh.release_interface(0) if @devh
|
60
|
+
@devh.close if @devh
|
61
|
+
@context.eventmachine_unregister
|
62
|
+
end
|
63
|
+
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def test_bulk_transfer
|
70
|
+
em_run do
|
71
|
+
ticks = 0
|
72
|
+
tr = devh.eventmachine_bulk_transfer(
|
73
|
+
:endpoint => @endpoint_in,
|
74
|
+
:timeout => 1500,
|
75
|
+
:dataIn => 123 )
|
76
|
+
# puts "started usb transfer #{tr}"
|
77
|
+
|
78
|
+
tr.callback do |data|
|
79
|
+
# puts "recved: #{data.inspect}"
|
80
|
+
|
81
|
+
assert false, "the bulk transfer shouldn't succeed"
|
82
|
+
EventMachine.stop
|
83
|
+
end
|
84
|
+
tr.errback do |text|
|
85
|
+
# puts "recv-err: #{text}"
|
86
|
+
assert true, "the bulk transfer should fail"
|
87
|
+
|
88
|
+
assert_operator ticks, :>=, 4
|
89
|
+
EventMachine.stop
|
90
|
+
end
|
91
|
+
|
92
|
+
EventMachine.add_periodic_timer(0.333) do
|
93
|
+
ticks += 1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_event_loop
|
99
|
+
em_run do
|
100
|
+
tr = devh.eventmachine_control_transfer(
|
101
|
+
:bmRequestType=>ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
|
102
|
+
:bRequest=>BOMS_GET_MAX_LUN,
|
103
|
+
:wValue=>0, :wIndex=>0, :dataIn=>1 )
|
104
|
+
|
105
|
+
# puts "started usb transfer #{tr}"
|
106
|
+
tr.callback do |data|
|
107
|
+
# puts "recved: #{data.inspect}"
|
108
|
+
assert true, "the control transfer should succeed"
|
109
|
+
EventMachine.stop
|
110
|
+
end
|
111
|
+
tr.errback do |text|
|
112
|
+
# puts "recv-err: #{text}"
|
113
|
+
assert false, "the control transfer shouldn't fail"
|
114
|
+
EventMachine.stop
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|