Giter VIP home page Giter VIP logo

python-libusb1's Introduction

Supports all transfer types, both in synchronous and asynchronous mode.

Home: http://github.com/vpelletier/python-libusb1

PyPI: http://pypi.python.org/pypi/libusb1

  • CPython 3.6+, pypy 2.0+. Older versions may work, but are not recommended as there is no automated regression testing set up for them.
  • libusb-1.0

python-libusb1 can be expected to work on:

[1]Beware of libusb-win32, which implements 0.1 API, not 1.0 .
[2]Beware of possible lack of select.poll if you want to use asynchronous API.

Releases from PyPI, with name libusb1. Installing from command line:

$ pip install libusb1

Latest version from source tree:

$ git clone https://github.com/vpelletier/python-libusb1.git
$ cd python-libusb1
$ pip install .

On Windows, installing wheels from pypi also installs the libusb dll within the usb1 python module. It does not install any driver, so you still need to decide which of libusbk or WinUSB to use for each device and install it appropriately (possibly using Zadig, or by providing a driver for your users to install).

Installing from source tree does not install the dll, so you need to install the library where ctypes can find it - and of course the driver as well.

pipy releases are signed. To verify the signature:

  • download the release file, note its URL
  • download its detached signature by adding .asc at the end of the release file URL
  • add the release key(s) to a gnupg keyring (KEYS file in the home repository), and use gnupg to validate the signature both corresponds to the distribution file and is trusted by your keyring
  • install the already-fetched release file

Finding a device and gaining exclusive access:

import usb1
with usb1.USBContext() as context:
    handle = context.openByVendorIDAndProductID(
        VENDOR_ID,
        PRODUCT_ID,
        skip_on_error=True,
    )
    if handle is None:
        # Device not present, or user is not allowed to access device.
    with handle.claimInterface(INTERFACE):
        # Do stuff with endpoints on claimed interface.

Synchronous I/O:

while True:
    data = handle.bulkRead(ENDPOINT, BUFFER_SIZE)
    # Process data...

Asynchronous I/O, with more error handling:

def processReceivedData(transfer):
    if transfer.getStatus() != usb1.TRANSFER_COMPLETED:
        # Transfer did not complete successfully, there is no data to read.
        # This example does not resubmit transfers on errors. You may want
        # to resubmit in some cases (timeout, ...).
        return
    data = transfer.getBuffer()[:transfer.getActualLength()]
    # Process data...
    # Resubmit transfer once data is processed.
    transfer.submit()

# Build a list of transfer objects and submit them to prime the pump.
transfer_list = []
for _ in range(TRANSFER_COUNT):
    transfer = handle.getTransfer()
    transfer.setBulk(
        usb1.ENDPOINT_IN | ENDPOINT,
        BUFFER_SIZE,
        callback=processReceivedData,
    )
    transfer.submit()
    transfer_list.append(transfer)
# Loop as long as there is at least one submitted transfer.
while any(x.isSubmitted() for x in transfer_list):
    try:
        context.handleEvents()
    except usb1.USBErrorInterrupted:
        pass

For more, see the example directory.

python-libusb1 main documentation is accessible with python's standard pydoc command.

python-libusb1 follows libusb-1.0 documentation as closely as possible, without taking decisions for you. Thanks to this, python-libusb1 does not need to duplicate the nice existing libusb1.0 documentation.

Some description is needed though on how to jump from libusb-1.0 documentation to python-libusb1, and vice-versa:

usb1 module groups libusb-1.0 functions as class methods. The first parameter (when it's a libusb_... pointer) defined the class the function belongs to. For example:

  • int libusb_init (libusb_context **context) becomes USBContext class constructor, USBContext.__init__(self)
  • ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list) becomes an USBContext method, returning a list of USBDevice instances, USBDevice.getDeviceList(self)
  • uint8_t libusb_get_bus_number (libusb_device *dev) becomes an USBDevice method, USBDevice.getBusNumber(self)

Error statuses are converted into usb1.USBError exceptions, with status as value instance property.

usb1 module also defines a few more functions and classes, which are otherwise not so convenient to call from Python: the event handling API needed by async API.

Initial release

Massive rework of usb1.py, making it more python-ish and fixing some memory leaks.

Deprecate "transfer" constructor parameter to allow instance reuse.

Some work on isochronous "in" transfers. They don't raise exceptions anymore, but data validity and python-induced latency impact weren't properly checked.

Fix asynchronous configuration transfers.

Stand-alone polling thread for multi-threaded apps.

More libusb methods exposed on objects, including ones not yet part of released libusb versions (up to their commit 4630fc2).

2to3 friendly.

Drop deprecated USBDevice.reprConfigurations method.

Add FreeBSD support.

Add Cygwin support.

OpenBSD support checked (no change).

Add fink and homebrew support on OSX.

Drop PATH_MAX definition.

Try harder when looking for libusb.

Fix FreeBSD ABI compatibility.

Easier to list connected devices.

Easier to terminate all async transfers for clean exit.

Fix few segfault causes.

pypy support.

Descriptor walk API documented.

Version and capability APIs exposed.

Some portability fixes (OSes, python versions).

Isochronous transfer refuses to round transfer size.

Better exception handling in enumeration.

Add examples.

Better documentation.

Wrap hotplug API.

Wrap port number API.

Wrap kernel auto-detach API.

Drop wrapper for libusb_strerror, with compatibility place-holder.

Add a few new upstream enum values.

Backward-incompatible change: Enum class now affects caller's local scope, not its global scope. This should not be of much importance, as:

  • This class is probably very little used outside libusb1.py

  • This class is probably mostly used at module level, where locals == globals.

    It is possible to get former behaviour by providing the new scope_dict parameter to Enum constructor:

    SOME_ENUM = libusb1.Enum({...}, scope_dict=globals())
    

Improve start-up time on CPython by not importing standard inspect module.

Fix some more USBTransfer memory leaks.

Add Transfer.iterISO for more efficient isochronous reception.

Fixed USBContext.waitForEvent.

Fix typo in USBInterfaceSetting.getClassTuple method name. Backward compatibility preserved.

Remove globals accesses from USBDeviceHandle destructor.

Assorted documentation improvements.

Made USBDevice instances hashable.

Relaxed licensing by moving from GPL v2+ to LGPL v2.1+, for consistency with libusb1.

Reduce (remove ?) the need to import libusb1 module by exposing USBError and constants in usb1 module.

Fix libusb1.LIBUSB_ENDPOINT_ENDPOINT_MASK and libusb1.LIBUSB_ENDPOINT_DIR_MASK naming.

Fix pydoc appearance of several USBContext methods.

Define exception classes for each error values.

Fix wheel generation (python3 setup.py bdist_wheel).

controlWrite, bulkWrite and interruptWrite now reject (with TypeError) numeric values for data parameter.

Fix libusb1.REQUEST_TYPE_* names (were TYPE_*). Preserve backward compatibility.

Add USBContext.getDeviceIterator method.

Rename USBContext.exit as USBContext.close for consistency with other USB* classes. Preserve backward compatibility.

Make USBDeviceHandle.claimInterface a context manager, for easier interface releasing.

Introduce USBPollerThread.stop .

Fix USBDeviceHandle.getSupportedLanguageList bug when running under python 3. While fixing this bug it was realised that this method returned ctypes objects. This was not intended, and it now returns regular integers.

Make USBTransfer.cancel raise specific error instances.

Fix USBTransfer.cancel exception raising introduced in 1.5.2: it was accidentally becomming a bound method, preventing the raise to actually happen (in at least CPython 2.x) or raising type conversion errors (in at least CPython 3.5.2).

