CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyftdi

Pure Python FTDI device driver for USB-to-serial/GPIO/SPI/I2C/JTAG bridge devices

Pending
Overview
Eval results
Files

usb-tools.mddocs/

USB Device Discovery

USB device enumeration, FTDI device detection, URL parsing, and device capability identification. Provides utilities for finding, identifying, and accessing FTDI devices on the system.

Capabilities

Device Discovery

Find and enumerate FTDI devices connected to the system.

class UsbTools:
    @staticmethod
    def find_all(vps: list, nb: int = 0) -> list:
        """
        Find all USB devices matching vendor/product specifications.
        
        Parameters:
        - vps: List of (vendor_id, product_id) tuples
        - nb: Maximum number of devices to return (0 = no limit)
        
        Returns:
        list: List of matching UsbDevice objects
        
        Example:
        - vps=[(0x403, 0x6014)]: Find FT232H devices
        - vps=[(0x403, None)]: Find all FTDI devices
        """
    
    @staticmethod
    def get_device(vendor: int, product: int, index: int = 0, 
                  serial: str = None, path: str = None):
        """
        Get specific USB device by criteria.
        
        Parameters:
        - vendor: USB vendor ID
        - product: USB product ID  
        - index: Device index if multiple matches
        - serial: Device serial number for exact match
        - path: USB device path for exact match
        
        Returns:
        UsbDevice: Matching device object
        
        Raises:
        - UsbToolsError: Device not found or access error
        """
    
    @staticmethod
    def show_devices(vendor: int, product: int = None, serial: str = None) -> str:
        """
        Generate human-readable device listing.
        
        Parameters:
        - vendor: USB vendor ID
        - product: USB product ID (None for all products)
        - serial: Filter by serial number
        
        Returns:
        str: Formatted device information
        """

URL Parsing and Construction

Parse and construct FTDI device URLs for consistent device addressing.

@staticmethod
def parse_url(url: str, scheme: str) -> dict:
    """
    Parse FTDI device URL into components.
    
    Parameters:
    - url: Device URL (e.g., 'ftdi://0x403:0x6014:0/1')
    - scheme: Expected URL scheme ('ftdi')
    
    Returns:
    dict: Parsed URL components with keys:
        - 'vendor': Vendor ID (int)
        - 'product': Product ID (int) 
        - 'index': Device index (int)
        - 'serial': Serial number (str)
        - 'interface': Interface number (int)
    
    Raises:
    - UsbToolsError: Invalid URL format
    """

@staticmethod  
def build_dev_strings(scheme: str, vps: list, default_vendor: int) -> list:
    """
    Build device URL strings for available devices.
    
    Parameters:
    - scheme: URL scheme ('ftdi')
    - vps: List of (vendor_id, product_id) tuples
    - default_vendor: Default vendor ID for short URLs
    
    Returns:
    list: List of device URL strings
    """

Device Information

Extract detailed information about USB devices and FTDI capabilities.

@staticmethod
def get_device_descriptor(device) -> dict:
    """
    Get USB device descriptor information.
    
    Parameters:
    - device: UsbDevice object
    
    Returns:
    dict: Device descriptor with USB configuration details
    """

@staticmethod
def get_string_descriptor(device, index: int) -> str:
    """
    Read USB string descriptor.
    
    Parameters:
    - device: UsbDevice object
    - index: String descriptor index
    
    Returns:
    str: String descriptor content
    """

@staticmethod
def get_interface_descriptor(device, interface: int) -> dict:
    """
    Get USB interface descriptor.
    
    Parameters:
    - device: UsbDevice object
    - interface: Interface number
    
    Returns:
    dict: Interface descriptor information
    """

FTDI-Specific Utilities

Utilities specifically for FTDI device identification and capability detection.

@staticmethod
def is_ftdi_device(device) -> bool:
    """
    Check if device is an FTDI device.
    
    Parameters:
    - device: UsbDevice object
    
    Returns:
    bool: True if device is FTDI
    """

@staticmethod
def get_ftdi_device_type(device) -> str:
    """
    Determine FTDI device type.
    
    Parameters:
    - device: UsbDevice object
    
    Returns:
    str: Device type ('ft232h', 'ft2232h', 'ft4232h', etc.)
    """

@staticmethod
def get_ftdi_interfaces(device) -> list:
    """
    Get available FTDI interfaces.
    
    Parameters:
    - device: UsbDevice object
    
    Returns:
    list: List of available interface numbers
    """

