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:
parent
4c654ec969
commit
1751076592
2614 changed files with 349009 additions and 0 deletions
384
lib/python3.11/site-packages/usb/backend/__init__.py
Normal file
384
lib/python3.11/site-packages/usb/backend/__init__.py
Normal 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)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
748
lib/python3.11/site-packages/usb/backend/libusb0.py
Normal file
748
lib/python3.11/site-packages/usb/backend/libusb0.py
Normal 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
|
975
lib/python3.11/site-packages/usb/backend/libusb1.py
Normal file
975
lib/python3.11/site-packages/usb/backend/libusb1.py
Normal 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
|
759
lib/python3.11/site-packages/usb/backend/openusb.py
Normal file
759
lib/python3.11/site-packages/usb/backend/openusb.py
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue