Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/plugins/wedo_plugin/usb/backend
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/wedo_plugin/usb/backend')
-rw-r--r--plugins/wedo_plugin/usb/backend/__init__.py368
-rw-r--r--plugins/wedo_plugin/usb/backend/libusb01.py582
-rw-r--r--plugins/wedo_plugin/usb/backend/libusb10.py654
-rw-r--r--plugins/wedo_plugin/usb/backend/openusb.py707
4 files changed, 2311 insertions, 0 deletions
diff --git a/plugins/wedo_plugin/usb/backend/__init__.py b/plugins/wedo_plugin/usb/backend/__init__.py
new file mode 100644
index 0000000..67ee00f
--- /dev/null
+++ b/plugins/wedo_plugin/usb/backend/__init__.py
@@ -0,0 +1,368 @@
+# 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.backend - Backend interface.
+
+This module exports:
+
+IBackend - backend interface.
+
+Backends are Python objects which implement the IBackend interface.
+The easiest way to do so is inherinting from IBackend.
+
+PyUSB already provides backends for libusb versions 0.1 and 1.0,
+and OpenUSB library. Backends modules included with PyUSB are required to
+export the get_backend() function, which returns an instance of a backend
+object. You can provide your own customized backend if you
+want to. Bellow you find a skeleton of a backend implementation module:
+
+import usb.backend
+
+class MyBackend(usb.backend.IBackend):
+ pass
+
+def get_backend():
+ return MyBackend()
+
+You can use your customized backend by passing it as the backend parameter of the
+usb.core.find() function. For example:
+
+import custom_backend
+import usb.core
+
+myidVendor = 0xfffe
+myidProduct = 0x0001
+
+mybackend = custom_backend.get_backend()
+
+dev = usb.core.find(backend = mybackend, idProduct=myidProduct,
+ idVendor=myidVendor)
+
+For custom backends, you are not required to supply the get_backend() function,
+since the application code will instantiate the backend.
+
+If you do not provide a backend to the find() function, it will use one of the
+defaults backend according to its internal rules. For details, consult the
+find() function documentation.
+"""
+
+__author__ = 'Wander Lairson Costa'
+
+__all__ = ['IBackend', 'libusb01', 'libusb10', 'openusb']
+
+def _not_implemented(func):
+ raise NotImplementedError(func.__name__)
+
+class IBackend(object):
+ r"""Backend interface.
+
+ IBackend is the basic interface for backend implementations. By default,
+ the methods of the interface raise a NotImplementedError exception. A
+ backend implementation should replace the methods to provide the funcionality
+ necessary.
+
+ As Python is a dynamic typed language, you are not obligated to inherit from
+ IBackend: everything that bahaves like an IBackend is an IBackend. But you
+ are strongly recommended to do so, inheriting from IBackend provides consistent
+ default behavior.
+ """
+ def enumerate_devices(self):
+ r"""This function is required to return an iterable object which
+ yields an implementation defined device identification for each
+ USB device found in the system.
+
+ The device identification object is used as argument to other methods
+ of the interface.
+ """
+ _not_implemented(self.enumerate_devices)
+
+ def get_device_descriptor(self, dev):
+ r"""Return the device descriptor of the given device.
+
+ The object returned is required to have all the Device Descriptor
+ fields accessible as member variables. They must be convertible (but
+ not required to be equal) to the int type.
+
+ dev is an object yielded by the iterator returned by the enumerate_devices()
+ method.
+ """
+ _not_implemented(self.get_device_descriptor)
+
+ def get_configuration_descriptor(self, dev, config):
+ r"""Return a configuration descriptor of the given device.
+
+ The object returned is required to have all the Configuration Descriptor
+ fields acessible as member variables. They must be convertible (but
+ not required to be equal) to the int type.
+
+ The dev parameter is the already described device identification object.
+ config 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.
+ """
+ _not_implemented(self.get_configuration_descriptor)
+
+ def get_interface_descriptor(self, dev, intf, alt, config):
+ r"""Return an interface descriptor of the given device.
+
+ The object returned is required to have all the Interface Descriptor
+ fields accessible as member variables. They must be convertible (but
+ not required to be equal) to the int type.
+
+ The dev parameter is the already described device identification object.
+ The intf parameter is the interface logical index (not the bInterfaceNumber field)
+ and alt is the alternate setting logical index (not the bAlternateSetting value).
+ Not every interface has more than one alternate setting. In this case, the alt
+ parameter should be zero. config is the configuration logical index (not the
+ bConfigurationValue field).
+ """
+ _not_implemented(self.get_interface_descriptor)
+
+ def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
+ r"""Return an endpoint descriptor of the given device.
+
+ The object returned is required to have all the Endpoint Descriptor
+ fields acessible as member variables. They must be convertible (but
+ not required to be equal) to the int type.
+
+ The ep parameter is the endpoint logical index (not the bEndpointAddress
+ field) of the endpoint descriptor desired. intf, alt and config are the same
+ values already described in the get_interface_descriptor() method.
+ """
+ _not_implemented(self.get_endpoint_descriptor)
+
+ def open_device(self, dev):
+ r"""Open the device for data exchange.
+
+ This method opens the device identified by the dev parameter for communication.
+ This method must be called before calling any communication related method, such
+ as transfer methods.
+
+ It returns a handle identifying the communication instance. This handle must be
+ passed to the communication methods.
+ """
+ _not_implemented(self.open_device)
+
+ def close_device(self, dev_handle):
+ r"""Close the device handle.
+
+ This method closes the device communication channel and releases any
+ system resources related to it.
+ """
+ _not_implemented(self.close_device)
+
+ def set_configuration(self, dev_handle, config_value):
+ r"""Set the active device configuration.
+
+ This method should be called to set the active configuration
+ of the device. The dev_handle parameter is the value returned
+ by the open_device() method and the config_value parameter is the
+ bConfigurationValue field of the related configuration descriptor.
+ """
+ _not_implemented(self.set_configuration)
+
+ def get_configuration(self, dev_handle):
+ r"""Get the current active device configuration.
+
+ This method returns the bConfigurationValue of the currently
+ active configuration. Depending on the backend and the OS,
+ either a cached value may be returned or a control request may
+ be issued. The dev_handle parameter is the value returned by
+ the open_device method.
+ """
+ _not_implemented(self.get_configuration)
+
+ def set_interface_altsetting(self, dev_handle, intf, altsetting):
+ r"""Set the interface alternate setting.
+
+ This method should only be called when the interface has more than
+ one alternate setting. The dev_handle is the value returned by the
+ open_device() method. intf and altsetting are respectivelly the
+ bInterfaceNumber and bAlternateSetting fields of the related interface.
+ """
+ _not_implemented(self.set_interface_altsetting)
+
+ def claim_interface(self, dev_handle, intf):
+ r"""Claim the given interface.
+
+ Interface claiming is not related to USB spec itself, but it is
+ generally an necessary call of the USB libraries. It requests exclusive
+ access to the interface on the system. This method must be called
+ before using one of the transfer methods.
+
+ dev_handle is the value returned by the open_device() method and
+ intf is the bInterfaceNumber field of the desired interface.
+ """
+ _not_implemented(self.claim_interface)
+
+ def release_interface(self, dev_handle, intf):
+ r"""Release the claimed interface.
+
+ dev_handle and intf are the same parameters of the claim_interface
+ method.
+ """
+ _not_implemented(self.release_interface)
+
+ def bulk_write(self, dev_handle, ep, intf, data, timeout):
+ r"""Perform a bulk write.
+
+ dev_handle is the value returned by the open_device() method.
+ The ep parameter is the bEndpointAddress field whose endpoint
+ the data will be sent to. intf is the bInterfaceNumber field
+ of the interface containing the endpoint. The data parameter
+ is the data to be sent. It must be an instance of the array.array
+ class. The timeout parameter specifies a time limit to the operation
+ in miliseconds.
+
+ The method returns the number of bytes written.
+ """
+ _not_implemented(self.bulk_write)
+
+ def bulk_read(self, dev_handle, ep, intf, size, timeout):
+ r"""Perform a bulk read.
+
+ dev_handle is the value returned by the open_device() method.
+ The ep parameter is the bEndpointAddress field whose endpoint
+ the data will be received from. intf is the bInterfaceNumber field
+ of the interface containing the endpoint. The size parameter
+ is the number of bytes to be read. The timeout parameter specifies
+ a time limit to the operation in miliseconds.
+
+ The method returns an array.array object containing the data read.
+ """
+ _not_implemented(self.bulk_read)
+
+ def intr_write(self, dev_handle, ep, intf, data, timeout):
+ r"""Perform an interrupt write.
+
+ dev_handle is the value returned by the open_device() method.
+ The ep parameter is the bEndpointAddress field whose endpoint
+ the data will be sent to. intf is the bInterfaceNumber field
+ of the interface containing the endpoint. The data parameter
+ is the data to be sent. It must be an instance of the array.array
+ class. The timeout parameter specifies a time limit to the operation
+ in miliseconds.
+
+ The method returns the number of bytes written.
+ """
+ _not_implemented(self.intr_write)
+
+ def intr_read(self, dev_handle, ep, intf, size, timeout):
+ r"""Perform an interrut read.
+
+ dev_handle is the value returned by the open_device() method.
+ The ep parameter is the bEndpointAddress field whose endpoint
+ the data will be received from. intf is the bInterfaceNumber field
+ of the interface containing the endpoint. The size parameter
+ is the number of bytes to be read. The timeout parameter specifies
+ a time limit to the operation in miliseconds.
+
+ The method returns an array.array object containing the data read.
+ """
+ _not_implemented(self.intr_read)
+
+ def iso_write(self, dev_handle, ep, intf, data, timeout):
+ r"""Perform an isochronous write.
+
+ dev_handle is the value returned by the open_device() method.
+ The ep parameter is the bEndpointAddress field whose endpoint
+ the data will be sent to. intf is the bInterfaceNumber field
+ of the interface containing the endpoint. The data parameter
+ is the data to be sent.It must be an instance of the array.array
+ class. The timeout parameter specifies a time limit to the operation
+ in miliseconds.
+
+ The method returns the number of bytes written.
+ """
+ _not_implemented(self.iso_write)
+
+ def iso_read(self, dev_handle, ep, intf, size, timeout):
+ r"""Perform an isochronous read.
+
+ dev_handle is the value returned by the open_device() method.
+ The ep parameter is the bEndpointAddress field whose endpoint
+ the data will be received from. intf is the bInterfaceNumber field
+ of the interface containing the endpoint. The size parameter
+ is the number of bytes to be read. The timeout parameter specifies
+ a time limit to the operation in miliseconds.
+
+ The method returns an array.array object containing the data read.
+ """
+ _not_implemented(self.iso_read)
+
+ def ctrl_transfer(self,
+ dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ data_or_wLength,
+ timeout):
+ r"""Perform a control transfer on the endpoint 0.
+
+ The direction of the transfer is inferred from the bmRequestType
+ field of the setup packet.
+
+ dev_handle is the value returned by the open_device() method.
+ bmRequestType, bRequest, wValue and wIndex are the same fields
+ of the setup packet. data_or_wLength is either the payload to be sent
+ to the device, if any, as an array.array object (None there is no
+ payload) for OUT requests in the data stage or the wLength field
+ specifying the number of bytes to read for IN requests in the data
+ stage. The timeout parameter specifies a time limit to the operation
+ in miliseconds.
+
+ Return the number of bytes written (for OUT transfers) or the data
+ read (for IN transfers), as an array.array object.
+ """
+ _not_implemented(self.ctrl_transfer)
+
+ def reset_device(self, dev_handle):
+ r"""Reset the device."""
+ _not_implemented(self.reset_device)
+
+ def is_kernel_driver_active(self, dev_handle, intf):
+ r"""Determine if a kernel driver is active on an interface.
+
+ If a kernel driver is active, you cannot claim the interface,
+ and the backend will be unable to perform I/O.
+ """
+ _not_implemented(self.is_kernel_driver_active)
+
+ def detach_kernel_driver(self, dev_handle, intf):
+ r"""Detach a kernel driver from an interface.
+
+ If successful, you will then be able to claim the interface
+ and perform I/O.
+ """
+ _not_implemented(self.detach_kernel_driver)
+
+ def attach_kernel_driver(self, dev_handle, intf):
+ r"""Re-attach an interface's kernel driver, which was previously
+ detached using detach_kernel_driver()."""
+ _not_implemented(self.attach_kernel_driver)
diff --git a/plugins/wedo_plugin/usb/backend/libusb01.py b/plugins/wedo_plugin/usb/backend/libusb01.py
new file mode 100644
index 0000000..cf344c0
--- /dev/null
+++ b/plugins/wedo_plugin/usb/backend/libusb01.py
@@ -0,0 +1,582 @@
+# 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.
+
+from ctypes import *
+import ctypes.util
+import os
+import usb.backend
+import usb.util
+import sys
+from usb.core import USBError
+from usb._debug import methodtrace
+import usb._interop as _interop
+import logging
+
+__author__ = 'Wander Lairson Costa'
+
+__all__ = ['get_backend']
+
+_logger = logging.getLogger('usb.backend.libusb01')
+
+# usb.h
+
+_PC_PATH_MAX = 4
+
+if sys.platform != 'win32' and sys.platform != 'cygwin':
+ _PATH_MAX = os.pathconf('.', _PC_PATH_MAX)
+else:
+ _PATH_MAX = 511
+
+# libusb-win32 makes all structures packed, while
+# default libusb only does for some structures
+# _PackPolicy defines the structure packing according
+# to the platform.
+class _PackPolicy(object):
+ pass
+
+if sys.platform == 'win32' or sys.platform == 'cygwin':
+ _PackPolicy._pack_ = 1
+
+# Data structures
+
+class _usb_descriptor_header(Structure):
+ _pack_ = 1
+ _fields_ = [('blength', c_uint8),
+ ('bDescriptorType', c_uint8)]
+
+class _usb_string_descriptor(Structure):
+ _pack_ = 1
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('wData', c_uint16)]
+
+class _usb_endpoint_descriptor(Structure, _PackPolicy):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bEndpointAddress', c_uint8),
+ ('bmAttributes', c_uint8),
+ ('wMaxPacketSize', c_uint16),
+ ('bInterval', c_uint8),
+ ('bRefresh', c_uint8),
+ ('bSynchAddress', c_uint8),
+ ('extra', POINTER(c_uint8)),
+ ('extralen', c_int)]
+
+class _usb_interface_descriptor(Structure, _PackPolicy):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bInterfaceNumber', c_uint8),
+ ('bAlternateSetting', c_uint8),
+ ('bNumEndpoints', c_uint8),
+ ('bInterfaceClass', c_uint8),
+ ('bInterfaceSubClass', c_uint8),
+ ('bInterfaceProtocol', c_uint8),
+ ('iInterface', c_uint8),
+ ('endpoint', POINTER(_usb_endpoint_descriptor)),
+ ('extra', POINTER(c_uint8)),
+ ('extralen', c_int)]
+
+class _usb_interface(Structure, _PackPolicy):
+ _fields_ = [('altsetting', POINTER(_usb_interface_descriptor)),
+ ('num_altsetting', c_int)]
+
+class _usb_config_descriptor(Structure, _PackPolicy):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('wTotalLength', c_uint16),
+ ('bNumInterfaces', c_uint8),
+ ('bConfigurationValue', c_uint8),
+ ('iConfiguration', c_uint8),
+ ('bmAttributes', c_uint8),
+ ('bMaxPower', c_uint8),
+ ('interface', POINTER(_usb_interface)),
+ ('extra', POINTER(c_uint8)),
+ ('extralen', c_int)]
+
+class _usb_device_descriptor(Structure, _PackPolicy):
+ _pack_ = 1
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bcdUSB', c_uint16),
+ ('bDeviceClass', c_uint8),
+ ('bDeviceSubClass', c_uint8),
+ ('bDeviceProtocol', c_uint8),
+ ('bMaxPacketSize0', c_uint8),
+ ('idVendor', c_uint16),
+ ('idProduct', c_uint16),
+ ('bcdDevice', c_uint16),
+ ('iManufacturer', c_uint8),
+ ('iProduct', c_uint8),
+ ('iSerialNumber', c_uint8),
+ ('bNumConfigurations', c_uint8)]
+
+class _usb_device(Structure, _PackPolicy):
+ pass
+
+class _usb_bus(Structure, _PackPolicy):
+ pass
+
+_usb_device._fields_ = [('next', POINTER(_usb_device)),
+ ('prev', POINTER(_usb_device)),
+ ('filename', c_int8 * (_PATH_MAX + 1)),
+ ('bus', POINTER(_usb_bus)),
+ ('descriptor', _usb_device_descriptor),
+ ('config', POINTER(_usb_config_descriptor)),
+ ('dev', c_void_p),
+ ('devnum', c_uint8),
+ ('num_children', c_ubyte),
+ ('children', POINTER(POINTER(_usb_device)))]
+
+_usb_bus._fields_ = [('next', POINTER(_usb_bus)),
+ ('prev', POINTER(_usb_bus)),
+ ('dirname', c_char * (_PATH_MAX + 1)),
+ ('devices', POINTER(_usb_device)),
+ ('location', c_uint32),
+ ('root_dev', POINTER(_usb_device))]
+
+_usb_dev_handle = c_void_p
+
+class _DeviceDescriptor:
+ def __init__(self, dev):
+ desc = dev.descriptor
+ self.bLength = desc.bLength
+ self.bDescriptorType = desc.bDescriptorType
+ self.bcdUSB = desc.bcdUSB
+ self.bDeviceClass = desc.bDeviceClass
+ self.bDeviceSubClass = desc.bDeviceSubClass
+ self.bDeviceProtocol = desc.bDeviceProtocol
+ self.bMaxPacketSize0 = desc.bMaxPacketSize0
+ self.idVendor = desc.idVendor
+ self.idProduct = desc.idProduct
+ self.bcdDevice = desc.bcdDevice
+ self.iManufacturer = desc.iManufacturer
+ self.iProduct = desc.iProduct
+ self.iSerialNumber = desc.iSerialNumber
+ self.bNumConfigurations = desc.bNumConfigurations
+ self.address = dev.devnum
+ self.bus = dev.bus[0].location
+
+_lib = None
+
+def _load_library():
+ if sys.platform != 'cygwin':
+ candidates = ('usb-0.1', 'usb', 'libusb0')
+ for candidate in candidates:
+ libname = ctypes.util.find_library(candidate)
+ if libname is not None: break
+ else:
+ # corner cases
+ # cygwin predefines library names with 'cyg' instead of 'lib'
+ try:
+ return CDLL('cygusb0.dll')
+ except:
+ _logger.error('Libusb 0 could not be loaded in cygwin', exc_info=True)
+
+ raise OSError('USB library could not be found')
+ return CDLL(libname)
+
+def _setup_prototypes(lib):
+ # usb_dev_handle *usb_open(struct usb_device *dev);
+ lib.usb_open.argtypes = [POINTER(_usb_device)]
+ lib.usb_open.restype = _usb_dev_handle
+
+ # int usb_close(usb_dev_handle *dev);
+ lib.usb_close.argtypes = [_usb_dev_handle]
+
+ # int usb_get_string(usb_dev_handle *dev,
+ # int index,
+ # int langid,
+ # char *buf,
+ # size_t buflen);
+ lib.usb_get_string.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_int,
+ c_char_p,
+ c_size_t
+ ]
+
+ # int usb_get_string_simple(usb_dev_handle *dev,
+ # int index,
+ # char *buf,
+ # size_t buflen);
+ lib.usb_get_string_simple.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_char_p,
+ c_size_t
+ ]
+
+ # int usb_get_descriptor_by_endpoint(usb_dev_handle *udev,
+ # int ep,
+ # unsigned char type,
+ # unsigned char index,
+ # void *buf,
+ # int size);
+ lib.usb_get_descriptor_by_endpoint.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_ubyte,
+ c_ubyte,
+ c_void_p,
+ c_int
+ ]
+
+ # int usb_get_descriptor(usb_dev_handle *udev,
+ # unsigned char type,
+ # unsigned char index,
+ # void *buf,
+ # int size);
+ lib.usb_get_descriptor.argtypes = [
+ _usb_dev_handle,
+ c_ubyte,
+ c_ubyte,
+ c_void_p,
+ c_int
+ ]
+
+ # int usb_bulk_write(usb_dev_handle *dev,
+ # int ep,
+ # const char *bytes,
+ # int size,
+ # int timeout);
+ lib.usb_bulk_write.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_char_p,
+ c_int,
+ c_int
+ ]
+
+ # int usb_bulk_read(usb_dev_handle *dev,
+ # int ep,
+ # char *bytes,
+ # int size,
+ # int timeout);
+ lib.usb_bulk_read.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_char_p,
+ c_int,
+ c_int
+ ]
+
+ # int usb_interrupt_write(usb_dev_handle *dev,
+ # int ep,
+ # const char *bytes,
+ # int size,
+ # int timeout);
+ lib.usb_interrupt_write.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_char_p,
+ c_int,
+ c_int
+ ]
+
+ # int usb_interrupt_read(usb_dev_handle *dev,
+ # int ep,
+ # char *bytes,
+ # int size,
+ # int timeout);
+ lib.usb_interrupt_read.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_char_p,
+ c_int,
+ c_int
+ ]
+
+ # int usb_control_msg(usb_dev_handle *dev,
+ # int requesttype,
+ # int request,
+ # int value,
+ # int index,
+ # char *bytes,
+ # int size,
+ # int timeout);
+ lib.usb_control_msg.argtypes = [
+ _usb_dev_handle,
+ c_int,
+ c_int,
+ c_int,
+ c_int,
+ c_char_p,
+ c_int,
+ c_int
+ ]
+
+ # int usb_set_configuration(usb_dev_handle *dev, int configuration);
+ lib.usb_set_configuration.argtypes = [_usb_dev_handle, c_int]
+
+ # int usb_claim_interface(usb_dev_handle *dev, int interface);
+ lib.usb_claim_interface.argtypes = [_usb_dev_handle, c_int]
+
+ # int usb_release_interface(usb_dev_handle *dev, int interface);
+ lib.usb_release_interface.argtypes = [_usb_dev_handle, c_int]
+
+ # int usb_set_altinterface(usb_dev_handle *dev, int alternate);
+ lib.usb_set_altinterface.argtypes = [_usb_dev_handle, c_int]
+
+ # int usb_resetep(usb_dev_handle *dev, unsigned int ep);
+ lib.usb_resetep.argtypes = [_usb_dev_handle, c_int]
+
+ # int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
+ lib.usb_clear_halt.argtypes = [_usb_dev_handle, c_int]
+
+ # int usb_reset(usb_dev_handle *dev);
+ lib.usb_reset.argtypes = [_usb_dev_handle]
+
+ # char *usb_strerror(void);
+ lib.usb_strerror.argtypes = []
+ lib.usb_strerror.restype = c_char_p
+
+ # void usb_set_debug(int level);
+ lib.usb_set_debug.argtypes = [c_int]
+
+ # struct usb_device *usb_device(usb_dev_handle *dev);
+ lib.usb_device.argtypes = [_usb_dev_handle]
+ lib.usb_device.restype = POINTER(_usb_device)
+
+ # struct usb_bus *usb_get_busses(void);
+ lib.usb_get_busses.restype = POINTER(_usb_bus)
+
+def _check(retval):
+ if retval is None:
+ errmsg = _lib.usb_strerror()
+ else:
+ ret = int(retval)
+ if ret < 0:
+ errmsg = _lib.usb_strerror()
+ # No error means that we need to get the error
+ # message from the return code
+ # Thanks to Nicholas Wheeler to point out the problem...
+ # Also see issue #2860940
+ if errmsg.lower() == 'no error':
+ errmsg = os.strerror(-ret)
+ else:
+ return ret
+ raise USBError(errmsg, ret)
+
+# implementation of libusb 0.1.x backend
+class _LibUSB(usb.backend.IBackend):
+ @methodtrace(_logger)
+ def enumerate_devices(self):
+ _check(_lib.usb_find_busses())
+ _check(_lib.usb_find_devices())
+ bus = _lib.usb_get_busses()
+ while bool(bus):
+ dev = bus[0].devices
+ while bool(dev):
+ yield dev[0]
+ dev = dev[0].next
+ bus = bus[0].next
+
+ @methodtrace(_logger)
+ def get_device_descriptor(self, dev):
+ return _DeviceDescriptor(dev)
+
+ @methodtrace(_logger)
+ def get_configuration_descriptor(self, dev, config):
+ if config >= dev.descriptor.bNumConfigurations:
+ raise IndexError('Invalid configuration index ' + str(config))
+ return dev.config[config]
+
+ @methodtrace(_logger)
+ def get_interface_descriptor(self, dev, intf, alt, config):
+ cfgdesc = self.get_configuration_descriptor(dev, config)
+ if intf >= cfgdesc.bNumInterfaces:
+ raise IndexError('Invalid interface index ' + str(interface))
+ interface = cfgdesc.interface[intf]
+ if alt >= interface.num_altsetting:
+ raise IndexError('Invalid alternate setting index ' + str(alt))
+ return interface.altsetting[alt]
+
+ @methodtrace(_logger)
+ def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
+ interface = self.get_interface_descriptor(dev, intf, alt, config)
+ if ep >= interface.bNumEndpoints:
+ raise IndexError('Invalid endpoint index ' + str(ep))
+ return interface.endpoint[ep]
+
+ @methodtrace(_logger)
+ def open_device(self, dev):
+ return _check(_lib.usb_open(dev))
+
+ @methodtrace(_logger)
+ def close_device(self, dev_handle):
+ _check(_lib.usb_close(dev_handle))
+
+ @methodtrace(_logger)
+ def set_configuration(self, dev_handle, config_value):
+ _check(_lib.usb_set_configuration(dev_handle, config_value))
+
+ @methodtrace(_logger)
+ def set_interface_altsetting(self, dev_handle, intf, altsetting):
+ _check(_lib.usb_set_altinterface(dev_handle, altsetting))
+
+ @methodtrace(_logger)
+ def get_configuration(self, dev_handle):
+ bmRequestType = usb.util.build_request_type(
+ usb.util.CTRL_IN,
+ usb.util.CTRL_TYPE_STANDARD,
+ usb.util.CTRL_RECIPIENT_DEVICE
+ )
+ return self.ctrl_transfer(dev_handle,
+ bmRequestType,
+ 0x08,
+ 0,
+ 0,
+ 1,
+ 100
+ )[0]
+
+
+ @methodtrace(_logger)
+ def claim_interface(self, dev_handle, intf):
+ _check(_lib.usb_claim_interface(dev_handle, intf))
+
+ @methodtrace(_logger)
+ def release_interface(self, dev_handle, intf):
+ _check(_lib.usb_release_interface(dev_handle, intf))
+
+ @methodtrace(_logger)
+ def bulk_write(self, dev_handle, ep, intf, data, timeout):
+ return self.__write(_lib.usb_bulk_write,
+ dev_handle,
+ ep,
+ intf,
+ data, timeout)
+
+ @methodtrace(_logger)
+ def bulk_read(self, dev_handle, ep, intf, size, timeout):
+ return self.__read(_lib.usb_bulk_read,
+ dev_handle,
+ ep,
+ intf,
+ size,
+ timeout)
+
+ @methodtrace(_logger)
+ def intr_write(self, dev_handle, ep, intf, data, timeout):
+ return self.__write(_lib.usb_interrupt_write,
+ dev_handle,
+ ep,
+ intf,
+ data,
+ timeout)
+
+ @methodtrace(_logger)
+ def intr_read(self, dev_handle, ep, intf, size, timeout):
+ return self.__read(_lib.usb_interrupt_read,
+ dev_handle,
+ ep,
+ intf,
+ size,
+ timeout)
+
+ @methodtrace(_logger)
+ def ctrl_transfer(self,
+ dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ data_or_wLength,
+ timeout):
+ if usb.util.ctrl_direction(bmRequestType) == usb.util.CTRL_OUT:
+ address, length = data_or_wLength.buffer_info()
+ length *= data_or_wLength.itemsize
+ return _check(_lib.usb_control_msg(
+ dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ cast(address, c_char_p),
+ length,
+ timeout
+ ))
+ else:
+ data = _interop.as_array((0,) * data_or_wLength)
+ read = int(_check(_lib.usb_control_msg(
+ dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ cast(data.buffer_info()[0],
+ c_char_p),
+ data_or_wLength,
+ timeout
+ )))
+ return data[:read]
+
+ @methodtrace(_logger)
+ def reset_device(self, dev_handle):
+ _check(_lib.usb_reset(dev_handle))
+
+ @methodtrace(_logger)
+ def detach_kernel_driver(self, dev_handle, intf):
+ _check(_lib.usb_detach_kernel_driver_np(dev_handle, intf))
+
+ def __write(self, fn, dev_handle, ep, intf, data, timeout):
+ address, length = data.buffer_info()
+ length *= data.itemsize
+ return int(_check(fn(
+ dev_handle,
+ ep,
+ cast(address, c_char_p),
+ length,
+ timeout
+ )))
+
+ def __read(self, fn, dev_handle, ep, intf, size, timeout):
+ data = _interop.as_array((0,) * size)
+ address, length = data.buffer_info()
+ length *= data.itemsize
+ ret = int(_check(fn(
+ dev_handle,
+ ep,
+ cast(address, c_char_p),
+ length,
+ timeout
+ )))
+ return data[:ret]
+
+def get_backend():
+ global _lib
+ try:
+ if _lib is None:
+ _lib = _load_library()
+ _setup_prototypes(_lib)
+ _lib.usb_init()
+ return _LibUSB()
+ except Exception:
+ _logger.error('Error loading libusb 0.1 backend', exc_info=True)
+ return None
diff --git a/plugins/wedo_plugin/usb/backend/libusb10.py b/plugins/wedo_plugin/usb/backend/libusb10.py
new file mode 100644
index 0000000..cb2a566
--- /dev/null
+++ b/plugins/wedo_plugin/usb/backend/libusb10.py
@@ -0,0 +1,654 @@
+# 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.
+
+from ctypes import *
+import ctypes.util
+import usb.util
+import sys
+import logging
+from usb._debug import methodtrace
+import usb._interop as _interop
+import errno
+
+__author__ = 'Wander Lairson Costa'
+
+__all__ = [
+ 'get_backend',
+ 'LIBUSB_SUCESS',
+ 'LIBUSB_ERROR_IO',
+ 'LIBUSB_ERROR_INVALID_PARAM',
+ 'LIBUSB_ERROR_ACCESS',
+ 'LIBUSB_ERROR_NO_DEVICE',
+ 'LIBUSB_ERROR_NOT_FOUND',
+ 'LIBUSB_ERROR_BUSY',
+ 'LIBUSB_ERROR_TIMEOUT',
+ 'LIBUSB_ERROR_OVERFLOW',
+ 'LIBUSB_ERROR_PIPE',
+ 'LIBUSB_ERROR_INTERRUPTED',
+ 'LIBUSB_ERROR_NO_MEM',
+ 'LIBUSB_ERROR_NOT_SUPPORTED',
+ 'LIBUSB_ERROR_OTHER'
+ ]
+
+_logger = logging.getLogger('usb.backend.libusb10')
+
+# libusb.h
+
+# return codes
+
+LIBUSB_SUCCESS = 0
+LIBUSB_ERROR_IO = -1
+LIBUSB_ERROR_INVALID_PARAM = -2
+LIBUSB_ERROR_ACCESS = -3
+LIBUSB_ERROR_NO_DEVICE = -4
+LIBUSB_ERROR_NOT_FOUND = -5
+LIBUSB_ERROR_BUSY = -6
+LIBUSB_ERROR_TIMEOUT = -7
+LIBUSB_ERROR_OVERFLOW = -8
+LIBUSB_ERROR_PIPE = -9
+LIBUSB_ERROR_INTERRUPTED = -10
+LIBUSB_ERROR_NO_MEM = -11
+LIBUSB_ERROR_NOT_SUPPORTED = -12
+LIBUSB_ERROR_OTHER = -99
+
+# map return codes to strings
+_str_error = {
+ LIBUSB_SUCCESS:'Success (no error)',
+ LIBUSB_ERROR_IO:'Input/output error',
+ LIBUSB_ERROR_INVALID_PARAM:'Invalid parameter',
+ LIBUSB_ERROR_ACCESS:'Access denied (insufficient permissions)',
+ LIBUSB_ERROR_NO_DEVICE:'No such device (it may have been disconnected)',
+ LIBUSB_ERROR_NOT_FOUND:'Entity not found',
+ LIBUSB_ERROR_BUSY:'Resource busy',
+ LIBUSB_ERROR_TIMEOUT:'Operation timed out',
+ LIBUSB_ERROR_OVERFLOW:'Overflow',
+ LIBUSB_ERROR_PIPE:'Pipe error',
+ LIBUSB_ERROR_INTERRUPTED:'System call interrupted (perhaps due to signal)',
+ LIBUSB_ERROR_NO_MEM:'Insufficient memory',
+ LIBUSB_ERROR_NOT_SUPPORTED:'Operation not supported or unimplemented on this platform',
+ LIBUSB_ERROR_OTHER:'Unknown error'
+}
+
+# map return code to errno values
+_libusb_errno = {
+ LIBUSB_SUCCESS:None,
+ LIBUSB_ERROR_IO:errno.__dict__.get('EIO', None),
+ LIBUSB_ERROR_INVALID_PARAM:errno.__dict__.get('EINVAL', None),
+ LIBUSB_ERROR_ACCESS:errno.__dict__.get('EACCES', None),
+ LIBUSB_ERROR_NO_DEVICE:errno.__dict__.get('ENODEV', None),
+ LIBUSB_ERROR_NOT_FOUND:errno.__dict__.get('ENOENT', None),
+ LIBUSB_ERROR_BUSY:errno.__dict__.get('EBUSY', None),
+ LIBUSB_ERROR_TIMEOUT:errno.__dict__.get('ETIMEDOUT', None),
+ LIBUSB_ERROR_OVERFLOW:errno.__dict__.get('EOVERFLOW', None),
+ LIBUSB_ERROR_PIPE:errno.__dict__.get('EPIPE', None),
+ LIBUSB_ERROR_INTERRUPTED:errno.__dict__.get('EINTR', None),
+ LIBUSB_ERROR_NO_MEM:errno.__dict__.get('ENOMEM', None),
+ LIBUSB_ERROR_NOT_SUPPORTED:errno.__dict__.get('ENOSYS', None),
+ LIBUSB_ERROR_OTHER:None
+}
+
+# Data structures
+
+class _libusb_endpoint_descriptor(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bEndpointAddress', c_uint8),
+ ('bmAttributes', c_uint8),
+ ('wMaxPacketSize', c_uint16),
+ ('bInterval', c_uint8),
+ ('bRefresh', c_uint8),
+ ('bSynchAddress', c_uint8),
+ ('extra', POINTER(c_ubyte)),
+ ('extra_length', c_int)]
+
+class _libusb_interface_descriptor(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bInterfaceNumber', c_uint8),
+ ('bAlternateSetting', c_uint8),
+ ('bNumEndpoints', c_uint8),
+ ('bInterfaceClass', c_uint8),
+ ('bInterfaceSubClass', c_uint8),
+ ('bInterfaceProtocol', c_uint8),
+ ('iInterface', c_uint8),
+ ('endpoint', POINTER(_libusb_endpoint_descriptor)),
+ ('extra', POINTER(c_ubyte)),
+ ('extra_length', c_int)]
+
+class _libusb_interface(Structure):
+ _fields_ = [('altsetting', POINTER(_libusb_interface_descriptor)),
+ ('num_altsetting', c_int)]
+
+class _libusb_config_descriptor(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('wTotalLength', c_uint16),
+ ('bNumInterfaces', c_uint8),
+ ('bConfigurationValue', c_uint8),
+ ('iConfiguration', c_uint8),
+ ('bmAttributes', c_uint8),
+ ('bMaxPower', c_uint8),
+ ('interface', POINTER(_libusb_interface)),
+ ('extra', POINTER(c_ubyte)),
+ ('extra_length', c_int)]
+
+class _libusb_device_descriptor(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bcdUSB', c_uint16),
+ ('bDeviceClass', c_uint8),
+ ('bDeviceSubClass', c_uint8),
+ ('bDeviceProtocol', c_uint8),
+ ('bMaxPacketSize0', c_uint8),
+ ('idVendor', c_uint16),
+ ('idProduct', c_uint16),
+ ('bcdDevice', c_uint16),
+ ('iManufacturer', c_uint8),
+ ('iProduct', c_uint8),
+ ('iSerialNumber', c_uint8),
+ ('bNumConfigurations', c_uint8)]
+
+_lib = None
+_init = None
+
+_libusb_device_handle = c_void_p
+
+def _load_library():
+ if sys.platform != 'cygwin':
+ candidates = ('usb-1.0', 'libusb-1.0', 'usb')
+ for candidate in candidates:
+ libname = ctypes.util.find_library(candidate)
+ if libname is not None: break
+ else:
+ # corner cases
+ # cygwin predefines library names with 'cyg' instead of 'lib'
+ try:
+ return CDLL('cygusb-1.0.dll')
+ except Exception:
+ _logger.error('Libusb 1.0 could not be loaded in cygwin', exc_info=True)
+
+ raise OSError('USB library could not be found')
+ # Windows backend uses stdcall calling convention
+ if sys.platform == 'win32':
+ l = WinDLL(libname)
+ else:
+ l = CDLL(libname)
+ # On FreeBSD 8/9, libusb 1.0 and libusb 0.1 are in the same shared
+ # object libusb.so, so if we found libusb library name, we must assure
+ # it is 1.0 version. We just try to get some symbol from 1.0 version
+ if not hasattr(l, 'libusb_init'):
+ raise OSError('USB library could not be found')
+ return l
+
+def _setup_prototypes(lib):
+ # void libusb_set_debug (libusb_context *ctx, int level)
+ lib.libusb_set_debug.argtypes = [c_void_p, c_int]
+
+ # int libusb_init (libusb_context **context)
+ lib.libusb_init.argtypes = [POINTER(c_void_p)]
+
+ # void libusb_exit (struct libusb_context *ctx)
+ lib.libusb_exit.argtypes = [c_void_p]
+
+ # ssize_t libusb_get_device_list (libusb_context *ctx,
+ # libusb_device ***list)
+ lib.libusb_get_device_list.argtypes = [
+ c_void_p,
+ POINTER(POINTER(c_void_p))
+ ]
+
+ # void libusb_free_device_list (libusb_device **list,
+ # int unref_devices)
+ lib.libusb_free_device_list.argtypes = [
+ POINTER(c_void_p),
+ c_int
+ ]
+
+ # libusb_device *libusb_ref_device (libusb_device *dev)
+ lib.libusb_ref_device.argtypes = [c_void_p]
+ lib.libusb_ref_device.restype = c_void_p
+
+ # void libusb_unref_device(libusb_device *dev)
+ lib.libusb_unref_device.argtypes = [c_void_p]
+
+ # int libusb_open(libusb_device *dev, libusb_device_handle **handle)
+ lib.libusb_open.argtypes = [c_void_p, POINTER(_libusb_device_handle)]
+
+ # void libusb_close(libusb_device_handle *dev_handle)
+ lib.libusb_close.argtypes = [_libusb_device_handle]
+
+ # int libusb_set_configuration(libusb_device_handle *dev,
+ # int configuration)
+ lib.libusb_set_configuration.argtypes = [_libusb_device_handle, c_int]
+
+ # int libusb_get_configuration(libusb_device_handle *dev,
+ # int *config)
+ lib.libusb_get_configuration.argtypes = [_libusb_device_handle, POINTER(c_int)]
+
+ # int libusb_claim_interface(libusb_device_handle *dev,
+ # int interface_number)
+ lib.libusb_claim_interface.argtypes = [_libusb_device_handle, c_int]
+
+ # int libusb_release_interface(libusb_device_handle *dev,
+ # int interface_number)
+ lib.libusb_release_interface.argtypes = [_libusb_device_handle, c_int]
+
+ # int libusb_set_interface_alt_setting(libusb_device_handle *dev,
+ # int interface_number,
+ # int alternate_setting)
+ lib.libusb_set_interface_alt_setting.argtypes = [
+ _libusb_device_handle,
+ c_int,
+ c_int
+ ]
+
+ # int libusb_reset_device (libusb_device_handle *dev)
+ lib.libusb_reset_device.argtypes = [_libusb_device_handle]
+
+ # int libusb_kernel_driver_active(libusb_device_handle *dev,
+ # int interface)
+ lib.libusb_kernel_driver_active.argtypes = [
+ _libusb_device_handle,
+ c_int
+ ]
+
+ # int libusb_detach_kernel_driver(libusb_device_handle *dev,
+ # int interface)
+ lib.libusb_detach_kernel_driver.argtypes = [
+ _libusb_device_handle,
+ c_int
+ ]
+
+ # int libusb_attach_kernel_driver(libusb_device_handle *dev,
+ # int interface)
+ lib.libusb_attach_kernel_driver.argtypes = [
+ _libusb_device_handle,
+ c_int
+ ]
+
+ # int libusb_get_device_descriptor(
+ # libusb_device *dev,
+ # struct libusb_device_descriptor *desc
+ # )
+ lib.libusb_get_device_descriptor.argtypes = [
+ c_void_p,
+ POINTER(_libusb_device_descriptor)
+ ]
+
+ # int libusb_get_config_descriptor(
+ # libusb_device *dev,
+ # uint8_t config_index,
+ # struct libusb_config_descriptor **config
+ # )
+ lib.libusb_get_config_descriptor.argtypes = [
+ c_void_p,
+ c_uint8,
+ POINTER(POINTER(_libusb_config_descriptor))
+ ]
+
+ # void libusb_free_config_descriptor(
+ # struct libusb_config_descriptor *config
+ # )
+ lib.libusb_free_config_descriptor.argtypes = [
+ POINTER(_libusb_config_descriptor)
+ ]
+
+ # int libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
+ # uint8_t desc_index,
+ # unsigned char *data,
+ # int length)
+ lib.libusb_get_string_descriptor_ascii.argtypes = [
+ _libusb_device_handle,
+ c_uint8,
+ POINTER(c_ubyte),
+ c_int
+ ]
+
+ # int libusb_control_transfer(libusb_device_handle *dev_handle,
+ # uint8_t bmRequestType,
+ # uint8_t bRequest,
+ # uint16_t wValue,
+ # uint16_t wIndex,
+ # unsigned char *data,
+ # uint16_t wLength,
+ # unsigned int timeout)
+ lib.libusb_control_transfer.argtypes = [
+ _libusb_device_handle,
+ c_uint8,
+ c_uint8,
+ c_uint16,
+ c_uint16,
+ POINTER(c_ubyte),
+ c_uint16,
+ c_uint
+ ]
+
+ #int libusb_bulk_transfer(
+ # struct libusb_device_handle *dev_handle,
+ # unsigned char endpoint,
+ # unsigned char *data,
+ # int length,
+ # int *transferred,
+ # unsigned int timeout
+ # )
+ lib.libusb_bulk_transfer.argtypes = [
+ _libusb_device_handle,
+ c_ubyte,
+ POINTER(c_ubyte),
+ c_int,
+ POINTER(c_int),
+ c_uint
+ ]
+
+ # int libusb_interrupt_transfer(
+ # libusb_device_handle *dev_handle,
+ # unsigned char endpoint,
+ # unsigned char *data,
+ # int length,
+ # int *actual_length,
+ # unsigned int timeout
+ # );
+ lib.libusb_interrupt_transfer.argtypes = [
+ _libusb_device_handle,
+ c_ubyte,
+ POINTER(c_ubyte),
+ c_int,
+ POINTER(c_int),
+ c_uint
+ ]
+
+ # uint8_t libusb_get_bus_number(libusb_device *dev)
+ lib.libusb_get_bus_number.argtypes = [c_void_p]
+ lib.libusb_get_bus_number.restype = c_uint8
+
+ # uint8_t libusb_get_device_address(libusb_device *dev)
+ lib.libusb_get_device_address.argtypes = [c_void_p]
+ lib.libusb_get_device_address.restype = c_uint8
+
+
+
+# check a libusb function call
+def _check(retval):
+ if isinstance(retval, int):
+ retval = c_int(retval)
+ if isinstance(retval, c_int):
+ if retval.value < 0:
+ from usb.core import USBError
+ ret = retval.value
+ raise USBError(_str_error[ret], ret, _libusb_errno[ret])
+ return retval
+
+# wrap a device
+class _Device(object):
+ def __init__(self, devid):
+ self.devid = _lib.libusb_ref_device(devid)
+ def __del__(self):
+ _lib.libusb_unref_device(self.devid)
+
+# wrap a descriptor and keep a reference to another object
+# Thanks to Thomas Reitmayr.
+class _WrapDescriptor(object):
+ def __init__(self, desc, obj = None):
+ self.obj = obj
+ self.desc = desc
+ def __getattr__(self, name):
+ return getattr(self.desc, name)
+
+# wrap a configuration descriptor
+class _ConfigDescriptor(object):
+ def __init__(self, desc):
+ self.desc = desc
+ def __del__(self):
+ _lib.libusb_free_config_descriptor(self.desc)
+ def __getattr__(self, name):
+ return getattr(self.desc.contents, name)
+
+# initialize and finalize the library
+class _Initializer(object):
+ def __init__(self):
+ _check(_lib.libusb_init(None))
+ def __del__(self):
+ _lib.libusb_exit(None)
+
+
+# iterator for libusb devices
+class _DevIterator(object):
+ def __init__(self):
+ self.dev_list = POINTER(c_void_p)()
+ self.num_devs = _check(_lib.libusb_get_device_list(
+ None,
+ byref(self.dev_list))
+ ).value
+ def __iter__(self):
+ for i in range(self.num_devs):
+ yield _Device(self.dev_list[i])
+ def __del__(self):
+ _lib.libusb_free_device_list(self.dev_list, 1)
+
+# implementation of libusb 1.0 backend
+class _LibUSB(usb.backend.IBackend):
+ @methodtrace(_logger)
+ def enumerate_devices(self):
+ return _DevIterator()
+
+ @methodtrace(_logger)
+ def get_device_descriptor(self, dev):
+ dev_desc = _libusb_device_descriptor()
+ _check(_lib.libusb_get_device_descriptor(dev.devid, byref(dev_desc)))
+ dev_desc.bus = _lib.libusb_get_bus_number(dev.devid)
+ dev_desc.address = _lib.libusb_get_device_address(dev.devid)
+ return dev_desc
+
+ @methodtrace(_logger)
+ def get_configuration_descriptor(self, dev, config):
+ cfg = POINTER(_libusb_config_descriptor)()
+ _check(_lib.libusb_get_config_descriptor(dev.devid,
+ config, byref(cfg)))
+ return _ConfigDescriptor(cfg)
+
+ @methodtrace(_logger)
+ def get_interface_descriptor(self, dev, intf, alt, config):
+ cfg = self.get_configuration_descriptor(dev, config)
+ if intf >= cfg.bNumInterfaces:
+ raise IndexError('Invalid interface index ' + str(intf))
+ i = cfg.interface[intf]
+ if alt >= i.num_altsetting:
+ raise IndexError('Invalid alternate setting index ' + str(alt))
+ return _WrapDescriptor(i.altsetting[alt], cfg)
+
+ @methodtrace(_logger)
+ def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
+ i = self.get_interface_descriptor(dev, intf, alt, config)
+ if ep > i.bNumEndpoints:
+ raise IndexError('Invalid endpoint index ' + str(ep))
+ return _WrapDescriptor(i.endpoint[ep], i)
+
+ @methodtrace(_logger)
+ def open_device(self, dev):
+ handle = _libusb_device_handle()
+ _check(_lib.libusb_open(dev.devid, byref(handle)))
+ return handle
+
+ @methodtrace(_logger)
+ def close_device(self, dev_handle):
+ _lib.libusb_close(dev_handle)
+
+ @methodtrace(_logger)
+ def set_configuration(self, dev_handle, config_value):
+ _check(_lib.libusb_set_configuration(dev_handle, config_value))
+
+ @methodtrace(_logger)
+ def get_configuration(self, dev_handle):
+ config = c_int()
+ _check(_lib.libusb_get_configuration(dev_handle, byref(config)))
+ return config.value
+
+ @methodtrace(_logger)
+ def set_interface_altsetting(self, dev_handle, intf, altsetting):
+ _check(_lib.libusb_set_interface_alt_setting(dev_handle,
+ intf,
+ altsetting))
+
+ @methodtrace(_logger)
+ def claim_interface(self, dev_handle, intf):
+ _check(_lib.libusb_claim_interface(dev_handle, intf))
+
+ @methodtrace(_logger)
+ def release_interface(self, dev_handle, intf):
+ _check(_lib.libusb_release_interface(dev_handle, intf))
+
+ @methodtrace(_logger)
+ def bulk_write(self, dev_handle, ep, intf, data, timeout):
+ return self.__write(_lib.libusb_bulk_transfer,
+ dev_handle,
+ ep,
+ intf,
+ data,
+ timeout)
+
+ @methodtrace(_logger)
+ def bulk_read(self, dev_handle, ep, intf, size, timeout):
+ return self.__read(_lib.libusb_bulk_transfer,
+ dev_handle,
+ ep,
+ intf,
+ size,
+ timeout)
+
+ @methodtrace(_logger)
+ def intr_write(self, dev_handle, ep, intf, data, timeout):
+ return self.__write(_lib.libusb_interrupt_transfer,
+ dev_handle,
+ ep,
+ intf,
+ data,
+ timeout)
+
+ @methodtrace(_logger)
+ def intr_read(self, dev_handle, ep, intf, size, timeout):
+ return self.__read(_lib.libusb_interrupt_transfer,
+ dev_handle,
+ ep,
+ intf,
+ size,
+ timeout)
+
+# TODO: implement isochronous
+# @methodtrace(_logger)
+# def iso_write(self, dev_handle, ep, intf, data, timeout):
+# pass
+
+
+# @methodtrace(_logger)
+# def iso_read(self, dev_handle, ep, intf, size, timeout):
+# pass
+
+ @methodtrace(_logger)
+ def ctrl_transfer(self,
+ dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ data_or_wLength,
+ timeout):
+ if usb.util.ctrl_direction(bmRequestType) == usb.util.CTRL_OUT:
+ buff = data_or_wLength
+ else:
+ buff = _interop.as_array((0,) * data_or_wLength)
+
+ addr, length = buff.buffer_info()
+ length *= buff.itemsize
+
+ ret = _check(_lib.libusb_control_transfer(dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ cast(addr,
+ POINTER(c_ubyte)),
+ length,
+ timeout))
+
+ if usb.util.ctrl_direction(bmRequestType) == usb.util.CTRL_OUT:
+ return ret.value
+ else:
+ return buff[:ret.value]
+
+ @methodtrace(_logger)
+ def reset_device(self, dev_handle):
+ _check(_lib.libusb_reset_device(dev_handle))
+
+ @methodtrace(_logger)
+ def is_kernel_driver_active(self, dev_handle, intf):
+ return bool(_check(_lib.libusb_kernel_driver_active(dev_handle, intf)))
+
+ @methodtrace(_logger)
+ def detach_kernel_driver(self, dev_handle, intf):
+ _check(_lib.libusb_detach_kernel_driver(dev_handle, intf))
+
+ @methodtrace(_logger)
+ def attach_kernel_driver(self, dev_handle, intf):
+ _check(_lib.libusb_attach_kernel_driver(dev_handle, intf))
+
+ def __write(self, fn, dev_handle, ep, intf, data, timeout):
+ address, length = data.buffer_info()
+ length *= data.itemsize
+ transferred = c_int()
+ _check(fn(dev_handle,
+ ep,
+ cast(address, POINTER(c_ubyte)),
+ length,
+ byref(transferred),
+ timeout))
+ return transferred.value
+
+ def __read(self, fn, dev_handle, ep, intf, size, timeout):
+ data = _interop.as_array((0,) * size)
+ address, length = data.buffer_info()
+ length *= data.itemsize
+ transferred = c_int()
+ _check(fn(dev_handle,
+ ep,
+ cast(address, POINTER(c_ubyte)),
+ length,
+ byref(transferred),
+ timeout))
+ return data[:transferred.value]
+
+def get_backend():
+ global _lib, _init
+ try:
+ if _lib is None:
+ _lib = _load_library()
+ _setup_prototypes(_lib)
+ _init = _Initializer()
+ return _LibUSB()
+ except Exception:
+ _logger.error('Error loading libusb 1.0 backend', exc_info=True)
+ return None
diff --git a/plugins/wedo_plugin/usb/backend/openusb.py b/plugins/wedo_plugin/usb/backend/openusb.py
new file mode 100644
index 0000000..23e4d45
--- /dev/null
+++ b/plugins/wedo_plugin/usb/backend/openusb.py
@@ -0,0 +1,707 @@
+# 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.
+
+from ctypes import *
+import ctypes.util
+import usb.util
+from usb._debug import methodtrace
+import logging
+import errno
+
+__author__ = 'Wander Lairson Costa'
+
+__all__ = [
+ 'get_backend'
+ 'OPENUSB_SUCCESS'
+ 'OPENUSB_PLATFORM_FAILURE'
+ 'OPENUSB_NO_RESOURCES'
+ 'OPENUSB_NO_BANDWIDTH'
+ 'OPENUSB_NOT_SUPPORTED'
+ 'OPENUSB_HC_HARDWARE_ERROR'
+ 'OPENUSB_INVALID_PERM'
+ 'OPENUSB_BUSY'
+ 'OPENUSB_BADARG'
+ 'OPENUSB_NOACCESS'
+ 'OPENUSB_PARSE_ERROR'
+ 'OPENUSB_UNKNOWN_DEVICE'
+ 'OPENUSB_INVALID_HANDLE'
+ 'OPENUSB_SYS_FUNC_FAILURE'
+ 'OPENUSB_NULL_LIST'
+ 'OPENUSB_CB_CONTINUE'
+ 'OPENUSB_CB_TERMINATE'
+ 'OPENUSB_IO_STALL'
+ 'OPENUSB_IO_CRC_ERROR'
+ 'OPENUSB_IO_DEVICE_HUNG'
+ 'OPENUSB_IO_REQ_TOO_BIG'
+ 'OPENUSB_IO_BIT_STUFFING'
+ 'OPENUSB_IO_UNEXPECTED_PID'
+ 'OPENUSB_IO_DATA_OVERRUN'
+ 'OPENUSB_IO_DATA_UNDERRUN'
+ 'OPENUSB_IO_BUFFER_OVERRUN'
+ 'OPENUSB_IO_BUFFER_UNDERRUN'
+ 'OPENUSB_IO_PID_CHECK_FAILURE'
+ 'OPENUSB_IO_DATA_TOGGLE_MISMATCH'
+ 'OPENUSB_IO_TIMEOUT'
+ 'OPENUSB_IO_CANCELED'
+ ]
+
+_logger = logging.getLogger('usb.backend.openusb')
+
+OPENUSB_SUCCESS = 0
+OPENUSB_PLATFORM_FAILURE = -1
+OPENUSB_NO_RESOURCES = -2
+OPENUSB_NO_BANDWIDTH = -3
+OPENUSB_NOT_SUPPORTED = -4
+OPENUSB_HC_HARDWARE_ERROR = -5
+OPENUSB_INVALID_PERM = -6
+OPENUSB_BUSY = -7
+OPENUSB_BADARG = -8
+OPENUSB_NOACCESS = -9
+OPENUSB_PARSE_ERROR = -10
+OPENUSB_UNKNOWN_DEVICE = -11
+OPENUSB_INVALID_HANDLE = -12
+OPENUSB_SYS_FUNC_FAILURE = -13
+OPENUSB_NULL_LIST = -14
+OPENUSB_CB_CONTINUE = -20
+OPENUSB_CB_TERMINATE = -21
+OPENUSB_IO_STALL = -50
+OPENUSB_IO_CRC_ERROR = -51
+OPENUSB_IO_DEVICE_HUNG = -52
+OPENUSB_IO_REQ_TOO_BIG = -53
+OPENUSB_IO_BIT_STUFFING = -54
+OPENUSB_IO_UNEXPECTED_PID = -55
+OPENUSB_IO_DATA_OVERRUN = -56
+OPENUSB_IO_DATA_UNDERRUN = -57
+OPENUSB_IO_BUFFER_OVERRUN = -58
+OPENUSB_IO_BUFFER_UNDERRUN = -59
+OPENUSB_IO_PID_CHECK_FAILURE = -60
+OPENUSB_IO_DATA_TOGGLE_MISMATCH = -61
+OPENUSB_IO_TIMEOUT = -62
+OPENUSB_IO_CANCELED = -63
+
+_openusb_errno = {
+ OPENUSB_SUCCESS:None,
+ OPENUSB_PLATFORM_FAILURE:None,
+ OPENUSB_NO_RESOURCES:errno.__dict__.get('ENOMEM', None),
+ OPENUSB_NO_BANDWIDTH:None,
+ OPENUSB_NOT_SUPPORTED:errno.__dict__.get('ENOSYS', None),
+ OPENUSB_HC_HARDWARE_ERROR:errno.__dict__.get('EIO', None),
+ OPENUSB_INVALID_PERM:errno.__dict__.get('EBADF', None),
+ OPENUSB_BUSY:errno.__dict__.get('EBUSY', None),
+ OPENUSB_BADARG:errno.__dict__.get('EINVAL', None),
+ OPENUSB_NOACCESS:errno.__dict__.get('EACCES', None),
+ OPENUSB_PARSE_ERROR:None,
+ OPENUSB_UNKNOWN_DEVICE:errno.__dict__.get('ENODEV', None),
+ OPENUSB_INVALID_HANDLE:errno.__dict__.get('EINVAL', None),
+ OPENUSB_SYS_FUNC_FAILURE:None,
+ OPENUSB_NULL_LIST:None,
+ OPENUSB_CB_CONTINUE:None,
+ OPENUSB_CB_TERMINATE:None,
+ OPENUSB_IO_STALL:errno.__dict__.get('EIO', None),
+ OPENUSB_IO_CRC_ERROR:errno.__dict__.get('EIO', None),
+ OPENUSB_IO_DEVICE_HUNG:errno.__dict__.get('EIO', None),
+ OPENUSB_IO_REQ_TOO_BIG:errno.__dict__.get('E2BIG', None),
+ OPENUSB_IO_BIT_STUFFING:None,
+ OPENUSB_IO_UNEXPECTED_PID:errno.__dict__.get('ESRCH', None),
+ OPENUSB_IO_DATA_OVERRUN:errno.__dict__.get('EOVERFLOW', None),
+ OPENUSB_IO_DATA_UNDERRUN:None,
+ OPENUSB_IO_BUFFER_OVERRUN:errno.__dict__.get('EOVERFLOW', None),
+ OPENUSB_IO_BUFFER_UNDERRUN:None,
+ OPENUSB_IO_PID_CHECK_FAILURE:None,
+ OPENUSB_IO_DATA_TOGGLE_MISMATCH:None,
+ OPENUSB_IO_TIMEOUT:errno.__dict__.get('ETIMEDOUT', None),
+ OPENUSB_IO_CANCELED:errno.__dict__.get('EINTR', None)
+}
+
+class _usb_endpoint_desc(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bEndpointAddress', c_uint8),
+ ('bmAttributes', c_uint8),
+ ('wMaxPacketSize', c_uint16),
+ ('bInterval', c_uint8),
+ ('bRefresh', c_uint8),
+ ('bSynchAddress', c_uint8)]
+
+class _usb_interface_desc(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bInterfaceNumber', c_uint8),
+ ('bAlternateSetting', c_uint8),
+ ('bNumEndpoints', c_uint8),
+ ('bInterfaceClass', c_uint8),
+ ('bInterfaceSubClass', c_uint8),
+ ('bInterfaceProtocol', c_uint8),
+ ('iInterface', c_uint8)]
+
+class _usb_config_desc(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('wTotalLength', c_uint16),
+ ('bNumInterfaces', c_uint8),
+ ('bConfigurationValue', c_uint8),
+ ('iConfiguration', c_uint8),
+ ('bmAttributes', c_uint8),
+ ('bMaxPower', c_uint8)]
+
+class _usb_device_desc(Structure):
+ _fields_ = [('bLength', c_uint8),
+ ('bDescriptorType', c_uint8),
+ ('bcdUSB', c_uint16),
+ ('bDeviceClass', c_uint8),
+ ('bDeviceSubClass', c_uint8),
+ ('bDeviceProtocol', c_uint8),
+ ('bMaxPacketSize0', c_uint8),
+ ('idVendor', c_uint16),
+ ('idProduct', c_uint16),
+ ('bcdDevice', c_uint16),
+ ('iManufacturer', c_uint8),
+ ('iProduct', c_uint8),
+ ('iSerialNumber', c_uint8),
+ ('bNumConfigurations', c_uint8)]
+
+class _openusb_request_result(Structure):
+ _fields_ = [('status', c_int32),
+ ('transfered_bytes', c_uint32)]
+
+class _openusb_ctrl_request(Structure):
+ class _openusb_ctrl_setup(Structure):
+ _fields_ = [('bmRequestType', c_uint8),
+ ('bRequest', c_uint8),
+ ('wValue', c_uint16),
+ ('wIndex', c_uint16)]
+ _fields_ = [('payload', POINTER(c_uint8)),
+ ('length', c_uint32),
+ ('timeout', c_uint32),
+ ('flags', c_uint32),
+ ('result', _openusb_request_result),
+ ('next', c_void_p)]
+
+class _openusb_intr_request(Structure):
+ _fields_ = [('interval', c_uint16),
+ ('payload', POINTER(c_uint8)),
+ ('length', c_uint32),
+ ('timeout', c_uint32),
+ ('flags', c_uint32),
+ ('result', _openusb_request_result),
+ ('next', c_void_p)]
+
+class _openusb_bulk_request(Structure):
+ _fields_ = [('payload', POINTER(c_uint8)),
+ ('length', c_uint32),
+ ('timeout', c_uint32),
+ ('flags', c_uint32),
+ ('result', _openusb_request_result),
+ ('next', c_void_p)]
+
+class _openusb_isoc_pkts(Structure):
+ class _openusb_isoc_packet(Structure):
+ _fields_ = [('payload', POINTER(c_uint8)),
+ ('length', c_uint32)]
+ _fields_ = [('num_packets', c_uint32),
+ ('packets', POINTER(_openusb_isoc_packet))]
+
+class _openusb_isoc_request(Structure):
+ _fields_ = [('start_frame', c_uint32),
+ ('flags', c_uint32),
+ ('pkts', _openusb_isoc_pkts),
+ ('isoc_results', POINTER(_openusb_request_result)),
+ ('isoc_status', c_int32),
+ ('next', c_void_p)]
+
+_openusb_devid = c_uint64
+_openusb_busid = c_uint64
+_openusb_handle = c_uint64
+_openusb_dev_handle = c_uint64
+
+_lib = None
+_ctx = None
+
+def _load_library():
+ libname = ctypes.util.find_library('openusb')
+ if libname is None:
+ raise OSError('USB library could not be found')
+ return CDLL(libname)
+
+def _setup_prototypes(lib):
+ # int32_t openusb_init(uint32_t flags , openusb_handle_t *handle);
+ lib.openusb_init.argtypes = [c_uint32, POINTER(_openusb_handle)]
+ lib.openusb_init.restype = c_int32
+
+ # void openusb_fini(openusb_handle_t handle );
+ lib.openusb_fini.argtypes = [_openusb_handle]
+
+ # uint32_t openusb_get_busid_list(openusb_handle_t handle,
+ # openusb_busid_t **busids,
+ # uint32_t *num_busids);
+ lib.openusb_get_busid_list.argtypes = [
+ _openusb_handle,
+ POINTER(POINTER(_openusb_busid)),
+ POINTER(c_uint32)
+ ]
+
+ # void openusb_free_busid_list(openusb_busid_t * busids);
+ lib.openusb_free_busid_list.argtypes = [POINTER(_openusb_busid)]
+
+ # uint32_t openusb_get_devids_by_bus(openusb_handle_t handle,
+ # openusb_busid_t busid,
+ # openusb_devid_t **devids,
+ # uint32_t *num_devids);
+ lib.openusb_get_devids_by_bus.argtypes = [
+ _openusb_handle,
+ _openusb_busid,
+ POINTER(POINTER(_openusb_devid)),
+ POINTER(c_uint32)
+ ]
+
+ lib.openusb_get_devids_by_bus.restype = c_int32
+
+ # void openusb_free_devid_list(openusb_devid_t * devids);
+ lib.openusb_free_devid_list.argtypes = [POINTER(_openusb_devid)]
+
+ # int32_t openusb_open_device(openusb_handle_t handle,
+ # openusb_devid_t devid ,
+ # uint32_t flags,
+ # openusb_dev_handle_t *dev);
+ lib.openusb_open_device.argtypes = [
+ _openusb_handle,
+ _openusb_devid,
+ c_uint32,
+ POINTER(_openusb_dev_handle)
+ ]
+
+ lib.openusb_open_device.restype = c_int32
+
+ # int32_t openusb_close_device(openusb_dev_handle_t dev);
+ lib.openusb_close_device.argtypes = [_openusb_dev_handle]
+ lib.openusb_close_device.restype = c_int32
+
+ # int32_t openusb_set_configuration(openusb_dev_handle_t dev,
+ # uint8_t cfg);
+ lib.openusb_set_configuration.argtypes = [_openusb_dev_handle, c_uint8]
+ lib.openusb_set_configuration.restype = c_int32
+
+ # int32_t openusb_get_configuration(openusb_dev_handle_t dev,
+ # uint8_t *cfg);
+ lib.openusb_get_configuration.argtypes = [_openusb_dev_handle, POINTER(c_uint8)]
+ lib.openusb_get_configuration.restype = c_int32
+
+ # int32_t openusb_claim_interface(openusb_dev_handle_t dev,
+ # uint8_t ifc,
+ # openusb_init_flag_t flags);
+ lib.openusb_claim_interface.argtypes = [
+ _openusb_dev_handle,
+ c_uint8,
+ c_int
+ ]
+
+ lib.openusb_claim_interface.restype = c_int32
+
+ # int32_t openusb_release_interface(openusb_dev_handle_t dev,
+ # uint8_t ifc);
+ lib.openusb_release_interface.argtypes = [
+ _openusb_dev_handle,
+ c_uint8
+ ]
+
+ lib.openusb_release_interface.restype = c_int32
+
+ # int32_topenusb_set_altsetting(openusb_dev_handle_t dev,
+ # uint8_t ifc,
+ # uint8_t alt);
+ lib.openusb_set_altsetting.argtypes = [
+ _openusb_dev_handle,
+ c_uint8,
+ c_uint8
+ ]
+ lib.openusb_set_altsetting.restype = c_int32
+
+ # int32_t openusb_reset(openusb_dev_handle_t dev);
+ lib.openusb_reset.argtypes = [_openusb_dev_handle]
+ lib.openusb_reset.restype = c_int32
+
+ # int32_t openusb_parse_device_desc(openusb_handle_t handle,
+ # openusb_devid_t devid,
+ # uint8_t *buffer,
+ # uint16_t buflen,
+ # usb_device_desc_t *devdesc);
+ lib.openusb_parse_device_desc.argtypes = [
+ _openusb_handle,
+ _openusb_devid,
+ POINTER(c_uint8),
+ c_uint16,
+ POINTER(_usb_device_desc)
+ ]
+
+ lib.openusb_parse_device_desc.restype = c_int32
+
+ # int32_t openusb_parse_config_desc(openusb_handle_t handle,
+ # openusb_devid_t devid,
+ # uint8_t *buffer,
+ # uint16_t buflen,
+ # uint8_t cfgidx,
+ # usb_config_desc_t *cfgdesc);
+ lib.openusb_parse_config_desc.argtypes = [
+ _openusb_handle,
+ _openusb_devid,
+ POINTER(c_uint8),
+ c_uint16,
+ c_uint8,
+ POINTER(_usb_config_desc)
+ ]
+ lib.openusb_parse_config_desc.restype = c_int32
+
+ # int32_t openusb_parse_interface_desc(openusb_handle_t handle,
+ # openusb_devid_t devid,
+ # uint8_t *buffer,
+ # uint16_t buflen,
+ # uint8_t cfgidx,
+ # uint8_t ifcidx,
+ # uint8_t alt,
+ # usb_interface_desc_t *ifcdesc);
+ lib.openusb_parse_interface_desc.argtypes = [
+ _openusb_handle,
+ _openusb_devid,
+ POINTER(c_uint8),
+ c_uint16,
+ c_uint8,
+ c_uint8,
+ c_uint8,
+ POINTER(_usb_interface_desc)
+ ]
+
+ lib.openusb_parse_interface_desc.restype = c_int32
+
+ # int32_t openusb_parse_endpoint_desc(openusb_handle_t handle,
+ # openusb_devid_t devid,
+ # uint8_t *buffer,
+ # uint16_t buflen,
+ # uint8_t cfgidx,
+ # uint8_t ifcidx,
+ # uint8_t alt,
+ # uint8_t eptidx,
+ # usb_endpoint_desc_t *eptdesc);
+ lib.openusb_parse_endpoint_desc.argtypes = [
+ _openusb_handle,
+ _openusb_devid,
+ POINTER(c_uint8),
+ c_uint16,
+ c_uint8,
+ c_uint8,
+ c_uint8,
+ c_uint8,
+ POINTER(_usb_endpoint_desc)
+ ]
+
+ lib.openusb_parse_interface_desc.restype = c_int32
+
+ # const char *openusb_strerror(int32_t error );
+ lib.openusb_strerror.argtypes = [c_int32]
+ lib.openusb_strerror.restype = c_char_p
+
+ # int32_t openusb_ctrl_xfer(openusb_dev_handle_t dev,
+ # uint8_t ifc,
+ # uint8_t ept,
+ # openusb_ctrl_request_t *ctrl);
+ lib.openusb_ctrl_xfer.argtypes = [
+ _openusb_dev_handle,
+ c_uint8,
+ c_uint8,
+ POINTER(_openusb_ctrl_request)
+ ]
+
+ lib.openusb_ctrl_xfer.restype = c_int32
+
+ # int32_t openusb_intr_xfer(openusb_dev_handle_t dev,
+ # uint8_t ifc,
+ # uint8_t ept,
+ # openusb_intr_request_t *intr);
+ lib.openusb_intr_xfer.argtypes = [
+ _openusb_dev_handle,
+ c_uint8,
+ c_uint8,
+ POINTER(_openusb_intr_request)
+ ]
+
+ lib.openusb_bulk_xfer.restype = c_int32
+
+ # int32_t openusb_bulk_xfer(openusb_dev_handle_t dev,
+ # uint8_t ifc,
+ # uint8_t ept,
+ # openusb_bulk_request_t *bulk);
+ lib.openusb_bulk_xfer.argtypes = [
+ _openusb_dev_handle,
+ c_uint8,
+ c_uint8,
+ POINTER(_openusb_bulk_request)
+ ]
+
+ lib.openusb_bulk_xfer.restype = c_int32
+
+ # int32_t openusb_isoc_xfer(openusb_dev_handle_t dev,
+ # uint8_t ifc,
+ # uint8_t ept,
+ # openusb_isoc_request_t *isoc);
+ lib.openusb_isoc_xfer.argtypes = [
+ _openusb_dev_handle,
+ c_uint8,
+ c_uint8,
+ POINTER(_openusb_isoc_request)
+ ]
+
+ lib.openusb_isoc_xfer.restype = c_int32
+
+def _check(retval):
+ ret = retval.value
+ if ret != 0:
+ from usb.core import USBError
+ raise USBError(_lib.openusb_strerror(ret), ret, _openusb_errno[ret])
+ return retval
+
+class _Context(object):
+ def __init__(self):
+ self.handle = _openusb_handle()
+ _check(_lib.openusb_init(0, byref(self.handle)))
+ def __del__(self):
+ _lib.openusb_fini(self.handle)
+
+class _BusIterator(object):
+ def __init__(self):
+ self.buslist = POINTER(openusb_busid)()
+ num_busids = c_uint32()
+ _check(_lib.openusb_get_busid_list(_ctx.handle,
+ byref(self.buslist),
+ byref(num_busids)))
+ self.num_busids = num_busids.value
+ def __iter__(self):
+ for i in range(self.num_busids):
+ yield self.buslist[i]
+ def __del__(self):
+ _lib.openusb_free_busid_list(self.buslist)
+
+class _DevIterator(object):
+ def __init__(self, busid):
+ self.devlist = POINTER(_openusb_devid)()
+ num_devids = c_uint32()
+ _check(_lib.openusb_get_devids_by_bus(_ctx.handle,
+ busid,
+ byref(self.devlist),
+ byref(num_devids)))
+ self.num_devids = num_devids.value
+ def __iter__(self):
+ for i in range(self.num_devids):
+ yield self.devlist[i]
+ def __del__(self):
+ _lib.openusb_free_devid_list(self.devlist)
+
+class _OpenUSB(usb.backend.IBackend):
+ @methodtrace(_logger)
+ def enumerate_devices(self):
+ for bus in _BusIterator():
+ for devid in _DevIterator(bus):
+ yield devid
+
+ @methodtrace(_logger)
+ def get_device_descriptor(self, dev):
+ desc = _usb_device_desc()
+ _check(_lib.openusb_parse_device_desc(_ctx.handle,
+ dev,
+ None,
+ 0,
+ byref(desc)))
+ desc.bus = None
+ desc.address = None
+ return desc
+
+ @methodtrace(_logger)
+ def get_configuration_descriptor(self, dev, config):
+ desc = _usb_config_desc()
+ _check(_lib.openusb_parse_config_desc(_ctx.handle,
+ dev,
+ None,
+ 0,
+ config,
+ byref(desc)))
+ return desc
+
+ @methodtrace(_logger)
+ def get_interface_descriptor(self, dev, intf, alt, config):
+ desc = _usb_interface_desc()
+ _check(_lib.openusb_parse_interface_desc(_ctx.handle,
+ dev,
+ None,
+ 0,
+ config,
+ intf,
+ alt,
+ byref(desc)))
+ return desc
+
+ @methodtrace(_logger)
+ def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
+ desc = _usb_endpoint_desc()
+ _check(_lib.openusb_parse_endpoint_desc(_ctx.handle,
+ dev,
+ None,
+ 0,
+ config,
+ intf,
+ alt,
+ ep,
+ byref(desc)))
+ return desc
+
+ @methodtrace(_logger)
+ def open_device(self, dev):
+ handle = _openusb_dev_handle()
+ _check(_lib.openusb_open_device(_ctx.handle, dev, 0, byref(handle)))
+ return handle
+
+ @methodtrace(_logger)
+ def close_device(self, dev_handle):
+ _lib.openusb_close_device(dev_handle)
+
+ @methodtrace(_logger)
+ def set_configuration(self, dev_handle, config_value):
+ _check(_lib.openusb_set_configuration(dev_handle, config_value))
+
+ @methodtrace(_logger)
+ def get_configuration(self, dev_handle):
+ config = c_uint8()
+ _check(_lib.openusb_get_configuration(dev_handle, byref(config)))
+ return config.value
+
+ @methodtrace(_logger)
+ def set_interface_altsetting(self, dev_handle, intf, altsetting):
+ _check(_lib.set_altsetting(dev_handle, intf, altsetting))
+
+ @methodtrace(_logger)
+ def claim_interface(self, dev_handle, intf):
+ _check(_lib.openusb_claim_interface(dev_handle, intf, 0))
+
+ @methodtrace(_logger)
+ def release_interface(self, dev_handle, intf):
+ _lib.openusb_release_interface(dev_handle, intf)
+
+ @methodtrace(_logger)
+ def bulk_write(self, dev_handle, ep, intf, data, timeout):
+ request = _openusb_bulk_request()
+ memset(byref(request), 0, sizeof(request))
+ request.payload, request.length = data.buffer_info()
+ request.timeout = timeout
+ _check(_lib.openusb_bulk_xfer(dev_handle, intf, ep, byref(request)))
+ return request.transfered_bytes.value
+
+ @methodtrace(_logger)
+ def bulk_read(self, dev_handle, ep, intf, size, timeout):
+ request = _openusb_bulk_request()
+ buffer = array.array('B', '\x00' * size)
+ memset(byref(request), 0, sizeof(request))
+ request.payload, request.length = buffer.buffer_info()
+ request.timeout = timeout
+ _check(_lib.openusb_bulk_xfer(dev_handle, intf, ep, byref(request)))
+ return buffer[:request.transfered_bytes.value]
+
+ @methodtrace(_logger)
+ def intr_write(self, dev_handle, ep, intf, data, timeout):
+ request = _openusb_intr_request()
+ memset(byref(request), 0, sizeof(request))
+ payload, request.length = data.buffer_info()
+ request.payload = cast(payload, POINTER(c_uint8))
+ request.timeout = timeout
+ _check(_lib.openusb_intr_xfer(dev_handle, intf, ep, byref(request)))
+ return request.transfered_bytes.value
+
+ @methodtrace(_logger)
+ def intr_read(self, dev_handle, ep, intf, size, timeout):
+ request = _openusb_intr_request()
+ buffer = array.array('B', '\x00' * size)
+ memset(byref(request), 0, sizeof(request))
+ payload, request.length = buffer.buffer_info()
+ request.payload = cast(payload, POINTER(c_uint8))
+ request.timeout = timeout
+ _check(_lib.openusb_intr_xfer(dev_handle, intf, ep, byref(request)))
+ return buffer[:request.transfered_bytes.value]
+
+# TODO: implement isochronous
+# @methodtrace(_logger)
+# def iso_write(self, dev_handle, ep, intf, data, timeout):
+# pass
+
+# @methodtrace(_logger)
+# def iso_read(self, dev_handle, ep, intf, size, timeout):
+# pass
+
+ @methodtrace(_logger)
+ def ctrl_transfer(self,
+ dev_handle,
+ bmRequestType,
+ bRequest,
+ wValue,
+ wIndex,
+ data_or_wLength,
+ timeout):
+ request = _openusb_ctrl_request()
+ request.setup.bmRequestType = bmRequestType
+ request.setup.bRequest = bRequest
+ request.setup.wValue
+ request.setup.wIndex
+ request.timeout = timeout
+
+ direction = usb.util.ctrl_direction(bmRequestType)
+
+ if direction == ENDPOINT_OUT:
+ buffer = data_or_wLength
+ else:
+ buffer = array.array('B', '\x00' * data_or_wLength)
+
+ payload, request.length = buffer.buffer_info()
+ request.payload = cast(payload, POINTER(c_uint8))
+
+ ret = _check(_lib.openusb_ctrl_xfer(dev_handle, 0, 0, byref(request)))
+
+ if direction == ENDPOINT_OUT:
+ ret
+ else:
+ buffer[:ret]
+
+ @methodtrace(_logger)
+ def reset_device(self, dev_handle):
+ _check(_lib.openusb_reset(dev_handle))
+
+def get_backend():
+ try:
+ global _lib, _ctx
+ if _lib is None:
+ _lib = _load_library()
+ _setup_prototypes(_lib)
+ _ctx = _Context()
+ return _OpenUSB()
+ except Exception:
+ _logger.error('Error loading OpenUSB backend', exc_info=True)
+ return None