Improve asynchronous transfer performance: (very) suboptimal code was used to initialise asynchronous transfer buffer. As a consequence, usb1 now exposes bytearrays where it used to expose bytes or str objects.

Deprecate libusb1 module import, which should not be needed since all (?) needed constants were re-bound to usb1 module.

Move testUSB1 module inside usb1, to eventually only expose usb1 as top-level module.

Fix getSupportedLanguageList.

Fix and extend get{,ASCII}StringDescriptor .

Fix iterISO and getISOBufferList.

Fix getASCIIStringDescriptor: unlike getStringDescriptor, this returns only the payload of the string descriptor, without its header.

Deprecate USBPollerThread . It is mileading users for which the simple version (a thread calling USBContext.handleEvents) would be enough. And for more advanced uses (ie, actually needing to poll non-libusb file descriptors), this class only works reliably with epoll: kqueue (which should tehcnically work) has a different API on python level, and poll (which has the same API as epoll on python level) lacks the critical ability to change the set of monitored file descriptors while a poll is already running, causing long pauses - if not deadlocks.

Fix asynchronous control transfers.

Document hotplug handler limitations.

Run 2to3 when running setup.py with python3, and reduce differences with python3.

Properly cast libusb_set_pollfd_notifiers arguments. Fix null pointer value: POINTER(None) is the type of a pointer which may be a null pointer, which falls back to c_void_p. But c_void_p() is an actual null pointer.

Expose bare string descriptors (aka string indexes) on USBDevice.

get{,ASCII}StringDescriptor now return None for descriptor 0 instead of raising UnicodeDecodeError. Use getSupportedLanguageList to access it.

Moved getManufacturer, getProduct and getSerialNumber to USBDeviceHandle. Kept shortcuts for these on USBDevice.

get{,ASCII}StringDescriptor now return None for descriptor 0, use getSupportedLanguageList to get its content.

getManufacturer, getProduct and getSerialNumber are now on USBDeviceHandle, with backward-compatibility aliases on their original location.

Synchronous bulk and interrupt API exposes number of bytes sent and received bytes even when a timeout occurs.

usb1.__version__ is now present, managed by versioneer.

Fix an occasional segfault when closing a transfer from inside its callback function.

Fix getExtra and libusb1.libusb_control_transfer_get_data .

Fix getMaxPower unit on SuperSpeed devices.

Release process rework:

  • embed libusb1 dll for easier deployment on Windows
  • cryptographically signed releases

Use libusb_free_pollfds whenever available (libusb1>=1.0.20).

Fix hotplug callback destruction at context teardown.

Drop remnants of python 2.6 support code.

Drop USBPollerThread and deprecate libusb-lock-related USBContext API.

Fix installation from pypi source tarball, broken in 1.8.1 .

Windows wheels: Update bundled libusb to 1.0.24 .

Fix soure-only build when wheel is not available.

Add support for pyinstaller.

Improve the way the windows dlls are embedded in wheels.

Fix support for python 3.10 .

Add support for homebrew on Apple M1.

NOTE: Release yanked from pypi and re-released as 2.0.0.

Drop python <3.4 support.

Do not load the C library on import. Allows applications to customise the lookup logic (see usb1.loadLibrary).

Add LIBUSB_SPEED_SUPER_PLUS.

Better control device iterator end of life.

Fix objects escaping control from their parent.

Fix a TypeError exception in USBContext.handleEvents .

Fix an AttributeError exception in USBContext.hotplugRegisterCallback .

Fix segfault in pypy3 when finalizing USBDevice objects .

Source only: convert examples to python3.

Release process: also run some examples scripts.

Update versioneer to be compatible with 3.11 .

Drop python <3.6 support (consequence of versioneer update), hence the major version change.

Fix bug preventing use of setPollFDNotifiers.

Wrap libusb_interrupt_event_handler, available since libusb 1.0.21, to help applications wake an event handling thread (ex: durring exit).

Windows wheels: Update bundled libusb dll to 1.0.26 .

python-libusb1's People

Contributors

asellappen avatar astraw avatar charignon avatar csouers avatar flameeyes avatar hmaarrfk avatar ickc avatar jefferson-lopes avatar jordan-bonecutter avatar jrast avatar kenichihiguchi avatar lschyi avatar maxtruxa avatar multiplemonomials avatar projectgus avatar teddyboomer avatar tirkarthi avatar twitwi avatar vpelletier avatar wesq3 avatar whitequark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-libusb1's Issues

Document accepted types for `data` argument to *write methods

The Pydoc for USBDeviceHandle.interruptWrite (and the other handle write methods) lists the data parameter but makes no mention that integers are not allowed (intentionally or not). Each write method calls create_binary_buffer with their write data. If an int is passed in, create_binary_buffer returns an empty buffer of length data.

bytesWrote = handle.interruptWrite(ENDPOINT, 0xf) # writes 15 bytes of \0
bytesWrote = handle.interruptWrite(ENDPOINT, '\x0f') # writes 0xf, 1 byte

Is this a bug? Or expected behavior? Either way I find surprising.

I can submit a pull request with doc changes if you like.

opening 2 devices with same vendorID and productID

It would be great if openByVendorIDAndProductID() took an optional argument serialNumber. That way,
if there were two or more USB devices with the same vendorID and productID, there would be an
easy way to get a usb handle on the correct one. The default could be serialNumber =None to just return the first device that was not already open.

Send control request with invalid bmRequestType

Hi, I need to send a control request with a invalid direction in bmRequestType.

The device I want to talk to is awful and requires me to send some requests with the device to host direction, how can I do this?

Since controlWrite sets the direction bit, I tried to use _controlTransfer directly, but I run into the following error.

