Class: LIBUSB::Context
- Inherits:
-
Object
- Object
- LIBUSB::Context
- Defined in:
- lib/libusb/context.rb,
lib/libusb/eventmachine.rb
Overview
Class representing a libusb session.
Defined Under Namespace
Classes: CompletionFlag, EMPollfdHandler, Pollfd
Instance Method Summary (collapse)
-
- (Object) debug=(level)
Set message verbosity.
-
- (Array<LIBUSB::Device>) devices(filter_hash = {})
Obtain a list of devices currently attached to the USB system, optionally matching certain criteria.
-
- (Object) eventmachine_register
Register libusb's file descriptors and timeouts to EventMachine.
- - (Object) eventmachine_unregister
-
- (Object) exit
Deinitialize libusb.
-
- (Object) handle_events(timeout = nil, completion_flag = nil)
Handle any pending events in blocking mode.
-
- (Context) initialize
constructor
Initialize libusb context.
-
- (Float?) next_timeout
Determine the next internal timeout that libusb needs to handle.
-
- (Object) on_pollfd_added {|pollfd| ... }
Register a notification block for file descriptor additions.
-
- (Object) on_pollfd_removed {|pollfd| ... }
Register a notification block for file descriptor removals.
-
- (Array<Pollfd>) pollfds
Retrieve a list of file descriptors that should be polled by your main loop as libusb event sources.
Constructor Details
- (Context) initialize
Initialize libusb context.
72 73 74 75 76 77 78 79 |
# File 'lib/libusb/context.rb', line 72 def initialize m = FFI::MemoryPointer.new :pointer res = Call.libusb_init(m) LIBUSB.raise_error res, "in libusb_init" if res!=0 @ctx = m.read_pointer @on_pollfd_added = nil @on_pollfd_removed = nil end |
Instance Method Details
- (Object) debug=(level)
Set message verbosity.
-
Level 0: no messages ever printed by the library (default)
-
Level 1: error messages are printed to stderr
-
Level 2: warning and error messages are printed to stderr
-
Level 3: informational messages are printed to stdout, warning and error messages are printed to stderr
The default level is 0, which means no messages are ever printed. If you choose to increase the message verbosity level, ensure that your application does not close the stdout/stderr file descriptors.
You are advised to set level 3. libusb is conservative with its message logging and most of the time, will only log messages that explain error conditions and other oddities. This will help you debug your software.
If the LIBUSB_DEBUG environment variable was set when libusb was initialized, this method does nothing: the message verbosity is fixed to the value in the environment variable.
If libusb was compiled without any message logging, this method does nothing: you'll never get any messages.
If libusb was compiled with verbose debug message logging, this method does nothing: you'll always get messages from all levels.
115 116 117 |
# File 'lib/libusb/context.rb', line 115 def debug=(level) Call.libusb_set_debug(@ctx, level) end |
- (Array<LIBUSB::Device>) devices(filter_hash = {})
Obtain a list of devices currently attached to the USB system, optionally matching certain criteria.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/libusb/context.rb', line 195 def devices(filter_hash={}) device_list.select do |dev| ( !filter_hash[:bClass] || (dev.bDeviceClass==CLASS_PER_INTERFACE ? dev.settings.map(&:bInterfaceClass).&([filter_hash[:bClass]].flatten).any? : [filter_hash[:bClass]].flatten.include?(dev.bDeviceClass))) && ( !filter_hash[:bSubClass] || (dev.bDeviceClass==CLASS_PER_INTERFACE ? dev.settings.map(&:bInterfaceSubClass).&([filter_hash[:bSubClass]].flatten).any? : [filter_hash[:bSubClass]].flatten.include?(dev.bDeviceSubClass))) && ( !filter_hash[:bProtocol] || (dev.bDeviceClass==CLASS_PER_INTERFACE ? dev.settings.map(&:bInterfaceProtocol).&([filter_hash[:bProtocol]].flatten).any? : [filter_hash[:bProtocol]].flatten.include?(dev.bDeviceProtocol))) && ( !filter_hash[:bMaxPacketSize0] || [filter_hash[:bMaxPacketSize0]].flatten.include?(dev.bMaxPacketSize0) ) && ( !filter_hash[:idVendor] || [filter_hash[:idVendor]].flatten.include?(dev.idVendor) ) && ( !filter_hash[:idProduct] || [filter_hash[:idProduct]].flatten.include?(dev.idProduct) ) && ( !filter_hash[:bcdUSB] || [filter_hash[:bcdUSB]].flatten.include?(dev.bcdUSB) ) && ( !filter_hash[:bcdDevice] || [filter_hash[:bcdDevice]].flatten.include?(dev.bcdDevice) ) end end |
- (Object) eventmachine_register
Register libusb's file descriptors and timeouts to EventMachine.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/libusb/eventmachine.rb', line 34 def eventmachine_register @eventmachine_attached_fds = {} @eventmachine_timer = nil pollfds = self.pollfds if pollfds pollfds.each do |pollfd| eventmachine_add_pollfd(pollfd) end self.on_pollfd_added do |pollfd| eventmachine_add_pollfd(pollfd) end self.on_pollfd_removed do |pollfd| eventmachine_rm_pollfd(pollfd) end else # Libusb pollfd API is not available on this platform. # Use simple polling timer, instead: EventMachine.add_periodic_timer(0.01) do @eventmachine_timer = self.handle_events 0 end end end |
- (Object) eventmachine_unregister
60 61 62 63 64 65 |
# File 'lib/libusb/eventmachine.rb', line 60 def eventmachine_unregister @eventmachine_timer.cancel if @eventmachine_timer @eventmachine_attached_fds.each do |fd, watcher| watcher.detach end end |
- (Object) exit
Deinitialize libusb.
Should be called after closing all open devices and before your application terminates.
84 85 86 |
# File 'lib/libusb/context.rb', line 84 def exit Call.libusb_exit(@ctx) end |
- (Object) handle_events(timeout = nil, completion_flag = nil)
Handle any pending events in blocking mode.
This method must be called when libusb is running asynchronous transfers. This gives libusb the opportunity to reap pending transfers, invoke callbacks, etc.
If a zero timeout is passed, this function will handle any already-pending events and then immediately return in non-blocking style.
If a non-zero timeout is passed and no events are currently pending, this method will block waiting for events to handle up until the specified timeout. If an event arrives or a signal is raised, this method will return early.
If the parameter completion_flag is used, then after obtaining the event handling lock this function will return immediately if the flag is set to completed. This allows for race free waiting for the completion of a specific transfer. See source of Transfer#submit_and_wait for a use case of completion_flag.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/libusb/context.rb', line 155 def handle_events(timeout=nil, completion_flag=nil) if completion_flag && !completion_flag.is_a?(Context::CompletionFlag) raise ArgumentError, "completion_flag is not a CompletionFlag" end if timeout timeval = Call::Timeval.new timeval.in_ms = timeout res = if Call.respond_to?(:libusb_handle_events_timeout_completed) Call.libusb_handle_events_timeout_completed(@ctx, timeval, completion_flag) else Call.libusb_handle_events_timeout(@ctx, timeval) end else res = if Call.respond_to?(:libusb_handle_events_completed) Call.libusb_handle_events_completed(@ctx, completion_flag ) else Call.libusb_handle_events(@ctx) end end LIBUSB.raise_error res, "in libusb_handle_events" if res<0 end |
- (Float?) next_timeout
Determine the next internal timeout that libusb needs to handle.
You only need to use this function if you are calling poll() or select() or similar on libusb's file descriptors yourself - you do not need to use it if you are calling #handle_events directly.
You should call this function in your main loop in order to determine how long to wait for select() or poll() to return results. libusb needs to be called into at this timeout, so you should use it as an upper bound on your select() or poll() call.
When the timeout has expired, call into #handle_events (perhaps in non-blocking mode) so that libusb can handle the timeout.
This function may return zero. If this is the case, it indicates that libusb has a timeout that has already expired so you should call #handle_events immediately. A return code of nil indicates that there are no pending timeouts.
On some platforms, this function will always returns nil (no pending timeouts). See libusb's notes on time-based events.
262 263 264 265 266 267 |
# File 'lib/libusb/context.rb', line 262 def next_timeout timeval = Call::Timeval.new res = Call.libusb_get_next_timeout @ctx, timeval LIBUSB.raise_error res, "in libusb_get_next_timeout" if res<0 res == 1 ? timeval.in_s : nil end |
- (Object) on_pollfd_added {|pollfd| ... }
Register a notification block for file descriptor additions.
This block will be invoked for every new file descriptor that libusb uses as an event source.
Note that file descriptors may have been added even before you register these notifiers (e.g. at #initialize time).
278 279 280 281 282 283 284 |
# File 'lib/libusb/context.rb', line 278 def on_pollfd_added &block @on_pollfd_added = proc do |fd, events, _| pollfd = Pollfd.new fd, events block.call pollfd end Call.libusb_set_pollfd_notifiers @ctx, @on_pollfd_added, @on_pollfd_removed, nil end |
- (Object) on_pollfd_removed {|pollfd| ... }
Register a notification block for file descriptor removals.
This block will be invoked for every removed file descriptor that libusb uses as an event source.
Note that the removal notifier may be called during #exit (e.g. when it is closing file descriptors that were opened and added to the poll set at #initialize time). If you don't want this, overwrite the notifier immediately before calling #exit.
297 298 299 300 301 302 303 |
# File 'lib/libusb/context.rb', line 297 def on_pollfd_removed &block @on_pollfd_removed = proc do |fd, _| pollfd = Pollfd.new fd block.call pollfd end Call.libusb_set_pollfd_notifiers @ctx, @on_pollfd_added, @on_pollfd_removed, nil end |
- (Array<Pollfd>) pollfds
Retrieve a list of file descriptors that should be polled by your main loop as libusb event sources.
As file descriptors are a Unix-specific concept, this function is not available on Windows and will always return nil.
224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/libusb/context.rb', line 224 def pollfds ppPollfds = Call.libusb_get_pollfds(@ctx) return nil if ppPollfds.null? offs = 0 pollfds = [] while !(pPollfd=ppPollfds.get_pointer(offs)).null? pollfd = Call::Pollfd.new pPollfd pollfds << Pollfd.new(pollfd[:fd], pollfd[:events]) offs += FFI.type_size :pointer end # ppPollfds has to be released by free() -> give the GC this job ppPollfds.autorelease = true pollfds end |