libusb 0.6.4-x86-mingw32 → 0.7.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/lib/libusb/call.rb CHANGED
@@ -228,14 +228,23 @@ module LIBUSB
228
228
  #
229
229
  # @see Bos::DeviceCapability
230
230
  BosTypes = enum :libusb_bos_type, [
231
- # Wireless USB device capability
232
- :BT_WIRELESS_USB_DEVICE_CAPABILITY, 1,
233
- # USB 2.0 extensions
234
- :BT_USB_2_0_EXTENSION, 2,
235
- # SuperSpeed USB device capability
236
- :BT_SS_USB_DEVICE_CAPABILITY, 3,
237
- # Container ID type
238
- :BT_CONTAINER_ID, 4,
231
+ :BT_WIRELESS_USB_DEVICE_CAPABILITY, 0x01, # Wireless USB device capability
232
+ :BT_USB_2_0_EXTENSION, 0x02, # USB 2.0 extensions
233
+ :BT_SS_USB_DEVICE_CAPABILITY, 0x03, # SuperSpeed USB device capability
234
+ :BT_CONTAINER_ID, 0x04, # Container ID type
235
+ :BT_PLATFORM_DESCRIPTOR, 0x05, # Platform descriptor
236
+ :BT_POWER_DELIVERY_CAPABILITY, 0x06, # Defines the various PD Capabilities of this device
237
+ :BT_BATTERY_INFO_CAPABILITY, 0x07, # Provides information on each battery supported by the device
238
+ :BT_PD_CONSUMER_PORT_CAPABILITY, 0x08, # The consumer characteristics of a port on the device
239
+ :BT_PD_PROVIDER_PORT_CAPABILITY, 0x09, # The provider characteristics of a port on the device
240
+ :BT_SUPERSPEED_PLUS, 0x0A, # Defines the set of SuperSpeed Plus USB specific device level capabilities
241
+ :BT_PRECISION_TIME_MEASUREMENT, 0x0B, # Precision Time Measurement (PTM) Capability Descriptor
242
+ :BT_Wireless_USB_Ext, 0x0C, # Defines the set of Wireless USB 1.1-specific device level capabilities
243
+ :BT_BILLBOARD, 0x0D, # Billboard capability
244
+ :BT_AUTHENTICATION, 0x0E, # Authentication Capability Descriptor
245
+ :BT_BILLBOARD_EX, 0x0F, # Billboard Ex capability
246
+ :BT_CONFIGURATION_SUMMARY, 0x10, # Summarizes configuration information for a function implemented by the device
247
+ :BT_FWStatus_Capability, 0x11, # Describes the capability to support FWStatus
239
248
  ]
240
249
 
241
250
  # Since libusb version 1.0.16.
@@ -274,6 +283,25 @@ module LIBUSB
274
283
  :LOG_LEVEL_DEBUG, 4,
275
284
  ]
276
285
 
286
+ # /** \ingroup libusb_lib
287
+ # * Log callback mode.
288
+ # *
289
+ # * Since version 1.0.23, \ref LIBUSB_API_VERSION >= 0x01000107
290
+ # *
291
+ # * \see libusb_set_log_cb()
292
+ # */
293
+ # enum libusb_log_cb_mode {
294
+ # /** Callback function handling all log messages. */
295
+ # LIBUSB_LOG_CB_GLOBAL = (1 << 0),
296
+ #
297
+ # /** Callback function handling context related log messages. */
298
+ # LIBUSB_LOG_CB_CONTEXT = (1 << 1)
299
+ # };
300
+ LogCbMode = enum :libusb_log_cb_mode, [
301
+ :LOG_CB_GLOBAL, (1 << 0),
302
+ :LOG_CB_CONTEXT, (1 << 1),
303
+ ]
304
+
277
305
  # Available option values for {Context#set_option}.
278
306
  Options = enum :libusb_option, [
279
307
  # Set the log message verbosity.
@@ -296,7 +324,7 @@ module LIBUSB
296
324
  #
297
325
  # If libusb was compiled with verbose debug message logging, this function
298
326
  # does nothing: you'll always get messages from all levels.
299
- :OPTION_LOG_LEVEL,
327
+ :OPTION_LOG_LEVEL, 0,
300
328
 
301
329
  # Use the UsbDk backend for a specific context, if available.
302
330
  #
@@ -306,7 +334,33 @@ module LIBUSB
306
334
  # Only valid on Windows.
307
335
  #
308
336
  # Available since libusb-1.0.22.
309
- :OPTION_USE_USBDK,
337
+ :OPTION_USE_USBDK, 1,
338
+
339
+ # Do not scan for devices
340
+ #
341
+ # With this option set, libusb will skip scanning devices in
342
+ # libusb_init_context().
343
+ #
344
+ # Hotplug functionality will also be deactivated.
345
+ #
346
+ # The option is useful in combination with libusb_wrap_sys_device(),
347
+ # which can access a device directly without prior device scanning.
348
+ #
349
+ # This is typically needed on Android, where access to USB devices
350
+ # is limited.
351
+ #
352
+ # Only valid on Linux. Ignored on all other platforms.
353
+ :OPTION_NO_DEVICE_DISCOVERY, 2,
354
+
355
+ # Set the context log callback functon.
356
+ #
357
+ # Set the log callback function either on a context or globally.
358
+ # This option must be provided a Proc argument or +nil+ to remove the callback.
359
+ # Using this option with a +nil+ context is equivalent to calling libusb_set_log_cb with mode :LOG_CB_GLOBAL.
360
+ # Using it with a non- +nil+ context is equivalent to calling libusb_set_log_cb with mode :LOG_CB_CONTEXT.
361
+ :OPTION_LOG_CB, 3,
362
+
363
+ :OPTION_MAX, 4,
310
364
  ]
