For embedded projects I want to control the FTDI CBUS pins as GPIOs. The libFTDI1 library allows to program the CBUS pins as GPIOs by setting the CBUS function to CBUS_IOMODE. I created a Python script available at the python_ft232_cbus_config repository (must be run as root!). The script reprograms CBUS2/3 to IOMODE, while leaving CBUS0/1 at their default (TXLED/RXLED). It should be fairly easy to change the script for your needs.
Once the CBUS pins are programmed as IOMODE, they can be controlled through libFTDI1. There is a C example in the source repository at examples/bitbang_cbus.c. However, there is one downside when using the library: The FTDI kernel driver gets detached automatically. Since I am a screen user, this means that my open sessions get closed automatically too! Using DONT_DETACH_SIO_MODULE seems not to do the trick, the library returns with error code -5 (unable to claim device). It seems that controlling FTDI from user space inherently conflicts with the in-kernel FTDI driver.
Already a while ago I tried to fix this by adding GPIO support to the kernel driver. Unfortunately this did not work out/I lost interest. However, Peter had a valuable hint back then: Control Transfers should be possible without detaching the kernel driver.
And indeed, with hacking a bit around with PyUSB it is possible:
def ftdi_set_bitmode(dev, bitmask): bmRequestType = usb.util.build_request_type(usb.util.CTRL_OUT, usb.util.CTRL_TYPE_VENDOR, usb.util.CTRL_RECIPIENT_DEVICE) wValue = bitmask | (BITMODE_CBUS << 8) dev.ctrl_transfer(bmRequestType, SIO_SET_BITMODE_REQUEST, wValue) def main(): """Main program""" dev = usb.core.find(custom_match = \ lambda d: \ d.idVendor==0x0403 and d.idProduct==0x6001 and d.serial_number=="A105N7O2") # Set CBUS2/3 high... ftdi_set_bitmode(dev, 0xCC)
Full source of the ftdi-cbus-ctrlep.py.
In my use-case, I connected two of the CBUS pins on a Toradex Aster carrier board to the reset and recovery line of the module. I then bound keys combinations in .screenrc which execute the ftdi-cbus-ctrlep-tdx.py Python scripts. This allows me to reset the board from my desktop while having the GNU screen terminal open using a simple key stroke.
When you experience issues such as “Error: The device has no langid” following the pyftdi installation instructions help to setup user access rights for the FTDI devices correctly.
Setting the bitmode was using BITMODE_CBUS as bit shift (it used to be
(BITMODE_CBUS << BITMODE_CBUS). It seems to work on some chips, but it is wrong. The mode should be shifted by 8. See also src/ftdi.c of flibftdi.