Traceback (most recent call last):
  File "./MD800E.py", line 140, in <module>
    main()
  File "./MD800E.py", line 95, in main
    dev.request(_Request.REG_READ, 0x0000, 0x0000)
  File "./MD800E.py", line 65, in request
    self._dev._controlTransfer(
  File "/usr/lib/python3.8/site-packages/usb1/__init__.py", line 1466, in _controlTransfer
    mayRaiseUSBError(result)
  File "/usr/lib/python3.8/site-packages/usb1/__init__.py", line 133, in mayRaiseUSBError
    __raiseUSBError(value)
  File "/usr/lib/python3.8/site-packages/usb1/__init__.py", line 125, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorIO: LIBUSB_ERROR_IO [-1]

Please find attached a capture of what my packets need to look like. Sorry for the zip, Github won't let me upload the capture directly.

md800e-512-384.zip

How to get data from a USB device

The method getDeviceList (usb1) shows the presence of the device and it really is (bladeRF), but the method openByVendorIDAndProductID (usb1, 0x2cf0, 0x5246) returns None and the device remains not available. No errors. What is the reason for this behavior and how to access the USB device.
OS Windows 7

```

import usb1
con = usb1.USBContext()
con.getDeviceList(usb1)
[<usb1.USBDevice object at 0x02A084D0>, <usb1.USBDevice object at 0x02A08670>,
<usb1.USBDevice object at 0x02A08690>, <usb1.USBDevice object at 0x02A08830>,
<usb1.USBDevice object at 0x02A08A50>, <usb1.USBDevice object at 0x02A08B70>,
<usb1.USBDevice object at 0x02A08C50>]
handl = con.openByVendorIDAndProductID(usb1, 0x2cf0, 0x5246)
print(handl)
None

libusb1 slightly slower than pyusb for large data.

I am using libusb1 to communicate to a device and am looking for ways to make the transfer faster.
The bulk transfer is 5959114 bytes to the USB Bulk endpoint 2. Currently, the bulkWrite call of usb1 is taking the longest amount of time of my project. I tested sending the same data with pyusb and found pyusb usually faster than libusb1. I hope my statistics and use case can help increase performance of this great repository. Following are the statistics I came up with, and how to reproduce them.

I hooked kernprof to my project and profiled usb1's bulkWrite function. Here are the results. I noticed the ctype conversion takes almost as much time as the transfer. Maybe there is a way to do this with zero copy in C?

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
  1378                                               @profile
  1379                                               def bulkWrite(self, endpoint, data, timeout=0):
  1380                                                   """
  1381                                                   Synchronous bulk write.
  1382                                                   endpoint: endpoint to send data to.
  1383                                                   data: data to send.
  1384                                                   timeout: in milliseconds, how long to wait for device acknowledgement.
  1385                                                     Set to 0 to disable.
  1386                                           
  1387                                                   Returns the number of bytes actually sent.
  1388                                                   """
  1389                                                   # pylint: disable=undefined-variable
  1390         4           20      5.0      0.0          endpoint = (endpoint & ~ENDPOINT_DIR_MASK) | ENDPOINT_OUT
  1391                                                   # pylint: enable=undefined-variable
  1392         4      1381478 345369.5     41.5          data = (c_char * len(data))(*data)
  1393         4      1945835 486458.8     58.5          return self._bulkTransfer(endpoint, data, sizeof(data), timeout)

Example Code

Code with usb1

from usb1 import USBContext
import math
c = USBContext()
h = c.openByVendorIDAndProductID(0x03fd, 0x000d)
h.claimInterface(0)
h.setInterfaceAltSetting(0,1)
data = bytearray(b"\\xf0\\x0f"* (int(math.ceil(0xb5db91/4.0))))
h.controlWrite(0x40, 0xb0, 0xb5A6, 0xdb91, b"")
h.bulkWrite(2,data,timeout=5000)

timeit line:

timeit.timeit('h.controlWrite(0x40, 0xb0, 0xb5A6, 0xdb91, b"");h.bulkWrite(2,data,timeout=5000)', setup='from usb1 import USBContext;c = USBContext();h = c.openByVendorIDAndProductID(0x03fd, 0x000d);h.claimInterface(0);h.setInterfaceAltSetting(0,1);import math;data = bytearray(b"\\xf0\\x0f"* (int(math.ceil(0xb5db91/4.0))));',number=20)

89.61355720099527 (Average 4.480677860049764s)

Code with pyusb

import usb.core
from time import time
dev = usb.core.find(idVendor=0x03fd, idProduct=0x000d)
dev.set_configuration()
cfg = dev.get_active_configuration()
intf=cfg[0,1]
intf.set_altsetting()
ep = intf.endpoints()[2]
data = bytearray(b"\\xf0\\x0f"*(int(math.ceil(0xb5db91/4.0))))
h.controlWrite(0x40, 0xb0, 0xb5A6, 0xdb91, b"")
h.bulkWrite(2,data,timeout=5000)

Here is the timeit line

import timeit
timeit.timeit('h.controlWrite(0x40, 0xb0, 0xb5A6, 0xdb91, b"");h.bulkWrite(2,data,timeout=5000)', setup='from usb1 import USBContext;c = USBContext();h = c.openByVendorIDAndProductID(0x03fd, 0x000d);h.claimInterface(0);h.setInterfaceAltSetting(0,1);import math;data = bytearray(b"\\xf0\\x0f"*(int(math.ceil(0xb5db91/4.0))))',number=20)

63.37948983995011 (Averate 3.1689744919975054s)

I can do a comparison with code in C directly calling libusb 1.0 if the benchmarks are useful.

Here is my code that I ran during the profiling: https://github.com/diamondman/proteusisc/blob/059d94e3625331c2786bd5a592388bd9f4caa893/proteusisc/drivers/xilinxPC1driver.py#L327-L333 (Please forgive the messyness. It is still alpha)

usb1.USBErrorNotSupported: LIBUSB_ERROR_NOT_SUPPORTED [-12]

Hello,

I got some new problems.
I try this package with android device(Samsung S5)
when I try to get the usb serial number,

File "C:\Python27\lib\site-packages\usb1.py", line 1870, in getSerialNumber
self.device_descriptor.iSerialNumber)
File "C:\Python27\lib\site-packages\usb1.py", line 1845, in _getASCIIStringDescriptor
temp_handle = self.open()
File "C:\Python27\lib\site-packages\usb1.py", line 1898, in open
mayRaiseUSBError(result)
File "C:\Python27\lib\site-packages\usb1.py", line 106, in mayRaiseUSBError
raiseUSBError(value)
File "C:\Python27\lib\site-packages\usb1.py", line 102, in raiseUSBError
raise STATUS_TO_EXCEPTION_DICT.get(value, USBError)(value)
usb1.USBErrorNotSupported: LIBUSB_ERROR_NOT_SUPPORTED [-12]

I guess that the problem is caused by driver or the libusb1 library
I use libusb-1.0.19 and ADB Interface's is libusb0 v1.2.6.0
May the library is not support this driver or not ?

Not Working on MacOS Sierra 10.12.6 | dlopen(libusb-1.0.dylib, 6): image not found

Hello I am running MacOS Sierra 10.12.6
installed both ways using pip and also downloading source, neither way works.

Error:
>>> import usb1 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "usb1/__init__.py", line 61, in <module> from . import libusb1 File "usb1/libusb1.py", line 199, in <module> libusb = _loadLibrary() File "usb1/libusb1.py", line 173, in _loadLibrary return dll_loader('libusb-1.0' + suffix, **loader_kw) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__ self._handle = _dlopen(self._name, mode) OSError: dlopen(libusb-1.0.dylib, 6): image not found

Any suggestions? Thanks in advance

LIBUSB_ERROR_NOT_SUPPORTED when trying to perform isochronous transfer

Hi. I'm trying to perform simple isochronous IN transfer on existing sound card device.
IN endpoint is located on interface 2, alternate setting 1.

I'm using Windows, libusbk backend. I've already tried WinUsb driver with the same result (driver is installed on root composite device using Zadig).

This is what I'm doing so far:

  1. Get libusb context (context = usb1.USBContext())
  2. Get device handle (using context.openByVendorIDAndProductID)
  3. handle.claimInterface(2)
  4. handle.setInterfaceAltSetting(2, 1)
  5. Create new transfer (handle.getTransfer(100))
  6. transfer.setIsochronous() - endpoint ID 0x81, transfer length: 17600, iso_transfer_length_list is empty.
  7. transfer.submit()

Unfortunately, call to submit throws LIBUSB_ERROR_NOT_SUPPORTED [-12] exception. I'm not sure why, as isochronous transfers should be supported in libusbk backend?
Do you have any examples how to perform isochronous transfer on non-zero interface and alternate setting? It would be very helpful to solve that issue.

ValueError: Invalid string descriptor

It seems usb1 is expecting the full string descriptor whereas libusb seems to returning only the string part.

If I hack the code at or around line 1350 to not check for the DT_STRING type and return the full result instead of just a subset it works as expected.

    manufacturer_string = device.getManufacturer()
  File "/usr/local/lib/python3.4/dist-packages/usb1/__init__.py", line 1961, in getManufacturer
    self.device_descriptor.iManufacturer)
  File "/usr/local/lib/python3.4/dist-packages/usb1/__init__.py", line 1953, in _getASCIIStringDescriptor
    return self.open().getASCIIStringDescriptor(descriptor)
  File "/usr/local/lib/python3.4/dist-packages/usb1/__init__.py", line 1351, in getASCIIStringDescriptor
    raise ValueError('Invalid string descriptor')
ValueError: Invalid string descriptor
        #if received < 2:# or descriptor_string[1] != DT_STRING:
        #    print('received : {}, descriptor_string[1] : {}'.format(received,descriptor_string[1]))
        #    raise ValueError('Invalid string descriptor')
        #return descriptor_string[2:min(
        #    received,
        #    descriptor_string[0],
        #)].decode('ASCII', errors=errors)
        return descriptor_string.decode('ASCII', errors=errors)

Check the version and the absolute path of the linked libusb library

Hi,

I need a confirmation : we can choose the path of the libusb-1.0-0.so.0 by manually setting the LIBUSB_BINARY before running pip install libusb1. Is that correct ? (for example if we work with the official source code)

Afterwhat, how can I see if it's working inside my code ? Any existing function or argument which return the path of the shared library ?

Thanks by advance.

RuntimeError when exiting the hotplug.py example

Hi,

first thank you for this library and your hard work! I tried to execute the hotplug.py from the examples directory. Works fine so far until I exit the program with ^C. This is the error that I get:

bash-3.2$ python libusb.py 
Registering hotplug callback...
Device arrived: Bus 250 Device 009: ID 05ac:821a
Device arrived: Bus 250 Device 006: ID 046d:c526
Device arrived: Bus 253 Device 004: ID 05ac:020c
Device arrived: Bus 250 Device 005: ID 05ac:0253
Device arrived: Bus 250 Device 004: ID 0a5c:4500
Device arrived: Bus 250 Device 003: ID 1a40:0101
Device arrived: Bus 253 Device 003: ID 05ac:1003
Device arrived: Bus 253 Device 002: ID 05ac:8242
Device arrived: Bus 250 Device 002: ID 0424:2513
Device arrived: Bus 250 Device 001: ID 05ac:8509
Device arrived: Bus 253 Device 001: ID 0424:2513
Callback registered. Monitoring events, ^C to exit
^CExiting
Traceback (most recent call last):
  File "libusb.py", line 126, in <module>
    main()
  File "libusb.py", line 123, in main
    print('Exiting')
  File "/Volumes/Data/Users/xxx/.local/share/virtualenvs/python-u35SbPCX/lib/python3.6/site-packages/usb1/__init__.py", line 2156, in __exit__
    self.close()
  File "/Volumes/Data/Users/xxx/.local/share/virtualenvs/python-u35SbPCX/lib/python3.6/site-packages/usb1/__init__.py", line 2189, in close
    self._exit()
  File "/Volumes/Data/Users/hetsch/.local/share/virtualenvs/python-u35SbPCX/lib/python3.6/site-packages/usb1/__init__.py", line 2197, in _exit
    for handle in self.__hotplug_callback_dict.keys():
RuntimeError: dictionary changed size during iteration

I haven't attached any devices, just started and and then imediately exited the program without any other interaction.

My environment:

Python 3.6.3 (default, Oct  4 2017, 06:09:05) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin

libusb1 1.6.4 (latest pypi version)

brew info libusb
libusb: stable 1.0.21 (bottled), HEAD
Library for USB device access
http://libusb.info
/usr/local/Cellar/libusb/1.0.21 (29 files, 510.5KB) *
Poured from bottle on 2017-09-13 at 17:18:48
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/libusb.rb

How to install libusb-1.0 dll for libusb1 on win64

I have some problem when I test this package on win64.

File "C:\Python27\lib\site-packages\libusb1.py", line 195, in
libusb = loadLibrary()
File "C:\Python27\lib\site-packages\libusb1.py", line 166, in loadLibrary
return dll_loader('libusb-1.0' + suffix, **loader_kw)
File "C:\Python27\lib\ctypes__init
.py", line 365, in init
self._handle = _dlopen(self._name, mode)
WindowsError: [Error 126] The specified module could not be found

then I download the binary for windows from http://libusb.info/
but I have no idea which file I should use and where I could put the dll file.
Could anyone help me, please

Would you consider LGPL licensing?

Hi,

Sorry if this is out of line, I just thought I'd ask if you'd be interested in licensing python-libusb1 as LGPL?

I started using your library in a non-GPL-compatible application and I somehow thought until now it was LGPL (I think probably because libusb is LGPL).

I noticed that the only significant contributions so far are yours, so it should be possible to relicense without any other contributor agreements.

My situation is of course entirely my fault for choosing an inappropriate GPL-licensed package. And licensing is entirely your personal choice so I don't mean to put any pressure on you. If you want to keep the current licensing then I'd understand entirely. I just thought I'd ask on the offchance.

Thanks again for all your work on python-libusb1 btw, it's really nice to work with!

Angus

USBErrorBusy with devices in hot-plug events notifications

Hello guys,

I've been playing and implementing some backend with usb1 and libusb1 for the past week,
trying to use the event to detect some devices and manage them once registered.

I've stumbled across a weird behaviour for me and would like to know if this is supposed to be a bug (in libusb or python-usb1) or this is expected behaviour that i'm supposed to handle.

The issues appears during hot plug events, when a device is plug-in while listening, trying to get the device.getSerialNumber() raise USBErrorBusy.

I've tried a multiple of solution including detachKernelDriver, claimInterface, releaseInterface and resetDevice but nothing seems to affect the issue.

Strangely if the devices are already plugging in before registering for hot-plugs event, the serialNumber can be retrieve and no USBErrorBusy is raised.

I've found an ugly work-around which is to fetch the device and serialNumber through a second USBContext instance instanciated on the fly, which make me feel like it's a bug somewhere.

I'm joining this issue with an sample script that reproduce the issue, you can easily test it with plugin a android phone in and out, and also having the phone already plug-in before launching the script.

Here the Work-around in details and next is a sample text output:

try:
    print "Device SerialNumber: %s" % device.getSerialNumber()
except Exception as e:
    with usb1.USBContext() as context:
        device_ = context.getByVendorIDAndProductID(device.getVendorID(), device.getProductID())
        serialNumber_ = device_.getSerialNumber()
        print "Fetching device with new usbContext fix usb_busy error: %s" % serialNumber_
Registering hotplug callback...
Device arrived: Bus 020 Device 024: ID 18d1:4ee2 - 1
Device SerialNumber: ENU7N15B14005190
Device arrived: Bus 026 Device 003: ID 05ac:8510 - 1
Device SerialNumber: CC2D820AKCDN9KB0
Device arrived: Bus 029 Device 007: ID 05ac:8286 - 1
Device SerialNumber: None
Device arrived: Bus 029 Device 004: ID 05ac:0262 - 1
Device SerialNumber: None
Device arrived: Bus 029 Device 003: ID 0a5c:4500 - 1
Device SerialNumber: None
Device arrived: Bus 029 Device 002: ID 0424:2512 - 1
Device SerialNumber: None
Device arrived: Bus 026 Device 001: ID 8087:0024 - 1
Device SerialNumber: None
Device arrived: Bus 029 Device 001: ID 8087:0024 - 1
Device SerialNumber: None
Callback registered. Monitoring events, ^C to exit

Device left: Bus 020 Device 024: ID 18d1:4ee2 - 1

Device arrived: Bus 020 Device 025: ID 18d1:4ee2 - 1
device.getSerialNumber failed with: LIBUSB_ERROR_BUSY [-6] (USBErrorBusy)
Fetching device with new usbContext fix usb_busy error: ENU7N15B14005190

Device left: Bus 020 Device 025: ID 18d1:4ee2 - 1

Device arrived: Bus 020 Device 023: ID 18d1:4ee2 - 1
device.getSerialNumber failed with: LIBUSB_ERROR_BUSY [-6] (USBErrorBusy)
Fetching device with new usbContext fix usb_busy error: ENU7N15B14005190

Could i fix the issue in the first place without needing my work-around ?
Should this be reported to libusb1 or handle directly in python-usb1 ?

Is there any device release business logic that should happen during hot-plug disconnect or connect event to make the usb "un-busy"

Thanks for the help guys.

hotplug.py

#!/usr/bin/env python
# Copyright (C) 2013-2016  Vincent Pelletier <[email protected]>
#
# 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
import usb1

eventType = {   usb1.HOTPLUG_EVENT_DEVICE_ARRIVED: 'arrived',
                usb1.HOTPLUG_EVENT_DEVICE_LEFT: 'left', }

def hotplug_callback(context, device, event):
    print "Device %s: %s - %s" % (eventType[event], device, device.getNumConfigurations())

    try:
        print "Device SerialNumber: %s" % device.getSerialNumber()
    except Exception as e:
        if type(e) is usb1.USBErrorNoDevice:
            return 

        print "device.getSerialNumber failed with: %s (%s)" % (e, type(e).__name__)        
        with usb1.USBContext() as context:
            device_ = context.getByVendorIDAndProductID(device.getVendorID(), device.getProductID())
            serialNumber_ = device_.getSerialNumber()
            print "Fetching device with new usbContext fix usb_busy error: %s" % serialNumber_
    pass

def main():
    with usb1.USBContext() as context:
        if not context.hasCapability(usb1.CAP_HAS_HOTPLUG):
            print 'Hotplug support is missing. Please update your libusb version.'
            return
        print 'Registering hotplug callback...'
        opaque = context.hotplugRegisterCallback(hotplug_callback)
        print 'Callback registered. Monitoring events, ^C to exit'
        try:
            while True:
                context.handleEvents()
        except (KeyboardInterrupt, SystemExit):
            print 'Exiting'

if __name__ == '__main__':
    main()

libusb has no hotplug support

On a fresh Win10 Build 1809 x64 I have installed Python2.7 and put the latest version libusb-1.0.22 dll into the example directory, run the example hotplug.py and got the result:
Hotplug support is missing. Please update your libusb version.

I am bit confused because y mentioned libusb as the dependencies, but this does not include hotplugging?
If there is any other workaround existing?

Regards,
Nic

OSError instead of ImportError when libusb binary is missing

_loadLibrary is called at import time. It tries to dlopen() the right binary, performs some sort of fallback if the call fails with OSError, but if the library can't be found, the original OSError is raised.
(see:

)

That means that the following correct-looking code ends up wrong:

try:
	import usb1
except ImportError:
	print("libusb not available")
	usb1 = None

the raise in question should probably be changed to:

	raise ImportError("could not find libusb binary") from oserr

(with except OSError as oserr at start of the block)

Lockup with USBPollerThread

As mentioned in the pull request for Hantek 6022 library, I have a problem with the USBPollerThread and synchronous API. The synchronous API will not be woken up if the event is handled by the poller thread and the call continues only after a timeout.
This happens with Ubuntu 16.04, libusb-1.0.20-1, libusb1-1.5.0

Any ideas how to test this further?

Minimal test program (for a hantek 6022):

import usb1
import select
from time import sleep

VENDOR_ID=0x04b4
PRODUCT_ID=0x6022

with usb1.USBContext() as context:
    usb1.USBPollerThread(context, select.poll()).start()
    device = context.getByVendorIDAndProductID(
            VENDOR_ID, PRODUCT_ID,
            skip_on_error=True,
            skip_on_access_error=True)
    handle = device.open()
    if handle is None:
        print("Cannot find scope")
        exit()
    handle.claimInterface(0)
    written = handle.controlWrite(0x40, 0xa0,
                            0xe600, 0x00, b'\x01')
    print(written)
    handle.releaseInterface(0)
    handle.close()

AttributeError: 'int' object has no attribute 'value' in function iterISO

I have a problem while trying to make an ISOCHRONOUS transfert.
I have two computers (work and home), and it did worked at work.
I've just reinstalled my home computer with ubuntu 16.04, and python-libusb1 is installed from last source.

I've got the following error, which refers to this part of code :
AttributeError: 'int' object has no attribute 'value'

Code : (line 694 of usb.py ) :
buffer_position = transfer.buffer.value
I can't figure out what I've done bad ! ;)

Thanks for you help !

Debian/Ubuntu package

I am a big fan of your work on this library, and believe the interface you present should be the standard way usb is interacted with in python. Unfortunately I can not rely on it when I am making debian/ubuntu packages because pip integration has always been problematic.

I would like to request a python-usb1 and python3-usb1 packages (or whatever you want to call them) be maintained in the debian package repository. I am aware that this process is a lot more complicated than publishing a project onto pypi, but I think it will be worth it to get people access to this great library.

I am willing to help get the packaging process started. I have never tried to get a package approved by the debian team for inclusion in the core repositories, but I have just built a package for a small python project I built, so I should be able to help at least getting it in a PPA or a private server.

Broken build on Linux

Recent addition of wheel as a setup dependency broke the installation on my Gentoo Linux system using this ebuild I wrote.

Download error on https://pypi.org/simple/wheel/: [Errno -3] Temporary failure in name resolution -- Some packages may not be found!
Couldn't find index page for 'wheel' (maybe misspelled?)
Download error on https://pypi.org/simple/: [Errno -3] Temporary failure in name resolution -- Some packages may not be found!
No local packages or working download links found for wheel
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/setuptools/installer.py", line 60, in fetch_build_egg
    pkg_resources.get_distribution('pip')
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 465, in get_distribution
    dist = get_provider(dist)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 341, in get_provider
    return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 884, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 770, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'pip' distribution was not found and is required by the application

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "setup.py", line 177, in <module>
    test_suite='usb1.testUSB1',
  File "/usr/lib/python3.7/site-packages/setuptools/__init__.py", line 152, in setup
    _install_setup_requires(attrs)
  File "/usr/lib/python3.7/site-packages/setuptools/__init__.py", line 147, in _install_setup_requires
    dist.fetch_build_eggs(dist.setup_requires)
  File "/usr/lib/python3.7/site-packages/setuptools/dist.py", line 676, in fetch_build_eggs
    replace_conflicting=True,
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 766, in resolve
    replace_conflicting=replace_conflicting
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 1049, in best_match
    return self.obtain(req, installer)
  File "/usr/lib/python3.7/site-packages/pkg_resources/__init__.py", line 1061, in obtain
    return installer(requirement)
  File "/usr/lib/python3.7/site-packages/setuptools/dist.py", line 732, in fetch_build_egg
    return fetch_build_egg(self, req)
  File "/usr/lib/python3.7/site-packages/setuptools/installer.py", line 68, in fetch_build_egg
    return _legacy_fetch_build_egg(dist, req)
  File "/usr/lib/python3.7/site-packages/setuptools/installer.py", line 51, in _legacy_fetch_build_egg
    return cmd.easy_install(req)
  File "/usr/lib/python3.7/site-packages/setuptools/command/easy_install.py", line 663, in easy_install
    raise DistutilsError(msg)
distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('wheel')

(Yes, the build process is sandboxed.)

The following patch fixes the problem: https://github.com/xHire/overlay/blob/master/dev-python/libusb1/files/libusb1-1.9.1-no_wheel_dependency.patch

In my opinion, the source tarball should be platform-independent. Unless I’m mistaken, wheel is only needed for Windows builds. It isn’t even packaged for Gentoo Linux. And python-libusb1 does build totally fine without it.

transfer.getStatus() always returns 0 and transfert interrupt is not freed

This is a simplified version of a code I am using

def processReceivedData(transfer):
    if transfer.getStatus() != usb1.TRANSFER_COMPLETED:
        print('Exiting transfer callback')
        # transfer.doom()
        return
    actual_sent = transfer.getActualLength()
    data = transfer.getBuffer()

    if actual_sent == len(data): #this is only way to return without submitting
        # transfer.close()
        return
    else:
        ... do something with data...
        transfer.submit()
with usb1.USBContext() as context:
    handle = context.openByVendorIDAndProductID()
    with handle.claimInterface(0):
        transfer = handle.getTransfer(0)  # libusb_alloc_transfer
        transfer = handle.getTransfer(0) 
        transfer.setInterrupt(endpoint=INT_IN_EP, buffer_or_len=3072, callback=processReceivedData, user_data=None, timeout=0)
        transfer.submit()
        handle.bulkWrite(endpoint=BULK_OUT_EP, data=buff, timeout=0) # configure device
        handle.bulkWrite(endpoint=BULK_OUT_EP, data=buff, timeout=0) # trigger raeding
        while transfer.isSubmitted():
            try:
                context.handleEvents()
            except usb1.USBErrorInterrupted as e:
                pass
        handle.bulkWrite(endpoint=BULK_OUT_EP, data=buff, timeout=0) # stop reading

The problem two parts:

  1. transfer.getStatus() is always returning 0, this does not happen in the C code I have for this device.
  2. I found a way to force the callback function to return, however, the interrupt is not being set free.

I tried to close or doom the transfer but all methods are raising errors. The original code I use in C to free the interrupt is:

  libusb_free_transfer(transfer);
  transfer_pointer = NULL;

getDevice() is mostly unusable with WinUSB

WinUSB always opens an USB device in exclusive mode. This means that you can't do something like...

handle = self.usb_context.openByVendorIDAndProductID(vendor_id, product_id)
serial = handle.getDevice().getSerialNumber()

because USBDevice.getSerialNumber() opens the device a second time internally and that fails with LIBUSB_ERROR_ACCESS.

I think getDevice() should return a "pre-opened" USBDevice object to avoid this.

Mypy Support?

I've got a WIP implementation of mypy type stubs for this package in adbpy/transports@43a26a8.

I haven't finished them yet but I'm opening this issue to get the conversation going. Is this something you would be interested in taking upstream once complete? Otherwise, I'll look into breaking them out into a separate stubs-only package.

getSupportedLanguageList does not work on Python 3.5

Hi. I just encountered a small issue in your library.
In getSupportedLanguageList, this line gives error about incompatible types (int and float):
for offset in xrange(1, length / 2):

Using binary shift instead, should solve this problem:
for offset in xrange(1, length >> 1):

usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]

Source:

import usb1

# Bus 003 Device 012: ID 1d57:fa20 Xenta
VENDOR_ID = 0x1D57
PRODUCT_ID = 0xFA20

with usb1.USBContext() as context:
    handle = context.openByVendorIDAndProductID(
        VENDOR_ID,
        PRODUCT_ID,
        skip_on_error=True,
    )
    if handle is None:
        print('Device not present, or user is not allowed to access device.')
    else:
        print(handle)

Error:

/usr/bin/python2.7 /home/bernardo/dev/psumon/psumon/tmp.py
Traceback (most recent call last):
  File "/home/bernardo/dev/psumon/psumon/tmp.py", line 12, in <module>
    skip_on_error=True,
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 2298, in openByVendorIDAndProductID
    return result.open()
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 2067, in open
    mayRaiseUSBError(libusb1.libusb_open(self.device_p, byref(handle)))
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 133, in mayRaiseUSBError
    __raiseUSBError(value)
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 125, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]

Process finished with exit code 1

Works fine when I invoke it with sudo:

$ sudo python tmp.py 
<usb1.USBDeviceHandle object at 0x7f3d2e170fd0>

I reckon from looking at python-libusb1/usb1/libusb1.py that LIBUSB_ERROR_ACCESS [-3] means Access denied (insufficient permissions).
Do I need to set any kinds of permission in my system before I can use this package?

Also, which value should INTERFACE hold in the following code?

    with handle.claimInterface(INTERFACE):
        # Do stuff with endpoints on claimed interface.

USBContext waitForEvent may not work correctly.

Hey, I am trying to use the USBPollerThread class, and my Python script seems to fall apart on the waitForEvent() method in USBContext, which is:

@_validContext
def waitForEvent(self):
    """
    See libusb_wait_for_event doc.
    """
    libusb1.libusb_wait_for_event(self.__context_p)

However the wrapper for libusb_wait_for_event() is:

  #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]

It looks like the context waitForEvent call is missing a timeval argument. Any ideas here? Maybe I'm missing something...

No partial data when timeout occured in bulk reads

When performing bulk reads from the device by using e.g. USBDeviceHandle.bulkRead(0x86, 0x1000, timeout=1000) and the timeout is hit, a 'libusb1.USBError' is raised and the partially transferred data is lost.
I would've expected that bulkRead (or _bulkTransfer which actually calls the underlying libusb1) ignores the timeout error and yields the partial data.

My (hacky) workaround looks like this:

    def _bulkTransfer(self, endpoint, data, length, timeout):
        transferred = c_int()
        try: mayRaiseUSBError(libusb1.libusb_bulk_transfer(
            self.__handle, endpoint, data, length, byref(transferred), timeout,
        ))
        except USBError as e:
            if e.value != libusb1.LIBUSB_ERROR_TIMEOUT: raise e
        return transferred.value

Can't install libusb with recent versions of setuptools

$ sudo -H pip3 install libusb1
Collecting libusb1
Using cached libusb1-1.6.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/private/tmp/pip-build-o4hqf9gk/libusb1/setup.py", line 16, in
from setuptools import setup
ImportError: cannot import name 'setup'

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in /private/tmp/pip-build-o4hqf9gk/libusb1/

I had to downgrade to setuptools version 20.10.1 to successfully install.

Cant' get macos to list devices

Hi,
I'm using Python3.6 with libusb1 from PyPI and libusb1 installed via HomeBrew, but I can't get my USB devices listed.

It lists standard apple devices, but not my serial ports, etc. However lsusb does list the devices (it's a bash script that parses the outupt of Sytem Profiler or System Information app).

I've read about libusb inf files for Windows (not sure why they're needed). Is there something similar required for Mac?

Is there a mailing list for python-libusb1 or should I use the libsub mailing list?

Thanks, Brendan.

Occasional segfault if `USBTransfer.close` is called in callback

During the entirety of the time that libusb is calling the callback that python-libusb1 provides, the thunk (stored in USBTransfer.__ctypesCallbackWrapper) needs to be kept alive. Calling USBTransfer.close within the callback destroys the (still-running) thunk, causing occasional segfaults in libffi when returning back to libusb.

Currently, the __submitted flag and before_submit/after_completion callbacks are used to keep the USBTransfer alive, and that's almost sufficient. The __ctypesCallbackWrapper is special, though; it needs to be guaranteed to live a little bit longer - until after __callbackWrapper has returned.

I think that the easiest fix here is to:

  1. Make __callbackWrapper a @staticmethod
  2. Create __ctypesCallbackWrapper in the class body rather than in __init__ so it's shared between all USBTransfers
  3. Use a dict of currently submitted transfers to get the USBTransfer object corresponding to the libusb transfer pointer that is provided to the callback

Hotplug support on windows

I've wasted a few days now trying to getting the hotplug code to run on Windows with no luck. This package always tells me my libusb driver is out of date. I have tried using native python, msys2, mingw, cygwin, miniconda... All the non-native python environments should have libusb1.0 installed so I am not sure why this package keeps finding/using some 0.1 lib. I've tried installing the pacakge from pypi and from source. Not sure what the trick is. Is there any way to get this package to use libusbK?

unorderable types in USBTransfer.cancel

I got an error when calling cancel on a transfer. Test code:

import usb1

def on_read_finished(transfer):
    pass

context = usb1.USBContext()
handle = context.openByVendorIDAndProductID(
    0x10c4, 0x842a, skip_on_error=True,
)
transfer = handle.getTransfer()
transfer.setBulk(0x81, 65536, callback=lambda:0)
transfer.submit()
transfer.cancel()

Error:

Traceback (most recent call last):
  File "scripts/repro.py", line 13, in 
    transfer.cancel()
  File "/usr/local/lib/python3.5/dist-packages/usb1.py", line 748, in cancel
    self.__mayRaiseUSBError(self.__libusb_cancel_transfer(self.__transfer))
  File "/usr/local/lib/python3.5/dist-packages/usb1.py", line 132, in mayRaiseUSBError
    if value < 0:
TypeError: unorderable types: USBTransfer() < int()

Python 3.5.2, libusb1 (1.5.2) installed via pip, libusb-1.0-0:amd64 version 2:1.0.20-1 installed via apt.``

Sign PyPI releases

Describe the bug

When a user downloads this python module using pip, there is no cryptographic authenticity or integrity validation to protect the user from a MITM attack.

Therefore, this project is making any other projects that obtain the libusb1 module via pip in their build process vulnerable to a watering hole attack.

Expected behavior

A developer should have a mechanism to cryptographically verify the integrity and authenticity of libusb1 when obtaining it through pip.

To Reproduce

pip install libusb1

Additional context

Possible solutions include:

  1. Using the --sign argument of twine when uploading packages to PyPI

  2. Publishing a cryptographically signed document (ideally using gpg) listing the hashes for all packages uploaded to PyPI, which users can then pass into pip using the --hash argument

RuntimeError: Set changed size during iteration

I can reliably reproduce this crash in my project when I'm calling usb_handle.close():

  File "/home/whitequark/Projects/Glasgow/software/glasgow/device/hardware.py", line 142, in close
    self.usb_handle.close()
  File "/home/whitequark/Projects/python-libusb1/build/lib/usb1/__init__.py", line 1234, in close
    for transfer in inflight:
RuntimeError: Set changed size during iteration

The following patch fixes the error for me:

--- a/python-libusb1/usb1/__init__.py Thu Oct  3 19:16:01 2019
+++ b/python-libusb1/usb1/__init__.py Thu Oct  3 19:16:04 2019
@@ -1231,7 +1231,7 @@
             transfer_set.add(transfer)
             transfer.doom()
         inflight = self.__inflight
-        for transfer in inflight:
+        for transfer in self.__set(inflight):
             try:
                 transfer.cancel()
             except (self.__USBErrorNotFound, self.__USBErrorNoDevice):

However I'm not sure if this is the correct way to do it.

failed to instal version 1.9 from sdist. error: option --single-version-externally-managed not recognized

I can't install libusb1 version 1.9 from sdist -- version 1.8 works.
Any idea what is going on?

$ python --version
Python 3.8.5

$ pip list
Package       Version
------------- -------
pip           20.3.1
pkg-resources 0.0.0
setuptools    51.0.0
wheel         0.36.1

$ pip install libusb1==1.9 --no-binary :all:
Collecting libusb1==1.9
  Using cached libusb1-1.9.tar.gz (79 kB)
Skipping wheel build for libusb1, due to binaries being disabled for it.
Installing collected packages: libusb1
    Running setup.py install for libusb1 ... error
    ERROR: Command errored out with exit status 1:
     command: /home/user/wspace/tmp/tmp-venv/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-0k22s29n/libusb1_4996cb72fe7547fa9623be2a334af9a9/setup.py'"'"'; __file__='"'"'/tmp/pip-install-0k22s29n/libusb1_4996cb72fe7547fa9623be2a334af9a9/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-8m2z6xqo/install-record.txt --single-version-externally-managed --compile --install-headers /home/user/wspace/tmp/tmp-venv/include/site/python3.8/libusb1
         cwd: /tmp/pip-install-0k22s29n/libusb1_4996cb72fe7547fa9623be2a334af9a9/
    Complete output (6 lines):
    usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
       or: setup.py --help [cmd1 cmd2 ...]
       or: setup.py --help-commands
       or: setup.py cmd --help
    
    error: option --single-version-externally-managed not recognized
    ----------------------------------------
ERROR: Command errored out with exit status 1: /home/user/wspace/tmp/tmp-venv/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-0k22s29n/libusb1_4996cb72fe7547fa9623be2a334af9a9/setup.py'"'"'; __file__='"'"'/tmp/pip-install-0k22s29n/libusb1_4996cb72fe7547fa9623be2a334af9a9/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-8m2z6xqo/install-record.txt --single-version-externally-managed --compile --install-headers /home/user/wspace/tmp/tmp-venv/include/site/python3.8/libusb1 Check the logs for full command output.

$ pip install libusb1==1.8 --no-binary :all:
Collecting libusb1==1.8
  Using cached libusb1-1.8.tar.gz (78 kB)
Skipping wheel build for libusb1, due to binaries being disabled for it.
Installing collected packages: libusb1
    Running setup.py install for libusb1 ... done
Successfully installed libusb1-1.8

Hang on cleanup

While tracking down an issue in another project, I wrote this script and found that it hangs in libusb_unlock_events() (called from libusb_close()).

I'm running Arch Linux current.

  • Python: 3.5.1
  • libusb: 1.0.20-1
  • python-libusb1 (from pip): 1.4.1
  • Kernel: 4.4.5-1 x64

The C program I based this script on does not hang, but probably does things slightly different.

Segmentation fault

USBDevice.getBusNumber() in usb1/init.py line(1991) causes Segmentation fault if accessed after usb1.USBContext() is closed.
I know it does not make much sense to access the device after closing the context manager, but it would be better if the error is caught instead of causing python process to crash.

Add PyInstaller Hook

Currently the DLL, which ships with the windows build, is not automatically included if PyInstaller is used to bundle a application. The PyInstaller Documentation recommends to provide the required hooks in the package itself and using a special setuptools entry point in order to make the hook discoverable.

The following hook would be required:

"""
PyInstaller Hook for usb1
"""
from PyInstaller.utils.hooks import collect_dynamic_libs
binaries = collect_dynamic_libs( 'usb1' ) 

Example on how to use python asyncio event loop with hotplug API

Hi Vincent,

you have an hotplug_advanced.py file in your examples directory which shows how to use libusb1 with a custom event loop and custom pollers. What I don't understand right now is how to use libusb1 in conjunction with python's asyncio library (to use/reuse asyncio's event loop). If it is not too much work, it might help if these advanced examples would integrate such an example.

USBTransfer memory leak.

Hi,

The usb1.USBTransfer.close() method needs a couple of extra lines to prevent a memory leak. You need to set the __user_data and __transfer_buffer both to None, to allow the object to be garbage collected. Without these, the user_data prevents garbage collection when I pass the transfer object itself as the argument to the callback (hence creating a reference cycle).

Sorry, I can't submit a patch, as git drives me f**king insane with its stupid command line.

Cheers,
Bryan

unable to find devices

Hi,
I am trying to list of usb devices in windows machine. I am using python 3.4 and following is my code:

import usb1

with usb1.USBContext() as context:
# handle = context.openByVendorIDAndProductID(
# skip_on_error=True,
# )
handle=context.open()
if handle is None:
#Device not present, or user is not allowed to access device.
print("No device found")
else:
print("device found")
# with handle.claimInterface(INTERFACE):
# Do stuff with endpoints on claimed interface.

And i am getting following error:
C:\Python34\python.exe C:/Users/Prabhu/PycharmProjects/USBTRACER/testsamples/usbtest1.py
Traceback (most recent call last):
File "C:/Users/Prabhu/PycharmProjects/USBTRACER/testsamples/usbtest1.py", line 1, in
import usb1
File "", line 2237, in _find_and_load
File "", line 2226, in _find_and_load_unlocked
File "", line 1191, in _load_unlocked
File "", line 1161, in _load_backward_compatible
File "C:\Python34\lib\site-packages\libusb1-1.5.0-py3.4.egg\usb1.py", line 60, in
import libusb1
File "", line 2237, in _find_and_load
File "", line 2226, in _find_and_load_unlocked
File "", line 1191, in _load_unlocked
File "", line 1161, in _load_backward_compatible
File "C:\Python34\lib\site-packages\libusb1-1.5.0-py3.4.egg\libusb1.py", line 193, in
libusb = loadLibrary()
File "C:\Python34\lib\site-packages\libusb1-1.5.0-py3.4.egg\libusb1.py", line 167, in loadLibrary
return dll_loader('libusb-1.0' + suffix, **loader_kw)
File "C:\Python34\Lib\ctypes__init
.py", line 351, in init
self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

Process finished with exit code 1

Thanks in advance.

Libusb1 Async Control Buffer Null

I've been using libusb1 for around 9 months for multiple usb devices and found out ew 1.6.0 versions and later cause problems with my devices. I'm pretty sure it's tied to this issue (#21) and using the getBuffer() command to get the most recent data sent when preforming a setControl call.
After some further inspection I couldn't find where the buffer is actually updated during a 0xC1 request. Any help would be much appreciated.

Here is some example code. I'm awaiting asyncControlTransfer which is calling setControl. This works perfectly fine with 1.5.3

transfer = await asyncusb.asyncControlTransfer(
            self.handle, 0xC1,
            0x20,
            0, 0, 8, timeout = self.CT_TIMEOUT)
result = transfer.getUserData()

def asyncControlTransfer(handle, *args, **kwargs):
    ct = handle.getTransfer()
    ct.setControl(*args, **kwargs)
    return asyncTransfer(ct)

def asyncTransfer(transfer):
    fut = asyncio.Future()
    def callback(t):
        try:
            result = t.getStatus()
            if result != TRANSFER_COMPLETED:
                raise USBTransferError(result)
            if not fut.cancelled():
                fut.set_result(t)
        except Exception as e:
            fut.set_exception(e)
    transfer.setCallback(callback)
    result = transfer.submit()
    return fut

Does not install properly on macOS Catalina

pip install finishes claiming success
but import fails
Do I really have to use some package manager?

➜  ~ python3 -m pip install libusb1 
Defaulting to user installation because normal site-packages is not writeable
Collecting libusb1
  Downloading libusb1-1.8.tar.gz (78 kB)
     |████████████████████████████████| 78 kB 1.7 MB/s 
Building wheels for collected packages: libusb1
  Building wheel for libusb1 (setup.py) ... done
  Created wheel for libusb1: filename=libusb1-1.8-py3-none-any.whl size=59991 sha256=8cd2f4578571cbc04d273ed0d4218e1298a50494f579a146b0f20f00983b7ee6
  Stored in directory: /Users/Martin/Library/Caches/pip/wheels/e0/c8/71/5aad28fb4e963a6ff65d532fc58c1a2f018559bbe9e2655e07
Successfully built libusb1
Installing collected packages: libusb1
Successfully installed libusb1-1.8
➜  ~ python3                         
Python 3.7.3 (default, Mar  6 2020, 22:34:30) 
[Clang 11.0.3 (clang-1103.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import usb1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/Martin/Library/Python/3.7/lib/python/site-packages/usb1/__init__.py", line 61, in <module>
    from . import libusb1
  File "/Users/Martin/Library/Python/3.7/lib/python/site-packages/usb1/libusb1.py", line 192, in <module>
    libusb = _loadLibrary()
  File "/Users/Martin/Library/Python/3.7/lib/python/site-packages/usb1/libusb1.py", line 166, in _loadLibrary
    return dll_loader('libusb-1.0' + suffix, **loader_kw)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(libusb-1.0.dylib, 6): image not found
>>> 

Inside Thonny the error message has the additional line:
Did find: file system relative paths not allowed in hardened programs

usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]

OS: macOS high Sierra version 10.13.6
Question: Any thoughts on what is not allowing permissions? (Using sudo makes no difference.)

Source:
`import usb1

VENDOR_ID = 0x1915
PRODUCT_ID = 0x520A
def main():
context = usb1.USBContext()
handle = context.openByVendorIDAndProductID(VENDOR_ID, PRODUCT_ID, skip_on_error=True,)
if handle is None:
# Device not present, or user is not allowed to access device
print("Device not present")
else:
print(handle)

if handle.kernelDriverActive(0):
print("usb taken, detach from kernel")
handle.detachKernelDriver(0)
handle.claimInterface(0)

device = context.getByVendorIDAndProductID(VENDOR_ID, PRODUCT_ID,skip_on_error=True)
print(handle.getDevice())`

if name == 'main':
main()

Error:
[Tue Aug 07 15:13] ew@Dev-iOS-MacBook-Pro: ~/Projects/Usb $ python scale_02.py
<usb1.USBDeviceHandle object at 0x105555690>
Traceback (most recent call last):
File "scale_02.py", line 32, in
main()
File "scale_02.py", line 26, in main
handle.claimInterface(0)
File "/usr/local/lib/python2.7/site-packages/usb1/init.py", line 1276, in claimInterface
libusb1.libusb_claim_interface(self.__handle, interface),
File "/usr/local/lib/python2.7/site-packages/usb1/init.py", line 133, in mayRaiseUSBError
__raiseUSBError(value)
File "/usr/local/lib/python2.7/site-packages/usb1/init.py", line 125, in raiseUSBError
raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]

Additional info on my USB device:
DEVICE ID 1915:520a on Bus 064 Address 006 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x1915
idProduct : 0x520a
bcdDevice : 0x101 Device 1.01
iManufacturer : 0x1 Perfect Company
iProduct : 0x2 USB HID scale
iSerialNumber : 0x0
bNumConfigurations : 0x1
CONFIGURATION 1: 98 mA ===================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x22 (34 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0xe0 Self Powered, Remote Wakeup
bMaxPower : 0x31 (98 mA)
INTERFACE 0: Human Interface Device ====================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x1
bInterfaceClass : 0x3 Human Interface Device
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x0
ENDPOINT 0x81: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0x8

I/O Problem

Hello,

I'm sorry if it's not the good place to post this but i'm new in github and i don't know where I should ask.

I'm using your tool to build a fuzzer over USB. I succeed to write data with the synchronous fonctions (bulkWrite) but I failed to read with the "bulkRead" fontion (Nothing is received). I want to try to use the asynchronous fonctions to see if it solves the problem but I have some problems to understand how I can use the snippet code you gave.

Do you have a full example of an asynchronous communication or a link to another project which use the asynchronous fonctions ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.