311
365
 
312
366
  typedef :pointer, :libusb_context
@@ -315,15 +369,60 @@ module LIBUSB
315
369
  typedef :pointer, :libusb_transfer
316
370
  typedef :int, :libusb_hotplug_callback_handle
317
371
 
318
- def self.try_attach_function(method, *args)
319
- if ffi_libraries.find{|lib| lib.find_function(method) }
320
- attach_function method, *args
372
+ # /** \ingroup libusb_lib
373
+ # * Callback function for handling log messages.
374
+ # * \param ctx the context which is related to the log message, or +nil+ if it
375
+ # * is a global log message
376
+ # * \param level the log level, see \ref libusb_log_level for a description
377
+ # * \param str the log message
378
+ # *
379
+ # * Since version 1.0.23, \ref LIBUSB_API_VERSION >= 0x01000107
380
+ # *
381
+ # * \see libusb_set_log_cb()
382
+ # */
383
+ # typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx,
384
+ # enum libusb_log_level level, const char *str);
385
+ callback :libusb_log_cb, [:libusb_context, :libusb_log_level, :string], :void
386
+
387
+ # @private
388
+ # /** \ingroup libusb_lib
389
+ # * Structure used for setting options through \ref libusb_init_context.
390
+ # *
391
+ # */
392
+ # struct libusb_init_option {
393
+ # /** Which option to set */
394
+ # enum libusb_option option;
395
+ # /** An integer value used by the option (if applicable). */
396
+ # union {
397
+ # int64_t ival;
398
+ # libusb_log_cb log_cbval;
399
+ # } value;
400
+ # };
401
+ class InitOptionValue < FFI::Union
402
+ layout :ival, :int64_t,
403
+ :log_cbval, :libusb_log_cb
404
+ end
405
+ class InitOption < FFI::Struct
406
+ layout :option, :libusb_option,
407
+ :value, InitOptionValue
408
+ end
409
+
410
+ class << self
411
+ private def try_attach_function(method, *args, **kwargs)
412
+ if ffi_libraries.find{|lib| lib.find_function(method) }
413
+ attach_function method, *args, **kwargs
414
+ end
321
415
  end
322
416
  end
323
417
 
324
418
  try_attach_function 'libusb_get_version', [], :pointer
325
419
 
326
420
  attach_function 'libusb_init', [ :pointer ], :int
421
+ # int LIBUSB_CALL libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options);
422
+ try_attach_function 'libusb_init_context', [:pointer, :pointer, :int], :int
423
+ # may be deprecated in the future in favor of libusb_init_context()+libusb_set_option()
424
+ # void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode);
425
+ try_attach_function 'libusb_set_log_cb', [:libusb_context, :libusb_log_cb, :int], :void
327
426
  attach_function 'libusb_exit', [ :pointer ], :void
328
427
  attach_function 'libusb_set_debug', [:pointer, :libusb_log_level], :void
329
428
  try_attach_function 'libusb_set_option', [:libusb_context, :libusb_option, :varargs], :int
@@ -348,6 +447,8 @@ module LIBUSB
348
447
  try_attach_function 'libusb_get_device_speed', [:pointer], :libusb_speed
349
448
  attach_function 'libusb_get_max_packet_size', [:pointer, :uint8], :int
350
449
  attach_function 'libusb_get_max_iso_packet_size', [:pointer, :uint8], :int
450
+ # int API_EXPORTED libusb_get_max_alt_packet_size(libusb_device *dev, int interface_number, int alternate_setting, unsigned char endpoint)
451
+ try_attach_function 'libusb_get_max_alt_packet_size', [:pointer, :int, :int, :uchar], :int
351
452
 
352
453
  try_attach_function 'libusb_get_ss_endpoint_companion_descriptor', [:pointer, :pointer, :pointer], :int
353
454
  try_attach_function 'libusb_free_ss_endpoint_companion_descriptor', [:pointer], :void
@@ -360,7 +461,11 @@ module LIBUSB
360
461
  try_attach_function 'libusb_free_ss_usb_device_capability_descriptor', [:pointer], :void
361
462
  try_attach_function 'libusb_get_container_id_descriptor', [:libusb_context, :pointer, :pointer], :int
362
463
  try_attach_function 'libusb_free_container_id_descriptor', [:pointer], :void
