DanielSank
DanielSank

Reputation: 3442

How do I connect to an FT230 with pylibftdi?

I have exactly one FTDI FT230X connected to my machine. I can see the device using lsusb:

$ lsusb
Bus 002 Device 005: ID 051d:0002 American Power Conversion Uninterruptible Power Supply
Bus 002 Device 004: ID 046d:c408 Logitech, Inc. Marble Mouse (4-button)
...
Bus 003 Device 010: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO)
...

That 0403:6015 entry is the FT230X. I'd like to talk to this thing in Python, so we do

>>> import pylibftdi
>>> dev = pylibftdi.Device()

but get an error message reading

~/.virtualenvs/labrad/local/lib/python2.7/site-packages/pylibftdi/device.pyc in __init__(self, device_id, mode, encoding, lazy_open, chunk_size, interface_select, device_index, auto_detach, **kwargs)
    114         # lazy_open tells us not to open immediately.
    115         if not lazy_open:
--> 116             self.open()
    117 
    118     def __del__(self):

~/.virtualenvs/labrad/local/lib/python2.7/site-packages/pylibftdi/device.pyc in open(self)
    154             self.fdll.ftdi_deinit(byref(self.ctx))
    155             del self.ctx
--> 156             raise FtdiError(msg)
    157 
    158         if self.auto_detach and self.driver.libftdi_version().major > 0:

FtdiError: device not found (-3)

We can also try specifying the serial number explicitly:

>>> import usb.core
>>> devs = list(usb.core.find(find_all=True))
>>> for x in str(devs).split(','):
        print(x)
[<DEVICE ID 051d:0002 on Bus 002 Address 005>
<DEVICE ID 046d:c408 on Bus 002 Address 004>
<DEVICE ID 04ca:006e on Bus 002 Address 003>
<DEVICE ID 8087:0024 on Bus 002 Address 002>
<DEVICE ID 1d6b:0002 on Bus 002 Address 001>
<DEVICE ID 1d6b:0003 on Bus 004 Address 001>
<DEVICE ID 1366:0101 on Bus 003 Address 009>
<DEVICE ID 0403:6015 on Bus 003 Address 010>  # <-- that one
<DEVICE ID 1d6b:0002 on Bus 003 Address 001>
<DEVICE ID 1050:0211 on Bus 001 Address 003>
<DEVICE ID 8087:0024 on Bus 001 Address 002>
<DEVICE ID 1d6b:0002 on Bus 001 Address 001>]

>>> my_dev = devs[7]
>>> ser = devs.serial_number
>>> import pylibftdi
>>> pylibftdi.Device(ser)

Same error.

Why is this happening? The pylibftdi documentation claims that the Device constructor should take the first available device, and there's only one in my case. The error message saying "device not found" makes me wonder whether the FT230X is supported by the driver that pylibftdi is using, which I believe to be libftdi1 in my case.

Upvotes: 2

Views: 909

Answers (1)

Evan
Evan

Reputation: 2357

pylibftdi has a hardcoded list of USB product IDs (idProduct) for which it will search in pylibftdi.driver.USB_PID_LIST. This does not include the FT230X chip, and it doesn't query libftdi for the chips supported by the underlying library:

From pylibftdi/driver.py:

# Opening / searching for a device uses this list of IDs to search
# by default. These can be extended directly after import if required.
FTDI_VENDOR_ID = 0x0403
USB_VID_LIST = [FTDI_VENDOR_ID]
USB_PID_LIST = [0x6001, 0x6010, 0x6011, 0x6014]

Unfortunately this doesn't seem to work:

>>> import pylibftdi
>>> pylibftdi.driver.USB_PID_LIST.append(0x6015)
>>> print(["%04x " % x for x in pylibftdi.USB_PID_LIST])
['6001 ', '6010 ', '6011 ', '6014 ', '6015 ']
>>> dev = pylibftdi.Device()  
Segmentation fault

The problem here seems to be when pylibftdi calls libusb to set auto-detach. If I do the following it seems to work:

>>> import pylibftdi
>>> pylibftdi.driver.USB_PID_LIST.append(0x6015)
>>> print(["%04x " % x for x in pylibftdi.USB_PID_LIST])  
['6001 ', '6010 ', '6011 ', '6014 ', '6015 ']
>>> dev = pylibftdi.Device(auto_detach=False)  
>>> dev
<pylibftdi.device.Device at 0x7f586d08f350>

For me, this doesn't prevent libftdi from successfully detaching the kernel driver (/dev/ttyUSB0 disappears when I run this), but it does prevent reattachment after the session closes.

Upvotes: 2

Related Questions