1367 lines
53 KiB
Python
1367 lines
53 KiB
Python
|
# Copyright (C) 2010-2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||
|
#
|
||
|
# This library is free software; you can redistribute it and/or
|
||
|
# modify it under the terms of the GNU Lesser General Public
|
||
|
# License as published by the Free Software Foundation; either
|
||
|
# version 2.1 of the License, or (at your option) any later version.
|
||
|
#
|
||
|
# This library is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
# Lesser General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU Lesser General Public
|
||
|
# License along with this library; if not, write to the Free Software
|
||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
||
|
# pylint: disable=invalid-name, too-few-public-methods, too-many-arguments
|
||
|
# pylint: disable=missing-docstring
|
||
|
"""
|
||
|
Python ctypes bindings for libusb-1.0.
|
||
|
|
||
|
You should not need to import this if you use usb1 module.
|
||
|
|
||
|
Declares all constants, data structures and exported symbols.
|
||
|
Some are only available after calling loadLibrary.
|
||
|
"""
|
||
|
from ctypes import (
|
||
|
Structure, LittleEndianStructure,
|
||
|
CFUNCTYPE, POINTER, addressof, sizeof, cast,
|
||
|
c_short, c_int, c_uint, c_long,
|
||
|
c_uint8, c_uint16, c_uint32,
|
||
|
c_void_p, c_char_p, py_object, pointer, c_char,
|
||
|
c_ssize_t, CDLL
|
||
|
)
|
||
|
import ctypes.util
|
||
|
import os.path
|
||
|
import platform
|
||
|
import sys
|
||
|
from threading import Lock
|
||
|
|
||
|
class Enum:
|
||
|
def __init__(self, member_dict, scope_dict=None):
|
||
|
if scope_dict is None:
|
||
|
# Affect caller's locals, not this module's.
|
||
|
# pylint: disable=protected-access
|
||
|
scope_dict = sys._getframe(1).f_locals
|
||
|
# pylint: enable=protected-access
|
||
|
forward_dict = {}
|
||
|
reverse_dict = {}
|
||
|
next_value = 0
|
||
|
for name, value in member_dict.items():
|
||
|
if value is None:
|
||
|
value = next_value
|
||
|
next_value += 1
|
||
|
forward_dict[name] = value
|
||
|
if value in reverse_dict:
|
||
|
raise ValueError('Multiple names for value %r: %r, %r' % (
|
||
|
value, reverse_dict[value], name
|
||
|
))
|
||
|
reverse_dict[value] = name
|
||
|
scope_dict[name] = value
|
||
|
self.forward_dict = forward_dict
|
||
|
self.reverse_dict = reverse_dict
|
||
|
|
||
|
def __call__(self, value):
|
||
|
return self.reverse_dict[value]
|
||
|
|
||
|
def get(self, value, default=None):
|
||
|
return self.reverse_dict.get(value, default)
|
||
|
|
||
|
def buffer_at(address, length):
|
||
|
"""
|
||
|
Simular to ctypes.string_at, but zero-copy and requires an integer address.
|
||
|
"""
|
||
|
return bytearray((c_char * length).from_address(address))
|
||
|
|
||
|
_desc_type_dict = {
|
||
|
'b': c_uint8,
|
||
|
'bcd': c_uint16,
|
||
|
'bm': c_uint8,
|
||
|
'dw': c_uint32,
|
||
|
'i': c_uint8,
|
||
|
'id': c_uint16,
|
||
|
'w': c_uint16,
|
||
|
}
|
||
|
|
||
|
def newStruct(field_name_list):
|
||
|
"""
|
||
|
Create a ctype structure class based on USB standard field naming
|
||
|
(type-prefixed).
|
||
|
"""
|
||
|
field_list = []
|
||
|
append = field_list.append
|
||
|
for field in field_name_list:
|
||
|
type_prefix = ''
|
||
|
for char in field:
|
||
|
if not char.islower():
|
||
|
break
|
||
|
type_prefix += char
|
||
|
append((field, _desc_type_dict[type_prefix]))
|
||
|
result = type('some_descriptor', (LittleEndianStructure, ), {})
|
||
|
# Not using type()'s 3rd param to initialise class, as per ctypes
|
||
|
# documentation:
|
||
|
# _pack_ must already be defined when _fields_ is assigned, otherwise it
|
||
|
# will have no effect.
|
||
|
# pylint: disable=protected-access
|
||
|
result._pack_ = 1
|
||
|
result._fields_ = field_list
|
||
|
# pylint: enable=protected-access
|
||
|
return result
|
||
|
|
||
|
def newDescriptor(field_name_list):
|
||
|
"""
|
||
|
Create a USB descriptor ctype structure, ie starting with bLength and
|
||
|
bDescriptorType fields.
|
||
|
|
||
|
See newStruct().
|
||
|
"""
|
||
|
return newStruct(['bLength', 'bDescriptorType'] + list(field_name_list))
|
||
|
|
||
|
class USBError(Exception):
|
||
|
value = None
|
||
|
|
||
|
def __init__(self, value=None):
|
||
|
Exception.__init__(self)
|
||
|
if value is not None:
|
||
|
self.value = value
|
||
|
|
||
|
def __str__(self):
|
||
|
return '%s [%s]' % (libusb_error.get(self.value, 'Unknown error'),
|
||
|
self.value)
|
||
|
|
||
|
c_uchar = c_uint8
|
||
|
c_int_p = POINTER(c_int)
|
||
|
|
||
|
LITTLE_ENDIAN = sys.byteorder == 'little'
|
||
|
|
||
|
class timeval(Structure):
|
||
|
_fields_ = [('tv_sec', c_long),
|
||
|
('tv_usec', c_long)]
|
||
|
timeval_p = POINTER(timeval)
|
||
|
|
||
|
def __getLibrary():
|
||
|
system = platform.system()
|
||
|
if system == 'Windows':
|
||
|
dll_loader = ctypes.WinDLL
|
||
|
suffix = '.dll'
|
||
|
else:
|
||
|
dll_loader = ctypes.CDLL
|
||
|
suffix = '.dylib' if system == 'Darwin' else '.so'
|
||
|
filename = 'libusb-1.0' + suffix
|
||
|
# If this is a binary wheel, use the integrated libusb unconditionally.
|
||
|
# To use the libusb from the Python installation or the OS, install from sdist:
|
||
|
# > pip install --no-binary :all: libusb1
|
||
|
if os.path.exists(os.path.join(os.path.dirname(__file__), filename)):
|
||
|
filename = os.path.join(os.path.dirname(__file__), filename)
|
||
|
try:
|
||
|
return dll_loader(filename, use_errno=True, use_last_error=True)
|
||
|
except OSError:
|
||
|
libusb_path = None
|
||
|
base_name = 'usb-1.0'
|
||
|
if 'FreeBSD' in system:
|
||
|
# libusb.so.2 on FreeBSD: load('libusb.so') would work fine, but...
|
||
|
# libusb.so.2debian on Debian GNU/kFreeBSD: here it wouldn't work.
|
||
|
# So use find_library instead.
|
||
|
base_name = 'usb'
|
||
|
elif system == 'Darwin':
|
||
|
for libusb_path in (
|
||
|
# macport standard path
|
||
|
'/opt/local/lib/libusb-1.0.dylib',
|
||
|
# fink standard path
|
||
|
'/sw/lib/libusb-1.0.dylib',
|
||
|
# homebrew standard path for symlink (Apple M1 Silicon)
|
||
|
'/opt/homebrew/opt/libusb/lib/libusb-1.0.dylib',
|
||
|
):
|
||
|
if os.path.exists(libusb_path):
|
||
|
break
|
||
|
else:
|
||
|
libusb_path = None
|
||
|
if libusb_path is None:
|
||
|
libusb_path = ctypes.util.find_library(base_name)
|
||
|
if libusb_path is None:
|
||
|
raise
|
||
|
return dll_loader(libusb_path, use_errno=True, use_last_error=True)
|
||
|
|
||
|
__load_lock = Lock()
|
||
|
__loaded = False
|
||
|
|
||
|
def loadLibrary(libusb=None):
|
||
|
"""
|
||
|
Load C library.
|
||
|
|
||
|
libusb (ctypes.CDLL, ctypes.WinDLL, None)
|
||
|
If None, the C library will be searched for in several platform-
|
||
|
dependent paths.
|
||
|
Otherwise, this is the C library to use as libusb. This is to allow
|
||
|
customising library lookup logic.
|
||
|
|
||
|
Only the first call actually loads the library.
|
||
|
|
||
|
Returns True if any of the following is true:
|
||
|
- the library was loaded by this call
|
||
|
- libusb argument is None
|
||
|
- libusb argument is the same object that was initially loaded.
|
||
|
"""
|
||
|
global __loaded # pylint: disable=global-statement
|
||
|
if not __loaded: # avoid touching the lock if we are already loaded
|
||
|
with __load_lock:
|
||
|
if not __loaded: # we were not loaded, check again under lock
|
||
|
__loadLibrary(libusb)
|
||
|
__loaded = True
|
||
|
return True
|
||
|
return libusb is None or globals()['libusb'] is libusb
|
||
|
|
||
|
def __loadLibrary(libusb): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
||
|
# WARNING: every local in this function will be stored in
|
||
|
# globals . Treat this namespace the same as the module's.
|
||
|
if libusb is None:
|
||
|
libusb = __getLibrary()
|
||
|
|
||
|
_libusb_transfer_fields = [
|
||
|
('dev_handle', libusb_device_handle_p),
|
||
|
('flags', c_uint8),
|
||
|
('endpoint', c_uchar),
|
||
|
('type', c_uchar),
|
||
|
('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', c_void_p),
|
||
|
('buffer', c_void_p),
|
||
|
('num_iso_packets', c_int),
|
||
|
('iso_packet_desc', libusb_iso_packet_descriptor)
|
||
|
]
|
||
|
if 'FreeBSD' in platform.system() and getattr(
|
||
|
libusb, 'libusb_get_string_descriptor', None
|
||
|
) is None:
|
||
|
# Old FreeBSD version has a slight ABI incompatibility.
|
||
|
# Work around it unless libusb_get_string_descriptor is available, as it
|
||
|
# is only available on fixed versions.
|
||
|
assert _libusb_transfer_fields[2][0] == 'endpoint'
|
||
|
_libusb_transfer_fields[2] = ('endpoint', c_uint32)
|
||
|
assert _libusb_transfer_fields[11][0] == 'num_iso_packets'
|
||
|
_libusb_transfer_fields.insert(11, ('os_priv', c_void_p))
|
||
|
|
||
|
# pylint: disable=protected-access
|
||
|
libusb_transfer._fields_ = _libusb_transfer_fields
|
||
|
# pylint: enable=protected-access
|
||
|
|
||
|
#int libusb_init(libusb_context **ctx);
|
||
|
libusb_init = libusb.libusb_init
|
||
|
libusb_init.argtypes = [libusb_context_p_p]
|
||
|
#void libusb_exit(libusb_context *ctx);
|
||
|
libusb_exit = libusb.libusb_exit
|
||
|
libusb_exit.argtypes = [libusb_context_p]
|
||
|
libusb_exit.restype = None
|
||
|
#void libusb_set_debug(libusb_context *ctx, int level);
|
||
|
libusb_set_debug = libusb.libusb_set_debug
|
||
|
libusb_set_debug.argtypes = [libusb_context_p, c_int]
|
||
|
libusb_set_debug.restype = None
|
||
|
#const struct libusb_version * libusb_get_version(void);
|
||
|
try:
|
||
|
libusb_get_version = libusb.libusb_get_version
|
||
|
except AttributeError:
|
||
|
_dummy_version = libusb_version(0, 0, 0, 0, b'', b'')
|
||
|
_dummy_version_p = pointer(_dummy_version)
|
||
|
def libusb_get_version():
|
||
|
return _dummy_version_p
|
||
|
else:
|
||
|
libusb_get_version.argtypes = []
|
||
|
libusb_get_version.restype = POINTER(libusb_version)
|
||
|
#int libusb_has_capability(uint32_t capability);
|
||
|
try:
|
||
|
libusb_has_capability = libusb.libusb_has_capability
|
||
|
except AttributeError:
|
||
|
def libusb_has_capability(_):
|
||
|
return 0
|
||
|
else:
|
||
|
libusb_has_capability.argtypes = [c_uint32]
|
||
|
libusb_has_capability.restype = c_int
|
||
|
try:
|
||
|
# Note: Should be equivalent to libusb_error.get (except libusb_error.get
|
||
|
# one raises on unknown values).
|
||
|
#char *libusb_error_name(int errcode);
|
||
|
libusb_error_name = libusb.libusb_error_name
|
||
|
except AttributeError:
|
||
|
# pylint: disable=unused-argument
|
||
|
def libusb_error_name(errcode):
|
||
|
return None
|
||
|
# pylint: enable=unused-argument
|
||
|
else:
|
||
|
libusb_error_name.argtypes = [c_int]
|
||
|
libusb_error_name.restype = c_char_p
|
||
|
#ssize_t libusb_get_device_list(libusb_context *ctx,
|
||
|
# libusb_device ***list);
|
||
|
libusb_get_device_list = libusb.libusb_get_device_list
|
||
|
libusb_get_device_list.argtypes = [libusb_context_p, libusb_device_p_p_p]
|
||
|
libusb_get_device_list.restype = c_ssize_t
|
||
|
#void libusb_free_device_list(libusb_device **list, int unref_devices);
|
||
|
libusb_free_device_list = libusb.libusb_free_device_list
|
||
|
libusb_free_device_list.argtypes = [libusb_device_p_p, c_int]
|
||
|
libusb_free_device_list.restype = None
|
||
|
#libusb_device *libusb_ref_device(libusb_device *dev);
|
||
|
libusb_ref_device = libusb.libusb_ref_device
|
||
|
libusb_ref_device.argtypes = [libusb_device_p]
|
||
|
libusb_ref_device.restype = libusb_device_p
|
||
|
#void libusb_unref_device(libusb_device *dev);
|
||
|
libusb_unref_device = libusb.libusb_unref_device
|
||
|
libusb_unref_device.argtypes = [libusb_device_p]
|
||
|
libusb_unref_device.restype = None
|
||
|
|
||
|
#int libusb_get_configuration(libusb_device_handle *dev, int *config);
|
||
|
libusb_get_configuration = libusb.libusb_get_configuration
|
||
|
libusb_get_configuration.argtypes = [libusb_device_handle_p, c_int_p]
|
||
|
#int libusb_get_device_descriptor(libusb_device *dev,
|
||
|
# struct libusb_device_descriptor *desc);
|
||
|
libusb_get_device_descriptor = libusb.libusb_get_device_descriptor
|
||
|
libusb_get_device_descriptor.argtypes = [
|
||
|
libusb_device_p, libusb_device_descriptor_p]
|
||
|
#int libusb_get_active_config_descriptor(libusb_device *dev,
|
||
|
# struct libusb_config_descriptor **config);
|
||
|
libusb_get_active_config_descriptor = libusb.libusb_get_active_config_descriptor
|
||
|
libusb_get_active_config_descriptor.argtypes = [
|
||
|
libusb_device_p, libusb_config_descriptor_p_p]
|
||
|
#int libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index,
|
||
|
# struct libusb_config_descriptor **config);
|
||
|
libusb_get_config_descriptor = libusb.libusb_get_config_descriptor
|
||
|
libusb_get_config_descriptor.argtypes = [
|
||
|
libusb_device_p, c_uint8, libusb_config_descriptor_p_p]
|
||
|
#int libusb_get_config_descriptor_by_value(libusb_device *dev,
|
||
|
# uint8_t bConfigurationValue, struct libusb_config_descriptor **config);
|
||
|
libusb_get_config_descriptor_by_value = \
|
||
|
libusb.libusb_get_config_descriptor_by_value
|
||
|
libusb_get_config_descriptor_by_value.argtypes = [
|
||
|
libusb_device_p, c_uint8, libusb_config_descriptor_p_p]
|
||
|
#void libusb_free_config_descriptor(struct libusb_config_descriptor *config);
|
||
|
libusb_free_config_descriptor = libusb.libusb_free_config_descriptor
|
||
|
libusb_free_config_descriptor.argtypes = [libusb_config_descriptor_p]
|
||
|
libusb_free_config_descriptor.restype = None
|
||
|
#uint8_t libusb_get_bus_number(libusb_device *dev);
|
||
|
libusb_get_bus_number = libusb.libusb_get_bus_number
|
||
|
libusb_get_bus_number.argtypes = [libusb_device_p]
|
||
|
libusb_get_bus_number.restype = c_uint8
|
||
|
try:
|
||
|
#uint8_t libusb_get_port_number(libusb_device *dev);
|
||
|
libusb_get_port_number = libusb.libusb_get_port_number
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
else:
|
||
|
libusb_get_port_number.argtypes = [libusb_device_p]
|
||
|
libusb_get_port_number.restype = c_uint8
|
||
|
try:
|
||
|
#int libusb_get_port_numbers(libusb_device *dev,
|
||
|
# uint8_t* port_numbers, int port_numbers_len);
|
||
|
libusb_get_port_numbers = libusb.libusb_get_port_numbers
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
else:
|
||
|
libusb_get_port_numbers.argtypes = [
|
||
|
libusb_device_p, POINTER(c_uint8), c_int]
|
||
|
libusb_get_port_numbers.restype = c_int
|
||
|
# Missing: libusb_get_port_path (deprecated since 1.0.16)
|
||
|
try:
|
||
|
#libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev);
|
||
|
libusb_get_parent = libusb.libusb_get_parent
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
else:
|
||
|
libusb_get_parent.argtypes = [libusb_device_p]
|
||
|
libusb_get_parent.restype = libusb_device_p
|
||
|
#uint8_t libusb_get_device_address(libusb_device *dev);
|
||
|
libusb_get_device_address = libusb.libusb_get_device_address
|
||
|
libusb_get_device_address.argtypes = [libusb_device_p]
|
||
|
libusb_get_device_address.restype = c_uint8
|
||
|
try:
|
||
|
#int libusb_get_device_speed(libusb_device *dev);
|
||
|
libusb_get_device_speed = libusb.libusb_get_device_speed
|
||
|
except AttributeError:
|
||
|
# Place holder
|
||
|
def libusb_get_device_speed(_):
|
||
|
# pylint: disable=undefined-variable
|
||
|
return LIBUSB_SPEED_UNKNOWN
|
||
|
# pylint: enable=undefined-variable
|
||
|
else:
|
||
|
libusb_get_device_speed.argtypes = [libusb_device_p]
|
||
|
#int libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint);
|
||
|
libusb_get_max_packet_size = libusb.libusb_get_max_packet_size
|
||
|
libusb_get_max_packet_size.argtypes = [libusb_device_p, c_uchar]
|
||
|
#int libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint);
|
||
|
try:
|
||
|
libusb_get_max_iso_packet_size = libusb.libusb_get_max_iso_packet_size
|
||
|
except AttributeError:
|
||
|
# FreeBSD's reimplementation of the API [used to ]lack[s] this function.
|
||
|
# It has been added in r234193, but is lacking in default 9.x install as
|
||
|
# of this change. Provide a fallback to error-out only if actually used.
|
||
|
# pylint: disable=unused-argument
|
||
|
def libusb_get_max_iso_packet_size(_, __):
|
||
|
raise NotImplementedError
|
||
|
# pylint: enable=unused-argument
|
||
|
else:
|
||
|
libusb_get_max_iso_packet_size.argtypes = [libusb_device_p, c_uchar]
|
||
|
|
||
|
#int libusb_open(libusb_device *dev, libusb_device_handle **handle);
|
||
|
libusb_open = libusb.libusb_open
|
||
|
libusb_open.argtypes = [libusb_device_p, libusb_device_handle_p_p]
|
||
|
#void libusb_close(libusb_device_handle *dev_handle);
|
||
|
libusb_close = libusb.libusb_close
|
||
|
libusb_close.argtypes = [libusb_device_handle_p]
|
||
|
libusb_close.restype = None
|
||
|
#libusb_device *libusb_get_device(libusb_device_handle *dev_handle);
|
||
|
libusb_get_device = libusb.libusb_get_device
|
||
|
libusb_get_device.argtypes = [libusb_device_handle_p]
|
||
|
libusb_get_device.restype = libusb_device_p
|
||
|
|
||
|
#int libusb_set_configuration(libusb_device_handle *dev, int configuration);
|
||
|
libusb_set_configuration = libusb.libusb_set_configuration
|
||
|
libusb_set_configuration.argtypes = [libusb_device_handle_p, c_int]
|
||
|
#int libusb_claim_interface(libusb_device_handle *dev, int iface);
|
||
|
libusb_claim_interface = libusb.libusb_claim_interface
|
||
|
libusb_claim_interface.argtypes = [libusb_device_handle_p, c_int]
|
||
|
#int libusb_release_interface(libusb_device_handle *dev, int iface);
|
||
|
libusb_release_interface = libusb.libusb_release_interface
|
||
|
libusb_release_interface.argtypes = [libusb_device_handle_p, c_int]
|
||
|
|
||
|
#libusb_device_handle *libusb_open_device_with_vid_pid(libusb_context *ctx,
|
||
|
# uint16_t vendor_id, uint16_t product_id);
|
||
|
libusb_open_device_with_vid_pid = libusb.libusb_open_device_with_vid_pid
|
||
|
libusb_open_device_with_vid_pid.argtypes = [
|
||
|
libusb_context_p, c_uint16, c_uint16]
|
||
|
libusb_open_device_with_vid_pid.restype = libusb_device_handle_p
|
||
|
|
||
|
#int libusb_set_interface_alt_setting(libusb_device_handle *dev,
|
||
|
# int interface_number, int alternate_setting);
|
||
|
libusb_set_interface_alt_setting = libusb.libusb_set_interface_alt_setting
|
||
|
libusb_set_interface_alt_setting.argtypes = [
|
||
|
libusb_device_handle_p, c_int, c_int]
|
||
|
#int libusb_clear_halt(libusb_device_handle *dev, unsigned char endpoint);
|
||
|
libusb_clear_halt = libusb.libusb_clear_halt
|
||
|
libusb_clear_halt.argtypes = [libusb_device_handle_p, c_uchar]
|
||
|
#int libusb_reset_device(libusb_device_handle *dev);
|
||
|
libusb_reset_device = libusb.libusb_reset_device
|
||
|
libusb_reset_device.argtypes = [libusb_device_handle_p]
|
||
|
|
||
|
#int libusb_kernel_driver_active(libusb_device_handle *dev, int interface);
|
||
|
libusb_kernel_driver_active = libusb.libusb_kernel_driver_active
|
||
|
libusb_kernel_driver_active.argtypes = [libusb_device_handle_p, c_int]
|
||
|
#int libusb_detach_kernel_driver(libusb_device_handle *dev, int interface);
|
||
|
libusb_detach_kernel_driver = libusb.libusb_detach_kernel_driver
|
||
|
libusb_detach_kernel_driver.argtypes = [libusb_device_handle_p, c_int]
|
||
|
#int libusb_attach_kernel_driver(libusb_device_handle *dev, int interface);
|
||
|
libusb_attach_kernel_driver = libusb.libusb_attach_kernel_driver
|
||
|
libusb_attach_kernel_driver.argtypes = [libusb_device_handle_p, c_int]
|
||
|
try:
|
||
|
#int libusb_set_auto_detach_kernel_driver(
|
||
|
# libusb_device_handle *dev, int enable);
|
||
|
libusb_set_auto_detach_kernel_driver = \
|
||
|
libusb.libusb_set_auto_detach_kernel_driver
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
else:
|
||
|
libusb_set_auto_detach_kernel_driver.argtypes = [
|
||
|
libusb_device_handle_p, c_int]
|
||
|
libusb_set_auto_detach_kernel_driver.restype = c_int
|
||
|
|
||
|
#struct libusb_transfer *libusb_alloc_transfer(int iso_packets);
|
||
|
libusb_alloc_transfer = libusb.libusb_alloc_transfer
|
||
|
libusb_alloc_transfer.argtypes = [c_int]
|
||
|
libusb_alloc_transfer.restype = libusb_transfer_p
|
||
|
#int libusb_submit_transfer(struct libusb_transfer *transfer);
|
||
|
libusb_submit_transfer = libusb.libusb_submit_transfer
|
||
|
libusb_submit_transfer.argtypes = [libusb_transfer_p]
|
||
|
#int libusb_cancel_transfer(struct libusb_transfer *transfer);
|
||
|
libusb_cancel_transfer = libusb.libusb_cancel_transfer
|
||
|
libusb_cancel_transfer.argtypes = [libusb_transfer_p]
|
||
|
#void libusb_free_transfer(struct libusb_transfer *transfer);
|
||
|
libusb_free_transfer = libusb.libusb_free_transfer
|
||
|
libusb_free_transfer.argtypes = [libusb_transfer_p]
|
||
|
libusb_free_transfer.restype = None
|
||
|
|
||
|
# sync I/O
|
||
|
|
||
|
#int libusb_control_transfer(libusb_device_handle *dev_handle,
|
||
|
# uint8_t request_type, uint8_t request, uint16_t value, uint16_t index,
|
||
|
# unsigned char *data, uint16_t length, unsigned int timeout);
|
||
|
libusb_control_transfer = libusb.libusb_control_transfer
|
||
|
libusb_control_transfer.argtypes = [libusb_device_handle_p, c_uint8, c_uint8,
|
||
|
c_uint16, c_uint16, c_void_p, c_uint16,
|
||
|
c_uint]
|
||
|
|
||
|
#int libusb_bulk_transfer(libusb_device_handle *dev_handle,
|
||
|
# unsigned char endpoint, unsigned char *data, int length,
|
||
|
# int *actual_length, unsigned int timeout);
|
||
|
libusb_bulk_transfer = libusb.libusb_bulk_transfer
|
||
|
libusb_bulk_transfer.argtypes = [libusb_device_handle_p, c_uchar, c_void_p,
|
||
|
c_int, c_int_p, 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);
|
||
|
libusb_interrupt_transfer = libusb.libusb_interrupt_transfer
|
||
|
libusb_interrupt_transfer.argtypes = [libusb_device_handle_p, c_uchar,
|
||
|
c_void_p, c_int, c_int_p, c_uint]
|
||
|
|
||
|
#int libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
|
||
|
# uint8_t index, unsigned char *data, int length);
|
||
|
libusb_get_string_descriptor_ascii = libusb.libusb_get_string_descriptor_ascii
|
||
|
libusb_get_string_descriptor_ascii.argtypes = [libusb_device_handle_p,
|
||
|
c_uint8, c_void_p, c_int]
|
||
|
|
||
|
# polling and timeouts
|
||
|
|
||
|
#int libusb_try_lock_events(libusb_context *ctx);
|
||
|
libusb_try_lock_events = libusb.libusb_try_lock_events
|
||
|
libusb_try_lock_events.argtypes = [libusb_context_p]
|
||
|
#void libusb_lock_events(libusb_context *ctx);
|
||
|
libusb_lock_events = libusb.libusb_lock_events
|
||
|
libusb_lock_events.argtypes = [libusb_context_p]
|
||
|
#void libusb_unlock_events(libusb_context *ctx);
|
||
|
libusb_unlock_events = libusb.libusb_unlock_events
|
||
|
libusb_unlock_events.argtypes = [libusb_context_p]
|
||
|
libusb_unlock_events.restype = None
|
||
|
#int libusb_event_handling_ok(libusb_context *ctx);
|
||
|
libusb_event_handling_ok = libusb.libusb_event_handling_ok
|
||
|
libusb_event_handling_ok.argtypes = [libusb_context_p]
|
||
|
#int libusb_event_handler_active(libusb_context *ctx);
|
||
|
libusb_event_handler_active = libusb.libusb_event_handler_active
|
||
|
libusb_event_handler_active.argtypes = [libusb_context_p]
|
||
|
#void libusb_lock_event_waiters(libusb_context *ctx);
|
||
|
libusb_lock_event_waiters = libusb.libusb_lock_event_waiters
|
||
|
libusb_lock_event_waiters.argtypes = [libusb_context_p]
|
||
|
libusb_lock_event_waiters.restype = None
|
||
|
#void libusb_unlock_event_waiters(libusb_context *ctx);
|
||
|
libusb_unlock_event_waiters = libusb.libusb_unlock_event_waiters
|
||
|
libusb_unlock_event_waiters.argtypes = []
|
||
|
libusb_unlock_event_waiters.restype = None
|
||
|
#int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv);
|
||
|
libusb_wait_for_event = libusb.libusb_wait_for_event
|
||
|
libusb_wait_for_event.argtypes = [libusb_context_p, timeval_p]
|
||
|
|
||
|
#int libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv);
|
||
|
libusb_handle_events_timeout = libusb.libusb_handle_events_timeout
|
||
|
libusb_handle_events_timeout.argtypes = [libusb_context_p, timeval_p]
|
||
|
#int libusb_handle_events_timeout_completed(libusb_context *ctx,
|
||
|
# struct timeval *tv, int *completed);
|
||
|
try:
|
||
|
libusb_handle_events_timeout_completed = libusb.\
|
||
|
libusb_handle_events_timeout_completed
|
||
|
except AttributeError:
|
||
|
# No safe replacement possible.
|
||
|
pass
|
||
|
else:
|
||
|
libusb_handle_events_timeout_completed.argtypes = [
|
||
|
libusb_context_p, timeval_p, c_int_p]
|
||
|
#int libusb_handle_events(libusb_context *ctx);
|
||
|
libusb_handle_events = libusb.libusb_handle_events
|
||
|
libusb_handle_events.argtypes = [libusb_context_p]
|
||
|
#int libusb_handle_events_completed(libusb_context *ctx, int *completed);
|
||
|
try:
|
||
|
libusb_handle_events_completed = libusb.libusb_handle_events_completed
|
||
|
except AttributeError:
|
||
|
# No safe replacement possible.
|
||
|
pass
|
||
|
else:
|
||
|
libusb_handle_events_completed.argtypes = [libusb_context_p, c_int_p]
|
||
|
#int libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv);
|
||
|
libusb_handle_events_locked = libusb.libusb_handle_events_locked
|
||
|
libusb_handle_events_locked.argtypes = [libusb_context_p, timeval_p]
|
||
|
#int libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv);
|
||
|
libusb_get_next_timeout = libusb.libusb_get_next_timeout
|
||
|
libusb_get_next_timeout.argtypes = [libusb_context_p, timeval_p]
|
||
|
|
||
|
#const struct libusb_pollfd **libusb_get_pollfds(libusb_context *ctx);
|
||
|
libusb_get_pollfds = libusb.libusb_get_pollfds
|
||
|
libusb_get_pollfds.argtypes = [libusb_context_p]
|
||
|
libusb_get_pollfds.restype = libusb_pollfd_p_p
|
||
|
#void libusb_set_pollfd_notifiers(libusb_context *ctx,
|
||
|
# libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
|
||
|
# void *user_data);
|
||
|
libusb_set_pollfd_notifiers = libusb.libusb_set_pollfd_notifiers
|
||
|
libusb_set_pollfd_notifiers.argtypes = [libusb_context_p,
|
||
|
libusb_pollfd_added_cb_p,
|
||
|
libusb_pollfd_removed_cb_p, py_object]
|
||
|
libusb_set_pollfd_notifiers.restype = None
|
||
|
try:
|
||
|
#void libusb_get_pollfds(const struct libusb_pollfd **);
|
||
|
libusb_free_pollfds = libusb.libusb_free_pollfds
|
||
|
libusb_free_pollfds.argtypes = [libusb_pollfd_p_p]
|
||
|
libusb_free_pollfds.restype = None
|
||
|
except AttributeError:
|
||
|
# Not a safe replacement in general, but the versions of libusb that lack
|
||
|
# libusb_free_pollfds() only provide that function on *nix, where
|
||
|
# Python's free() and libusb's free() are ~always the same anyways.
|
||
|
libusb_free_pollfds = CDLL(None).free
|
||
|
|
||
|
#int libusb_hotplug_register_callback(libusb_context *ctx,
|
||
|
# libusb_hotplug_event events, libusb_hotplug_flag flags,
|
||
|
# int vendor_id, int product_id, int dev_class,
|
||
|
# libusb_hotplug_callback_fn cb_fn, void *user_data,
|
||
|
# libusb_hotplug_callback_handle *handle);
|
||
|
try:
|
||
|
libusb_hotplug_register_callback = libusb.libusb_hotplug_register_callback
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
else:
|
||
|
libusb_hotplug_register_callback.argtypes = [
|
||
|
libusb_context_p,
|
||
|
c_int, c_int,
|
||
|
c_int, c_int, c_int,
|
||
|
libusb_hotplug_callback_fn_p, c_void_p,
|
||
|
POINTER(libusb_hotplug_callback_handle),
|
||
|
]
|
||
|
libusb_hotplug_register_callback.restype = c_int
|
||
|
|
||
|
#void libusb_hotplug_deregister_callback(libusb_context *ctx,
|
||
|
# libusb_hotplug_callback_handle handle);
|
||
|
try:
|
||
|
libusb_hotplug_deregister_callback = \
|
||
|
libusb.libusb_hotplug_deregister_callback
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
else:
|
||
|
libusb_hotplug_deregister_callback.argtypes = [
|
||
|
libusb_context_p,
|
||
|
libusb_hotplug_callback_handle,
|
||
|
]
|
||
|
libusb_hotplug_deregister_callback.restype = None
|
||
|
|
||
|
globals().update(locals())
|
||
|
|
||
|
# libusb.h
|
||
|
def bswap16(x):
|
||
|
return ((x & 0xff) << 8) | (x >> 8)
|
||
|
|
||
|
if LITTLE_ENDIAN:
|
||
|
def libusb_cpu_to_le16(x):
|
||
|
return x
|
||
|
def libusb_le16_to_cpu(x):
|
||
|
return x
|
||
|
else:
|
||
|
libusb_cpu_to_le16 = bswap16
|
||
|
libusb_le16_to_cpu = bswap16
|
||
|
|
||
|
# standard USB stuff
|
||
|
|
||
|
# Device and/or Interface Class codes
|
||
|
libusb_class_code = Enum({
|
||
|
# In the context of a device descriptor,
|
||
|
# this bDeviceClass value indicates that each interface specifies its
|
||
|
# own class information and all interfaces operate independently.
|
||
|
'LIBUSB_CLASS_PER_INTERFACE': 0,
|
||
|
# Audio class
|
||
|
'LIBUSB_CLASS_AUDIO': 1,
|
||
|
# Communications class
|
||
|
'LIBUSB_CLASS_COMM': 2,
|
||
|
# Human Interface Device class
|
||
|
'LIBUSB_CLASS_HID': 3,
|
||
|
# Physical
|
||
|
'LIBUSB_CLASS_PHYSICAL': 5,
|
||
|
# Printer class
|
||
|
'LIBUSB_CLASS_PRINTER': 7,
|
||
|
# Picture transfer protocol class
|
||
|
'LIBUSB_CLASS_PTP': 6,
|
||
|
# Mass storage class
|
||
|
'LIBUSB_CLASS_MASS_STORAGE': 8,
|
||
|
# Hub class
|
||
|
'LIBUSB_CLASS_HUB': 9,
|
||
|
# Data class
|
||
|
'LIBUSB_CLASS_DATA': 10,
|
||
|
# Smart Card
|
||
|
'LIBUSB_CLASS_SMART_CARD': 0x0b,
|
||
|
# Content Security
|
||
|
'LIBUSB_CLASS_CONTENT_SECURITY': 0x0d,
|
||
|
# Video
|
||
|
'LIBUSB_CLASS_VIDEO': 0x0e,
|
||
|
# Personal Healthcare
|
||
|
'LIBUSB_CLASS_PERSONAL_HEALTHCARE': 0x0f,
|
||
|
# Diagnostic Device
|
||
|
'LIBUSB_CLASS_DIAGNOSTIC_DEVICE': 0xdc,
|
||
|
# Wireless class
|
||
|
'LIBUSB_CLASS_WIRELESS': 0xe0,
|
||
|
# Application class
|
||
|
'LIBUSB_CLASS_APPLICATION': 0xfe,
|
||
|
# Class is vendor-specific
|
||
|
'LIBUSB_CLASS_VENDOR_SPEC': 0xff
|
||
|
})
|
||
|
# pylint: disable=undefined-variable
|
||
|
LIBUSB_CLASS_IMAGE = LIBUSB_CLASS_PTP
|
||
|
# pylint: enable=undefined-variable
|
||
|
|
||
|
# Descriptor types as defined by the USB specification.
|
||
|
libusb_descriptor_type = Enum({
|
||
|
# Device descriptor. See libusb_device_descriptor.
|
||
|
'LIBUSB_DT_DEVICE': 0x01,
|
||
|
# Configuration descriptor. See libusb_config_descriptor.
|
||
|
'LIBUSB_DT_CONFIG': 0x02,
|
||
|
# String descriptor
|
||
|
'LIBUSB_DT_STRING': 0x03,
|
||
|
# Interface descriptor. See libusb_interface_descriptor.
|
||
|
'LIBUSB_DT_INTERFACE': 0x04,
|
||
|
# Endpoint descriptor. See libusb_endpoint_descriptor.
|
||
|
'LIBUSB_DT_ENDPOINT': 0x05,
|
||
|
# HID descriptor
|
||
|
'LIBUSB_DT_HID': 0x21,
|
||
|
# HID report descriptor
|
||
|
'LIBUSB_DT_REPORT': 0x22,
|
||
|
# Physical descriptor
|
||
|
'LIBUSB_DT_PHYSICAL': 0x23,
|
||
|
# Hub descriptor
|
||
|
'LIBUSB_DT_HUB': 0x29,
|
||
|
})
|
||
|
|
||
|
# Descriptor sizes per descriptor type
|
||
|
LIBUSB_DT_DEVICE_SIZE = 18
|
||
|
LIBUSB_DT_CONFIG_SIZE = 9
|
||
|
LIBUSB_DT_INTERFACE_SIZE = 9
|
||
|
LIBUSB_DT_ENDPOINT_SIZE = 7
|
||
|
LIBUSB_DT_ENDPOINT_AUDIO_SIZE = 9 # Audio extension
|
||
|
LIBUSB_DT_HUB_NONVAR_SIZE = 7
|
||
|
|
||
|
LIBUSB_ENDPOINT_ADDRESS_MASK = 0x0f # in bEndpointAddress
|
||
|
LIBUSB_ENDPOINT_DIR_MASK = 0x80
|
||
|
# BBB
|
||
|
USB_ENDPOINT_ADDRESS_MASK = LIBUSB_ENDPOINT_ADDRESS_MASK
|
||
|
USB_ENDPOINT_DIR_MASK = LIBUSB_ENDPOINT_DIR_MASK
|
||
|
|
||
|
# Endpoint direction. Values for bit 7 of the endpoint address scheme.
|
||
|
libusb_endpoint_direction = Enum({
|
||
|
# In: device-to-host
|
||
|
'LIBUSB_ENDPOINT_IN': 0x80,
|
||
|
# Out: host-to-device
|
||
|
'LIBUSB_ENDPOINT_OUT': 0x00
|
||
|
})
|
||
|
|
||
|
LIBUSB_TRANSFER_TYPE_MASK = 0x03 # in bmAttributes
|
||
|
|
||
|
# Endpoint transfer type. Values for bits 0:1 of the endpoint attributes field.
|
||
|
libusb_transfer_type = Enum({
|
||
|
# 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,
|
||
|
})
|
||
|
|
||
|
# Standard requests, as defined in table 9-3 of the USB2 specifications
|
||
|
libusb_standard_request = Enum({
|
||
|
# Request status of the specific recipient
|
||
|
'LIBUSB_REQUEST_GET_STATUS': 0x00,
|
||
|
# Clear or disable a specific feature
|
||
|
'LIBUSB_REQUEST_CLEAR_FEATURE': 0x01,
|
||
|
# 0x02 is reserved
|
||
|
# Set or enable a specific feature
|
||
|
'LIBUSB_REQUEST_SET_FEATURE': 0x03,
|
||
|
# 0x04 is reserved
|
||
|
# Set device address for all future accesses
|
||
|
'LIBUSB_REQUEST_SET_ADDRESS': 0x05,
|
||
|
# Get the specified descriptor
|
||
|
'LIBUSB_REQUEST_GET_DESCRIPTOR': 0x06,
|
||
|
# Used to update existing descriptors or add new descriptors
|
||
|
'LIBUSB_REQUEST_SET_DESCRIPTOR': 0x07,
|
||
|
# Get the current device configuration value
|
||
|
'LIBUSB_REQUEST_GET_CONFIGURATION': 0x08,
|
||
|
# Set device configuration
|
||
|
'LIBUSB_REQUEST_SET_CONFIGURATION': 0x09,
|
||
|
# Return the selected alternate setting for the specified interface
|
||
|
'LIBUSB_REQUEST_GET_INTERFACE': 0x0a,
|
||
|
# Select an alternate interface for the specified interface
|
||
|
'LIBUSB_REQUEST_SET_INTERFACE': 0x0b,
|
||
|
# Set then report an endpoint's synchronization frame
|
||
|
'LIBUSB_REQUEST_SYNCH_FRAME': 0x0c,
|
||
|
})
|
||
|
|
||
|
# Request type bits of the bmRequestType field in control transfers.
|
||
|
libusb_request_type = Enum({
|
||
|
# Standard
|
||
|
'LIBUSB_REQUEST_TYPE_STANDARD': (0x00 << 5),
|
||
|
# Class
|
||
|
'LIBUSB_REQUEST_TYPE_CLASS': (0x01 << 5),
|
||
|
# Vendor
|
||
|
'LIBUSB_REQUEST_TYPE_VENDOR': (0x02 << 5),
|
||
|
# Reserved
|
||
|
'LIBUSB_REQUEST_TYPE_RESERVED': (0x03 << 5),
|
||
|
})
|
||
|
|
||
|
# BBB
|
||
|
# pylint: disable=undefined-variable
|
||
|
LIBUSB_TYPE_STANDARD = LIBUSB_REQUEST_TYPE_STANDARD
|
||
|
LIBUSB_TYPE_CLASS = LIBUSB_REQUEST_TYPE_CLASS
|
||
|
LIBUSB_TYPE_VENDOR = LIBUSB_REQUEST_TYPE_VENDOR
|
||
|
LIBUSB_TYPE_RESERVED = LIBUSB_REQUEST_TYPE_RESERVED
|
||
|
# pylint: enable=undefined-variable
|
||
|
|
||
|
# Recipient bits of the bmRequestType field in control transfers. Values 4
|
||
|
# through 31 are reserved.
|
||
|
libusb_request_recipient = Enum({
|
||
|
# Device
|
||
|
'LIBUSB_RECIPIENT_DEVICE': 0x00,
|
||
|
# Interface
|
||
|
'LIBUSB_RECIPIENT_INTERFACE': 0x01,
|
||
|
# Endpoint
|
||
|
'LIBUSB_RECIPIENT_ENDPOINT': 0x02,
|
||
|
# Other
|
||
|
'LIBUSB_RECIPIENT_OTHER': 0x03,
|
||
|
})
|
||
|
|
||
|
LIBUSB_ISO_SYNC_TYPE_MASK = 0x0c
|
||
|
|
||
|
# Synchronization type for isochronous endpoints. Values for bits 2:3 of the
|
||
|
# bmAttributes field in libusb_endpoint_descriptor.
|
||
|
libusb_iso_sync_type = Enum({
|
||
|
# No synchronization
|
||
|
'LIBUSB_ISO_SYNC_TYPE_NONE': 0,
|
||
|
# Asynchronous
|
||
|
'LIBUSB_ISO_SYNC_TYPE_ASYNC': 1,
|
||
|
# Adaptive
|
||
|
'LIBUSB_ISO_SYNC_TYPE_ADAPTIVE': 2,
|
||
|
# Synchronous
|
||
|
'LIBUSB_ISO_SYNC_TYPE_SYNC': 3,
|
||
|
})
|
||
|
|
||
|
LIBUSB_ISO_USAGE_TYPE_MASK = 0x30
|
||
|
|
||
|
# Usage type for isochronous endpoints. Values for bits 4:5 of the
|
||
|
# bmAttributes field in libusb_endpoint_descriptor.
|
||
|
libusb_iso_usage_type = Enum({
|
||
|
# Data endpoint
|
||
|
'LIBUSB_ISO_USAGE_TYPE_DATA': 0,
|
||
|
# Feedback endpoint
|
||
|
'LIBUSB_ISO_USAGE_TYPE_FEEDBACK': 1,
|
||
|
# Implicit feedback Data endpoint
|
||
|
'LIBUSB_ISO_USAGE_TYPE_IMPLICIT': 2,
|
||
|
})
|
||
|
|
||
|
# A structure representing the standard USB device descriptor. This
|
||
|
# descriptor is documented in section 9.6.1 of the USB 2.0 specification.
|
||
|
# All multiple-byte fields are represented in host-endian format.
|
||
|
class libusb_device_descriptor(Structure):
|
||
|
_fields_ = [
|
||
|
# Size of this descriptor (in bytes)
|
||
|
('bLength', c_uint8),
|
||
|
# Descriptor type. Will have value LIBUSB_DT_DEVICE in this
|
||
|
# context.
|
||
|
('bDescriptorType', c_uint8),
|
||
|
# USB specification release number in binary-coded decimal. A
|
||
|
# value of 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1,
|
||
|
# etc.
|
||
|
('bcdUSB', c_uint16),
|
||
|
# USB-IF class code for the device. See libusb_class_code.
|
||
|
('bDeviceClass', c_uint8),
|
||
|
# USB-IF subclass code for the device, qualified by the
|
||
|
# bDeviceClass value
|
||
|
('bDeviceSubClass', c_uint8),
|
||
|
# USB-IF protocol code for the device, qualified by the
|
||
|
# bDeviceClass and bDeviceSubClass values
|
||
|
('bDeviceProtocol', c_uint8),
|
||
|
# Maximum packet size for endpoint 0
|
||
|
('bMaxPacketSize0', c_uint8),
|
||
|
# USB-IF vendor ID
|
||
|
('idVendor', c_uint16),
|
||
|
# USB-IF product ID
|
||
|
('idProduct', c_uint16),
|
||
|
# Device release number in binary-coded decimal
|
||
|
('bcdDevice', c_uint16),
|
||
|
# Index of string descriptor describing manufacturer
|
||
|
('iManufacturer', c_uint8),
|
||
|
# Index of string descriptor describing product
|
||
|
('iProduct', c_uint8),
|
||
|
# Index of string descriptor containing device serial number
|
||
|
('iSerialNumber', c_uint8),
|
||
|
# Number of possible configurations
|
||
|
('bNumConfigurations', c_uint8)]
|
||
|
libusb_device_descriptor_p = POINTER(libusb_device_descriptor)
|
||
|
|
||
|
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', c_void_p),
|
||
|
('extra_length', c_int)]
|
||
|
libusb_endpoint_descriptor_p = POINTER(libusb_endpoint_descriptor)
|
||
|
|
||
|
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', libusb_endpoint_descriptor_p),
|
||
|
('extra', c_void_p),
|
||
|
('extra_length', c_int)]
|
||
|
libusb_interface_descriptor_p = POINTER(libusb_interface_descriptor)
|
||
|
|
||
|
class libusb_interface(Structure):
|
||
|
_fields_ = [('altsetting', libusb_interface_descriptor_p),
|
||
|
('num_altsetting', c_int)]
|
||
|
libusb_interface_p = POINTER(libusb_interface)
|
||
|
|
||
|
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),
|
||
|
('MaxPower', c_uint8),
|
||
|
('interface', libusb_interface_p),
|
||
|
('extra', c_void_p),
|
||
|
('extra_length', c_int)]
|
||
|
libusb_config_descriptor_p = POINTER(libusb_config_descriptor)
|
||
|
libusb_config_descriptor_p_p = POINTER(libusb_config_descriptor_p)
|
||
|
|
||
|
class libusb_control_setup(Structure):
|
||
|
_fields_ = [
|
||
|
('bmRequestType', c_uint8),
|
||
|
('bRequest', c_uint8),
|
||
|
('wValue', c_uint16),
|
||
|
('wIndex', c_uint16),
|
||
|
('wLength', c_uint16)]
|
||
|
libusb_control_setup_p = POINTER(libusb_control_setup)
|
||
|
|
||
|
LIBUSB_CONTROL_SETUP_SIZE = sizeof(libusb_control_setup)
|
||
|
|
||
|
# Structure representing a libusb session. The concept of individual libusb
|
||
|
# sessions allows for your program to use two libraries (or dynamically
|
||
|
# load two modules) which both independently use libusb. This will prevent
|
||
|
# interference between the individual libusb users - for example
|
||
|
# libusb_set_debug() will not affect the other user of the library, and
|
||
|
# libusb_exit() will not destroy resources that the other user is still
|
||
|
# using.
|
||
|
#
|
||
|
# Sessions are created by libusb_init() and destroyed through libusb_exit().
|
||
|
# If your application is guaranteed to only ever include a single libusb
|
||
|
# user (i.e. you), you do not have to worry about contexts: pass NULL in
|
||
|
# every function call where a context is required. The default context
|
||
|
# will be used.
|
||
|
#
|
||
|
# For more information, see \ref contexts.
|
||
|
#class libusb_context(Structure):
|
||
|
# pass
|
||
|
#libusb_context_p = POINTER(libusb_context)
|
||
|
libusb_context_p = c_void_p # Any pointer is fine
|
||
|
libusb_context_p_p = POINTER(libusb_context_p)
|
||
|
|
||
|
# Structure representing a USB device detected on the system. This is an
|
||
|
# opaque type for which you are only ever provided with a pointer, usually
|
||
|
# originating from libusb_get_device_list().
|
||
|
#
|
||
|
# Certain operations can be performed on a device, but in order to do any
|
||
|
# I/O you will have to first obtain a device handle using libusb_open().
|
||
|
#
|
||
|
# Devices are reference counted with libusb_device_ref() and
|
||
|
# libusb_device_unref(), and are freed when the reference count reaches 0.
|
||
|
# New devices presented by libusb_get_device_list() have a reference count of
|
||
|
# 1, and libusb_free_device_list() can optionally decrease the reference count
|
||
|
# on all devices in the list. libusb_open() adds another reference which is
|
||
|
# later destroyed by libusb_close().
|
||
|
#class libusb_device(Structure):
|
||
|
# pass
|
||
|
#libusb_device_p = POINTER(libusb_device)
|
||
|
libusb_device_p = c_void_p # Any pointer is fine
|
||
|
libusb_device_p_p = POINTER(libusb_device_p)
|
||
|
libusb_device_p_p_p = POINTER(libusb_device_p_p)
|
||
|
|
||
|
# Structure representing a handle on a USB device. This is an opaque type for
|
||
|
# which you are only ever provided with a pointer, usually originating from
|
||
|
# libusb_open().
|
||
|
#
|
||
|
# A device handle is used to perform I/O and other operations. When finished
|
||
|
# with a device handle, you should call libusb_close().
|
||
|
class libusb_device_handle(Structure):
|
||
|
pass
|
||
|
libusb_device_handle_p = POINTER(libusb_device_handle)
|
||
|
libusb_device_handle_p_p = POINTER(libusb_device_handle_p)
|
||
|
|
||
|
class libusb_version(Structure):
|
||
|
_fields_ = [
|
||
|
('major', c_uint16),
|
||
|
('minor', c_uint16),
|
||
|
('micro', c_uint16),
|
||
|
('nano', c_uint16),
|
||
|
('rc', c_char_p),
|
||
|
('describe', c_char_p),
|
||
|
]
|
||
|
|
||
|
libusb_speed = Enum({
|
||
|
# The OS doesn't report or know the device speed.
|
||
|
'LIBUSB_SPEED_UNKNOWN': 0,
|
||
|
# The device is operating at low speed (1.5MBit/s).
|
||
|
'LIBUSB_SPEED_LOW': 1,
|
||
|
# The device is operating at full speed (12MBit/s).
|
||
|
'LIBUSB_SPEED_FULL': 2,
|
||
|
# The device is operating at high speed (480MBit/s).
|
||
|
'LIBUSB_SPEED_HIGH': 3,
|
||
|
# The device is operating at super speed (5000MBit/s).
|
||
|
'LIBUSB_SPEED_SUPER': 4,
|
||
|
# The device is operating at super speed plus (10000MBit/s)
|
||
|
'LIBUSB_SPEED_SUPER_PLUS': 5,
|
||
|
})
|
||
|
|
||
|
libusb_supported_speed = Enum({
|
||
|
# Low speed operation supported (1.5MBit/s).
|
||
|
'LIBUSB_LOW_SPEED_OPERATION': 1,
|
||
|
# Full speed operation supported (12MBit/s).
|
||
|
'LIBUSB_FULL_SPEED_OPERATION': 2,
|
||
|
# High speed operation supported (480MBit/s).
|
||
|
'LIBUSB_HIGH_SPEED_OPERATION': 4,
|
||
|
# Superspeed operation supported (5000MBit/s).
|
||
|
'LIBUSB_5GBPS_OPERATION': 8,
|
||
|
})
|
||
|
|
||
|
# Error codes. Most libusb functions return 0 on success or one of these
|
||
|
# codes on failure.
|
||
|
libusb_error = Enum({
|
||
|
# Success (no error)
|
||
|
'LIBUSB_SUCCESS': 0,
|
||
|
# Input/output error
|
||
|
'LIBUSB_ERROR_IO': -1,
|
||
|
# Invalid parameter
|
||
|
'LIBUSB_ERROR_INVALID_PARAM': -2,
|
||
|
# Access denied (insufficient permissions)
|
||
|
'LIBUSB_ERROR_ACCESS': -3,
|
||
|
# No such device (it may have been disconnected)
|
||
|
'LIBUSB_ERROR_NO_DEVICE': -4,
|
||
|
# Entity not found
|
||
|
'LIBUSB_ERROR_NOT_FOUND': -5,
|
||
|
# Resource busy
|
||
|
'LIBUSB_ERROR_BUSY': -6,
|
||
|
# Operation timed out
|
||
|
'LIBUSB_ERROR_TIMEOUT': -7,
|
||
|
# Overflow
|
||
|
'LIBUSB_ERROR_OVERFLOW': -8,
|
||
|
# Pipe error
|
||
|
'LIBUSB_ERROR_PIPE': -9,
|
||
|
# System call interrupted (perhaps due to signal)
|
||
|
'LIBUSB_ERROR_INTERRUPTED': -10,
|
||
|
# Insufficient memory
|
||
|
'LIBUSB_ERROR_NO_MEM': -11,
|
||
|
# Operation not supported or unimplemented on this platform
|
||
|
'LIBUSB_ERROR_NOT_SUPPORTED': -12,
|
||
|
# Other error
|
||
|
'LIBUSB_ERROR_OTHER': -99,
|
||
|
})
|
||
|
|
||
|
# Transfer status codes
|
||
|
libusb_transfer_status = Enum({
|
||
|
# Transfer completed without error. Note that this does not indicate
|
||
|
# that the entire amount of requested data was transferred.
|
||
|
'LIBUSB_TRANSFER_COMPLETED': 0,
|
||
|
# Transfer failed
|
||
|
'LIBUSB_TRANSFER_ERROR': 1,
|
||
|
# Transfer timed out
|
||
|
'LIBUSB_TRANSFER_TIMED_OUT': 2,
|
||
|
# Transfer was cancelled
|
||
|
'LIBUSB_TRANSFER_CANCELLED': 3,
|
||
|
# For bulk/interrupt endpoints: halt condition detected (endpoint
|
||
|
# stalled). For control endpoints: control request not supported.
|
||
|
'LIBUSB_TRANSFER_STALL': 4,
|
||
|
# Device was disconnected
|
||
|
'LIBUSB_TRANSFER_NO_DEVICE': 5,
|
||
|
# Device sent more data than requested
|
||
|
'LIBUSB_TRANSFER_OVERFLOW': 6,
|
||
|
})
|
||
|
|
||
|
# libusb_transfer.flags values
|
||
|
libusb_transfer_flags = Enum({
|
||
|
# Report short frames as errors
|
||
|
'LIBUSB_TRANSFER_SHORT_NOT_OK': 1 << 0,
|
||
|
# Automatically free() transfer buffer during libusb_free_transfer()
|
||
|
'LIBUSB_TRANSFER_FREE_BUFFER': 1 << 1,
|
||
|
# Automatically call libusb_free_transfer() after callback returns.
|
||
|
# If this flag is set, it is illegal to call libusb_free_transfer()
|
||
|
# from your transfer callback, as this will result in a double-free
|
||
|
# when this flag is acted upon.
|
||
|
'LIBUSB_TRANSFER_FREE_TRANSFER': 1 << 2,
|
||
|
# Terminate transfers that are a multiple of the endpoint's
|
||
|
# wMaxPacketSize with an extra zero length packet.
|
||
|
'LIBUSB_TRANSFER_ADD_ZERO_PACKET': 1 << 3,
|
||
|
})
|
||
|
|
||
|
# 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_iso_packet_descriptor_p = POINTER(libusb_iso_packet_descriptor)
|
||
|
|
||
|
class libusb_transfer(Structure):
|
||
|
pass
|
||
|
libusb_transfer_p = POINTER(libusb_transfer)
|
||
|
|
||
|
libusb_transfer_cb_fn_p = CFUNCTYPE(None, libusb_transfer_p)
|
||
|
|
||
|
libusb_capability = Enum({
|
||
|
# The libusb_has_capability() API is available.
|
||
|
'LIBUSB_CAP_HAS_CAPABILITY': 0x0000,
|
||
|
# Hotplug support is available.
|
||
|
'LIBUSB_CAP_HAS_HOTPLUG': 0x0001,
|
||
|
# The library can access HID devices without requiring user intervention.
|
||
|
'LIBUSB_CAP_HAS_HID_ACCESS': 0x0100,
|
||
|
# The library supports detaching of the default USB driver.
|
||
|
'LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER': 0x0101,
|
||
|
})
|
||
|
|
||
|
libusb_log_level = Enum({
|
||
|
'LIBUSB_LOG_LEVEL_NONE': 0,
|
||
|
'LIBUSB_LOG_LEVEL_ERROR': 1,
|
||
|
'LIBUSB_LOG_LEVEL_WARNING': 2,
|
||
|
'LIBUSB_LOG_LEVEL_INFO': 3,
|
||
|
'LIBUSB_LOG_LEVEL_DEBUG': 4,
|
||
|
})
|
||
|
|
||
|
# Note on libusb_strerror, libusb_setlocale and future functions in the
|
||
|
# same spirit:
|
||
|
# I do not think end-user-facing messages belong to a technical library.
|
||
|
# Such features bring a new, non essential set of problems, and is a luxury
|
||
|
# I do not want to spend time supporting considering limited resources and
|
||
|
# more important stuff to work on.
|
||
|
# For backward compatibility, expose libusb_strerror placeholder.
|
||
|
# pylint: disable=unused-argument
|
||
|
def libusb_strerror(errcode):
|
||
|
return None
|
||
|
# pylint: enable=unused-argument
|
||
|
|
||
|
# Get the data section of a control transfer. This convenience function is here
|
||
|
# to remind you that the data does not start until 8 bytes into the actual
|
||
|
# buffer, as the setup packet comes first.
|
||
|
#
|
||
|
# Calling this function only makes sense from a transfer callback function,
|
||
|
# or situations where you have already allocated a suitably sized buffer at
|
||
|
# transfer->buffer.
|
||
|
#
|
||
|
# \param transfer a transfer
|
||
|
# \returns pointer to the first byte of the data section
|
||
|
|
||
|
def libusb_control_transfer_get_data(transfer_p):
|
||
|
transfer = transfer_p.contents
|
||
|
return buffer_at(transfer.buffer, transfer.length)[
|
||
|
LIBUSB_CONTROL_SETUP_SIZE:]
|
||
|
|
||
|
def libusb_control_transfer_get_setup(transfer_p):
|
||
|
return cast(transfer_p.contents.buffer, libusb_control_setup_p)
|
||
|
|
||
|
def libusb_fill_control_setup(
|
||
|
setup_p, bmRequestType, bRequest, wValue, wIndex, wLength):
|
||
|
setup = cast(setup_p, libusb_control_setup_p).contents
|
||
|
setup.bmRequestType = bmRequestType
|
||
|
setup.bRequest = bRequest
|
||
|
setup.wValue = libusb_cpu_to_le16(wValue)
|
||
|
setup.wIndex = libusb_cpu_to_le16(wIndex)
|
||
|
setup.wLength = libusb_cpu_to_le16(wLength)
|
||
|
|
||
|
# pylint: disable=redefined-builtin
|
||
|
def libusb_fill_control_transfer(
|
||
|
transfer_p, dev_handle, buffer, callback, user_data, timeout):
|
||
|
transfer = transfer_p.contents
|
||
|
transfer.dev_handle = dev_handle
|
||
|
transfer.endpoint = 0
|
||
|
# pylint: disable=undefined-variable
|
||
|
transfer.type = LIBUSB_TRANSFER_TYPE_CONTROL
|
||
|
# pylint: enable=undefined-variable
|
||
|
transfer.timeout = timeout
|
||
|
transfer.buffer = cast(buffer, c_void_p)
|
||
|
if buffer is not None:
|
||
|
setup = cast(buffer, libusb_control_setup_p).contents
|
||
|
# pylint: disable=undefined-variable
|
||
|
transfer.length = LIBUSB_CONTROL_SETUP_SIZE + \
|
||
|
libusb_le16_to_cpu(setup.wLength)
|
||
|
# pylint: enable=undefined-variable
|
||
|
transfer.user_data = user_data
|
||
|
transfer.callback = callback
|
||
|
# pylint: enable=redefined-builtin
|
||
|
|
||
|
# pylint: disable=redefined-builtin
|
||
|
def libusb_fill_bulk_transfer(
|
||
|
transfer_p, dev_handle, endpoint, buffer, length,
|
||
|
callback, user_data, timeout):
|
||
|
transfer = transfer_p.contents
|
||
|
transfer.dev_handle = dev_handle
|
||
|
transfer.endpoint = endpoint
|
||
|
# pylint: disable=undefined-variable
|
||
|
transfer.type = LIBUSB_TRANSFER_TYPE_BULK
|
||
|
# pylint: enable=undefined-variable
|
||
|
transfer.timeout = timeout
|
||
|
transfer.buffer = cast(buffer, c_void_p)
|
||
|
transfer.length = length
|
||
|
transfer.user_data = user_data
|
||
|
transfer.callback = callback
|
||
|
# pylint: enable=redefined-builtin
|
||
|
|
||
|
# pylint: disable=redefined-builtin
|
||
|
def libusb_fill_interrupt_transfer(
|
||
|
transfer_p, dev_handle, endpoint, buffer,
|
||
|
length, callback, user_data, timeout):
|
||
|
transfer = transfer_p.contents
|
||
|
transfer.dev_handle = dev_handle
|
||
|
transfer.endpoint = endpoint
|
||
|
# pylint: disable=undefined-variable
|
||
|
transfer.type = LIBUSB_TRANSFER_TYPE_INTERRUPT
|
||
|
# pylint: enable=undefined-variable
|
||
|
transfer.timeout = timeout
|
||
|
transfer.buffer = cast(buffer, c_void_p)
|
||
|
transfer.length = length
|
||
|
transfer.user_data = user_data
|
||
|
transfer.callback = callback
|
||
|
# pylint: enable=redefined-builtin
|
||
|
|
||
|
# pylint: disable=redefined-builtin
|
||
|
def libusb_fill_iso_transfer(
|
||
|
transfer_p, dev_handle, endpoint, buffer, length,
|
||
|
num_iso_packets, callback, user_data, timeout):
|
||
|
transfer = transfer_p.contents
|
||
|
transfer.dev_handle = dev_handle
|
||
|
transfer.endpoint = endpoint
|
||
|
# pylint: disable=undefined-variable
|
||
|
transfer.type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
|
||
|
# pylint: enable=undefined-variable
|
||
|
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
|
||
|
# pylint: enable=redefined-builtin
|
||
|
|
||
|
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))
|
||
|
|
||
|
def get_iso_packet_list(transfer_p):
|
||
|
"""
|
||
|
Python-specific helper extracting a list of iso packet descriptors,
|
||
|
because it's not as straight-forward as in C.
|
||
|
"""
|
||
|
return _get_iso_packet_list(transfer_p.contents)
|
||
|
|
||
|
def _get_iso_packet_buffer(transfer, offset, length):
|
||
|
return buffer_at(transfer.buffer + offset, length)
|
||
|
|
||
|
def get_iso_packet_buffer_list(transfer_p):
|
||
|
"""
|
||
|
Python-specific helper extracting a list of iso packet buffers.
|
||
|
"""
|
||
|
transfer = transfer_p.contents
|
||
|
offset = 0
|
||
|
result = []
|
||
|
append = result.append
|
||
|
for iso_transfer in _get_iso_packet_list(transfer):
|
||
|
length = iso_transfer.length
|
||
|
append(_get_iso_packet_buffer(transfer, offset, length))
|
||
|
offset += length
|
||
|
return result
|
||
|
|
||
|
def get_extra(descriptor):
|
||
|
"""
|
||
|
Python-specific helper to access "extra" field of descriptors,
|
||
|
because it's not as straight-forward as in C.
|
||
|
Returns a list, where each entry is an individual extra descriptor.
|
||
|
"""
|
||
|
result = []
|
||
|
extra_length = descriptor.extra_length
|
||
|
if extra_length:
|
||
|
extra = buffer_at(descriptor.extra, extra_length)
|
||
|
append = result.append
|
||
|
while extra:
|
||
|
length = extra[0]
|
||
|
if not 0 < length <= len(extra):
|
||
|
raise ValueError(
|
||
|
'Extra descriptor %i is incomplete/invalid' % (
|
||
|
len(result),
|
||
|
),
|
||
|
)
|
||
|
append(extra[:length])
|
||
|
extra = extra[length:]
|
||
|
return result
|
||
|
|
||
|
def libusb_set_iso_packet_lengths(transfer_p, length):
|
||
|
transfer = transfer_p.contents
|
||
|
for iso_packet_desc in _get_iso_packet_list(transfer):
|
||
|
iso_packet_desc.length = length
|
||
|
|
||
|
def libusb_get_iso_packet_buffer(transfer_p, packet):
|
||
|
transfer = transfer_p.contents
|
||
|
offset = 0
|
||
|
if packet >= transfer.num_iso_packets:
|
||
|
return None
|
||
|
iso_packet_desc_list = _get_iso_packet_list(transfer)
|
||
|
for i in range(packet):
|
||
|
offset += iso_packet_desc_list[i].length
|
||
|
return _get_iso_packet_buffer(
|
||
|
transfer, offset, iso_packet_desc_list[packet].length)
|
||
|
|
||
|
def libusb_get_iso_packet_buffer_simple(transfer_p, packet):
|
||
|
transfer = transfer_p.contents
|
||
|
if packet >= transfer.num_iso_packets:
|
||
|
return None
|
||
|
iso_length = transfer.iso_packet_desc.length
|
||
|
return _get_iso_packet_buffer(transfer, iso_length * packet, iso_length)
|
||
|
|
||
|
# sync I/O
|
||
|
|
||
|
# pylint: disable=undefined-variable
|
||
|
def libusb_get_descriptor(dev, desc_type, desc_index, data, length):
|
||
|
return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
|
||
|
LIBUSB_REQUEST_GET_DESCRIPTOR,
|
||
|
(desc_type << 8) | desc_index, 0, data,
|
||
|
length, 1000)
|
||
|
# pylint: enable=undefined-variable
|
||
|
|
||
|
# pylint: disable=undefined-variable
|
||
|
def libusb_get_string_descriptor(dev, desc_index, langid, data, length):
|
||
|
return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
|
||
|
LIBUSB_REQUEST_GET_DESCRIPTOR,
|
||
|
(LIBUSB_DT_STRING << 8) | desc_index,
|
||
|
langid, data, length, 1000)
|
||
|
# pylint: enable=undefined-variable
|
||
|
|
||
|
# polling and timeouts
|
||
|
|
||
|
class libusb_pollfd(Structure):
|
||
|
_fields_ = [
|
||
|
('fd', c_int),
|
||
|
('events', c_short),
|
||
|
]
|
||
|
libusb_pollfd_p = POINTER(libusb_pollfd)
|
||
|
libusb_pollfd_p_p = POINTER(libusb_pollfd_p)
|
||
|
|
||
|
libusb_pollfd_added_cb_p = CFUNCTYPE(None, c_int, c_short, py_object)
|
||
|
libusb_pollfd_removed_cb_p = CFUNCTYPE(None, c_int, py_object)
|
||
|
|
||
|
#typedef int libusb_hotplug_callback_handle;
|
||
|
libusb_hotplug_callback_handle = c_int
|
||
|
|
||
|
libusb_hotplug_flag = Enum({
|
||
|
'LIBUSB_HOTPLUG_ENUMERATE': 1,
|
||
|
})
|
||
|
|
||
|
libusb_hotplug_event = Enum({
|
||
|
'LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED': 0x01,
|
||
|
'LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT': 0x02,
|
||
|
})
|
||
|
|
||
|
LIBUSB_HOTPLUG_MATCH_ANY = -1
|
||
|
|
||
|
#typedef int (*libusb_hotplug_callback_fn)(libusb_context *ctx,
|
||
|
# libusb_device *device, libusb_hotplug_event event, void *user_data);
|
||
|
libusb_hotplug_callback_fn_p = CFUNCTYPE(
|
||
|
c_int, libusb_context_p, libusb_device_p, c_int, c_void_p)
|
||
|
|
||
|
# /libusb.h
|