@staticmethod
def get_ftdi_capabilities(device) -> dict:
    """
    Determine FTDI device capabilities.
    
    Parameters:
    - device: UsbDevice object
    
    Returns:
    dict: Capability information including:
        - 'mpsse': MPSSE support
        - 'interfaces': Number of interfaces
        - 'gpio_pins': GPIO pin count
        - 'max_speed': Maximum clock speed
    """

Device Descriptor Utilities

Helper class for USB device descriptor parsing.

class UsbDeviceDescriptor:
    """USB device descriptor parser and utilities."""
    
    def __init__(self, device):
        """Initialize with USB device."""
    
    def get_vendor_id(self) -> int:
        """Get USB vendor ID."""
    
    def get_product_id(self) -> int:
        """Get USB product ID."""
    
    def get_device_version(self) -> tuple:
        """Get device version as (major, minor) tuple."""
    
    def get_manufacturer(self) -> str:
        """Get manufacturer string."""
    
    def get_product(self) -> str:
        """Get product string."""
    
    def get_serial_number(self) -> str:
        """Get device serial number."""
    
    def get_configuration_count(self) -> int:
        """Get number of USB configurations."""
    
    def get_interface_count(self) -> int:
        """Get number of USB interfaces."""

Usage Examples

Basic Device Discovery

from pyftdi.usbtools import UsbTools

# Find all FTDI devices
ftdi_devices = UsbTools.find_all([(0x403, None)])
print(f"Found {len(ftdi_devices)} FTDI devices")

# Show device information
device_info = UsbTools.show_devices(0x403)
print(device_info)

# Get specific device
try:
    device = UsbTools.get_device(0x403, 0x6014, index=0)
    print(f"Found FT232H device: {device}")
except Exception as e:
    print(f"FT232H not found: {e}")

URL Operations

from pyftdi.usbtools import UsbTools

# Parse device URL
url = 'ftdi://0x403:0x6014:12345678/1'
parsed = UsbTools.parse_url(url, 'ftdi')
print(f"Vendor: 0x{parsed['vendor']:04x}")
print(f"Product: 0x{parsed['product']:04x}")
print(f"Serial: {parsed['serial']}")
print(f"Interface: {parsed['interface']}")

# Build device URLs for all available FTDI devices
urls = UsbTools.build_dev_strings('ftdi', [(0x403, None)], 0x403)
for url in urls:
    print(f"Available device: {url}")

Device Capability Detection

from pyftdi.usbtools import UsbTools

# Find and analyze FTDI devices
devices = UsbTools.find_all([(0x403, None)])

for device in devices:
    if UsbTools.is_ftdi_device(device):
        device_type = UsbTools.get_ftdi_device_type(device)
        interfaces = UsbTools.get_ftdi_interfaces(device)
        capabilities = UsbTools.get_ftdi_capabilities(device)
        
        print(f"Device: {device_type}")
        print(f"Interfaces: {interfaces}")
        print(f"MPSSE: {capabilities['mpsse']}")
        print(f"GPIO pins: {capabilities['gpio_pins']}")
        print(f"Max speed: {capabilities['max_speed']} Hz")
        print("---")

Device Selection Helper

from pyftdi.usbtools import UsbTools

def select_ftdi_device(device_type=None, serial=None):
    """Interactive device selection."""
    devices = UsbTools.find_all([(0x403, None)])
    
    if not devices:
        print("No FTDI devices found")
        return None
    
    # Filter by type if specified
    if device_type:
        devices = [d for d in devices if UsbTools.get_ftdi_device_type(d) == device_type]
    
    # Filter by serial if specified  
    if serial:
        devices = [d for d in devices if UsbTools.get_device_descriptor(d).get('serial') == serial]
    
    if len(devices) == 1:
        return devices[0]
    elif len(devices) > 1:
        print("Multiple devices found:")
        for i, device in enumerate(devices):
            desc = UsbTools.get_device_descriptor(device)
            print(f"{i}: {desc['product']} (Serial: {desc['serial']})")
        
        choice = int(input("Select device: "))
        return devices[choice]
    else:
        print("No matching devices found")
        return None

# Usage
device = select_ftdi_device(device_type='ft232h')
if device:
    print(f"Selected: {device}")

Device Information Display

from pyftdi.usbtools import UsbTools, UsbDeviceDescriptor

