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
110
lib/python3.11/site-packages/usb/__init__.py
Normal file
110
lib/python3.11/site-packages/usb/__init__.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
# 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"""PyUSB - Easy USB access in Python
|
||||
|
||||
This package exports the following modules and subpackages:
|
||||
|
||||
core - the main USB implementation
|
||||
legacy - the compatibility layer with 0.x version
|
||||
backend - the support for backend implementations.
|
||||
control - USB standard control requests.
|
||||
libloader - helper module for backend library loading.
|
||||
|
||||
Since version 1.0, main PyUSB implementation lives in the 'usb.core'
|
||||
module. New applications are encouraged to use it.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
__author__ = 'Wander Lairson Costa'
|
||||
|
||||
# Use Semantic Versioning, http://semver.org/
|
||||
try:
|
||||
from usb._version import version as __version__
|
||||
except ImportError:
|
||||
__version__ = '0.0.0'
|
||||
|
||||
def _get_extended_version_info(version):
|
||||
import re
|
||||
m = re.match(r'(\d+)\.(\d+)(\.(\d+))?[.-]?(.*)', version)
|
||||
major, minor, _, patch, suffix = m.groups()
|
||||
return int(major), int(minor), int(patch or "0"), suffix
|
||||
|
||||
extended_version_info = _get_extended_version_info(__version__)
|
||||
version_info = extended_version_info[:3]
|
||||
|
||||
__all__ = ['legacy', 'control', 'core', 'backend', 'util', 'libloader']
|
||||
|
||||
def _setup_log():
|
||||
from usb import _debug
|
||||
logger = logging.getLogger('usb')
|
||||
debug_level = os.getenv('PYUSB_DEBUG')
|
||||
|
||||
if debug_level is not None:
|
||||
_debug.enable_tracing(True)
|
||||
filename = os.getenv('PYUSB_LOG_FILENAME')
|
||||
|
||||
LEVELS = {'debug': logging.DEBUG,
|
||||
'info': logging.INFO,
|
||||
'warning': logging.WARNING,
|
||||
'error': logging.ERROR,
|
||||
'critical': logging.CRITICAL}
|
||||
|
||||
level = LEVELS.get(debug_level, logging.CRITICAL + 10)
|
||||
logger.setLevel(level = level)
|
||||
|
||||
try:
|
||||
handler = logging.FileHandler(filename)
|
||||
except:
|
||||
handler = logging.StreamHandler()
|
||||
|
||||
fmt = logging.Formatter('%(asctime)s %(levelname)s:%(name)s:%(message)s')
|
||||
handler.setFormatter(fmt)
|
||||
logger.addHandler(handler)
|
||||
else:
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
# We set the log level to avoid delegation to the
|
||||
# parent log handler (if there is one).
|
||||
# Thanks to Chris Clark to pointing this out.
|
||||
logger.setLevel(logging.CRITICAL + 10)
|
||||
|
||||
logger.addHandler(NullHandler())
|
||||
|
||||
|
||||
_setup_log()
|
||||
|
||||
# We import all 'legacy' module symbols to provide compatibility
|
||||
# with applications that use 0.x versions.
|
||||
from usb.legacy import *
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
79
lib/python3.11/site-packages/usb/_debug.py
Normal file
79
lib/python3.11/site-packages/usb/_debug.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
# 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.
|
||||
|
||||
__author__ = 'Wander Lairson Costa'
|
||||
|
||||
__all__ = ['methodtrace', 'functiontrace']
|
||||
|
||||
import functools
|
||||
import logging
|
||||
|
||||
_enable_tracing = False
|
||||
|
||||
def enable_tracing(enable):
|
||||
global _enable_tracing
|
||||
_enable_tracing = enable
|
||||
|
||||
def _trace_function_call(logger, fname, *args, **named_args):
|
||||
logger.debug(
|
||||
# TODO: check if 'f' is a method or a free function
|
||||
fname + '(' + \
|
||||
', '.join((str(val) for val in args)) + \
|
||||
', '.join((name + '=' + str(val) for name, val in named_args.items())) + ')'
|
||||
)
|
||||
|
||||
# decorator for methods calls tracing
|
||||
def methodtrace(logger):
|
||||
def decorator_logging(f):
|
||||
if not _enable_tracing:
|
||||
return f
|
||||
def do_trace(*args, **named_args):
|
||||
# this if is just a optimization to avoid unecessary string formatting
|
||||
if logging.DEBUG >= logger.getEffectiveLevel():
|
||||
fn = type(args[0]).__name__ + '.' + f.__name__
|
||||
_trace_function_call(logger, fn, *args[1:], **named_args)
|
||||
return f(*args, **named_args)
|
||||
functools.update_wrapper(do_trace, f)
|
||||
return do_trace
|
||||
return decorator_logging
|
||||
|
||||
# decorator for methods calls tracing
|
||||
def functiontrace(logger):
|
||||
def decorator_logging(f):
|
||||
if not _enable_tracing:
|
||||
return f
|
||||
def do_trace(*args, **named_args):
|
||||
# this if is just a optimization to avoid unecessary string formatting
|
||||
if logging.DEBUG >= logger.getEffectiveLevel():
|
||||
_trace_function_call(logger, f.__name__, *args, **named_args)
|
||||
return f(*args, **named_args)
|
||||
functools.update_wrapper(do_trace, f)
|
||||
return do_trace
|
||||
return decorator_logging
|
69
lib/python3.11/site-packages/usb/_interop.py
Normal file
69
lib/python3.11/site-packages/usb/_interop.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
# 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.
|
||||
|
||||
# All the hacks necessary to assure compatibility across all
|
||||
# supported versions come here.
|
||||
# Please, note that there is one version check for each
|
||||
# hack we need to do, this makes maintenance easier... ^^
|
||||
|
||||
import sys
|
||||
import array
|
||||
import usb.util as util
|
||||
|
||||
__all__ = []
|
||||
|
||||
# we support Python >= 3.9
|
||||
assert sys.hexversion >= 0x030900f0
|
||||
|
||||
def as_array(data_or_length=None):
|
||||
"""Convert loosely specified `data_or_length` to a byte array.
|
||||
|
||||
The following types of `data_or_length` are supported:
|
||||
|
||||
- an `array('B')` value (no-op, returns it back);
|
||||
- the `None` value (returns an new empty array);
|
||||
- an integer length (returns a new array with the specified size);
|
||||
- lists or iterables of small enough integers;
|
||||
- strings.
|
||||
"""
|
||||
|
||||
if isinstance(data_or_length, array.array) and data_or_length.typecode == 'B':
|
||||
return data_or_length
|
||||
|
||||
if isinstance(data_or_length, str):
|
||||
return array.array('B', data_or_length.encode('utf-8'))
|
||||
|
||||
if data_or_length is None:
|
||||
return array.array('B')
|
||||
|
||||
try:
|
||||
return util.create_buffer(data_or_length)
|
||||
except TypeError:
|
||||
return array.array('B', data_or_length)
|
96
lib/python3.11/site-packages/usb/_lookup.py
Normal file
96
lib/python3.11/site-packages/usb/_lookup.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
# 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._lookups - Lookup tables for USB
|
||||
"""
|
||||
|
||||
descriptors = {
|
||||
0x1 : "Device",
|
||||
0x2 : "Configuration",
|
||||
0x3 : "String",
|
||||
0x4 : "Interface",
|
||||
0x5 : "Endpoint",
|
||||
0x6 : "Device qualifier",
|
||||
0x7 : "Other speed configuration",
|
||||
0x8 : "Interface power",
|
||||
0x9 : "OTG",
|
||||
0xA : "Debug",
|
||||
0xB : "Interface association",
|
||||
0xC : "Security",
|
||||
0xD : "Key",
|
||||
0xE : "Encryption type",
|
||||
0xF : "Binary device object store (BOS)",
|
||||
0x10 : "Device capability",
|
||||
0x11 : "Wireless endpoint companion",
|
||||
0x30 : "SuperSpeed endpoint companion",
|
||||
}
|
||||
|
||||
device_classes = {
|
||||
0x0 : "Specified at interface",
|
||||
0x2 : "Communications Device",
|
||||
0x9 : "Hub",
|
||||
0xF : "Personal Healthcare Device",
|
||||
0xDC : "Diagnostic Device",
|
||||
0xE0 : "Wireless Controller",
|
||||
0xEF : "Miscellaneous",
|
||||
0xFF : "Vendor-specific",
|
||||
}
|
||||
|
||||
interface_classes = {
|
||||
0x0 : "Reserved",
|
||||
0x1 : "Audio",
|
||||
0x2 : "CDC Communication",
|
||||
0x3 : "Human Interface Device",
|
||||
0x5 : "Physical",
|
||||
0x6 : "Image",
|
||||
0x7 : "Printer",
|
||||
0x8 : "Mass Storage",
|
||||
0x9 : "Hub",
|
||||
0xA : "CDC Data",
|
||||
0xB : "Smart Card",
|
||||
0xD : "Content Security",
|
||||
0xE : "Video",
|
||||
0xF : "Personal Healthcare",
|
||||
0xDC : "Diagnostic Device",
|
||||
0xE0 : "Wireless Controller",
|
||||
0xEF : "Miscellaneous",
|
||||
0xFE : "Application Specific",
|
||||
0xFF : "Vendor Specific",
|
||||
}
|
||||
|
||||
ep_attributes = {
|
||||
0x0 : "Control",
|
||||
0x1 : "Isochronous",
|
||||
0x2 : "Bulk",
|
||||
0x3 : "Interrupt",
|
||||
}
|
||||
|
||||
MAX_POWER_UNITS_USB2p0 = 2 # mA
|
||||
MAX_POWER_UNITS_USB_SUPERSPEED = 8 # mA
|
142
lib/python3.11/site-packages/usb/_objfinalizer.py
Normal file
142
lib/python3.11/site-packages/usb/_objfinalizer.py
Normal file
|
@ -0,0 +1,142 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# 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.
|
||||
|
||||
__all__ = ['AutoFinalizedObject']
|
||||
|
||||
|
||||
class _AutoFinalizedObjectBase(object):
|
||||
"""
|
||||
Base class for objects that get automatically
|
||||
finalized on delete or at exit.
|
||||
"""
|
||||
|
||||
def _finalize_object(self):
|
||||
"""Actually finalizes the object (frees allocated resources etc.).
|
||||
|
||||
Returns: None
|
||||
|
||||
Derived classes should implement this.
|
||||
"""
|
||||
pass
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""Creates a new object instance and adds the private finalizer
|
||||
attributes to it.
|
||||
|
||||
Returns: new object instance
|
||||
|
||||
Arguments:
|
||||
* *args, **kwargs -- ignored
|
||||
"""
|
||||
instance = super(_AutoFinalizedObjectBase, cls).__new__(cls)
|
||||
instance._finalize_called = False
|
||||
return instance
|
||||
|
||||
def _do_finalize_object(self):
|
||||
"""Helper method that finalizes the object if not already done.
|
||||
|
||||
Returns: None
|
||||
"""
|
||||
if not self._finalize_called: # race-free?
|
||||
self._finalize_called = True
|
||||
self._finalize_object()
|
||||
|
||||
def finalize(self):
|
||||
"""Finalizes the object if not already done.
|
||||
|
||||
Returns: None
|
||||
"""
|
||||
# this is the "public" finalize method
|
||||
raise NotImplementedError(
|
||||
"finalize() must be implemented by AutoFinalizedObject."
|
||||
)
|
||||
|
||||
def __del__(self):
|
||||
self.finalize()
|
||||
|
||||
|
||||
import weakref
|
||||
|
||||
def _do_finalize_object_ref(obj_ref):
|
||||
"""Helper function for weakref.finalize() that dereferences a weakref
|
||||
to an object and calls its _do_finalize_object() method if the object
|
||||
is still alive. Does nothing otherwise.
|
||||
|
||||
Returns: None (implicit)
|
||||
|
||||
Arguments:
|
||||
* obj_ref -- weakref to an object
|
||||
"""
|
||||
obj = obj_ref()
|
||||
if obj is not None:
|
||||
# else object disappeared
|
||||
obj._do_finalize_object()
|
||||
|
||||
|
||||
class AutoFinalizedObject(_AutoFinalizedObjectBase):
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""Creates a new object instance and adds the private finalizer
|
||||
attributes to it.
|
||||
|
||||
Returns: new object instance
|
||||
|
||||
Arguments:
|
||||
* *args, **kwargs -- passed to the parent instance creator
|
||||
(which ignores them)
|
||||
"""
|
||||
# Note: Do not pass a (hard) reference to instance to the
|
||||
# finalizer as func/args/kwargs, it'd keep the object
|
||||
# alive until the program terminates.
|
||||
# A weak reference is fine.
|
||||
#
|
||||
# Note 2: When using weakrefs and not calling finalize() in
|
||||
# __del__, the object may already have disappeared
|
||||
# when weakref.finalize() kicks in.
|
||||
# Make sure that _finalizer() gets called,
|
||||
# i.e. keep __del__() from the base class.
|
||||
#
|
||||
# Note 3: the _finalize_called attribute is (probably) useless
|
||||
# for this class
|
||||
instance = super(AutoFinalizedObject, cls).__new__(
|
||||
cls, *args, **kwargs
|
||||
)
|
||||
|
||||
instance._finalizer = weakref.finalize(
|
||||
instance, _do_finalize_object_ref, weakref.ref(instance)
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
def finalize(self):
|
||||
"""Finalizes the object if not already done."""
|
||||
self._finalizer()
|
16
lib/python3.11/site-packages/usb/_version.py
Normal file
16
lib/python3.11/site-packages/usb/_version.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
# file generated by setuptools_scm
|
||||
# don't change, don't track in version control
|
||||
TYPE_CHECKING = False
|
||||
if TYPE_CHECKING:
|
||||
from typing import Tuple, Union
|
||||
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
||||
else:
|
||||
VERSION_TUPLE = object
|
||||
|
||||
version: str
|
||||
__version__: str
|
||||
__version_tuple__: VERSION_TUPLE
|
||||
version_tuple: VERSION_TUPLE
|
||||
|
||||
__version__ = version = '1.3.1'
|
||||
__version_tuple__ = version_tuple = (1, 3, 1)
|
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
|
262
lib/python3.11/site-packages/usb/control.py
Normal file
262
lib/python3.11/site-packages/usb/control.py
Normal file
|
@ -0,0 +1,262 @@
|
|||
# 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.control - USB standard control requests
|
||||
|
||||
This module exports:
|
||||
|
||||
get_status - get recipeint status
|
||||
clear_feature - clear a recipient feature
|
||||
set_feature - set a recipient feature
|
||||
get_descriptor - get a device descriptor
|
||||
set_descriptor - set a device descriptor
|
||||
get_configuration - get a device configuration
|
||||
set_configuration - set a device configuration
|
||||
get_interface - get a device interface
|
||||
set_interface - set a device interface
|
||||
"""
|
||||
|
||||
__author__ = 'Wander Lairson Costa'
|
||||
|
||||
__all__ = ['get_status',
|
||||
'clear_feature',
|
||||
'set_feature',
|
||||
'get_descriptor',
|
||||
'set_descriptor',
|
||||
'get_configuration',
|
||||
'set_configuration',
|
||||
'get_interface',
|
||||
'set_interface',
|
||||
'ENDPOINT_HALT',
|
||||
'FUNCTION_SUSPEND',
|
||||
'DEVICE_REMOTE_WAKEUP',
|
||||
'U1_ENABLE',
|
||||
'U2_ENABLE',
|
||||
'LTM_ENABLE']
|
||||
|
||||
import usb.util as util
|
||||
import usb.core as core
|
||||
|
||||
USBError = core.USBError
|
||||
|
||||
def _parse_recipient(recipient, direction):
|
||||
if recipient is None:
|
||||
r = util.CTRL_RECIPIENT_DEVICE
|
||||
wIndex = 0
|
||||
elif isinstance(recipient, core.Interface):
|
||||
r = util.CTRL_RECIPIENT_INTERFACE
|
||||
wIndex = recipient.bInterfaceNumber
|
||||
elif isinstance(recipient, core.Endpoint):
|
||||
r = util.CTRL_RECIPIENT_ENDPOINT
|
||||
wIndex = recipient.bEndpointAddress
|
||||
else:
|
||||
raise ValueError('Invalid recipient.')
|
||||
bmRequestType = util.build_request_type(
|
||||
direction,
|
||||
util.CTRL_TYPE_STANDARD,
|
||||
r
|
||||
)
|
||||
return (bmRequestType, wIndex)
|
||||
|
||||
# standard feature selectors from USB 2.0/3.0
|
||||
ENDPOINT_HALT = 0
|
||||
FUNCTION_SUSPEND = 0
|
||||
DEVICE_REMOTE_WAKEUP = 1
|
||||
U1_ENABLE = 48
|
||||
U2_ENABLE = 49
|
||||
LTM_ENABLE = 50
|
||||
|
||||
def get_status(dev, recipient = None):
|
||||
r"""Return the status for the specified recipient.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
|
||||
The recipient can be None (on which the status will be queried
|
||||
from the device), an Interface or Endpoint descriptors.
|
||||
|
||||
The status value is returned as an integer with the lower
|
||||
word being the two bytes status value.
|
||||
"""
|
||||
bmRequestType, wIndex = _parse_recipient(recipient, util.CTRL_IN)
|
||||
ret = dev.ctrl_transfer(bmRequestType = bmRequestType,
|
||||
bRequest = 0x00,
|
||||
wIndex = wIndex,
|
||||
data_or_wLength = 2)
|
||||
return ret[0] | (ret[1] << 8)
|
||||
|
||||
def clear_feature(dev, feature, recipient = None):
|
||||
r"""Clear/disable a specific feature.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
|
||||
feature is the feature you want to disable.
|
||||
|
||||
The recipient can be None (on which the status will be queried
|
||||
from the device), an Interface or Endpoint descriptors.
|
||||
"""
|
||||
if feature == ENDPOINT_HALT:
|
||||
dev.clear_halt(recipient)
|
||||
else:
|
||||
bmRequestType, wIndex = _parse_recipient(recipient, util.CTRL_OUT)
|
||||
dev.ctrl_transfer(bmRequestType = bmRequestType,
|
||||
bRequest = 0x01,
|
||||
wIndex = wIndex,
|
||||
wValue = feature)
|
||||
|
||||
def set_feature(dev, feature, recipient = None):
|
||||
r"""Set/enable a specific feature.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
|
||||
feature is the feature you want to enable.
|
||||
|
||||
The recipient can be None (on which the status will be queried
|
||||
from the device), an Interface or Endpoint descriptors.
|
||||
"""
|
||||
bmRequestType, wIndex = _parse_recipient(recipient, util.CTRL_OUT)
|
||||
dev.ctrl_transfer(bmRequestType = bmRequestType,
|
||||
bRequest = 0x03,
|
||||
wIndex = wIndex,
|
||||
wValue = feature)
|
||||
|
||||
def get_descriptor(dev, desc_size, desc_type, desc_index, wIndex = 0):
|
||||
r"""Return the specified descriptor.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
|
||||
desc_size is the descriptor size.
|
||||
|
||||
desc_type and desc_index are the descriptor type and index,
|
||||
respectively. wIndex index is used for string descriptors
|
||||
and represents the Language ID. For other types of descriptors,
|
||||
it is zero.
|
||||
"""
|
||||
wValue = desc_index | (desc_type << 8)
|
||||
|
||||
bmRequestType = util.build_request_type(
|
||||
util.CTRL_IN,
|
||||
util.CTRL_TYPE_STANDARD,
|
||||
util.CTRL_RECIPIENT_DEVICE)
|
||||
|
||||
desc = dev.ctrl_transfer(
|
||||
bmRequestType = bmRequestType,
|
||||
bRequest = 0x06,
|
||||
wValue = wValue,
|
||||
wIndex = wIndex,
|
||||
data_or_wLength = desc_size)
|
||||
|
||||
if len(desc) < 2:
|
||||
raise USBError('Invalid descriptor')
|
||||
|
||||
return desc
|
||||
|
||||
def set_descriptor(dev, desc, desc_type, desc_index, wIndex = None):
|
||||
r"""Update an existing descriptor or add a new one.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
|
||||
The desc parameter is the descriptor to be sent to the device.
|
||||
desc_type and desc_index are the descriptor type and index,
|
||||
respectively. wIndex index is used for string descriptors
|
||||
and represents the Language ID. For other types of descriptors,
|
||||
it is zero.
|
||||
"""
|
||||
wValue = desc_index | (desc_type << 8)
|
||||
|
||||
bmRequestType = util.build_request_type(
|
||||
util.CTRL_OUT,
|
||||
util.CTRL_TYPE_STANDARD,
|
||||
util.CTRL_RECIPIENT_DEVICE)
|
||||
|
||||
dev.ctrl_transfer(
|
||||
bmRequestType = bmRequestType,
|
||||
bRequest = 0x07,
|
||||
wValue = wValue,
|
||||
wIndex = wIndex,
|
||||
data_or_wLength = desc)
|
||||
|
||||
def get_configuration(dev):
|
||||
r"""Get the current active configuration of the device.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
|
||||
This function differs from the Device.get_active_configuration
|
||||
method because the later may use cached data, while this
|
||||
function always does a device request.
|
||||
"""
|
||||
bmRequestType = util.build_request_type(
|
||||
util.CTRL_IN,
|
||||
util.CTRL_TYPE_STANDARD,
|
||||
util.CTRL_RECIPIENT_DEVICE)
|
||||
|
||||
return dev.ctrl_transfer(
|
||||
bmRequestType,
|
||||
bRequest = 0x08,
|
||||
data_or_wLength = 1)[0]
|
||||
|
||||
def set_configuration(dev, bConfigurationNumber):
|
||||
r"""Set the current device configuration.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
"""
|
||||
dev.set_configuration(bConfigurationNumber)
|
||||
|
||||
def get_interface(dev, bInterfaceNumber):
|
||||
r"""Get the current alternate setting of the interface.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
"""
|
||||
bmRequestType = util.build_request_type(
|
||||
util.CTRL_IN,
|
||||
util.CTRL_TYPE_STANDARD,
|
||||
util.CTRL_RECIPIENT_INTERFACE)
|
||||
|
||||
return dev.ctrl_transfer(
|
||||
bmRequestType = bmRequestType,
|
||||
bRequest = 0x0a,
|
||||
wIndex = bInterfaceNumber,
|
||||
data_or_wLength = 1)[0]
|
||||
|
||||
def set_interface(dev, bInterfaceNumber, bAlternateSetting):
|
||||
r"""Set the alternate setting of the interface.
|
||||
|
||||
dev is the Device object to which the request will be
|
||||
sent to.
|
||||
"""
|
||||
dev.set_interface_altsetting(bInterfaceNumber, bAlternateSetting)
|
||||
|
1347
lib/python3.11/site-packages/usb/core.py
Normal file
1347
lib/python3.11/site-packages/usb/core.py
Normal file
File diff suppressed because it is too large
Load diff
361
lib/python3.11/site-packages/usb/legacy.py
Normal file
361
lib/python3.11/site-packages/usb/legacy.py
Normal file
|
@ -0,0 +1,361 @@
|
|||
# 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.
|
||||
|
||||
import usb.core as core
|
||||
import usb.util as util
|
||||
import usb._objfinalizer as _objfinalizer
|
||||
import usb.control as control
|
||||
|
||||
from itertools import groupby
|
||||
|
||||
__author__ = 'Wander Lairson Costa'
|
||||
|
||||
USBError = core.USBError
|
||||
|
||||
CLASS_AUDIO = 1
|
||||
CLASS_COMM = 2
|
||||
CLASS_DATA = 10
|
||||
CLASS_HID = 3
|
||||
CLASS_HUB = 9
|
||||
CLASS_MASS_STORAGE = 8
|
||||
CLASS_PER_INTERFACE = 0
|
||||
CLASS_PRINTER = 7
|
||||
CLASS_WIRELESS_CONTROLLER = 224
|
||||
CLASS_VENDOR_SPEC = 255
|
||||
DT_CONFIG = 2
|
||||
DT_CONFIG_SIZE = 9
|
||||
DT_DEVICE = 1
|
||||
DT_DEVICE_SIZE = 18
|
||||
DT_ENDPOINT = 5
|
||||
DT_ENDPOINT_AUDIO_SIZE = 9
|
||||
DT_ENDPOINT_SIZE = 7
|
||||
DT_HID = 33
|
||||
DT_HUB = 41
|
||||
DT_HUB_NONVAR_SIZE = 7
|
||||
DT_INTERFACE = 4
|
||||
DT_INTERFACE_SIZE = 9
|
||||
DT_PHYSICAL = 35
|
||||
DT_REPORT = 34
|
||||
DT_STRING = 3
|
||||
ENDPOINT_ADDRESS_MASK = 15
|
||||
ENDPOINT_DIR_MASK = 128
|
||||
ENDPOINT_IN = 128
|
||||
ENDPOINT_OUT = 0
|
||||
ENDPOINT_TYPE_BULK = 2
|
||||
ENDPOINT_TYPE_CONTROL = 0
|
||||
ENDPOINT_TYPE_INTERRUPT = 3
|
||||
ENDPOINT_TYPE_ISOCHRONOUS = 1
|
||||
ENDPOINT_TYPE_MASK = 3
|
||||
ERROR_BEGIN = 500000
|
||||
MAXALTSETTING = 128
|
||||
MAXCONFIG = 8
|
||||
MAXENDPOINTS = 32
|
||||
MAXINTERFACES = 32
|
||||
PROTOCOL_BLUETOOTH_PRIMARY_CONTROLLER = 1
|
||||
RECIP_DEVICE = 0
|
||||
RECIP_ENDPOINT = 2
|
||||
RECIP_INTERFACE = 1
|
||||
RECIP_OTHER = 3
|
||||
REQ_CLEAR_FEATURE = 1
|
||||
REQ_GET_CONFIGURATION = 8
|
||||
REQ_GET_DESCRIPTOR = 6
|
||||
REQ_GET_INTERFACE = 10
|
||||
REQ_GET_STATUS = 0
|
||||
REQ_SET_ADDRESS = 5
|
||||
REQ_SET_CONFIGURATION = 9
|
||||
REQ_SET_DESCRIPTOR = 7
|
||||
REQ_SET_FEATURE = 3
|
||||
REQ_SET_INTERFACE = 11
|
||||
REQ_SYNCH_FRAME = 12
|
||||
SUBCLASS_RF_CONTROLLER = 1
|
||||
TYPE_CLASS = 32
|
||||
TYPE_RESERVED = 96
|
||||
TYPE_STANDARD = 0
|
||||
TYPE_VENDOR = 64
|
||||
|
||||
class Endpoint(object):
|
||||
r"""Endpoint descriptor object."""
|
||||
def __init__(self, ep):
|
||||
self.address = ep.bEndpointAddress
|
||||
self.interval = ep.bInterval
|
||||
self.maxPacketSize = ep.wMaxPacketSize
|
||||
self.type = util.endpoint_type(ep.bmAttributes)
|
||||
|
||||
class Interface(object):
|
||||
r"""Interface descriptor object."""
|
||||
def __init__(self, intf):
|
||||
self.alternateSetting = intf.bAlternateSetting
|
||||
self.interfaceNumber = intf.bInterfaceNumber
|
||||
self.iInterface = intf.iInterface
|
||||
self.interfaceClass = intf.bInterfaceClass
|
||||
self.interfaceSubClass = intf.bInterfaceSubClass
|
||||
self.interfaceProtocol = intf.bInterfaceProtocol
|
||||
self.endpoints = [Endpoint(e) for e in intf]
|
||||
|
||||
class Configuration(object):
|
||||
r"""Configuration descriptor object."""
|
||||
def __init__(self, cfg):
|
||||
self.iConfiguration = cfg.iConfiguration
|
||||
self.maxPower = cfg.bMaxPower << 1
|
||||
self.remoteWakeup = (cfg.bmAttributes >> 5) & 1
|
||||
self.selfPowered = (cfg.bmAttributes >> 6) & 1
|
||||
self.totalLength = cfg.wTotalLength
|
||||
self.value = cfg.bConfigurationValue
|
||||
self.interfaces = [
|
||||
list(g) for k, g in groupby(
|
||||
sorted(
|
||||
[Interface(i) for i in cfg],
|
||||
key=lambda i: i.interfaceNumber
|
||||
),
|
||||
lambda i: i.alternateSetting)
|
||||
]
|
||||
|
||||
class DeviceHandle(_objfinalizer.AutoFinalizedObject):
|
||||
def __init__(self, dev):
|
||||
self.dev = dev
|
||||
self.__claimed_interface = None
|
||||
|
||||
def _finalize_object(self):
|
||||
if hasattr(self, 'dev') and self.dev:
|
||||
util.dispose_resources(self.dev)
|
||||
self.dev = None
|
||||
|
||||
def bulkWrite(self, endpoint, buffer, timeout = 100):
|
||||
r"""Perform a bulk write request to the endpoint specified.
|
||||
|
||||
Arguments:
|
||||
endpoint: endpoint number.
|
||||
buffer: sequence data buffer to write.
|
||||
This parameter can be any sequence type.
|
||||
timeout: operation timeout in milliseconds. (default: 100)
|
||||
Returns the number of bytes written.
|
||||
"""
|
||||
return self.dev.write(endpoint, buffer, timeout)
|
||||
|
||||
def bulkRead(self, endpoint, size, timeout = 100):
|
||||
r"""Performs a bulk read request to the endpoint specified.
|
||||
|
||||
Arguments:
|
||||
endpoint: endpoint number.
|
||||
size: number of bytes to read.
|
||||
timeout: operation timeout in milliseconds. (default: 100)
|
||||
Returns a tuple with the data read.
|
||||
"""
|
||||
return self.dev.read(endpoint, size, timeout)
|
||||
|
||||
def interruptWrite(self, endpoint, buffer, timeout = 100):
|
||||
r"""Perform a interrupt write request to the endpoint specified.
|
||||
|
||||
Arguments:
|
||||
endpoint: endpoint number.
|
||||
buffer: sequence data buffer to write.
|
||||
This parameter can be any sequence type.
|
||||
timeout: operation timeout in milliseconds. (default: 100)
|
||||
Returns the number of bytes written.
|
||||
"""
|
||||
return self.dev.write(endpoint, buffer, timeout)
|
||||
|
||||
def interruptRead(self, endpoint, size, timeout = 100):
|
||||
r"""Performs a interrupt read request to the endpoint specified.
|
||||
|
||||
Arguments:
|
||||
endpoint: endpoint number.
|
||||
size: number of bytes to read.
|
||||
timeout: operation timeout in milliseconds. (default: 100)
|
||||
Returns a tuple with the data read.
|
||||
"""
|
||||
return self.dev.read(endpoint, size, timeout)
|
||||
|
||||
def controlMsg(self, requestType, request, buffer, value = 0, index = 0, timeout = 100):
|
||||
r"""Perform a control request to the default control pipe on a device.
|
||||
|
||||
Arguments:
|
||||
requestType: specifies the direction of data flow, the type
|
||||
of request, and the recipient.
|
||||
request: specifies the request.
|
||||
buffer: if the transfer is a write transfer, buffer is a sequence
|
||||
with the transfer data, otherwise, buffer is the number of
|
||||
bytes to read.
|
||||
value: specific information to pass to the device. (default: 0)
|
||||
index: specific information to pass to the device. (default: 0)
|
||||
timeout: operation timeout in milliseconds. (default: 100)
|
||||
Returns the number of bytes written.
|
||||
"""
|
||||
return self.dev.ctrl_transfer(
|
||||
requestType,
|
||||
request,
|
||||
wValue = value,
|
||||
wIndex = index,
|
||||
data_or_wLength = buffer,
|
||||
timeout = timeout)
|
||||
|
||||
def clearHalt(self, endpoint):
|
||||
r"""Clears any halt status on the specified endpoint.
|
||||
|
||||
Arguments:
|
||||
endpoint: endpoint number.
|
||||
"""
|
||||
self.dev.clear_halt(endpoint)
|
||||
|
||||
def claimInterface(self, interface):
|
||||
r"""Claims the interface with the Operating System.
|
||||
|
||||
Arguments:
|
||||
interface: interface number or an Interface object.
|
||||
"""
|
||||
if isinstance(interface, Interface):
|
||||
interface = interface.interfaceNumber
|
||||
|
||||
util.claim_interface(self.dev, interface)
|
||||
self.__claimed_interface = interface
|
||||
|
||||
def releaseInterface(self):
|
||||
r"""Release an interface previously claimed with claimInterface."""
|
||||
util.release_interface(self.dev, self.__claimed_interface)
|
||||
self.__claimed_interface = -1
|
||||
|
||||
def reset(self):
|
||||
r"""Reset the specified device by sending a RESET
|
||||
down the port it is connected to."""
|
||||
self.dev.reset()
|
||||
|
||||
def resetEndpoint(self, endpoint):
|
||||
r"""Reset all states for the specified endpoint.
|
||||
|
||||
Arguments:
|
||||
endpoint: endpoint number.
|
||||
"""
|
||||
self.clearHalt(endpoint)
|
||||
|
||||
def setConfiguration(self, configuration):
|
||||
r"""Set the active configuration of a device.
|
||||
|
||||
Arguments:
|
||||
configuration: a configuration value or a Configuration object.
|
||||
"""
|
||||
if isinstance(configuration, Configuration):
|
||||
configuration = configuration.value
|
||||
|
||||
self.dev.set_configuration(configuration)
|
||||
|
||||
def setAltInterface(self, alternate):
|
||||
r"""Sets the active alternate setting of the current interface.
|
||||
|
||||
Arguments:
|
||||
alternate: an alternate setting number or an Interface object.
|
||||
"""
|
||||
if isinstance(alternate, Interface):
|
||||
alternate = alternate.alternateSetting
|
||||
|
||||
self.dev.set_interface_altsetting(self.__claimed_interface, alternate)
|
||||
|
||||
def getString(self, index, length, langid = None):
|
||||
r"""Retrieve the string descriptor specified by index
|
||||
and langid from a device.
|
||||
|
||||
Arguments:
|
||||
index: index of descriptor in the device.
|
||||
length: number of bytes of the string (ignored)
|
||||
langid: Language ID. If it is omitted, the first
|
||||
language will be used.
|
||||
"""
|
||||
return util.get_string(self.dev, index, langid).encode('ascii')
|
||||
|
||||
def getDescriptor(self, desc_type, desc_index, length, endpoint = -1):
|
||||
r"""Retrieves a descriptor from the device identified by the type
|
||||
and index of the descriptor.
|
||||
|
||||
Arguments:
|
||||
desc_type: descriptor type.
|
||||
desc_index: index of the descriptor.
|
||||
len: descriptor length.
|
||||
endpoint: ignored.
|
||||
"""
|
||||
return control.get_descriptor(self.dev, length, desc_type, desc_index)
|
||||
|
||||
def detachKernelDriver(self, interface):
|
||||
r"""Detach a kernel driver from the interface (if one is attached,
|
||||
we have permission and the operation is supported by the OS)
|
||||
|
||||
Arguments:
|
||||
interface: interface number or an Interface object.
|
||||
"""
|
||||
if isinstance(interface, Interface):
|
||||
interface = interface.interfaceNumber
|
||||
|
||||
self.dev.detach_kernel_driver(interface)
|
||||
|
||||
class Device(object):
|
||||
r"""Device descriptor object"""
|
||||
def __init__(self, dev):
|
||||
self.deviceClass = dev.bDeviceClass
|
||||
self.deviceSubClass = dev.bDeviceSubClass
|
||||
self.deviceProtocol = dev.bDeviceProtocol
|
||||
self.deviceVersion = str((dev.bcdDevice >> 12) & 0xf) + \
|
||||
str((dev.bcdDevice >> 8) & 0xf) + \
|
||||
'.' + \
|
||||
str((dev.bcdDevice >> 4) & 0xf) + \
|
||||
str(dev.bcdDevice & 0xf)
|
||||
self.devnum = dev.address
|
||||
self.filename = ''
|
||||
self.iManufacturer = dev.iManufacturer
|
||||
self.iProduct = dev.iProduct
|
||||
self.iSerialNumber = dev.iSerialNumber
|
||||
self.idProduct = dev.idProduct
|
||||
self.idVendor = dev.idVendor
|
||||
self.maxPacketSize = dev.bMaxPacketSize0
|
||||
self.usbVersion = str((dev.bcdUSB >> 12) & 0xf) + \
|
||||
str((dev.bcdUSB >> 8) & 0xf) + \
|
||||
'.' + \
|
||||
str((dev.bcdUSB >> 4) & 0xf) + \
|
||||
str(dev.bcdUSB & 0xf)
|
||||
self.configurations = [Configuration(c) for c in dev]
|
||||
self.dev = dev
|
||||
|
||||
def open(self):
|
||||
r"""Open the device for use.
|
||||
|
||||
Returns a DeviceHandle object
|
||||
"""
|
||||
return DeviceHandle(self.dev)
|
||||
|
||||
class Bus(object):
|
||||
r"""Bus object."""
|
||||
def __init__(self, devices):
|
||||
self.dirname = ''
|
||||
self.devices = [Device(d) for d in devices]
|
||||
self.location = self.devices[0].dev.bus
|
||||
|
||||
def busses():
|
||||
r"""Returns a tuple with the usb busses."""
|
||||
return (Bus(g) for k, g in groupby(
|
||||
sorted(core.find(find_all=True), key=lambda d: d.bus),
|
||||
lambda d: d.bus))
|
||||
|
208
lib/python3.11/site-packages/usb/libloader.py
Normal file
208
lib/python3.11/site-packages/usb/libloader.py
Normal file
|
@ -0,0 +1,208 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# 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.
|
||||
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import logging
|
||||
import os.path
|
||||
import platform
|
||||
import sys
|
||||
|
||||
__all__ = [
|
||||
'LibraryException',
|
||||
'LibraryNotFoundException',
|
||||
'NoLibraryCandidatesException',
|
||||
'LibraryNotLoadedException',
|
||||
'LibraryMissingSymbolsException',
|
||||
'locate_library',
|
||||
'load_library',
|
||||
'load_locate_library'
|
||||
]
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger('usb.libloader')
|
||||
|
||||
|
||||
class LibraryException(OSError):
|
||||
pass
|
||||
|
||||
class LibraryNotFoundException(LibraryException):
|
||||
pass
|
||||
|
||||
class NoLibraryCandidatesException(LibraryNotFoundException):
|
||||
pass
|
||||
|
||||
class LibraryNotLoadedException(LibraryException):
|
||||
pass
|
||||
|
||||
class LibraryMissingSymbolsException(LibraryException):
|
||||
pass
|
||||
|
||||
|
||||
def locate_library(candidates, find_library=ctypes.util.find_library):
|
||||
"""Tries to locate a library listed in candidates using the given
|
||||
find_library() function (or ctypes.util.find_library).
|
||||
Returns the first library found, which can be the library's name
|
||||
or the path to the library file, depending on find_library().
|
||||
Returns None if no library is found.
|
||||
|
||||
arguments:
|
||||
* candidates -- iterable with library names
|
||||
* find_library -- function that takes one positional arg (candidate)
|
||||
and returns a non-empty str if a library has been found.
|
||||
Any "false" value (None,False,empty str) is interpreted
|
||||
as "library not found".
|
||||
Defaults to ctypes.util.find_library if not given or
|
||||
None.
|
||||
"""
|
||||
if find_library is None:
|
||||
find_library = ctypes.util.find_library
|
||||
|
||||
use_dll_workaround = (
|
||||
sys.platform == 'win32' and find_library is ctypes.util.find_library
|
||||
)
|
||||
|
||||
use_apple_silicon_workaround = (
|
||||
sys.platform == 'darwin' and platform.machine() == 'arm64'
|
||||
and find_library is ctypes.util.find_library
|
||||
)
|
||||
|
||||
for candidate in candidates:
|
||||
# Workaround for CPython 3.3 issue#16283 / pyusb #14
|
||||
if use_dll_workaround:
|
||||
candidate += '.dll'
|
||||
|
||||
libname = find_library(candidate)
|
||||
if libname:
|
||||
return libname
|
||||
|
||||
# On Apple Silicon, also check in `/opt/homebrew/lib`: homebrew patches
|
||||
# the Python interpreters it distributes to check that directory, but
|
||||
# other/stock interpreters don't know about it
|
||||
if use_apple_silicon_workaround:
|
||||
libname = "/opt/homebrew/lib/" + candidate + ".dylib"
|
||||
if os.path.isfile(libname):
|
||||
return libname
|
||||
|
||||
return None
|
||||
|
||||
def load_library(lib, name=None, lib_cls=None):
|
||||
"""Loads a library. Catches and logs exceptions.
|
||||
|
||||
Returns: the loaded library or None
|
||||
|
||||
arguments:
|
||||
* lib -- path to/name of the library to be loaded
|
||||
* name -- the library's identifier (for logging)
|
||||
Defaults to None.
|
||||
* lib_cls -- library class. Defaults to None (-> ctypes.CDLL).
|
||||
"""
|
||||
try:
|
||||
if lib_cls:
|
||||
return lib_cls(lib)
|
||||
else:
|
||||
return ctypes.CDLL(lib)
|
||||
except Exception:
|
||||
if name:
|
||||
lib_msg = '%s (%s)' % (name, lib)
|
||||
else:
|
||||
lib_msg = lib
|
||||
|
||||
lib_msg += ' could not be loaded'
|
||||
|
||||
if sys.platform == 'cygwin':
|
||||
lib_msg += ' in cygwin'
|
||||
_LOGGER.error(lib_msg, exc_info=True)
|
||||
return None
|
||||
|
||||
def load_locate_library(candidates, cygwin_lib, name,
|
||||
win_cls=None, cygwin_cls=None, others_cls=None,
|
||||
find_library=None, check_symbols=None):
|
||||
"""Locates and loads a library.
|
||||
|
||||
Returns: the loaded library
|
||||
|
||||
arguments:
|
||||
* candidates -- candidates list for locate_library()
|
||||
* cygwin_lib -- name of the cygwin library
|
||||
* name -- lib identifier (for logging). Defaults to None.
|
||||
* win_cls -- class that is used to instantiate the library on
|
||||
win32 platforms. Defaults to None (-> ctypes.CDLL).
|
||||
* cygwin_cls -- library class for cygwin platforms.
|
||||
Defaults to None (-> ctypes.CDLL).
|
||||
* others_cls -- library class for all other platforms.
|
||||
Defaults to None (-> ctypes.CDLL).
|
||||
* find_library -- see locate_library(). Defaults to None.
|
||||
* check_symbols -- either None or a list of symbols that the loaded lib
|
||||
must provide (hasattr(<>)) in order to be considered
|
||||
valid. LibraryMissingSymbolsException is raised if
|
||||
any symbol is missing.
|
||||
|
||||
raises:
|
||||
* NoLibraryCandidatesException
|
||||
* LibraryNotFoundException
|
||||
* LibraryNotLoadedException
|
||||
* LibraryMissingSymbolsException
|
||||
"""
|
||||
if sys.platform == 'cygwin':
|
||||
if cygwin_lib:
|
||||
loaded_lib = load_library(cygwin_lib, name, cygwin_cls)
|
||||
else:
|
||||
raise NoLibraryCandidatesException(name)
|
||||
elif candidates:
|
||||
lib = locate_library(candidates, find_library)
|
||||
if lib:
|
||||
_LOGGER.debug("%r found as %s", (name or candidates), lib)
|
||||
if sys.platform == 'win32':
|
||||
loaded_lib = load_library(lib, name, win_cls)
|
||||
else:
|
||||
loaded_lib = load_library(lib, name, others_cls)
|
||||
else:
|
||||
_LOGGER.error('%r could not be found', (name or candidates))
|
||||
raise LibraryNotFoundException(name)
|
||||
else:
|
||||
raise NoLibraryCandidatesException(name)
|
||||
|
||||
if loaded_lib is None:
|
||||
raise LibraryNotLoadedException(name)
|
||||
elif check_symbols:
|
||||
symbols_missing = [
|
||||
s for s in check_symbols if not hasattr(loaded_lib, s)
|
||||
]
|
||||
if symbols_missing:
|
||||
msg = ('%r, missing symbols: %r', lib, symbols_missing )
|
||||
_LOGGER.error(msg)
|
||||
raise LibraryMissingSymbolsException(lib)
|
||||
else:
|
||||
return loaded_lib
|
||||
else:
|
||||
return loaded_lib
|
321
lib/python3.11/site-packages/usb/util.py
Normal file
321
lib/python3.11/site-packages/usb/util.py
Normal file
|
@ -0,0 +1,321 @@
|
|||
# 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.util - Utility functions.
|
||||
|
||||
This module exports:
|
||||
|
||||
endpoint_address - return the endpoint absolute address.
|
||||
endpoint_direction - return the endpoint transfer direction.
|
||||
endpoint_type - return the endpoint type
|
||||
ctrl_direction - return the direction of a control transfer
|
||||
build_request_type - build a bmRequestType field of a control transfer.
|
||||
find_descriptor - find an inner descriptor.
|
||||
claim_interface - explicitly claim an interface.
|
||||
release_interface - explicitly release an interface.
|
||||
dispose_resources - release internal resources allocated by the object.
|
||||
get_langids - retrieve the list of supported string languages from the device.
|
||||
get_string - retrieve a string descriptor from the device.
|
||||
"""
|
||||
|
||||
__author__ = 'Wander Lairson Costa'
|
||||
|
||||
import operator
|
||||
import array
|
||||
|
||||
# descriptor type
|
||||
DESC_TYPE_DEVICE = 0x01
|
||||
DESC_TYPE_CONFIG = 0x02
|
||||
DESC_TYPE_STRING = 0x03
|
||||
DESC_TYPE_INTERFACE = 0x04
|
||||
DESC_TYPE_ENDPOINT = 0x05
|
||||
|
||||
# endpoint direction
|
||||
ENDPOINT_IN = 0x80
|
||||
ENDPOINT_OUT = 0x00
|
||||
|
||||
# endpoint type
|
||||
ENDPOINT_TYPE_CTRL = 0x00
|
||||
ENDPOINT_TYPE_ISO = 0x01
|
||||
ENDPOINT_TYPE_BULK = 0x02
|
||||
ENDPOINT_TYPE_INTR = 0x03
|
||||
|
||||
# control request type
|
||||
CTRL_TYPE_STANDARD = (0 << 5)
|
||||
CTRL_TYPE_CLASS = (1 << 5)
|
||||
CTRL_TYPE_VENDOR = (2 << 5)
|
||||
CTRL_TYPE_RESERVED = (3 << 5)
|
||||
|
||||
# control request recipient
|
||||
CTRL_RECIPIENT_DEVICE = 0
|
||||
CTRL_RECIPIENT_INTERFACE = 1
|
||||
CTRL_RECIPIENT_ENDPOINT = 2
|
||||
CTRL_RECIPIENT_OTHER = 3
|
||||
|
||||
# control request direction
|
||||
CTRL_OUT = 0x00
|
||||
CTRL_IN = 0x80
|
||||
|
||||
_ENDPOINT_ADDR_MASK = 0x0f
|
||||
_ENDPOINT_DIR_MASK = 0x80
|
||||
_ENDPOINT_TRANSFER_TYPE_MASK = 0x03
|
||||
_CTRL_DIR_MASK = 0x80
|
||||
|
||||
# speed type
|
||||
SPEED_LOW = 1
|
||||
SPEED_FULL = 2
|
||||
SPEED_HIGH = 3
|
||||
SPEED_SUPER = 4
|
||||
SPEED_UNKNOWN = 0
|
||||
|
||||
def endpoint_address(address):
|
||||
r"""Return the endpoint absolute address.
|
||||
|
||||
The address parameter is the bEndpointAddress field
|
||||
of the endpoint descriptor.
|
||||
"""
|
||||
return address & _ENDPOINT_ADDR_MASK
|
||||
|
||||
def endpoint_direction(address):
|
||||
r"""Return the endpoint direction.
|
||||
|
||||
The address parameter is the bEndpointAddress field
|
||||
of the endpoint descriptor.
|
||||
The possible return values are ENDPOINT_OUT or ENDPOINT_IN.
|
||||
"""
|
||||
return address & _ENDPOINT_DIR_MASK
|
||||
|
||||
def endpoint_type(bmAttributes):
|
||||
r"""Return the transfer type of the endpoint.
|
||||
|
||||
The bmAttributes parameter is the bmAttributes field
|
||||
of the endpoint descriptor.
|
||||
The possible return values are: ENDPOINT_TYPE_CTRL,
|
||||
ENDPOINT_TYPE_ISO, ENDPOINT_TYPE_BULK or ENDPOINT_TYPE_INTR.
|
||||
"""
|
||||
return bmAttributes & _ENDPOINT_TRANSFER_TYPE_MASK
|
||||
|
||||
def ctrl_direction(bmRequestType):
|
||||
r"""Return the direction of a control request.
|
||||
|
||||
The bmRequestType parameter is the value of the
|
||||
bmRequestType field of a control transfer.
|
||||
The possible return values are CTRL_OUT or CTRL_IN.
|
||||
"""
|
||||
return bmRequestType & _CTRL_DIR_MASK
|
||||
|
||||
def build_request_type(direction, type, recipient):
|
||||
r"""Build a bmRequestType field for control requests.
|
||||
|
||||
These is a conventional function to build a bmRequestType
|
||||
for a control request.
|
||||
|
||||
The direction parameter can be CTRL_OUT or CTRL_IN.
|
||||
The type parameter can be CTRL_TYPE_STANDARD, CTRL_TYPE_CLASS,
|
||||
CTRL_TYPE_VENDOR or CTRL_TYPE_RESERVED values.
|
||||
The recipient can be CTRL_RECIPIENT_DEVICE, CTRL_RECIPIENT_INTERFACE,
|
||||
CTRL_RECIPIENT_ENDPOINT or CTRL_RECIPIENT_OTHER.
|
||||
|
||||
Return the bmRequestType value.
|
||||
"""
|
||||
return recipient | type | direction
|
||||
|
||||
def create_buffer(length):
|
||||
r"""Create a buffer to be passed to a read function.
|
||||
|
||||
A read function may receive an out buffer so the data
|
||||
is read inplace and the object can be reused, avoiding
|
||||
the overhead of creating a new object at each new read
|
||||
call. This function creates a compatible sequence buffer
|
||||
of the given length.
|
||||
"""
|
||||
# Return an array with `length` zeros or raise a `TypeError`.
|
||||
return array.array('B', length * b"\x00")
|
||||
|
||||
def find_descriptor(desc, find_all=False, custom_match=None, **args):
|
||||
r"""Find an inner descriptor.
|
||||
|
||||
find_descriptor works in the same way as the core.find() function does,
|
||||
but it acts on general descriptor objects. For example, suppose you
|
||||
have a Device object called dev and want a Configuration of this
|
||||
object with its bConfigurationValue equals to 1, the code would
|
||||
be like so:
|
||||
|
||||
>>> cfg = util.find_descriptor(dev, bConfigurationValue=1)
|
||||
|
||||
You can use any field of the Descriptor as a match criteria, and you
|
||||
can supply a customized match just like core.find() does. The
|
||||
find_descriptor function also accepts the find_all parameter to get
|
||||
an iterator instead of just one descriptor.
|
||||
"""
|
||||
def desc_iter(**kwargs):
|
||||
for d in desc:
|
||||
tests = (val == getattr(d, key) for key, val in kwargs.items())
|
||||
if all(tests) and (custom_match is None or custom_match(d)):
|
||||
yield d
|
||||
|
||||
if find_all:
|
||||
return desc_iter(**args)
|
||||
else:
|
||||
try:
|
||||
return next(desc_iter(**args))
|
||||
except StopIteration:
|
||||
return None
|
||||
|
||||
def claim_interface(device, interface):
|
||||
r"""Explicitly claim an interface.
|
||||
|
||||
PyUSB users normally do not have to worry about interface claiming,
|
||||
as the library takes care of it automatically. But there are situations
|
||||
where you need deterministic interface claiming. For these uncommon
|
||||
cases, you can use claim_interface.
|
||||
|
||||
If the interface is already claimed, either through a previously call
|
||||
to claim_interface or internally by the device object, nothing happens.
|
||||
"""
|
||||
device._ctx.managed_claim_interface(device, interface)
|
||||
|
||||
def release_interface(device, interface):
|
||||
r"""Explicitly release an interface.
|
||||
|
||||
This function is used to release an interface previously claimed,
|
||||
either through a call to claim_interface or internally by the
|
||||
device object.
|
||||
|
||||
Normally, you do not need to worry about claiming policies, as
|
||||
the device object takes care of it automatically.
|
||||
"""
|
||||
device._ctx.managed_release_interface(device, interface)
|
||||
|
||||
def dispose_resources(device):
|
||||
r"""Release internal resources allocated by the object.
|
||||
|
||||
Sometimes you need to provide deterministic resources
|
||||
freeing, for example to allow another application to
|
||||
talk to the device. As Python does not provide deterministic
|
||||
destruction, this function releases all internal resources
|
||||
allocated by the device, like device handle and interface
|
||||
policy.
|
||||
|
||||
After calling this function, you can continue using the device
|
||||
object normally. If the resources will be necessary again, it
|
||||
will be allocated automatically.
|
||||
"""
|
||||
device._ctx.dispose(device)
|
||||
|
||||
def get_langids(dev):
|
||||
r"""Retrieve the list of supported Language IDs from the device.
|
||||
|
||||
Most client code should not call this function directly, but instead use
|
||||
the langids property on the Device object, which will call this function as
|
||||
needed and cache the result.
|
||||
|
||||
USB LANGIDs are 16-bit integers familiar to Windows developers, where
|
||||
for example instead of en-US you say 0x0409. See the file USB_LANGIDS.pdf
|
||||
somewhere on the usb.org site for a list, which does not claim to be
|
||||
complete. It requires "system software must allow the enumeration and
|
||||
selection of LANGIDs that are not currently on this list." It also requires
|
||||
"system software should never request a LANGID not defined in the LANGID
|
||||
code array (string index = 0) presented by a device." Client code can
|
||||
check this tuple before issuing string requests for a specific language ID.
|
||||
|
||||
dev is the Device object whose supported language IDs will be retrieved.
|
||||
|
||||
The return value is a tuple of integer LANGIDs, possibly empty if the
|
||||
device does not support strings at all (which USB 3.1 r1.0 section
|
||||
9.6.9 allows). In that case client code should not request strings at all.
|
||||
|
||||
A USBError may be raised from this function for some devices that have no
|
||||
string support, instead of returning an empty tuple. The accessor for the
|
||||
langids property on Device catches that case and supplies an empty tuple,
|
||||
so client code can ignore this detail by using the langids property instead
|
||||
of directly calling this function.
|
||||
"""
|
||||
from usb.control import get_descriptor
|
||||
buf = get_descriptor(
|
||||
dev,
|
||||
254,
|
||||
DESC_TYPE_STRING,
|
||||
0
|
||||
)
|
||||
|
||||
# The array is retrieved by asking for string descriptor zero, which is
|
||||
# never the index of a real string. The returned descriptor has bLength
|
||||
# and bDescriptorType bytes followed by pairs of bytes representing
|
||||
# little-endian LANGIDs. That is, buf[0] contains the length of the
|
||||
# returned array, buf[2] is the least-significant byte of the first LANGID
|
||||
# (if any), buf[3] is the most-significant byte, and in general the LSBs of
|
||||
# all the LANGIDs are given by buf[2:buf[0]:2] and MSBs by buf[3:buf[0]:2].
|
||||
# If the length of buf came back odd, something is wrong.
|
||||
|
||||
if len(buf) < 4 or buf[0] < 4 or buf[0]&1 != 0:
|
||||
return ()
|
||||
|
||||
return tuple(map(lambda x,y: x+(y<<8), buf[2:buf[0]:2], buf[3:buf[0]:2]))
|
||||
|
||||
def get_string(dev, index, langid = None):
|
||||
r"""Retrieve a string descriptor from the device.
|
||||
|
||||
dev is the Device object which the string will be read from.
|
||||
|
||||
index is the string descriptor index and langid is the Language
|
||||
ID of the descriptor. If langid is omitted, the string descriptor
|
||||
of the first Language ID will be returned.
|
||||
|
||||
Zero is never the index of a real string. The USB spec allows a device to
|
||||
use zero in a string index field to indicate that no string is provided.
|
||||
So the caller does not have to treat that case specially, this function
|
||||
returns None if passed an index of zero, and generates no traffic
|
||||
to the device.
|
||||
|
||||
The return value is the unicode string present in the descriptor, or None
|
||||
if the requested index was zero.
|
||||
"""
|
||||
if 0 == index:
|
||||
return None
|
||||
|
||||
from usb.control import get_descriptor
|
||||
|
||||
if langid is None:
|
||||
langids = dev.langids
|
||||
if 0 == len(langids):
|
||||
raise ValueError("The device has no langid"
|
||||
" (permission issue, no string descriptors supported or device error)")
|
||||
langid = langids[0]
|
||||
|
||||
buf = get_descriptor(
|
||||
dev,
|
||||
254, # maximum even length
|
||||
DESC_TYPE_STRING,
|
||||
index,
|
||||
langid
|
||||
)
|
||||
blen = buf[0] & 0xfe # should be even, ignore any trailing byte (see #154)
|
||||
return buf[2:blen].tobytes().decode('utf-16-le')
|
Loading…
Add table
Add a link
Reference in a new issue