464
+ try_attach_function 'libusb_get_platform_descriptor', [:libusb_context, :pointer, :pointer], :int
465
+ try_attach_function 'libusb_free_platform_descriptor', [:pointer], :void
363
466
 
467
+ # int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle);
468
+ try_attach_function 'libusb_wrap_sys_device', [:libusb_context, :intptr_t, :pointer], :int
364
469
  attach_function 'libusb_open', [:pointer, :pointer], :int
365
470
  attach_function 'libusb_close', [:pointer], :void
366
471
  attach_function 'libusb_get_device', [:libusb_device_handle], :pointer
@@ -431,7 +536,7 @@ module LIBUSB
431
536
  :wLength, :uint16
432
537
  end
433
538
 
434
- class Transfer < FFI::ManagedStruct
539
+ class Transfer < FFI::Struct
435
540
  layout :dev_handle, :libusb_device_handle,
436
541
  :flags, :uint8,
437
542
  :endpoint, :uchar,
@@ -445,8 +550,19 @@ module LIBUSB
445
550
  :buffer, :pointer,
446
551
  :num_iso_packets, :int
447
552
 
448
- def self.release(ptr)
449
- Call.libusb_free_transfer(ptr)
553
+ def initialize(*)
554
+ super
555
+
556
+ ptr = pointer
557
+ def ptr.free_struct(id)
558
+ Call.libusb_free_transfer(self)
559
+ return unless @ctx
560
+ @ctx.unref_context
561
+ end
562
+ # The ctx pointer is not yet assigned.
563
+ # It happens at LIBUSB::Transfer#dev_handle= later on.
564
+ ptr.instance_variable_set(:@ctx, nil)
565
+ ObjectSpace.define_finalizer(self, ptr.method(:free_struct))
450
566
  end
451
567
  end
452
568
 
@@ -16,8 +16,9 @@
16
16
  require 'libusb/call'
17
17
 
18
18
  module LIBUSB
19
- class Configuration < FFI::ManagedStruct
19
+ class Configuration < FFI::Struct
20
20
  include Comparable
21
+ include ContextReference
21
22
 
22
23
  layout :bLength, :uint8,
23
24
  :bDescriptorType, :uint8,
@@ -108,10 +109,8 @@ module LIBUSB
108
109
  def initialize(device, *args)
109
110
  @device = device
110
111
  super(*args)
111
- end
112
112
 
113
- def self.release(ptr)
114
- Call.libusb_free_config_descriptor(ptr)
113
+ register_context(device.context.instance_variable_get(:@ctx), :libusb_free_config_descriptor)
115
114
  end
116
115
 
117
116
  # @return [Device] the device this configuration belongs to.
@@ -34,6 +34,7 @@ module LIBUSB
34
34
  Call::HotplugEvents,
35
35
  Call::HotplugFlags,
36
36
  Call::LogLevels,
37
+ Call::LogCbMode,
37
38
  Call::Options,
38
39
  ].each do |enum|
39
40
  enum.to_h.each{|k,v| const_set(k,v) }
@@ -52,6 +53,9 @@ module LIBUSB
52
53
  end
53
54
  end
54
55
 
56
+ class RemainingReferencesError < Error
57
+ end
58
+
55
59
  # @private
56
60
  ErrorClassForResult = {}
57
61
 
@@ -95,23 +95,87 @@ module LIBUSB
95
95
  end
96
96
  end
97
97
 
98
-
99
98
  # Initialize libusb context.
100
- def initialize
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
- res = Call.libusb_init(m)
103
- LIBUSB.raise_error res, "in libusb_init" if res!=0
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
- Call.libusb_exit(@ctx)
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 expect_option_args(exp, is)
123
- raise ArgumentError, "wrong number of arguments (given #{is+1}, expected #{exp+1})" if is != exp
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 = proc do |fd, events, _|
336
- pollfd = Pollfd.new fd, events
337
- block.call pollfd
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 = proc do |fd, _|
355
- pollfd = Pollfd.new fd
356
- block.call pollfd
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(args={}, &block)
397
- events = args.delete(:events) || (HOTPLUG_EVENT_DEVICE_ARRIVED | HOTPLUG_EVENT_DEVICE_LEFT)
398
- flags = args.delete(:flags) || 0
399
- vendor_id = args.delete(:vendor_id) || HOTPLUG_MATCH_ANY
400
- product_id = args.delete(:product_id) || HOTPLUG_MATCH_ANY
401
- dev_class = args.delete(:dev_class) || HOTPLUG_MATCH_ANY
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 @ctx, pDevice
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
@@ -1,7 +1,7 @@
1
1
  module LIBUSB
2
- LIBUSB_VERSION = ENV['LIBUSB_VERSION'] || '1.0.22'
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
- LIBUSB_SOURCE_SHA1 = '10116aa265aac4273a0c894faa089370262ec0dc'
4
+ LIBUSB_SOURCE_SHA256 = 'ffaa41d741a8a3bee244ac8e54a72ea05bf2879663c098c82fc5757853441575'
5
5
 
6
6
  MINI_PORTILE_VERSION = '~> 2.1'
7
7
  end