class HIDAPI::Engine
A wrapper around the USB context that makes it easy to locate HID devices.
Constants
- HID_CLASS
Contains the class code for HID devices from LIBUSB.
Public Class Methods
new()
click to toggle source
Creates a new engine.
# File lib/hidapi/engine.rb, line 14 def initialize @context = LIBUSB::Context.new end
Public Instance Methods
enumerate(vendor_id = 0, product_id = 0, options = {})
click to toggle source
Enumerates the HID devices matching the vendor and product IDs.
Both vendor_id and product_id are optional. They will act as a wild card if set to 0 (the default).
# File lib/hidapi/engine.rb, line 23 def enumerate(vendor_id = 0, product_id = 0, options = {}) raise HIDAPI::HidApiError, 'not initialized' unless @context if vendor_id.is_a?(Hash) || (vendor_id.is_a?(String) && options.empty?) options = vendor_id vendor_id = 0 product_id = 0 end if product_id.is_a?(Hash) || (product_id.is_a?(String) && options.empty?) options = product_id product_id = 0 end if options.is_a?(String) || options.is_a?(Symbol) options = { as: options } end unless options.nil? || options.is_a?(Hash) raise ArgumentError, 'options hash is invalid' end klass = (options || {}).delete(:as) || 'HIDAPI::Device' klass = Object.const_get(klass) unless klass == :no_mapping filters = { bClass: HID_CLASS } unless vendor_id.nil? || vendor_id.to_i == 0 filters[:idVendor] = vendor_id.to_i end unless product_id.nil? || product_id.to_i == 0 filters[:idProduct] = product_id.to_i end list = @context.devices(filters) if klass != :no_mapping list.to_a.map{ |dev| klass.new(dev) } else list.to_a end end
get_device(vendor_id, product_id, serial_number = nil, options = {})
click to toggle source
Gets the first device with the specified vendor_id, product_id, and optionally serial_number.
# File lib/hidapi/engine.rb, line 68 def get_device(vendor_id, product_id, serial_number = nil, options = {}) raise ArgumentError, 'vendor_id must be provided' if vendor_id.to_i == 0 raise ArgumentError, 'product_id must be provided' if product_id.to_i == 0 if serial_number.is_a?(Hash) options = serial_number serial_number = nil end klass = (options || {}).delete(:as) || 'HIDAPI::Device' klass = Object.const_get(klass) unless klass == :no_mapping list = enumerate(vendor_id, product_id, as: :no_mapping) return nil unless list && list.count > 0 if serial_number.to_s == '' if klass != :no_mapping return klass.new(list.first) else return list.first end end list.each do |dev| if dev.serial_number == serial_number if klass != :no_mapping return klass.new(dev) else return dev end end end nil end
get_device_by_path(path, options = {})
click to toggle source
Gets the device with the specified path.
# File lib/hidapi/engine.rb, line 110 def get_device_by_path(path, options = {}) # Our linux setup routine creates convenient /dev/hidapi/* links. # If the user wants to open one of those, we can simple parse the link to generate # the path that the library expects. if File.exist?(path) hidapi_regex = /^\/dev\/hidapi\// usb_bus_regex = /^\/dev\/bus\/usb\/(?<BUS>\d+)\/(?<ADDR>\d+)$/ if hidapi_regex.match(path) path = File.expand_path(File.readlink(path), File.dirname(path)) elsif !usb_bus_regex.match(path) raise HIDAPI::DevicePathInvalid, 'Cannot open file paths other than /dev/hidapi/XXX or /dev/bus/usb/XXX/XXX paths.' end # path should now be in the form /dev/bus/usb/AAA/BBB match = usb_bus_regex.match(path) raise HIDAPI::DevicePathInvalid, "Link target does not appear valid (#{path})." unless match interface = (options.delete(:interface) || 0).to_s(16) path = HIDAPI::Device.validate_path("#{match['BUS']}:#{match['ADDR']}:#{interface}") end valid_path = HIDAPI::Device.validate_path(path) raise HIDAPI::DevicePathInvalid, "Path should be in BUS:ADDRESS:INTERFACE format with each value being in hexadecimal (ie - 0001:01A:00), not #{path}." unless valid_path path = valid_path klass = (options || {}).delete(:as) || 'HIDAPI::Device' klass = Object.const_get(klass) unless klass == :no_mapping enumerate(as: :no_mapping).each do |usb_dev| usb_dev.settings.each do |intf_desc| if intf_desc.bInterfaceClass == HID_CLASS dev_path = HIDAPI::Device.make_path(usb_dev, intf_desc.bInterfaceNumber) if dev_path == path if klass != :no_mapping return klass.new(usb_dev, intf_desc.bInterfaceNumber) else return usb_dev end end end end end end
open(vendor_id, product_id, serial_number = nil, options = {})
click to toggle source
Opens the first device with the specified vendor_id, product_id, and optionally serial_number.
# File lib/hidapi/engine.rb, line 103 def open(vendor_id, product_id, serial_number = nil, options = {}) dev = get_device(vendor_id, product_id, serial_number, options) dev.open if dev end
open_path(path, options = {})
click to toggle source
Opens the device with the specified path.
# File lib/hidapi/engine.rb, line 161 def open_path(path, options = {}) dev = get_device_by_path(path, options) dev.open if dev end
usb_code_for_current_locale()
click to toggle source
Gets the USB code for the current locale.
# File lib/hidapi/engine.rb, line 168 def usb_code_for_current_locale @usb_code_for_current_locale ||= begin locale = I18n.locale if locale locale = locale.to_s.partition('.')[0] # remove encoding result = HIDAPI::Language.get_by_code(locale) unless result locale = locale.partition('_')[0] # chop off extra specification result = HIDAPI::Language.get_by_code(locale) end result ? result[:usb_code] : 0 else 0 end end end