diff options
Diffstat (limited to 'plugins/wedo_plugin/usb/core.py')
-rw-r--r-- | plugins/wedo_plugin/usb/core.py | 856 |
1 files changed, 0 insertions, 856 deletions
diff --git a/plugins/wedo_plugin/usb/core.py b/plugins/wedo_plugin/usb/core.py deleted file mode 100644 index c90d011..0000000 --- a/plugins/wedo_plugin/usb/core.py +++ /dev/null @@ -1,856 +0,0 @@ -# Copyright (C) 2009-2011 Wander Lairson Costa -# -# The following terms apply to all files associated -# with the software unless explicitly disclaimed in individual files. -# -# The authors hereby grant permission to use, copy, modify, distribute, -# and license this software and its documentation for any purpose, provided -# that existing copyright notices are retained in all copies and that this -# notice is included verbatim in any distributions. No written agreement, -# license, or royalty fee is required for any of the authorized uses. -# Modifications to this software may be copyrighted by their authors -# and need not follow the licensing terms described here, provided that -# the new terms are clearly indicated on the first page of each file where -# they apply. -# -# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -# MODIFICATIONS. - -r"""usb.core - Core USB features. - -This module exports: - -Device - a class representing a USB device. -Configuration - a class representing a configuration descriptor. -Interface - a class representing an interface descriptor. -Endpoint - a class representing an endpoint descriptor. -find() - a function to find USB devices. -""" - -__author__ = 'Wander Lairson Costa' - -__all__ = ['Device', 'Configuration', 'Interface', 'Endpoint', 'find'] - -import usb.util as util -import copy -import operator -import usb._interop as _interop -import logging - -_logger = logging.getLogger('usb.core') - -_DEFAULT_TIMEOUT = 1000 - -def _set_attr(input, output, fields): - for f in fields: - setattr(output, f, int(getattr(input, f))) - -class _ResourceManager(object): - def __init__(self, dev, backend): - self.backend = backend - self._active_cfg_index = None - self.dev = dev - self.handle = None - self._claimed_intf = _interop._set() - self._alt_set = {} - self._ep_type_map = {} - - def managed_open(self): - if self.handle is None: - self.handle = self.backend.open_device(self.dev) - return self.handle - - def managed_close(self): - if self.handle is not None: - self.backend.close_device(self.handle) - self.handle = None - - def managed_set_configuration(self, device, config): - if config is None: - cfg = device[0] - elif isinstance(config, Configuration): - cfg = config - elif config == 0: # unconfigured state - class FakeConfiguration(object): - def __init__(self): - self.index = None - self.bConfigurationValue = 0 - cfg = FakeConfiguration() - else: - cfg = util.find_descriptor(device, bConfigurationValue=config) - self.managed_open() - self.backend.set_configuration(self.handle, cfg.bConfigurationValue) - # cache the index instead of the object to avoid cyclic references - # of the device and Configuration (Device tracks the _ResourceManager, - # which tracks the Configuration, which tracks the Device) - self._active_cfg_index = cfg.index - # after changing configuration, our alternate setting and endpoint type caches - # are not valid anymore - self._ep_type_map.clear() - self._alt_set.clear() - - def managed_claim_interface(self, device, intf): - self.managed_open() - if intf is None: - cfg = self.get_active_configuration(device) - i = cfg[(0,0)].bInterfaceNumber - elif isinstance(intf, Interface): - i = intf.bInterfaceNumber - else: - i = intf - if i not in self._claimed_intf: - self.backend.claim_interface(self.handle, i) - self._claimed_intf.add(i) - - def managed_release_interface(self, device, intf): - if intf is None: - cfg = self.get_active_configuration(device) - i = cfg[(0,0)].bInterfaceNumber - elif isinstance(intf, Interface): - i = intf.bInterfaceNumber - else: - i = intf - if i in self._claimed_intf: - self.backend.release_interface(self.handle, i) - self._claimed_intf.remove(i) - - def managed_set_interface(self, device, intf, alt): - if intf is None: - i = self.get_interface(device, intf) - elif isinstance(intf, Interface): - i = intf - else: - cfg = self.get_active_configuration(device) - if alt is not None: - i = util.find_descriptor(cfg, bInterfaceNumber=intf, bAlternateSetting=alt) - else: - i = util.find_descriptor(cfg, bInterfaceNumber=intf) - self.managed_claim_interface(device, i) - if alt is None: - alt = i.bAlternateSetting - self.backend.set_interface_altsetting(self.handle, i.bInterfaceNumber, alt) - self._alt_set[i.bInterfaceNumber] = alt - - def get_interface(self, device, intf): - # TODO: check the viability of issuing a GET_INTERFACE - # request when we don't have a alternate setting cached - if intf is None: - cfg = self.get_active_configuration(device) - return cfg[(0,0)] - elif isinstance(intf, Interface): - return intf - else: - cfg = self.get_active_configuration(device) - if intf in self._alt_set: - return util.find_descriptor(cfg, - bInterfaceNumber=intf, - bAlternateSetting=self._alt_set[intf]) - else: - return util.find_descriptor(cfg, bInterfaceNumber=intf) - - def get_active_configuration(self, device): - if self._active_cfg_index is None: - self.managed_open() - cfg = util.find_descriptor( - device, - bConfigurationValue=self.backend.get_configuration(self.handle) - ) - if cfg is None: - raise USBError('Configuration not set') - self._active_cfg_index = cfg.index - return cfg - return device[self._active_cfg_index] - - def get_endpoint_type(self, device, address, intf): - intf = self.get_interface(device, intf) - key = (address, intf.bInterfaceNumber, intf.bAlternateSetting) - try: - return self._ep_type_map[key] - except KeyError: - e = util.find_descriptor(intf, bEndpointAddress=address) - etype = util.endpoint_type(e.bmAttributes) - self._ep_type_map[key] = etype - return etype - - def release_all_interfaces(self, device): - claimed = copy.copy(self._claimed_intf) - for i in claimed: - self.managed_release_interface(device, i) - - def dispose(self, device, close_handle = True): - self.release_all_interfaces(device) - if close_handle: - self.managed_close() - self._ep_type_map.clear() - self._alt_set.clear() - self._active_cfg_index = None - -class USBError(IOError): - r"""Exception class for USB errors. - - Backends must raise this exception when USB related errors occur. - The backend specific error code is available through the - 'backend_error_code' member variable. - """ - - def __init__(self, strerror, error_code = None, errno = None): - r"""Initialize the object. - - This initializes the USBError object. The strerror and errno are passed - to the parent object. The error_code parameter is attributed to the - backend_error_code member variable. - """ - IOError.__init__(self, errno, strerror) - self.backend_error_code = error_code - -class Endpoint(object): - r"""Represent an endpoint object. - - This class contains all fields of the Endpoint Descriptor - according to the USB Specification. You may access them as class - properties. For example, to access the field bEndpointAddress - of the endpoint descriptor: - - >>> import usb.core - >>> dev = usb.core.find() - >>> for cfg in dev: - >>> for i in cfg: - >>> for e in i: - >>> print e.bEndpointAddress - """ - - def __init__(self, device, endpoint, interface = 0, - alternate_setting = 0, configuration = 0): - r"""Initialize the Endpoint object. - - The device parameter is the device object returned by the find() - function. endpoint is the endpoint logical index (not the endpoint address). - The configuration parameter is the logical index of the - configuration (not the bConfigurationValue field). The interface - parameter is the interface logical index (not the bInterfaceNumber field) - and alternate_setting is the alternate setting logical index (not the - bAlternateSetting value). Not every interface has more than one alternate - setting. In this case, the alternate_setting parameter should be zero. - By "logical index" we mean the relative order of the configurations returned by the - peripheral as a result of GET_DESCRIPTOR request. - """ - self.device = device - intf = Interface(device, interface, alternate_setting, configuration) - self.interface = intf.bInterfaceNumber - self.index = endpoint - - backend = device._ctx.backend - - desc = backend.get_endpoint_descriptor( - device._ctx.dev, - endpoint, - interface, - alternate_setting, - configuration - ) - - _set_attr( - desc, - self, - ( - 'bLength', - 'bDescriptorType', - 'bEndpointAddress', - 'bmAttributes', - 'wMaxPacketSize', - 'bInterval', - 'bRefresh', - 'bSynchAddress' - ) - ) - - def write(self, data, timeout = None): - r"""Write data to the endpoint. - - The parameter data contains the data to be sent to the endpoint and - timeout is the time limit of the operation. The transfer type and - endpoint address are automatically inferred. - - The method returns the number of bytes written. - - For details, see the Device.write() method. - """ - return self.device.write(self.bEndpointAddress, data, self.interface, timeout) - - def read(self, size, timeout = None): - r"""Read data from the endpoint. - - The parameter size is the number of bytes to read and timeout is the - time limit of the operation.The transfer type and endpoint address - are automatically inferred. - - The method returns an array.array object with the data read. - - For details, see the Device.read() method. - """ - return self.device.read(self.bEndpointAddress, size, self.interface, timeout) - -class Interface(object): - r"""Represent an interface object. - - This class contains all fields of the Interface Descriptor - according to the USB Specification. You may access them as class - properties. For example, to access the field bInterfaceNumber - of the interface descriptor: - - >>> import usb.core - >>> dev = usb.core.find() - >>> for cfg in dev: - >>> for i in cfg: - >>> print i.bInterfaceNumber - """ - - def __init__(self, device, interface = 0, - alternate_setting = 0, configuration = 0): - r"""Initialize the interface object. - - The device parameter is the device object returned by the find() - function. The configuration parameter is the logical index of the - configuration (not the bConfigurationValue field). The interface - parameter is the interface logical index (not the bInterfaceNumber field) - and alternate_setting is the alternate setting logical index (not the - bAlternateSetting value). Not every interface has more than one alternate - setting. In this case, the alternate_setting parameter should be zero. - By "logical index" we mean the relative order of the configurations returned by the - peripheral as a result of GET_DESCRIPTOR request. - """ - self.device = device - self.alternate_index = alternate_setting - self.index = interface - self.configuration = configuration - - backend = device._ctx.backend - - desc = backend.get_interface_descriptor( - self.device._ctx.dev, - interface, - alternate_setting, - configuration - ) - - _set_attr( - desc, - self, - ( - 'bLength', - 'bDescriptorType', - 'bInterfaceNumber', - 'bAlternateSetting', - 'bNumEndpoints', - 'bInterfaceClass', - 'bInterfaceSubClass', - 'bInterfaceProtocol', - 'iInterface', - ) - ) - - def set_altsetting(self): - r"""Set the interface alternate setting.""" - self.device.set_interface_altsetting( - self.bInterfaceNumber, - self.bAlternateSetting - ) - - def __iter__(self): - r"""Iterate over all endpoints of the interface.""" - for i in range(self.bNumEndpoints): - yield Endpoint( - self.device, - i, - self.index, - self.alternate_index, - self.configuration - ) - def __getitem__(self, index): - r"""Return the Endpoint object in the given position.""" - return Endpoint( - self.device, - index, - self.index, - self.alternate_index, - self.configuration - ) - -class Configuration(object): - r"""Represent a configuration object. - - This class contains all fields of the Configuration Descriptor - according to the USB Specification. You may access them as class - properties. For example, to access the field bConfigurationValue - of the configuration descriptor: - - >>> import usb.core - >>> dev = usb.core.find() - >>> for cfg in dev: - >>> print cfg.bConfigurationValue - """ - - def __init__(self, device, configuration = 0): - r"""Initialize the configuration object. - - The device parameter is the device object returned by the find() - function. The configuration parameter is the logical index of the - configuration (not the bConfigurationValue field). By "logical index" - we mean the relative order of the configurations returned by the - peripheral as a result of GET_DESCRIPTOR request. - """ - self.device = device - self.index = configuration - - backend = device._ctx.backend - - desc = backend.get_configuration_descriptor( - self.device._ctx.dev, - configuration - ) - - _set_attr( - desc, - self, - ( - 'bLength', - 'bDescriptorType', - 'wTotalLength', - 'bNumInterfaces', - 'bConfigurationValue', - 'iConfiguration', - 'bmAttributes', - 'bMaxPower' - ) - ) - - def set(self): - r"""Set this configuration as the active one.""" - self.device.set_configuration(self.bConfigurationValue) - - def __iter__(self): - r"""Iterate over all interfaces of the configuration.""" - for i in range(self.bNumInterfaces): - alt = 0 - try: - while True: - yield Interface(self.device, i, alt, self.index) - alt += 1 - except (USBError, IndexError): - pass - def __getitem__(self, index): - r"""Return the Interface object in the given position. - - index is a tuple of two values with interface index and - alternate setting index, respectivally. Example: - - >>> interface = config[(0, 0)] - """ - return Interface(self.device, index[0], index[1], self.index) - - -class Device(object): - r"""Device object. - - This class contains all fields of the Device Descriptor according - to the USB Specification. You may access them as class properties. - For example, to access the field bDescriptorType of the device - descriptor: - - >>> import usb.core - >>> dev = usb.core.find() - >>> dev.bDescriptorType - - Additionally, the class provides methods to communicate with - the hardware. Typically, an application will first call the - set_configuration() method to put the device in a known configured - state, optionally call the set_interface_altsetting() to select the - alternate setting (if there is more than one) of the interface used, - and call the write() and read() method to send and receive data. - - When working in a new hardware, one first try would be like this: - - >>> import usb.core - >>> dev = usb.core.find(idVendor=myVendorId, idProduct=myProductId) - >>> dev.set_configuration() - >>> dev.write(1, 'test') - - This sample finds the device of interest (myVendorId and myProductId should be - replaced by the corresponding values of your device), then configures the device - (by default, the configuration value is 1, which is a typical value for most - devices) and then writes some data to the endpoint 0x01. - - Timeout values for the write, read and ctrl_transfer methods are specified in - miliseconds. If the parameter is omitted, Device.default_timeout value will - be used instead. This property can be set by the user at anytime. - """ - - def __init__(self, dev, backend): - r"""Initialize the Device object. - - Library users should normally get a Device instance through - the find function. The dev parameter is the identification - of a device to the backend and its meaning is opaque outside - of it. The backend parameter is a instance of a backend - object. - """ - self._ctx = _ResourceManager(dev, backend) - self.__default_timeout = _DEFAULT_TIMEOUT - - desc = backend.get_device_descriptor(dev) - - _set_attr( - desc, - self, - ( - 'bLength', - 'bDescriptorType', - 'bcdUSB', - 'bDeviceClass', - 'bDeviceSubClass', - 'bDeviceProtocol', - 'bMaxPacketSize0', - 'idVendor', - 'idProduct', - 'bcdDevice', - 'iManufacturer', - 'iProduct', - 'iSerialNumber', - 'bNumConfigurations', - 'address', - 'bus' - ) - ) - - self.bus = int(desc.bus) if desc.bus is not None else None - self.address = int(desc.address) if desc.address is not None else None - - def set_configuration(self, configuration = None): - r"""Set the active configuration. - - The configuration parameter is the bConfigurationValue field of the - configuration you want to set as active. If you call this method - without parameter, it will use the first configuration found. - As a device hardly ever has more than one configuration, calling - the method without parameter is enough to get the device ready. - """ - self._ctx.managed_set_configuration(self, configuration) - - def get_active_configuration(self): - r"""Return a Configuration object representing the current configuration set.""" - return self._ctx.get_active_configuration(self) - - def set_interface_altsetting(self, interface = None, alternate_setting = None): - r"""Set the alternate setting for an interface. - - When you want to use an interface and it has more than one alternate setting, - you should call this method to select the alternate setting you would like - to use. If you call the method without one or the two parameters, it will - be selected the first one found in the Device in the same way of set_configuration - method. - - Commonly, an interface has only one alternate setting and this call is - not necessary. For most of the devices, either it has more than one alternate - setting or not, it is not harmful to make a call to this method with no arguments, - as devices will silently ignore the request when there is only one alternate - setting, though the USB Spec allows devices with no additional alternate setting - return an error to the Host in response to a SET_INTERFACE request. - - If you are in doubt, you may want to call it with no arguments wrapped by - a try/except clause: - - >>> try: - >>> dev.set_interface_altsetting() - >>> except usb.core.USBError: - >>> pass - """ - self._ctx.managed_set_interface(self, interface, alternate_setting) - - def reset(self): - r"""Reset the device.""" - self._ctx.dispose(self, False) - self._ctx.backend.reset_device(self._ctx.handle) - self._ctx.dispose(self, True) - - def write(self, endpoint, data, interface = None, timeout = None): - r"""Write data to the endpoint. - - This method is used to send data to the device. The endpoint parameter - corresponds to the bEndpointAddress member whose endpoint you want to - communicate with. The interface parameter is the bInterfaceNumber field - of the interface descriptor which contains the endpoint. If you do not - provide one, the first one found will be used, as explained in the - set_interface_altsetting() method. - - The data parameter should be a sequence like type convertible to - array type (see array module). - - The timeout is specified in miliseconds. - - The method returns the number of bytes written. - """ - backend = self._ctx.backend - - fn_map = { - util.ENDPOINT_TYPE_BULK:backend.bulk_write, - util.ENDPOINT_TYPE_INTR:backend.intr_write, - util.ENDPOINT_TYPE_ISO:backend.iso_write - } - - intf = self._ctx.get_interface(self, interface) - fn = fn_map[self._ctx.get_endpoint_type(self, endpoint, intf)] - self._ctx.managed_claim_interface(self, intf) - - return fn( - self._ctx.handle, - endpoint, - intf.bInterfaceNumber, - _interop.as_array(data), - self.__get_timeout(timeout) - ) - - def read(self, endpoint, size, interface = None, timeout = None): - r"""Read data from the endpoint. - - This method is used to receive data from the device. The endpoint parameter - corresponds to the bEndpointAddress member whose endpoint you want to - communicate with. The interface parameter is the bInterfaceNumber field - of the interface descriptor which contains the endpoint. If you do not - provide one, the first one found will be used, as explained in the - set_interface_altsetting() method. The size parameters tells how many - bytes you want to read. - - The timeout is specified in miliseconds. - - The method returns an array object with the data read. - """ - backend = self._ctx.backend - - fn_map = { - util.ENDPOINT_TYPE_BULK:backend.bulk_read, - util.ENDPOINT_TYPE_INTR:backend.intr_read, - util.ENDPOINT_TYPE_ISO:backend.iso_read - } - - intf = self._ctx.get_interface(self, interface) - fn = fn_map[self._ctx.get_endpoint_type(self, endpoint, intf)] - self._ctx.managed_claim_interface(self, intf) - - return fn( - self._ctx.handle, - endpoint, - intf.bInterfaceNumber, - size, - self.__get_timeout(timeout) - ) - - - def ctrl_transfer(self, bmRequestType, bRequest, wValue=0, wIndex=0, - data_or_wLength = None, timeout = None): - r"""Do a control transfer on the endpoint 0. - - This method is used to issue a control transfer over the - endpoint 0(endpoint 0 is required to always be a control endpoint). - - The parameters bmRequestType, bRequest, wValue and wIndex are the - same of the USB Standard Control Request format. - - Control requests may or may not have a data payload to write/read. - In cases which it has, the direction bit of the bmRequestType - field is used to infere the desired request direction. For - host to device requests (OUT), data_or_wLength parameter is - the data payload to send, and it must be a sequence type convertible - to an array object. In this case, the return value is the number of data - payload written. For device to host requests (IN), data_or_wLength - is the wLength parameter of the control request specifying the - number of bytes to read in data payload. In this case, the return - value is the data payload read, as an array object. - """ - if util.ctrl_direction(bmRequestType) == util.CTRL_OUT: - a = _interop.as_array(data_or_wLength) - elif data_or_wLength is None: - a = 0 - else: - a = data_or_wLength - - self._ctx.managed_open() - - return self._ctx.backend.ctrl_transfer( - self._ctx.handle, - bmRequestType, - bRequest, - wValue, - wIndex, - a, - self.__get_timeout(timeout) - ) - - def is_kernel_driver_active(self, interface): - r"""Determine if there is kernel driver associated with the interface. - - If a kernel driver is active, and the object will be unable to perform I/O. - """ - self._ctx.managed_open() - return self._ctx.backend.is_kernel_driver_active(self._ctx.handle, interface) - - def detach_kernel_driver(self, interface): - r"""Detach a kernel driver. - - If successful, you will then be able to perform I/O. - """ - self._ctx.managed_open() - self._ctx.backend.detach_kernel_driver(self._ctx.handle, interface) - - def attach_kernel_driver(self, interface): - r"""Re-attach an interface's kernel driver, which was previously - detached using detach_kernel_driver().""" - self._ctx.managed_open() - self._ctx.backend.attach_kernel_driver(self._ctx.handle, interface) - - def __iter__(self): - r"""Iterate over all configurations of the device.""" - for i in range(self.bNumConfigurations): - yield Configuration(self, i) - - def __getitem__(self, index): - r"""Return the Configuration object in the given position.""" - return Configuration(self, index) - - def __del__(self): - self._ctx.dispose(self) - - def __get_timeout(self, timeout): - if timeout is not None: - return timeout - return self.__default_timeout - - def __set_def_tmo(self, tmo): - if tmo < 0: - raise ValueError('Timeout cannot be a negative value') - self.__default_timeout = tmo - - def __get_def_tmo(self): - return self.__default_timeout - - default_timeout = property( - __get_def_tmo, - __set_def_tmo, - doc = 'Default timeout for transfer I/O functions' - ) - -def find(find_all=False, backend = None, custom_match = None, **args): - r"""Find an USB device and return it. - - find() is the function used to discover USB devices. - You can pass as arguments any combination of the - USB Device Descriptor fields to match a device. For example: - - find(idVendor=0x3f4, idProduct=0x2009) - - will return the Device object for the device with - idVendor Device descriptor field equals to 0x3f4 and - idProduct equals to 0x2009. - - If there is more than one device which matchs the criteria, - the first one found will be returned. If a matching device cannot - be found the function returns None. If you want to get all - devices, you can set the parameter find_all to True, then find - will return an list with all matched devices. If no matching device - is found, it will return an empty list. Example: - - printers = find(find_all=True, bDeviceClass=7) - - This call will get all the USB printers connected to the system. - (actually may be not, because some devices put their class - information in the Interface Descriptor). - - You can also use a customized match criteria: - - dev = find(custom_match = lambda d: d.idProduct=0x3f4 and d.idvendor=0x2009) - - A more accurate printer finder using a customized match would be like - so: - - def is_printer(dev): - import usb.util - if dev.bDeviceClass == 7: - return True - for cfg in dev: - if usb.util.find_descriptor(cfg, bInterfaceClass=7) is not None: - return True - - printers = find(find_all=True, custom_match = is_printer) - - Now even if the device class code is in the interface descriptor the - printer will be found. - - You can combine a customized match with device descriptor fields. In this - case, the fields must match and the custom_match must return True. In the our - previous example, if we would like to get all printers belonging to the - manufacturer 0x3f4, the code would be like so: - - printers = find(find_all=True, idVendor=0x3f4, custom_match=is_printer) - - If you want to use find as a 'list all devices' function, just call - it with find_all = True: - - devices = find(find_all=True) - - Finally, you may pass a custom backend to the find function: - - find(backend = MyBackend()) - - PyUSB has builtin backends for libusb 0.1, libusb 1.0 and OpenUSB. - If you do not supply a backend explicitly, find() function will select - one of the predefineds backends according to system availability. - - Backends are explained in the usb.backend module. - """ - - def device_iter(k, v): - for dev in backend.enumerate_devices(): - d = Device(dev, backend) - if (custom_match is None or custom_match(d)) and \ - _interop._reduce( - lambda a, b: a and b, - map( - operator.eq, - v, - map(lambda i: getattr(d, i), k) - ), - True - ): - yield d - - if backend is None: - import usb.backend.libusb10 as libusb10 - import usb.backend.libusb01 as libusb01 - import usb.backend.openusb as openusb - - for m in (libusb10, openusb, libusb01): - backend = m.get_backend() - if backend is not None: - _logger.info('find(): using backend "%s"', m.__name__) - break - else: - raise ValueError('No backend available') - - k, v = args.keys(), args.values() - - if find_all: - return [d for d in device_iter(k, v)] - else: - try: - return _interop._next(device_iter(k, v)) - except StopIteration: - return None |