def display_device_info(device):
    """Display comprehensive device information."""
    desc = UsbDeviceDescriptor(device)
    
    print(f"Vendor ID: 0x{desc.get_vendor_id():04x}")
    print(f"Product ID: 0x{desc.get_product_id():04x}")
    print(f"Manufacturer: {desc.get_manufacturer()}")
    print(f"Product: {desc.get_product()}")
    print(f"Serial: {desc.get_serial_number()}")
    
    version = desc.get_device_version()
    print(f"Version: {version[0]}.{version[1]}")
    
    print(f"Configurations: {desc.get_configuration_count()}")
    print(f"Interfaces: {desc.get_interface_count()}")
    
    if UsbTools.is_ftdi_device(device):
        device_type = UsbTools.get_ftdi_device_type(device)
        capabilities = UsbTools.get_ftdi_capabilities(device)
        print(f"FTDI Type: {device_type}")
        print(f"MPSSE Support: {capabilities['mpsse']}")
        print(f"GPIO Pins: {capabilities['gpio_pins']}")

# Display info for all FTDI devices
devices = UsbTools.find_all([(0x403, None)])
for i, device in enumerate(devices):
    print(f"\nDevice {i}:")
    display_device_info(device)

Custom Device Filter

from pyftdi.usbtools import UsbTools

class FtdiDeviceFilter:
    """Custom FTDI device filtering and selection."""
    
    @staticmethod
    def find_high_speed_devices():
        """Find FTDI devices capable of high-speed operation."""
        devices = UsbTools.find_all([(0x403, None)])
        high_speed = []
        
        for device in devices:
            caps = UsbTools.get_ftdi_capabilities(device)
            if caps['max_speed'] >= 30000000:  # 30 MHz or higher
                high_speed.append(device)
        
        return high_speed
    
    @staticmethod
    def find_mpsse_devices():
        """Find devices with MPSSE support."""
        devices = UsbTools.find_all([(0x403, None)])
        mpsse_devices = []
        
        for device in devices:
            caps = UsbTools.get_ftdi_capabilities(device)
            if caps['mpsse']:
                mpsse_devices.append(device)
        
        return mpsse_devices
    
    @staticmethod
    def find_multi_interface_devices():
        """Find devices with multiple interfaces."""
        devices = UsbTools.find_all([(0x403, None)])
        multi_if = []
        
        for device in devices:
            interfaces = UsbTools.get_ftdi_interfaces(device)
            if len(interfaces) > 1:
                multi_if.append(device)
        
        return multi_if

# Usage
filter = FtdiDeviceFilter()

print("High-speed devices:")
for device in filter.find_high_speed_devices():
    print(f"  {UsbTools.get_ftdi_device_type(device)}")

print("\nMPSSE devices:")
for device in filter.find_mpsse_devices():
    print(f"  {UsbTools.get_ftdi_device_type(device)}")

print("\nMulti-interface devices:")
for device in filter.find_multi_interface_devices():
    interfaces = UsbTools.get_ftdi_interfaces(device)
    print(f"  {UsbTools.get_ftdi_device_type(device)}: {len(interfaces)} interfaces")

Exception Handling

from pyftdi.usbtools import UsbTools, UsbToolsError

try:
    devices = UsbTools.find_all([(0x403, 0x6014)])
    
    if devices:
        device = UsbTools.get_device(0x403, 0x6014, index=0)
        desc = UsbTools.get_device_descriptor(device)
        print(f"Found device: {desc['product']}")
    else:
        print("No FT232H devices found")
        
except UsbToolsError as e:
    print(f"USB tools error: {e}")
except Exception as e:
    print(f"General error: {e}")

Types

# Exception types
class UsbToolsError(Exception):
    """USB tools operation error"""

# USB descriptor types
USB_DESC_DEVICE = 1
USB_DESC_CONFIGURATION = 2
USB_DESC_STRING = 3
USB_DESC_INTERFACE = 4
USB_DESC_ENDPOINT = 5

# FTDI device type constants
FTDI_DEVICES = {
    0x6001: 'ft232r',
    0x6010: 'ft2232h', 
    0x6011: 'ft4232h',
    0x6014: 'ft232h',
    0x6015: 'ft230x'
}

Install with Tessl CLI

npx tessl i tessl/pypi-pyftdi

docs

core-ftdi.md

eeprom.md

gpio.md

i2c.md

index.md

jtag.md

serial.md

spi.md

usb-tools.md

tile.json