libusb 0.6.4-x86-mingw32 → 0.7.1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.appveyor.yml +33 -0
- data/.github/workflows/ci.yml +185 -0
- data/.gitignore +1 -0
- data/.travis.yml +12 -7
- data/Gemfile +4 -1
- data/History.md +46 -0
- data/README.md +29 -4
- data/Rakefile +43 -14
- data/lib/libusb/bos.rb +85 -29
- data/lib/libusb/call.rb +132 -16
- data/lib/libusb/configuration.rb +3 -4
- data/lib/libusb/constants.rb +4 -0
- data/lib/libusb/context.rb +176 -35
- data/lib/libusb/context_reference.rb +38 -0
- data/lib/libusb/dependencies.rb +2 -2
- data/lib/libusb/dev_handle.rb +34 -24
- data/lib/libusb/device.rb +50 -8
- data/lib/libusb/endpoint.rb +3 -2
- data/lib/libusb/eventmachine.rb +8 -4
- data/lib/libusb/gem_helper.rb +9 -6
- data/lib/libusb/libusb_recipe.rb +2 -3
- data/lib/libusb/ss_companion.rb +9 -6
- data/lib/libusb/transfer.rb +10 -6
- data/lib/libusb/version_gem.rb +1 -1
- data/lib/libusb-1.0.dll +0 -0
- data/lib/libusb.rb +106 -18
- data/libusb.gemspec +1 -5
- data/test/test_libusb_bos.rb +22 -0
- data/test/test_libusb_bulk_stream_transfer.rb +23 -12
- data/test/test_libusb_context.rb +47 -0
- data/test/test_libusb_descriptors.rb +44 -11
- data/test/test_libusb_gc.rb +15 -0
- data/test/test_libusb_hotplug.rb +3 -1
- data/test/test_libusb_iso_transfer.rb +6 -0
- data/test/test_libusb_mass_storage.rb +6 -6
- metadata +7 -62
- data/appveyor.yml +0 -36
data/lib/libusb/context.rb
CHANGED
@@ -95,23 +95,87 @@ module LIBUSB
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
|
99
98
|
# Initialize libusb context.
|
100
|
-
|
99
|
+
#
|
100
|
+
# @param [Hash{Call::Options => Object}] options Options are available since libusb-1.0.27
|
101
|
+
# @option options [Integer, Symbol] :OPTION_LOG_LEVEL The log Level as a Integer or Symbol. See Call::LogLevels
|
102
|
+
# @option options [nil] :OPTION_USE_USBDK Enable the use of USBDK driver. Pass a +nil+ as value like so: +OPTION_USE_USBDK: nil+
|
103
|
+
# @option options [nil] :OPTION_NO_DEVICE_DISCOVERY Disable device discovery for use with libusb_wrap_sys_device(). Pass a +nil+ as value like so: +OPTION_NO_DEVICE_DISCOVERY: nil+
|
104
|
+
# @option options [Proc] :OPTION_LOG_CB Set a context related log callback Proc. It is called with parameters (context, level, logstring).
|
105
|
+
def initialize(options={})
|
101
106
|
m = FFI::MemoryPointer.new :pointer
|
102
|
-
|
103
|
-
|
107
|
+
if options.empty?
|
108
|
+
res = Call.libusb_init(m)
|
109
|
+
LIBUSB.raise_error res, "in libusb_init" if res!=0
|
110
|
+
else
|
111
|
+
raise ArgumentError, "options require libusb-1.0.27+" unless Call.respond_to?(:libusb_init_context)
|
112
|
+
i_opts = options.size
|
113
|
+
p_opts = FFI::MemoryPointer.new(Call::InitOption, i_opts)
|
114
|
+
options.each_with_index do |(k, v), i|
|
115
|
+
opt = Call::InitOption.new(p_opts + i * Call::InitOption.size)
|
116
|
+
opt[:option] = k
|
117
|
+
|
118
|
+
ffitype, ffival = LIBUSB.send(:option_args_to_ffi, k, Array(v), self)
|
119
|
+
case ffitype
|
120
|
+
when NilClass then nil
|
121
|
+
when :libusb_log_level then
|
122
|
+
opt[:value][:ival] = ffival
|
123
|
+
when :libusb_log_cb then
|
124
|
+
opt[:value][:log_cbval] = ffival
|
125
|
+
else raise ArgumentError, "internal error: unexpected ffitype: #{ffitype.inspect}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
res = Call.libusb_init_context(m, p_opts, i_opts)
|
129
|
+
LIBUSB.raise_error res, "in libusb_init_context" if res!=0
|
130
|
+
end
|
104
131
|
@ctx = m.read_pointer
|
105
132
|
@on_pollfd_added = nil
|
106
133
|
@on_pollfd_removed = nil
|
107
134
|
@hotplug_callbacks = {}
|
135
|
+
|
136
|
+
def @ctx.free_context(id)
|
137
|
+
@free_context = true
|
138
|
+
if @refs == 0
|
139
|
+
# puts "final libusb_exit #{to_i} #{id} #{caller[0]}"
|
140
|
+
if id # Is Context is about to be garbage collected?
|
141
|
+
# In GC mode there's no way to call the registered collbacks, since they are GC'ed as well.
|
142
|
+
# So disable callbacks now.
|
143
|
+
Call.libusb_set_log_cb(self, nil, LOG_CB_CONTEXT)
|
144
|
+
Call.libusb_set_pollfd_notifiers(self, nil, nil, nil)
|
145
|
+
end
|
146
|
+
Call.libusb_exit(self)
|
147
|
+
@refs = nil
|
148
|
+
end
|
149
|
+
end
|
150
|
+
def @ctx.ref_context
|
151
|
+
@refs += 1
|
152
|
+
# puts "ref_context #{to_i} #{@refs} #{caller[1]}"
|
153
|
+
self
|
154
|
+
end
|
155
|
+
def @ctx.unref_context
|
156
|
+
@refs -= 1
|
157
|
+
# puts "unref_context #{to_i} #{@refs}"
|
158
|
+
raise "more unref_context than ref_context" if @refs < 0
|
159
|
+
free_context(true) if @refs == 0 && @free_context
|
160
|
+
self
|
161
|
+
end
|
162
|
+
def @ctx.setref_context
|
163
|
+
@refs = 0
|
164
|
+
@free_context = false
|
165
|
+
end
|
166
|
+
def @ctx.refs
|
167
|
+
@refs
|
168
|
+
end
|
169
|
+
@ctx.setref_context
|
170
|
+
ObjectSpace.define_finalizer(self, @ctx.method(:free_context))
|
108
171
|
end
|
109
172
|
|
110
173
|
# Deinitialize libusb.
|
111
174
|
#
|
112
175
|
# Should be called after closing all open devices and before your application terminates.
|
113
176
|
def exit
|
114
|
-
|
177
|
+
raise RemainingReferencesError, "#{@ctx.refs} remaining references to LIBUSB::Context" if @ctx.refs.to_i > 0
|
178
|
+
@ctx.free_context nil
|
115
179
|
end
|
116
180
|
|
117
181
|
# @deprecated Use {Context#set_option} instead using the +:OPTION_LOG_LEVEL+ option.
|
@@ -119,30 +183,37 @@ module LIBUSB
|
|
119
183
|
Call.libusb_set_debug(@ctx, level)
|
120
184
|
end
|
121
185
|
|
122
|
-
def
|
123
|
-
|
186
|
+
private def wrap_log_cb(block, mode)
|
187
|
+
if block
|
188
|
+
cb_proc = proc do |p_ctx, lev, str|
|
189
|
+
ctx = case p_ctx
|
190
|
+
when FFI::Pointer::NULL then nil
|
191
|
+
when @ctx then self
|
192
|
+
else p_ctx.to_i
|
193
|
+
end
|
194
|
+
block.call(ctx, lev, str)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Avoid garbage collection of the proc, since only the function pointer is given to libusb
|
199
|
+
if Call::LogCbMode.to_native(mode, nil) & LOG_CB_GLOBAL != 0
|
200
|
+
@@log_cb_proc = cb_proc
|
201
|
+
end
|
202
|
+
if Call::LogCbMode.to_native(mode, nil) & LOG_CB_CONTEXT != 0
|
203
|
+
@log_cb_proc = cb_proc
|
204
|
+
end
|
205
|
+
cb_proc
|
124
206
|
end
|
125
|
-
private :expect_option_args
|
126
207
|
|
127
|
-
# Set a libusb option from the {Call::Options option list}.
|
208
|
+
# Set a context related libusb option from the {Call::Options option list}.
|
128
209
|
#
|
129
210
|
# @param [Symbol, Fixnum] option
|
130
211
|
# @param args Zero or more arguments depending on +option+
|
212
|
+
# @see set_options
|
131
213
|
def set_option(option, *args)
|
132
214
|
if Call.respond_to?(:libusb_set_option)
|
133
215
|
# Available since libusb-1.0.22
|
134
|
-
|
135
|
-
ffi_args = case option
|
136
|
-
when :OPTION_LOG_LEVEL, LIBUSB::OPTION_LOG_LEVEL
|
137
|
-
expect_option_args(1, args.length)
|
138
|
-
[:libusb_log_level, args[0]]
|
139
|
-
when :OPTION_USE_USBDK, LIBUSB::OPTION_USE_USBDK
|
140
|
-
expect_option_args(0, args.length)
|
141
|
-
[]
|
142
|
-
else
|
143
|
-
raise ArgumentError, "unknown option #{option.inspect}"
|
144
|
-
end
|
145
|
-
|
216
|
+
ffi_args = LIBUSB.send(:option_args_to_ffi, option, args, self)
|
146
217
|
res = Call.libusb_set_option(@ctx, option, *ffi_args)
|
147
218
|
LIBUSB.raise_error res, "in libusb_set_option" if res<0
|
148
219
|
|
@@ -154,6 +225,69 @@ module LIBUSB
|
|
154
225
|
end
|
155
226
|
end
|
156
227
|
|
228
|
+
# Convenience function to set context related options in the libusb library.
|
229
|
+
#
|
230
|
+
# Use this function to configure any number of options within the library.
|
231
|
+
# It takes a Hash the same way as given to {Context.initialize}.
|
232
|
+
# See also {Call::Options option list}.
|
233
|
+
#
|
234
|
+
# @param [Hash{Call::Options => Object}] options Option hash
|
235
|
+
# @see set_option
|
236
|
+
def set_options(options={})
|
237
|
+
options.each do |k, v|
|
238
|
+
set_option(k, *Array(v))
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
if Call.respond_to?(:libusb_set_log_cb)
|
243
|
+
# Set log handler.
|
244
|
+
#
|
245
|
+
# libusb will redirect its log messages to the provided method block.
|
246
|
+
# libusb supports redirection of per context and global log messages.
|
247
|
+
# Log messages sent to the context will be sent to the global log handler too.
|
248
|
+
#
|
249
|
+
# If libusb is compiled without message logging or USE_SYSTEM_LOGGING_FACILITY
|
250
|
+
# is defined then global callback function will never be called.
|
251
|
+
# If ENABLE_DEBUG_LOGGING is defined then per context callback function will
|
252
|
+
# never be called.
|
253
|
+
#
|
254
|
+
# To disable the log callback, execute set_log_cb without a block.
|
255
|
+
#
|
256
|
+
# Available since libusb-1.0.23, LIBUSB_API_VERSION >= 0x01000107
|
257
|
+
#
|
258
|
+
# @param [Symbol, Integer] mode mode of callback function operation.
|
259
|
+
# Several modes can be selected for a single callback function, see Call::LogCbMode for a description.
|
260
|
+
#
|
261
|
+
# @yieldparam [Context, nil] context The context which is related to the log message, or +nil+ if it is a global log message.
|
262
|
+
# @yieldparam [Symbol] level The log level, see Call::LogLevels for a description.
|
263
|
+
# @yieldparam [String] str The log message.
|
264
|
+
#
|
265
|
+
# @see Call::LogCbMode
|
266
|
+
#
|
267
|
+
def set_log_cb(mode, &block)
|
268
|
+
cb_proc = wrap_log_cb(block, mode)
|
269
|
+
Call.libusb_set_log_cb(@ctx, cb_proc, mode)
|
270
|
+
self
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
if Call.respond_to?(:libusb_wrap_sys_device)
|
275
|
+
def wrap_sys_device(dev_io)
|
276
|
+
dev_io = dev_io.is_a?(IO) ? dev_io.fileno : dev_io
|
277
|
+
|
278
|
+
ppHandle = FFI::MemoryPointer.new :pointer
|
279
|
+
res = Call.libusb_wrap_sys_device(@ctx, dev_io, ppHandle)
|
280
|
+
LIBUSB.raise_error res, "in libusb_wrap_sys_device" if res!=0
|
281
|
+
handle = DevHandle.new self, ppHandle.read_pointer
|
282
|
+
return handle unless block_given?
|
283
|
+
begin
|
284
|
+
yield handle
|
285
|
+
ensure
|
286
|
+
handle.close
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
157
291
|
def device_list
|
158
292
|
pppDevs = FFI::MemoryPointer.new :pointer
|
159
293
|
size = Call.libusb_get_device_list(@ctx, pppDevs)
|
@@ -327,14 +461,18 @@ module LIBUSB
|
|
327
461
|
# This block will be invoked for every new file descriptor that
|
328
462
|
# libusb uses as an event source.
|
329
463
|
#
|
464
|
+
# To disable the notification callback, execute on_pollfd_added without a block.
|
465
|
+
#
|
330
466
|
# Note that file descriptors may have been added even before you register these
|
331
467
|
# notifiers (e.g. at {Context#initialize} time).
|
332
468
|
#
|
333
469
|
# @yieldparam [Pollfd] pollfd The added file descriptor is yielded to the block
|
334
470
|
def on_pollfd_added &block
|
335
|
-
@on_pollfd_added =
|
336
|
-
|
337
|
-
|
471
|
+
@on_pollfd_added = if block
|
472
|
+
proc do |fd, events, _|
|
473
|
+
pollfd = Pollfd.new fd, events
|
474
|
+
block.call pollfd
|
475
|
+
end
|
338
476
|
end
|
339
477
|
Call.libusb_set_pollfd_notifiers @ctx, @on_pollfd_added, @on_pollfd_removed, nil
|
340
478
|
end
|
@@ -344,6 +482,8 @@ module LIBUSB
|
|
344
482
|
# This block will be invoked for every removed file descriptor that
|
345
483
|
# libusb uses as an event source.
|
346
484
|
#
|
485
|
+
# To disable the notification callback, execute on_pollfd_removed without a block.
|
486
|
+
#
|
347
487
|
# Note that the removal notifier may be called during {Context#exit}
|
348
488
|
# (e.g. when it is closing file descriptors that were opened and added to the poll
|
349
489
|
# set at {Context#initialize} time). If you don't want this, overwrite the notifier
|
@@ -351,9 +491,11 @@ module LIBUSB
|
|
351
491
|
#
|
352
492
|
# @yieldparam [Pollfd] pollfd The removed file descriptor is yielded to the block
|
353
493
|
def on_pollfd_removed &block
|
354
|
-
@on_pollfd_removed =
|
355
|
-
|
356
|
-
|
494
|
+
@on_pollfd_removed = if block
|
495
|
+
proc do |fd, _|
|
496
|
+
pollfd = Pollfd.new fd
|
497
|
+
block.call pollfd
|
498
|
+
end
|
357
499
|
end
|
358
500
|
Call.libusb_set_pollfd_notifiers @ctx, @on_pollfd_added, @on_pollfd_removed, nil
|
359
501
|
end
|
@@ -393,19 +535,18 @@ module LIBUSB
|
|
393
535
|
# @yieldparam [Symbol] event a {Call::HotplugEvents HotplugEvents} symbol
|
394
536
|
# @yieldreturn [Symbol] +:finish+ to deregister the callback, +:repeat+ to receive additional events
|
395
537
|
# @raise [ArgumentError, LIBUSB::Error] in case of failure
|
396
|
-
def on_hotplug_event(
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
|
538
|
+
def on_hotplug_event(events: HOTPLUG_EVENT_DEVICE_ARRIVED | HOTPLUG_EVENT_DEVICE_LEFT,
|
539
|
+
flags: 0,
|
540
|
+
vendor_id: HOTPLUG_MATCH_ANY,
|
541
|
+
product_id: HOTPLUG_MATCH_ANY,
|
542
|
+
dev_class: HOTPLUG_MATCH_ANY,
|
543
|
+
&block)
|
403
544
|
|
404
545
|
handle = HotplugCallback.new self, @ctx, @hotplug_callbacks
|
405
546
|
|
406
547
|
block2 = proc do |ctx, pDevice, event, _user_data|
|
407
548
|
raise "internal error: unexpected context" unless @ctx==ctx
|
408
|
-
dev = Device.new
|
549
|
+
dev = Device.new self, pDevice
|
409
550
|
|
410
551
|
blres = block.call(dev, event)
|
411
552
|
|
@@ -0,0 +1,38 @@
|
|
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
|
+
module ContextReference
|
18
|
+
def register_context(ctx, free_sym)
|
19
|
+
ptr = pointer
|
20
|
+
def ptr.free_struct(id)
|
21
|
+
return unless @ctx
|
22
|
+
Call.send(@free_sym, self)
|
23
|
+
@ctx.unref_context
|
24
|
+
end
|
25
|
+
ptr.instance_variable_set(:@free_sym, free_sym)
|
26
|
+
ptr.instance_variable_set(:@ctx, ctx.ref_context)
|
27
|
+
ObjectSpace.define_finalizer(self, ptr.method(:free_struct))
|
28
|
+
end
|
29
|
+
|
30
|
+
def free
|
31
|
+
ptr = pointer
|
32
|
+
ptr.free_struct nil
|
33
|
+
ptr.instance_variable_set(:@ctx, nil)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private_constant :ContextReference
|
38
|
+
end
|
data/lib/libusb/dependencies.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module LIBUSB
|
2
|
-
LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.
|
2
|
+
LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.27'
|
3
3
|
LIBUSB_SOURCE_URI = "https://github.com/libusb/libusb/releases/download/v#{LIBUSB_VERSION}/libusb-#{LIBUSB_VERSION}.tar.bz2"
|
4
|
-
|
4
|
+
LIBUSB_SOURCE_SHA256 = 'ffaa41d741a8a3bee244ac8e54a72ea05bf2879663c098c82fc5757853441575'
|
5
5
|
|
6
6
|
MINI_PORTILE_VERSION = '~> 2.1'
|
7
7
|
end
|
data/lib/libusb/dev_handle.rb
CHANGED
@@ -372,19 +372,22 @@ module LIBUSB
|
|
372
372
|
# @yieldparam [String, Integer, LIBUSB::Error] result result of the transfer is yielded to the block,
|
373
373
|
# when the asynchronous transfer has finished
|
374
374
|
# @raise [ArgumentError, LIBUSB::Error] in case of failure
|
375
|
-
def bulk_transfer(
|
376
|
-
|
377
|
-
|
375
|
+
def bulk_transfer(timeout: 1000,
|
376
|
+
endpoint:,
|
377
|
+
dataIn: nil,
|
378
|
+
dataOut: nil,
|
379
|
+
allow_device_memory: false,
|
380
|
+
&block)
|
381
|
+
|
378
382
|
endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
|
379
383
|
if endpoint&ENDPOINT_IN != 0
|
380
|
-
dataIn
|
384
|
+
dataIn || raise(ArgumentError, "no :dataIn given for bulk read")
|
381
385
|
else
|
382
|
-
dataOut
|
386
|
+
dataOut || raise(ArgumentError, "no :dataOut given for bulk write")
|
383
387
|
end
|
384
|
-
raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
|
385
388
|
|
386
389
|
# reuse transfer struct to speed up transfer
|
387
|
-
@bulk_transfer ||= BulkTransfer.new dev_handle: self, allow_device_memory:
|
390
|
+
@bulk_transfer ||= BulkTransfer.new dev_handle: self, allow_device_memory: allow_device_memory
|
388
391
|
tr = @bulk_transfer
|
389
392
|
tr.endpoint = endpoint
|
390
393
|
tr.timeout = timeout
|
@@ -440,19 +443,21 @@ module LIBUSB
|
|
440
443
|
# @yieldparam [String, Integer, LIBUSB::Error] result result of the transfer is yielded to the block,
|
441
444
|
# when the asynchronous transfer has finished
|
442
445
|
# @raise [ArgumentError, LIBUSB::Error] in case of failure
|
443
|
-
def interrupt_transfer(
|
444
|
-
|
445
|
-
|
446
|
+
def interrupt_transfer(timeout: 1000,
|
447
|
+
endpoint:,
|
448
|
+
dataIn: nil,
|
449
|
+
dataOut: nil,
|
450
|
+
allow_device_memory: false,
|
451
|
+
&block)
|
446
452
|
endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
|
447
453
|
if endpoint&ENDPOINT_IN != 0
|
448
|
-
dataIn
|
454
|
+
dataIn || raise(ArgumentError, "no :dataIn given for interrupt read")
|
449
455
|
else
|
450
|
-
dataOut
|
456
|
+
dataOut || raise(ArgumentError, "no :dataOut given for interrupt write")
|
451
457
|
end
|
452
|
-
raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
|
453
458
|
|
454
459
|
# reuse transfer struct to speed up transfer
|
455
|
-
@interrupt_transfer ||= InterruptTransfer.new dev_handle: self, allow_device_memory:
|
460
|
+
@interrupt_transfer ||= InterruptTransfer.new dev_handle: self, allow_device_memory: allow_device_memory
|
456
461
|
tr = @interrupt_transfer
|
457
462
|
tr.endpoint = endpoint
|
458
463
|
tr.timeout = timeout
|
@@ -497,22 +502,27 @@ module LIBUSB
|
|
497
502
|
# @yieldparam [String, Integer, LIBUSB::Error] result result of the transfer is yielded to the block,
|
498
503
|
# when the asynchronous transfer has finished
|
499
504
|
# @raise [ArgumentError, LIBUSB::Error] in case of failure
|
500
|
-
def control_transfer(
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
505
|
+
def control_transfer(bmRequestType:,
|
506
|
+
bRequest:,
|
507
|
+
wValue:,
|
508
|
+
wIndex:,
|
509
|
+
timeout: 1000,
|
510
|
+
dataIn: nil,
|
511
|
+
dataOut: nil,
|
512
|
+
allow_device_memory: false,
|
513
|
+
&block)
|
514
|
+
|
506
515
|
if bmRequestType&ENDPOINT_IN != 0
|
507
|
-
|
516
|
+
raise ArgumentError, "invalid param :dataOut" unless dataOut.nil?
|
517
|
+
dataIn ||= 0
|
508
518
|
dataOut = ''
|
509
519
|
else
|
510
|
-
|
520
|
+
raise ArgumentError, "invalid param :dataIn" unless dataIn.nil?
|
521
|
+
dataOut ||= ''
|
511
522
|
end
|
512
|
-
raise ArgumentError, "invalid params #{args.inspect}" unless args.empty?
|
513
523
|
|
514
524
|
# reuse transfer struct to speed up transfer
|
515
|
-
@control_transfer ||= ControlTransfer.new dev_handle: self, allow_device_memory:
|
525
|
+
@control_transfer ||= ControlTransfer.new dev_handle: self, allow_device_memory: allow_device_memory
|
516
526
|
tr = @control_transfer
|
517
527
|
tr.timeout = timeout
|
518
528
|
if dataIn
|
data/lib/libusb/device.rb
CHANGED
@@ -21,24 +21,27 @@ module LIBUSB
|
|
21
21
|
# Devices of the system can be obtained with {Context#devices} .
|
22
22
|
class Device
|
23
23
|
include Comparable
|
24
|
+
include ContextReference
|
24
25
|
|
25
26
|
# @return [Context] the context this device belongs to.
|
26
27
|
attr_reader :context
|
27
28
|
|
28
29
|
def initialize context, pDev
|
29
30
|
@context = context
|
30
|
-
def pDev.unref_device(id)
|
31
|
-
Call.libusb_unref_device(self)
|
32
|
-
end
|
33
|
-
ObjectSpace.define_finalizer(self, pDev.method(:unref_device))
|
34
|
-
Call.libusb_ref_device(pDev)
|
35
31
|
@pDev = pDev
|
32
|
+
register_context(context.instance_variable_get(:@ctx), :libusb_unref_device)
|
33
|
+
Call.libusb_ref_device(pDev)
|
36
34
|
|
37
35
|
@pDevDesc = Call::DeviceDescriptor.new
|
38
36
|
res = Call.libusb_get_device_descriptor(@pDev, @pDevDesc)
|
39
37
|
LIBUSB.raise_error res, "in libusb_get_device_descriptor" if res!=0
|
40
38
|
end
|
41
39
|
|
40
|
+
# The pointer for ContextReference
|
41
|
+
private def pointer
|
42
|
+
@pDev
|
43
|
+
end
|
44
|
+
|
42
45
|
# Open the device and obtain a device handle.
|
43
46
|
#
|
44
47
|
# A handle allows you to perform I/O on the device in question.
|
@@ -160,6 +163,44 @@ module LIBUSB
|
|
160
163
|
res
|
161
164
|
end
|
162
165
|
|
166
|
+
if Call.respond_to?(:libusb_get_max_alt_packet_size)
|
167
|
+
|
168
|
+
# Calculate the maximum packet size which a specific endpoint is capable of
|
169
|
+
# sending or receiving in the duration of 1 microframe
|
170
|
+
#
|
171
|
+
# Only the active configuration is examined. The calculation is based on the
|
172
|
+
# wMaxPacketSize field in the endpoint descriptor as described in section
|
173
|
+
# 9.6.6 in the USB 2.0 specifications.
|
174
|
+
#
|
175
|
+
# If acting on an isochronous or interrupt endpoint, this function will
|
176
|
+
# multiply the value found in bits 0:10 by the number of transactions per
|
177
|
+
# microframe (determined by bits 11:12). Otherwise, this function just
|
178
|
+
# returns the numeric value found in bits 0:10. For USB 3.0 device, it
|
179
|
+
# will attempts to retrieve the Endpoint Companion Descriptor to return
|
180
|
+
# wBytesPerInterval.
|
181
|
+
#
|
182
|
+
# This function is useful for setting up isochronous transfers, for example
|
183
|
+
# you might pass the return value from this function to
|
184
|
+
# +IsochronousTransfer.packet_lengths=+ in order to set the length field of every
|
185
|
+
# isochronous packet in a transfer.
|
186
|
+
#
|
187
|
+
# Available since libusb-1.0.27.
|
188
|
+
#
|
189
|
+
# @param [Interface, Fixnum] interface the interface or its bInterfaceNumber of the interface the endpoint belongs to
|
190
|
+
# @param [Setting, Fixnum] alternate_setting the alternate setting or its bAlternateSetting
|
191
|
+
# @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
|
192
|
+
# @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
|
193
|
+
# @see max_iso_packet_size
|
194
|
+
def max_alt_packet_size(interface, alternate_setting, endpoint)
|
195
|
+
interface = interface.bInterfaceNumber if interface.respond_to? :bInterfaceNumber
|
196
|
+
alternate_setting = alternate_setting.bAlternateSetting if alternate_setting.respond_to? :bAlternateSetting
|
197
|
+
endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
|
198
|
+
res = Call.libusb_get_max_alt_packet_size(@pDev, interface, alternate_setting, endpoint)
|
199
|
+
LIBUSB.raise_error res, "in libusb_get_max_alt_packet_size" unless res>=0
|
200
|
+
res
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
163
204
|
# Calculate the maximum packet size which a specific endpoint is capable is
|
164
205
|
# sending or receiving in the duration of 1 microframe.
|
165
206
|
#
|
@@ -179,6 +220,7 @@ module LIBUSB
|
|
179
220
|
#
|
180
221
|
# @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
|
181
222
|
# @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
|
223
|
+
# @see max_alt_packet_size
|
182
224
|
def max_iso_packet_size(endpoint)
|
183
225
|
endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
|
184
226
|
res = Call.libusb_get_max_iso_packet_size(@pDev, endpoint)
|
@@ -310,7 +352,7 @@ module LIBUSB
|
|
310
352
|
def manufacturer
|
311
353
|
return @manufacturer if defined? @manufacturer
|
312
354
|
@manufacturer = try_string_descriptor_ascii(self.iManufacturer)
|
313
|
-
@manufacturer.strip
|
355
|
+
@manufacturer = @manufacturer.strip if @manufacturer
|
314
356
|
@manufacturer
|
315
357
|
end
|
316
358
|
|
@@ -319,7 +361,7 @@ module LIBUSB
|
|
319
361
|
def product
|
320
362
|
return @product if defined? @product
|
321
363
|
@product = try_string_descriptor_ascii(self.iProduct)
|
322
|
-
@product.strip
|
364
|
+
@product = @product.strip if @product
|
323
365
|
@product
|
324
366
|
end
|
325
367
|
|
@@ -328,7 +370,7 @@ module LIBUSB
|
|
328
370
|
def serial_number
|
329
371
|
return @serial_number if defined? @serial_number
|
330
372
|
@serial_number = try_string_descriptor_ascii(self.iSerialNumber)
|
331
|
-
@serial_number.strip
|
373
|
+
@serial_number = @serial_number.strip if @serial_number
|
332
374
|
@serial_number
|
333
375
|
end
|
334
376
|
|
data/lib/libusb/endpoint.rb
CHANGED
@@ -181,13 +181,14 @@ module LIBUSB
|
|
181
181
|
# @return [SsCompanion]
|
182
182
|
def ss_companion
|
183
183
|
ep_comp = FFI::MemoryPointer.new :pointer
|
184
|
+
ctx = device.context.instance_variable_get(:@ctx)
|
184
185
|
res = Call.libusb_get_ss_endpoint_companion_descriptor(
|
185
|
-
|
186
|
+
ctx,
|
186
187
|
pointer,
|
187
188
|
ep_comp
|
188
189
|
)
|
189
190
|
LIBUSB.raise_error res, "in libusb_get_ss_endpoint_companion_descriptor" if res!=0
|
190
|
-
SsCompanion.new ep_comp.read_pointer
|
191
|
+
SsCompanion.new ctx, ep_comp.read_pointer
|
191
192
|
end
|
192
193
|
end
|
193
194
|
end
|
data/lib/libusb/eventmachine.rb
CHANGED
@@ -62,6 +62,10 @@ class Context
|
|
62
62
|
@eventmachine_attached_fds.each do |fd, watcher|
|
63
63
|
watcher.detach
|
64
64
|
end
|
65
|
+
|
66
|
+
# Deregister callbacks
|
67
|
+
on_pollfd_added
|
68
|
+
on_pollfd_removed
|
65
69
|
end
|
66
70
|
|
67
71
|
class EMPollfdHandler < EventMachine::Connection
|
@@ -118,7 +122,7 @@ class DevHandle
|
|
118
122
|
include EM::Deferrable
|
119
123
|
|
120
124
|
def initialize(opts, dev_handle, transfer_method)
|
121
|
-
dev_handle.send(transfer_method, opts) do |res|
|
125
|
+
dev_handle.send(transfer_method, **opts) do |res|
|
122
126
|
EM.next_tick do
|
123
127
|
if res.kind_of?(LIBUSB::Error)
|
124
128
|
fail res
|
@@ -134,7 +138,7 @@ class DevHandle
|
|
134
138
|
#
|
135
139
|
# @see Context#eventmachine_register
|
136
140
|
# DevHandle#interrupt_transfer
|
137
|
-
def eventmachine_interrupt_transfer(opts
|
141
|
+
def eventmachine_interrupt_transfer(**opts)
|
138
142
|
eventmachine_transfer(opts, :interrupt_transfer)
|
139
143
|
end
|
140
144
|
|
@@ -151,7 +155,7 @@ class DevHandle
|
|
151
155
|
#
|
152
156
|
# @see Context#eventmachine_register
|
153
157
|
# DevHandle#bulk_transfer
|
154
|
-
def eventmachine_bulk_transfer(opts
|
158
|
+
def eventmachine_bulk_transfer(**opts)
|
155
159
|
eventmachine_transfer(opts, :bulk_transfer)
|
156
160
|
end
|
157
161
|
|
@@ -171,7 +175,7 @@ class DevHandle
|
|
171
175
|
#
|
172
176
|
# @see Context#eventmachine_register
|
173
177
|
# DevHandle#control_transfer
|
174
|
-
def eventmachine_control_transfer(opts
|
178
|
+
def eventmachine_control_transfer(**opts)
|
175
179
|
eventmachine_transfer(opts, :control_transfer)
|
176
180
|
end
|
177
181
|
|
data/lib/libusb/gem_helper.rb
CHANGED
@@ -66,7 +66,7 @@ module LIBUSB
|
|
66
66
|
yield if block_given?
|
67
67
|
rescue
|
68
68
|
Bundler.ui.error "Untagging #{version_tag} due to error."
|
69
|
-
|
69
|
+
sh_with_status %W[git tag -d #{version_tag}]
|
70
70
|
raise
|
71
71
|
end
|
72
72
|
|
@@ -87,9 +87,9 @@ module LIBUSB
|
|
87
87
|
|
88
88
|
self.ruby_platform = ruby_platform
|
89
89
|
self.recipe = LIBUSB::LibusbRecipe.new
|
90
|
-
recipe.host =
|
91
|
-
recipe.configure_options << "--host=#{
|
92
|
-
recipe.configure_options << "CC=#{
|
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
93
|
self.libusb_dll = Pathname.new(recipe.path) + libusb_dllname
|
94
94
|
|
95
95
|
file libusb_dll do
|
@@ -98,8 +98,11 @@ module LIBUSB
|
|
98
98
|
|
99
99
|
task "libusb_dll:#{ruby_platform}" => libusb_dll
|
100
100
|
|
101
|
-
desc 'Cross compile libusb for
|
102
|
-
task :cross =>
|
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|
|
103
106
|
spec = Gem::Specification::load("libusb.gemspec").dup
|
104
107
|
spec.platform = Gem::Platform.new(ruby_platform)
|
105
108
|
spec.extensions = []
|
data/lib/libusb/libusb_recipe.rb
CHANGED
@@ -11,7 +11,8 @@ module LIBUSB
|
|
11
11
|
def initialize
|
12
12
|
super("libusb", LIBUSB_VERSION)
|
13
13
|
self.target = File.join(ROOT, "ports")
|
14
|
-
self.files = [url: LIBUSB_SOURCE_URI,
|
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
|
15
16
|
self.configure_options = []
|
16
17
|
end
|
17
18
|
|
@@ -24,7 +25,5 @@ module LIBUSB
|
|
24
25
|
self.activate
|
25
26
|
self
|
26
27
|
end
|
27
|
-
|
28
|
-
public :files_hashs
|
29
28
|
end
|
30
29
|
end
|