MikrofonSensor und TemperaturSenor die zwei Python programme funktionieren. mit den jeweiligen 2 json Datein. Beim TemperaturSensor wird im Terminal keine Wertre ausgegeben aber in der json Datei kann man die Temp und Hum sehen.

This commit is contained in:
Chiara 2025-05-28 14:53:44 +02:00
parent 4c654ec969
commit 1751076592
2614 changed files with 349009 additions and 0 deletions

View file

@ -0,0 +1,384 @@
# Copyright 2009-2017 Wander Lairson Costa
# Copyright 2009-2021 PyUSB contributors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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. Below 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.
"""
import usb._objfinalizer as _objfinalizer
__author__ = 'Wander Lairson Costa'
__all__ = ['IBackend', 'libusb0', 'libusb1', 'openusb']
def _not_implemented(func):
raise NotImplementedError(func.__name__)
class IBackend(_objfinalizer.AutoFinalizedObject):
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 behaves 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_parent(self, dev):
"""Return the parent device of the given device."""
_not_implemented(self.get_parent)
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 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 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. dev, 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 respectively 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 milliseconds.
The method returns the number of bytes written.
"""
_not_implemented(self.bulk_write)
def bulk_read(self, dev_handle, ep, intf, buff, 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 buff parameter
is the buffer to receive the data read, the length of the buffer
tells how many bytes should be read. The timeout parameter
specifies a time limit to the operation in milliseconds.
The method returns the number of bytes actually 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 milliseconds.
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 interrupt 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 buff parameter
is the buffer to receive the data read, the length of the buffer
tells how many bytes should be read. The timeout parameter
specifies a time limit to the operation in milliseconds.
The method returns the number of bytes actually 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 milliseconds.
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 buff parameter
is buffer to receive the data read, the length of the buffer tells
how many bytes should be read. The timeout parameter specifies
a time limit to the operation in milliseconds.
The method returns the number of bytes actually read.
"""
_not_implemented(self.iso_read)
def ctrl_transfer(self,
dev_handle,
bmRequestType,
bRequest,
wValue,
wIndex,
data,
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 is an array object, for OUT requests
it contains the bytes to transmit in the data stage and for
IN requests it is the buffer to hold the data read. The number
of bytes requested to transmit or receive is equal to the length
of the array times the data.itemsize field. The timeout parameter
specifies a time limit to the operation in milliseconds.
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 clear_halt(self, dev_handle, ep):
r"""Clear the halt/stall condition for the endpoint."""
_not_implemented(self.clear_halt)
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)

View file

@ -0,0 +1,748 @@
# Copyright 2009-2017 Wander Lairson Costa
# Copyright 2009-2021 PyUSB contributors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ctypes import *
import errno
import os
import usb.backend
import usb.util
import sys
from usb.core import USBError, USBTimeoutError
from usb._debug import methodtrace
import usb._interop as _interop
import logging
import usb.libloader
__author__ = 'Wander Lairson Costa'
__all__ = ['get_backend']
_logger = logging.getLogger('usb.backend.libusb0')
_USBFS_MAXDRIVERNAME = 255
# usb.h
if sys.platform.find('bsd') != -1 or sys.platform.find('mac') != -1 or \
sys.platform.find('darwin') != -1 or sys.platform.find('sunos5') != -1:
_PATH_MAX = 1024
elif sys.platform == 'win32' or sys.platform == 'cygwin':
_PATH_MAX = 511
else:
_PATH_MAX = os.pathconf('.', 'PC_PATH_MAX')
# 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
self.port_number = None
self.port_numbers = None
self.speed = None
_lib = None
def _load_library(find_library=None):
return usb.libloader.load_locate_library(
('usb-0.1', 'usb', 'libusb0'),
'cygusb0.dll', 'Libusb 0',
find_library=find_library
)
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)
# linux only
# int usb_get_driver_np(usb_dev_handle *dev,
# int interface,
# char *name,
# unsigned int namelen);
if hasattr(lib, 'usb_get_driver_np'):
lib.usb_get_driver_np.argtypes = \
[_usb_dev_handle, c_int, c_char_p, c_uint]
# int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface);
if hasattr(lib, 'usb_detach_kernel_driver_np'):
lib.usb_detach_kernel_driver_np.argtypes = [_usb_dev_handle, c_int]
# libusb-win32 only
# int usb_isochronous_setup_async(usb_dev_handle *dev,
# void **context,
# unsigned char ep,
# int pktsize)
if hasattr(lib, 'usb_isochronous_setup_async'):
lib.usb_isochronous_setup_async.argtypes = \
[_usb_dev_handle, POINTER(c_void_p), c_uint8, c_int]
# int usb_bulk_setup_async(usb_dev_handle *dev,
# void **context,
# unsigned char ep)
if hasattr(lib, 'usb_bulk_setup_async'):
lib.usb_bulk_setup_async.argtypes = \
[_usb_dev_handle, POINTER(c_void_p), c_uint8]
# int usb_interrupt_setup_async(usb_dev_handle *dev,
# void **context,
# unsigned char ep)
if hasattr(lib, 'usb_interrupt_setup_async'):
lib.usb_interrupt_setup_async.argtypes = \
[_usb_dev_handle, POINTER(c_void_p), c_uint8]
# int usb_submit_async(void *context, char *bytes, int size)
if hasattr(lib, 'usb_submit_async'):
lib.usb_submit_async.argtypes = [c_void_p, c_char_p, c_int]
# int usb_reap_async(void *context, int timeout)
if hasattr(lib, 'usb_reap_async'):
lib.usb_reap_async.argtypes = [c_void_p, c_int]
# int usb_reap_async_nocancel(void *context, int timeout)
if hasattr(lib, 'usb_reap_async_nocancel'):
lib.usb_reap_async_nocancel.argtypes = [c_void_p, c_int]
# int usb_cancel_async(void *context)
if hasattr(lib, 'usb_cancel_async'):
lib.usb_cancel_async.argtypes = [c_void_p]
# int usb_free_async(void **context)
if hasattr(lib, 'usb_free_async'):
lib.usb_free_async.argtypes = [POINTER(c_void_p)]
def _check(ret):
if ret is None:
errmsg = _lib.usb_strerror()
else:
if hasattr(ret, 'value'):
ret = ret.value
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
if ret is not None and -ret == errno.ETIMEDOUT:
raise USBTimeoutError(errmsg, ret, -ret)
raise USBError(errmsg, ret)
def _has_iso_transfer():
return hasattr(_lib, 'usb_isochronous_setup_async')
# 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))
config_desc = dev.config[config]
config_desc.extra_descriptors = config_desc.extra[:config_desc.extralen]
return config_desc
@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(intf))
interface = cfgdesc.interface[intf]
if alt >= interface.num_altsetting:
raise IndexError('Invalid alternate setting index ' + str(alt))
intf_desc = interface.altsetting[alt]
intf_desc.extra_descriptors = intf_desc.extra[:intf_desc.extralen]
return intf_desc
@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))
ep_desc = interface.endpoint[ep]
ep_desc.extra_descriptors = ep_desc.extra[:ep_desc.extralen]
return ep_desc
@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 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
)
buff = usb.util.create_buffer(1)
ret = self.ctrl_transfer(
dev_handle,
bmRequestType,
0x08,
0,
0,
buff,
100)
assert ret == 1
return buff[0]
@methodtrace(_logger)
def set_interface_altsetting(self, dev_handle, intf, altsetting):
_check(_lib.usb_set_altinterface(dev_handle, altsetting))
@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, buff, timeout):
return self.__read(_lib.usb_bulk_read,
dev_handle,
ep,
intf,
buff,
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, buff, timeout):
return self.__read(_lib.usb_interrupt_read,
dev_handle,
ep,
intf,
buff,
timeout)
@methodtrace(_logger)
def iso_write(self, dev_handle, ep, intf, data, timeout):
if not _has_iso_transfer():
return usb.backend.IBackend.iso_write(self, dev_handle, ep, intf, data, timeout)
return self.__iso_transfer(dev_handle, ep, intf, data, timeout)
@methodtrace(_logger)
def iso_read(self, dev_handle, ep, intf, buff, timeout):
if not _has_iso_transfer():
return usb.backend.IBackend.iso_read(self, dev_handle, ep, intf, buff, timeout)
return self.__iso_transfer(dev_handle, ep, intf, buff, timeout)
@methodtrace(_logger)
def ctrl_transfer(self,
dev_handle,
bmRequestType,
bRequest,
wValue,
wIndex,
data,
timeout):
address, length = data.buffer_info()
length *= data.itemsize
return _check(_lib.usb_control_msg(
dev_handle,
bmRequestType,
bRequest,
wValue,
wIndex,
cast(address, c_char_p),
length,
timeout
))
@methodtrace(_logger)
def clear_halt(self, dev_handle, ep):
_check(_lib.usb_clear_halt(dev_handle, ep))
@methodtrace(_logger)
def reset_device(self, dev_handle):
_check(_lib.usb_reset(dev_handle))
@methodtrace(_logger)
def is_kernel_driver_active(self, dev_handle, intf):
if sys.platform == 'linux':
# based on the implementation of libusb_kernel_driver_active()
# (see op_kernel_driver_active() in libusb/os/linux_usbfs.c)
# and the fact that usb_get_driver_np() is a wrapper for
# IOCTL_USBFS_GETDRIVER
try:
driver_name = self.__get_driver_name(dev_handle, intf)
# 'usbfs' is not considered a [foreign] kernel driver because
# it is what we use to access the device from userspace
return driver_name != b'usbfs'
except USBError as err:
# ENODATA means that no kernel driver is attached
if err.backend_error_code == -errno.ENODATA:
return False
raise
elif sys.platform == 'darwin':
# on mac os/darwin we assume all users are running libusb-compat,
# which, in turn, uses libusb_kernel_driver_active()
try:
driver_name = self.__get_driver_name(dev_handle, intf)
return True
except USBError as err:
# ENODATA means that no kernel driver is attached
if err.backend_error_code == -errno.ENODATA:
return False
raise
elif sys.platform.startswith('freebsd') or sys.platform.startswith('dragonfly'):
# this is similar to the Linux implementation, but the generic
# driver is called 'ugen' and usb_get_driver_np() simply returns an
# empty string is no driver is attached (see comments on PR #366)
driver_name = self.__get_driver_name(dev_handle, intf)
# 'ugen' is not considered a [foreign] kernel driver because
# it is what we use to access the device from userspace
return driver_name != b'ugen'
else:
raise NotImplementedError(self.is_kernel_driver_active.__name__)
@methodtrace(_logger)
def detach_kernel_driver(self, dev_handle, intf):
if not hasattr(_lib, 'usb_detach_kernel_driver_np'):
raise NotImplementedError(self.detach_kernel_driver.__name__)
_check(_lib.usb_detach_kernel_driver_np(dev_handle, intf))
def __get_driver_name(self, dev_handle, intf):
if not hasattr(_lib, 'usb_get_driver_np'):
raise NotImplementedError('usb_get_driver_np')
buf = usb.util.create_buffer(_USBFS_MAXDRIVERNAME + 1)
name, length = buf.buffer_info()
length *= buf.itemsize
_check(_lib.usb_get_driver_np(
dev_handle,
intf,
cast(name, c_char_p),
length))
return cast(name, c_char_p).value
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, buff, timeout):
address, length = buff.buffer_info()
length *= buff.itemsize
ret = int(_check(fn(
dev_handle,
ep,
cast(address, c_char_p),
length,
timeout
)))
return ret
def __iso_transfer(self, dev_handle, ep, intf, data, timeout):
context = c_void_p()
buff, length = data.buffer_info()
length *= data.itemsize
_check(_lib.usb_isochronous_setup_async(
dev_handle,
byref(context),
ep,
0))
transmitted = 0
try:
while transmitted < length:
_check(_lib.usb_submit_async(
context,
cast(buff + transmitted, c_char_p),
length - transmitted))
ret = _check(_lib.usb_reap_async(context, timeout))
if not ret:
return transmitted
transmitted += ret
except:
if not transmitted:
raise
finally:
_check(_lib.usb_free_async(byref(context)))
return transmitted
def get_backend(find_library=None):
global _lib
try:
if _lib is None:
_lib = _load_library(find_library)
_setup_prototypes(_lib)
_lib.usb_init()
return _LibUSB()
except usb.libloader.LibraryException:
# exception already logged (if any)
_logger.error('Error loading libusb 0.1 backend', exc_info=False)
return None
except Exception:
_logger.error('Error loading libusb 0.1 backend', exc_info=True)
return None

View file

@ -0,0 +1,975 @@
# Copyright 2009-2017 Wander Lairson Costa
# Copyright 2009-2021 PyUSB contributors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ctypes import *
import usb.util
import sys
import logging
from usb._debug import methodtrace
import usb._interop as _interop
import usb._objfinalizer as _objfinalizer
import errno
import math
from usb.core import USBError, USBTimeoutError
import usb.libloader
__author__ = 'Wander Lairson Costa'
__all__ = [
'get_backend',
'LIBUSB_SUCCESS',
'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',
'LIBUSB_TRANSFER_COMPLETED',
'LIBUSB_TRANSFER_ERROR',
'LIBUSB_TRANSFER_TIMED_OUT',
'LIBUSB_TRANSFER_CANCELLED',
'LIBUSB_TRANSFER_STALL',
'LIBUSB_TRANSFER_NO_DEVICE',
'LIBUSB_TRANSFER_OVERFLOW',
]
_logger = logging.getLogger('usb.backend.libusb1')
# libusb.h
# transfer_type codes
# Control endpoint
_LIBUSB_TRANSFER_TYPE_CONTROL = 0
# Isochronous endpoint
_LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1
# Bulk endpoint
_LIBUSB_TRANSFER_TYPE_BULK = 2
# Interrupt endpoint
_LIBUSB_TRANSFER_TYPE_INTERRUPT = 3
# 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_map = {
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 = {
0: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
}
# Transfer status codes:
# Note that this does not indicate
# that the entire amount of requested data was transferred.
LIBUSB_TRANSFER_COMPLETED = 0
LIBUSB_TRANSFER_ERROR = 1
LIBUSB_TRANSFER_TIMED_OUT = 2
LIBUSB_TRANSFER_CANCELLED = 3
LIBUSB_TRANSFER_STALL = 4
LIBUSB_TRANSFER_NO_DEVICE = 5
LIBUSB_TRANSFER_OVERFLOW = 6
# map return codes to strings
_str_transfer_error = {
LIBUSB_TRANSFER_COMPLETED:'Success (no error)',
LIBUSB_TRANSFER_ERROR:'Transfer failed',
LIBUSB_TRANSFER_TIMED_OUT:'Transfer timed out',
LIBUSB_TRANSFER_CANCELLED:'Transfer was cancelled',
LIBUSB_TRANSFER_STALL:'For bulk/interrupt endpoints: halt condition '\
'detected (endpoint stalled). For control '\
'endpoints: control request not supported.',
LIBUSB_TRANSFER_NO_DEVICE:'Device was disconnected',
LIBUSB_TRANSFER_OVERFLOW:'Device sent more data than requested'
}
# map transfer codes to errno codes
_transfer_errno = {
LIBUSB_TRANSFER_COMPLETED:0,
LIBUSB_TRANSFER_ERROR:errno.__dict__.get('EIO', None),
LIBUSB_TRANSFER_TIMED_OUT:errno.__dict__.get('ETIMEDOUT', None),
LIBUSB_TRANSFER_CANCELLED:errno.__dict__.get('EAGAIN', None),
LIBUSB_TRANSFER_STALL:errno.__dict__.get('EIO', None),
LIBUSB_TRANSFER_NO_DEVICE:errno.__dict__.get('ENODEV', None),
LIBUSB_TRANSFER_OVERFLOW:errno.__dict__.get('EOVERFLOW', None)
}
def _strerror(errcode):
try:
return _lib.libusb_strerror(errcode).decode('utf8')
except AttributeError:
return _str_error_map[errcode]
# 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)]
# Isochronous packet descriptor.
class _libusb_iso_packet_descriptor(Structure):
_fields_ = [('length', c_uint),
('actual_length', c_uint),
('status', c_int)] # enum libusb_transfer_status
_libusb_device_handle = c_void_p
class _libusb_transfer(Structure):
pass
_libusb_transfer_p = POINTER(_libusb_transfer)
_libusb_transfer_cb_fn_p = CFUNCTYPE(None, _libusb_transfer_p)
_libusb_transfer._fields_ = [('dev_handle', _libusb_device_handle),
('flags', c_uint8),
('endpoint', c_uint8),
('type', c_uint8),
('timeout', c_uint),
('status', c_int), # enum libusb_transfer_status
('length', c_int),
('actual_length', c_int),
('callback', _libusb_transfer_cb_fn_p),
('user_data', py_object),
('buffer', c_void_p),
('num_iso_packets', c_int),
('iso_packet_desc', _libusb_iso_packet_descriptor)
]
def _get_iso_packet_list(transfer):
list_type = _libusb_iso_packet_descriptor * transfer.num_iso_packets
return list_type.from_address(addressof(transfer.iso_packet_desc))
_lib = None
_lib_object = None
def _load_library(find_library=None):
# Windows backend uses stdcall calling convention
#
# 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 sys.platform == 'win32':
win_cls = WinDLL
else:
win_cls = None
return usb.libloader.load_locate_library(
('usb-1.0', 'libusb-1.0', 'usb'),
'cygusb-1.0.dll', 'Libusb 1',
win_cls=win_cls,
find_library=find_library, check_symbols=('libusb_init',))
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))
]
# libusb_device *libusb_get_parent (libusb_device *dev)
lib.libusb_get_parent.argtypes = [c_void_p]
lib.libusb_get_parent.restype = 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
]
# libusb_transfer* libusb_alloc_transfer(int iso_packets);
lib.libusb_alloc_transfer.argtypes = [c_int]
lib.libusb_alloc_transfer.restype = POINTER(_libusb_transfer)
# void libusb_free_transfer(struct libusb_transfer *transfer)
lib.libusb_free_transfer.argtypes = [POINTER(_libusb_transfer)]
# int libusb_submit_transfer(struct libusb_transfer *transfer);
lib.libusb_submit_transfer.argtypes = [POINTER(_libusb_transfer)]
if hasattr(lib, 'libusb_strerror'):
# const char *libusb_strerror(enum libusb_error errcode)
lib.libusb_strerror.argtypes = [c_uint]
lib.libusb_strerror.restype = c_char_p
# int libusb_clear_halt(libusb_device_handle *dev, unsigned char endpoint)
lib.libusb_clear_halt.argtypes = [_libusb_device_handle, c_ubyte]
# void libusb_set_iso_packet_lengths(
# libusb_transfer* transfer,
# unsigned int length
# );
def libusb_set_iso_packet_lengths(transfer_p, length):
r"""This function is inline in the libusb.h file, so we must implement
it.
lib.libusb_set_iso_packet_lengths.argtypes = [
POINTER(_libusb_transfer),
c_int
]
"""
transfer = transfer_p.contents
for iso_packet_desc in _get_iso_packet_list(transfer):
iso_packet_desc.length = length
lib.libusb_set_iso_packet_lengths = libusb_set_iso_packet_lengths
#int libusb_get_max_iso_packet_size(libusb_device* dev,
# unsigned char endpoint);
lib.libusb_get_max_iso_packet_size.argtypes = [c_void_p,
c_ubyte]
# void libusb_fill_iso_transfer(
# struct libusb_transfer* transfer,
# libusb_device_handle* dev_handle,
# unsigned char endpoint,
# unsigned char* buffer,
# int length,
# int num_iso_packets,
# libusb_transfer_cb_fn callback,
# void * user_data,
# unsigned int timeout
# );
def libusb_fill_iso_transfer(_libusb_transfer_p, dev_handle, endpoint, buffer, length,
num_iso_packets, callback, user_data, timeout):
r"""This function is inline in the libusb.h file, so we must implement
it.
lib.libusb_fill_iso_transfer.argtypes = [
_libusb_transfer,
_libusb_device_handle,
c_ubyte,
POINTER(c_ubyte),
c_int,
c_int,
_libusb_transfer_cb_fn_p,
c_void_p,
c_uint
]
"""
transfer = _libusb_transfer_p.contents
transfer.dev_handle = dev_handle
transfer.endpoint = endpoint
transfer.type = _LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
transfer.timeout = timeout
transfer.buffer = cast(buffer, c_void_p)
transfer.length = length
transfer.num_iso_packets = num_iso_packets
transfer.user_data = user_data
transfer.callback = callback
lib.libusb_fill_iso_transfer = libusb_fill_iso_transfer
# 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
try:
# uint8_t libusb_get_device_speed(libusb_device *dev)
lib.libusb_get_device_speed.argtypes = [c_void_p]
lib.libusb_get_device_speed.restype = c_uint8
except AttributeError:
pass
try:
# uint8_t libusb_get_port_number(libusb_device *dev)
lib.libusb_get_port_number.argtypes = [c_void_p]
lib.libusb_get_port_number.restype = c_uint8
except AttributeError:
pass
try:
# int libusb_get_port_numbers(libusb_device *dev,
# uint8_t* port_numbers,
# int port_numbers_len)
lib.libusb_get_port_numbers.argtypes = [
c_void_p,
POINTER(c_uint8),
c_int
]
lib.libusb_get_port_numbers.restype = c_int
except AttributeError:
pass
#int libusb_handle_events(libusb_context *ctx);
lib.libusb_handle_events.argtypes = [c_void_p]
# check a libusb function call
def _check(ret):
if hasattr(ret, 'value'):
ret = ret.value
if ret < 0:
if ret == LIBUSB_ERROR_NOT_SUPPORTED:
raise NotImplementedError(_strerror(ret))
elif ret == LIBUSB_ERROR_TIMEOUT:
raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
else:
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
return ret
# wrap a device
class _Device(_objfinalizer.AutoFinalizedObject):
def __init__(self, devid):
self.devid = _lib.libusb_ref_device(devid)
@methodtrace(_logger)
def _finalize_object(self):
if hasattr(self, 'devid'):
_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(_objfinalizer.AutoFinalizedObject):
def __init__(self, desc):
self.desc = desc
def _finalize_object(self):
if hasattr(self, 'desc'):
_lib.libusb_free_config_descriptor(self.desc)
def __getattr__(self, name):
return getattr(self.desc.contents, name)
# iterator for libusb devices
class _DevIterator(_objfinalizer.AutoFinalizedObject):
def __init__(self, ctx):
self.dev_list = POINTER(c_void_p)()
self.num_devs = _check(_lib.libusb_get_device_list(
ctx,
byref(self.dev_list))
)
def __iter__(self):
for i in range(self.num_devs):
yield _Device(self.dev_list[i])
def _finalize_object(self):
if hasattr(self, 'dev_list'):
_lib.libusb_free_device_list(self.dev_list, 1)
class _DeviceHandle(object):
def __init__(self, dev):
self.handle = _libusb_device_handle()
self.devid = dev.devid
_check(_lib.libusb_open(self.devid, byref(self.handle)))
class _IsoTransferHandler(_objfinalizer.AutoFinalizedObject):
def __init__(self, dev_handle, ep, buff, timeout):
address, length = buff.buffer_info()
packet_length = _lib.libusb_get_max_iso_packet_size(dev_handle.devid, ep)
packet_count = int(math.ceil(float(length) / packet_length))
self.transfer = _lib.libusb_alloc_transfer(packet_count)
_lib.libusb_fill_iso_transfer(self.transfer,
dev_handle.handle,
ep,
cast(address, POINTER(c_ubyte)),
length,
packet_count,
_libusb_transfer_cb_fn_p(self.__callback),
None,
timeout)
self.__set_packets_length(length, packet_length)
def _finalize_object(self):
if hasattr(self, 'transfer'):
_lib.libusb_free_transfer(self.transfer)
def submit(self, ctx = None):
self.__callback_done = 0
_check(_lib.libusb_submit_transfer(self.transfer))
while not self.__callback_done:
_check(_lib.libusb_handle_events(ctx))
status = int(self.transfer.contents.status)
if status != LIBUSB_TRANSFER_COMPLETED:
raise usb.USBError(_str_transfer_error[status],
status,
_transfer_errno[status])
return self.__compute_size_transf_data()
def __compute_size_transf_data(self):
return sum([t.actual_length for t in
_get_iso_packet_list(self.transfer.contents)])
def __set_packets_length(self, n, packet_length):
_lib.libusb_set_iso_packet_lengths(self.transfer, packet_length)
r = n % packet_length
if r:
iso_packets = _get_iso_packet_list(self.transfer.contents)
# When the device is disconnected, this list may
# return with length 0
if len(iso_packets):
iso_packets[-1].length = r
def __callback(self, transfer):
self.__callback_done = 1
# implementation of libusb 1.0 backend
class _LibUSB(usb.backend.IBackend):
@methodtrace(_logger)
def __init__(self, lib):
usb.backend.IBackend.__init__(self)
self.lib = lib
self.ctx = c_void_p()
_check(self.lib.libusb_init(byref(self.ctx)))
@methodtrace(_logger)
def _finalize_object(self):
if hasattr(self, 'ctx') and self.ctx:
self.lib.libusb_exit(self.ctx)
@methodtrace(_logger)
def enumerate_devices(self):
return _DevIterator(self.ctx)
@methodtrace(_logger)
def get_parent(self, dev):
_parent = self.lib.libusb_get_parent(dev.devid)
if _parent is None:
return None
else:
return _Device(_parent)
@methodtrace(_logger)
def get_device_descriptor(self, dev):
dev_desc = _libusb_device_descriptor()
_check(self.lib.libusb_get_device_descriptor(dev.devid, byref(dev_desc)))
dev_desc.bus = self.lib.libusb_get_bus_number(dev.devid)
dev_desc.address = self.lib.libusb_get_device_address(dev.devid)
# Only available in newer versions of libusb
try:
dev_desc.speed = self.lib.libusb_get_device_speed(dev.devid)
except AttributeError:
dev_desc.speed = None
# Only available in newer versions of libusb
try:
dev_desc.port_number = self.lib.libusb_get_port_number(dev.devid)
except AttributeError:
dev_desc.port_number = None
# Only available in newer versions of libusb
try:
buff = (c_uint8 * 7)() # USB 3.0 maximum depth is 7
written = dev_desc.port_numbers = self.lib.libusb_get_port_numbers(
dev.devid, buff, len(buff))
if written > 0:
dev_desc.port_numbers = tuple(buff[:written])
else:
dev_desc.port_numbers = None
except AttributeError:
dev_desc.port_numbers = None
return dev_desc
@methodtrace(_logger)
def get_configuration_descriptor(self, dev, config):
cfg = POINTER(_libusb_config_descriptor)()
_check(self.lib.libusb_get_config_descriptor(
dev.devid,
config, byref(cfg)))
config_desc = _ConfigDescriptor(cfg)
config_desc.extra_descriptors = (
config_desc.extra[:config_desc.extra_length])
return config_desc
@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))
intf_desc = i.altsetting[alt]
intf_desc.extra_descriptors = intf_desc.extra[:intf_desc.extra_length]
return _WrapDescriptor(intf_desc, 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))
ep_desc = i.endpoint[ep]
ep_desc.extra_descriptors = ep_desc.extra[:ep_desc.extra_length]
return _WrapDescriptor(ep_desc, i)
@methodtrace(_logger)
def open_device(self, dev):
return _DeviceHandle(dev)
@methodtrace(_logger)
def close_device(self, dev_handle):
self.lib.libusb_close(dev_handle.handle)
@methodtrace(_logger)
def set_configuration(self, dev_handle, config_value):
_check(self.lib.libusb_set_configuration(dev_handle.handle, config_value))
@methodtrace(_logger)
def get_configuration(self, dev_handle):
config = c_int()
_check(self.lib.libusb_get_configuration(dev_handle.handle, byref(config)))
return config.value
@methodtrace(_logger)
def set_interface_altsetting(self, dev_handle, intf, altsetting):
_check(self.lib.libusb_set_interface_alt_setting(
dev_handle.handle,
intf,
altsetting))
@methodtrace(_logger)
def claim_interface(self, dev_handle, intf):
_check(self.lib.libusb_claim_interface(dev_handle.handle, intf))
@methodtrace(_logger)
def release_interface(self, dev_handle, intf):
_check(self.lib.libusb_release_interface(dev_handle.handle, intf))
@methodtrace(_logger)
def bulk_write(self, dev_handle, ep, intf, data, timeout):
return self.__write(self.lib.libusb_bulk_transfer,
dev_handle,
ep,
intf,
data,
timeout)
@methodtrace(_logger)
def bulk_read(self, dev_handle, ep, intf, buff, timeout):
return self.__read(self.lib.libusb_bulk_transfer,
dev_handle,
ep,
intf,
buff,
timeout)
@methodtrace(_logger)
def intr_write(self, dev_handle, ep, intf, data, timeout):
return self.__write(self.lib.libusb_interrupt_transfer,
dev_handle,
ep,
intf,
data,
timeout)
@methodtrace(_logger)
def intr_read(self, dev_handle, ep, intf, buff, timeout):
return self.__read(self.lib.libusb_interrupt_transfer,
dev_handle,
ep,
intf,
buff,
timeout)
@methodtrace(_logger)
def iso_write(self, dev_handle, ep, intf, data, timeout):
handler = _IsoTransferHandler(dev_handle, ep, data, timeout)
return handler.submit(self.ctx)
@methodtrace(_logger)
def iso_read(self, dev_handle, ep, intf, buff, timeout):
handler = _IsoTransferHandler(dev_handle, ep, buff, timeout)
return handler.submit(self.ctx)
@methodtrace(_logger)
def ctrl_transfer(self,
dev_handle,
bmRequestType,
bRequest,
wValue,
wIndex,
data,
timeout):
addr, length = data.buffer_info()
length *= data.itemsize
ret = _check(self.lib.libusb_control_transfer(
dev_handle.handle,
bmRequestType,
bRequest,
wValue,
wIndex,
cast(addr, POINTER(c_ubyte)),
length,
timeout))
return ret
@methodtrace(_logger)
def clear_halt(self, dev_handle, ep):
_check(self.lib.libusb_clear_halt(dev_handle.handle, ep))
@methodtrace(_logger)
def reset_device(self, dev_handle):
_check(self.lib.libusb_reset_device(dev_handle.handle))
@methodtrace(_logger)
def is_kernel_driver_active(self, dev_handle, intf):
return bool(_check(self.lib.libusb_kernel_driver_active(dev_handle.handle,
intf)))
@methodtrace(_logger)
def detach_kernel_driver(self, dev_handle, intf):
_check(self.lib.libusb_detach_kernel_driver(dev_handle.handle, intf))
@methodtrace(_logger)
def attach_kernel_driver(self, dev_handle, intf):
_check(self.lib.libusb_attach_kernel_driver(dev_handle.handle, intf))
def __write(self, fn, dev_handle, ep, intf, data, timeout):
address, length = data.buffer_info()
length *= data.itemsize
transferred = c_int()
retval = fn(dev_handle.handle,
ep,
cast(address, POINTER(c_ubyte)),
length,
byref(transferred),
timeout)
# do not assume LIBUSB_ERROR_TIMEOUT means no I/O.
if not (transferred.value and retval == LIBUSB_ERROR_TIMEOUT):
_check(retval)
return transferred.value
def __read(self, fn, dev_handle, ep, intf, buff, timeout):
address, length = buff.buffer_info()
length *= buff.itemsize
transferred = c_int()
retval = fn(dev_handle.handle,
ep,
cast(address, POINTER(c_ubyte)),
length,
byref(transferred),
timeout)
# do not assume LIBUSB_ERROR_TIMEOUT means no I/O.
if not (transferred.value and retval == LIBUSB_ERROR_TIMEOUT):
_check(retval)
return transferred.value
def get_backend(find_library=None):
global _lib, _lib_object
try:
if _lib_object is None:
_lib = _load_library(find_library=find_library)
_setup_prototypes(_lib)
_lib_object = _LibUSB(_lib)
return _lib_object
except usb.libloader.LibraryException:
# exception already logged (if any)
_logger.error('Error loading libusb 1.0 backend', exc_info=False)
return None
except Exception:
_logger.error('Error loading libusb 1.0 backend', exc_info=True)
return None

View file

@ -0,0 +1,759 @@
# Copyright 2009-2017 Wander Lairson Costa
# Copyright 2009-2021 PyUSB contributors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ctypes import *
import ctypes.util
import usb.util
from usb._debug import methodtrace
import logging
import errno
import sys
import usb._interop as _interop
import usb._objfinalizer as _objfinalizer
import usb.util as util
import usb.libloader
from usb.core import USBError, USBTimeoutError
__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),
('transferred_bytes', c_uint32)]
class _openusb_ctrl_request(Structure):
def __init__(self):
super(_openusb_ctrl_request, self).__init__()
self.setup.bmRequestType = 0
self.setup.bRequest = 0
self.setup.wValue = 0
self.setup.wIndex = 0
self.payload = None
self.length = 0
self.timeout = 0
self.flags = 0
self.result.status = 0
self.result.transferred_bytes = 0
self.next = None
class _openusb_ctrl_setup(Structure):
_fields_ = [('bmRequestType', c_uint8),
('bRequest', c_uint8),
('wValue', c_uint16),
('wIndex', c_uint16)]
_fields_ = [('setup', _openusb_ctrl_setup),
('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(find_library=None):
# FIXME: cygwin name is "openusb"?
# (that's what the original _load_library() function
# would have searched for)
return usb.libloader.load_locate_library(
('openusb',), 'openusb', "OpenUSB library", find_library=find_library
)
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_intr_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(ret):
if hasattr(ret, 'value'):
ret = ret.value
if ret != 0:
if ret == OPENUSB_IO_TIMEOUT:
raise USBTimeoutError(_lib.openusb_strerror(ret), ret, _openusb_errno[ret])
else:
raise USBError(_lib.openusb_strerror(ret), ret, _openusb_errno[ret])
return ret
class _Context(_objfinalizer.AutoFinalizedObject):
def __init__(self):
self.handle = _openusb_handle()
_check(_lib.openusb_init(0, byref(self.handle)))
def _finalize_object(self):
if hasattr(self, 'handle'):
_lib.openusb_fini(self.handle)
class _BusIterator(_objfinalizer.AutoFinalizedObject):
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 _finalize_object(self):
if hasattr(self, 'buslist'):
_lib.openusb_free_busid_list(self.buslist)
class _DevIterator(_objfinalizer.AutoFinalizedObject):
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 _finalize_object(self):
if hasattr(self, 'devlist'):
_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
desc.port_number = None
desc.port_numbers = None
desc.speed = 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)))
desc.extra_descriptors = None
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)))
desc.extra_descriptors = None
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)))
desc.extra_descriptors = None
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.openusb_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))
payload, request.length = data.buffer_info()
request.payload = cast(payload, POINTER(c_uint8))
request.timeout = timeout
_check(_lib.openusb_bulk_xfer(dev_handle, intf, ep, byref(request)))
return request.result.transferred_bytes
@methodtrace(_logger)
def bulk_read(self, dev_handle, ep, intf, buff, timeout):
request = _openusb_bulk_request()
memset(byref(request), 0, sizeof(request))
payload, request.length = buff.buffer_info()
request.payload = cast(payload, POINTER(c_uint8))
request.timeout = timeout
_check(_lib.openusb_bulk_xfer(dev_handle, intf, ep, byref(request)))
return request.result.transferred_bytes
@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.result.transferred_bytes
@methodtrace(_logger)
def intr_read(self, dev_handle, ep, intf, buff, timeout):
request = _openusb_intr_request()
memset(byref(request), 0, sizeof(request))
payload, request.length = buff.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.result.transferred_bytes
# 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,
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)
payload, request.length = data.buffer_info()
request.length *= data.itemsize
request.payload = cast(payload, POINTER(c_uint8))
_check(_lib.openusb_ctrl_xfer(dev_handle, 0, 0, byref(request)))
return request.result.transferred_bytes
@methodtrace(_logger)
def reset_device(self, dev_handle):
_check(_lib.openusb_reset(dev_handle))
@methodtrace(_logger)
def clear_halt(self, dev_handle, ep):
bmRequestType = util.build_request_type(
util.CTRL_OUT,
util.CTRL_TYPE_STANDARD,
util.CTRL_RECIPIENT_ENDPOINT)
self.ctrl_transfer(
dev_handle,
bmRequestType,
0x03,
0,
ep,
_interop.as_array(),
1000)
def get_backend(find_library=None):
try:
global _lib, _ctx
if _lib is None:
_lib = _load_library(find_library)
_setup_prototypes(_lib)
_ctx = _Context()
_logger.warning('OpenUSB backend deprecated (https://github.com/pyusb/pyusb/issues/284)')
return _OpenUSB()
except usb.libloader.LibraryException:
# exception already logged (if any)
_logger.error('Error loading OpenUSB backend', exc_info=False)
return None
except Exception:
_logger.error('Error loading OpenUSB backend', exc_info=True)
return None