eblot / pyftdi

FTDI device driver written in pure Python
Other
509 stars 213 forks source link

show_devices() doesn't detect newly connected devices and crashes on disconnect #276

Open F3zz1k opened 2 years ago

F3zz1k commented 2 years ago

If show_devices() is run before a device is plugged in then pyftdi will not detect any newly connected devices even if show_devices() is run again. If show_devices() is run after a device is plugged in and then run again after said device is unplugged then it will crash with the following traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/site-packages/pyftdi/ftdi.py", line 407, in show_devices
    devdescs = UsbTools.list_devices(url or 'ftdi:///?',
  File "/usr/lib/python3.9/site-packages/pyftdi/usbtools.py", line 294, in list_devices
    candidates, _ = cls.enumerate_candidates(urlparts, vdict, pdict,
  File "/usr/lib/python3.9/site-packages/pyftdi/usbtools.py", line 437, in enumerate_candidates
    devices = cls.find_all(vps)
  File "/usr/lib/python3.9/site-packages/pyftdi/usbtools.py", line 121, in find_all
    description = UsbTools.get_string(dev, dev.iProduct)
  File "/usr/lib/python3.9/site-packages/pyftdi/usbtools.py", line 575, in get_string
    return usb_get_string(device, stridx)
  File "/usr/lib/python3.9/site-packages/usb/util.py", line 317, in get_string
    buf = get_descriptor(
  File "/usr/lib/python3.9/site-packages/usb/control.py", line 172, in get_descriptor
    desc = dev.ctrl_transfer(
  File "/usr/lib/python3.9/site-packages/usb/core.py", line 1082, in ctrl_transfer
    ret = self._ctx.backend.ctrl_transfer(
  File "/usr/lib/python3.9/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
    ret = _check(self.lib.libusb_control_transfer(
  File "/usr/lib/python3.9/site-packages/usb/backend/libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 19] No such device (it may have been disconnected)

code to reproduce error:

from pyftdi.ftdi import Ftdi
Ftdi.show_devices()  # run without a device plugged in
#plug in a device
Ftdi.show_devices()   # this shows nothing
from pyftdi.ftdi import Ftdi
Ftdi.show_devices()  # run with a device plugged in
#unplug a device
Ftdi.show_devices()   # this crashes
TedKus commented 2 years ago

from https://github.com/TedKus/useftdi/blob/main/useftdi/useftdi_core.py we built a function to list and return the url. the trouble is that windows won't let python know if a new usb device showed up (i think). we found it easier to just restart. Hope this helps. Ted

def get_available_ftdi_urls(): """ get_available_ftdi_urls()

Prints all availible FTDI interfaces currently connected to the machine.

Returns: List: List of Tuples for each ftdi connection found. Tuples are
               returned as (url, description) pairs.
"""

io_buffer = StringIO()
with redirect_stdout(io_buffer):
    Ftdi.show_devices()  # normally prints to stdout and returns None
response = io_buffer.getvalue()

# parse out list of connected devices
response = response.lstrip('Available interfaces:').strip()

connections = []
for connection in response.split('\n'):
    if connection == '':
        continue
    url, desc = connection.split()
    desc = desc.replace('(', '').replace(')', '')
    connections.append((url, desc))

if not connections:
    raise IOError("No FTDI devices found. Check USB connections..."
                  " Restart python to try again.")

return connections