<commit_before># Copyright (C) 2010-2018  <NAME> <<EMAIL>>
#
# 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.
Locates and loads libusb1 dynamic library.
"""
from ctypes import (
    Structure, LittleEndianStructure,
    CFUNCTYPE, POINTER, addressof, sizeof, cast,
    c_short, c_int, c_uint, c_size_t, 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 platform
import os.path
import sys

class Enum(object):
    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 _loadLibrary():
    system = platform.system()
    if system == 'Windows':
        dll_loader = ctypes.WinDLL
        suffix = '.dll'
    else:
        dll_loader = ctypes.CDLL
        suffix = system == 'Darwin' and '.dylib' or '.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',
                ):
                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)

libusb = _loadLibrary()

# libusb.h
def bswap16(x):
    return ((x & 0xff) << 8) | (x >> 8)

if LITTLE_ENDIAN:<commit_msg>Add path to dylib for Apple M1<commit_after># Copyright (C) 2010-2018  <NAME> <<EMAIL>>
#
# 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.
Locates and loads libusb1 dynamic library.
"""
from ctypes import (
    Structure, LittleEndianStructure,
    CFUNCTYPE, POINTER, addressof, sizeof, cast,
    c_short, c_int, c_uint, c_size_t, 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 platform
import os.path
import sys

class Enum(object):
    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 _loadLibrary():
    system = platform.system()
    if system == 'Windows':
        dll_loader = ctypes.WinDLL
        suffix = '.dll'
    else:
        dll_loader = ctypes.CDLL
        suffix = system == 'Darwin' and '.dylib' or '.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)

libusb = _loadLibrary()

# libusb.h
def bswap16(x):
    return ((x & 0xff) << 8) | (x >> 8)

if LITTLE_ENDIAN:
{'fraction_non_alphanumeric': 0.09481539670070699, 'fraction_numerical': 0.01021209740769835, 'mean_word_length': 2.4315363881401617, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7509036', 'n_tokens_mistral': 3978, 'n_tokens_neox': 3806, 'n_words': 1172}