Add UART bridge serial port listing option

This commit is contained in:
Joey Yakimowich-Payne 2026-09-19 22:04:42 -06:00
commit 57c0b3606b
2 changed files with 42 additions and 0 deletions

View file

@ -2496,6 +2496,12 @@ The checksum is the sum of the first four bytes modulo 256. Firmware and Python
### Finding your USB↔UART adapter “description” (port filtering)
If you have multiple serial/COM devices, you can filter which ports the bridge will consider using the port **description** (or vendor/product text) shown by the OS.
Run `uv run controller-uart-bridge --list-ports` to print port names,
descriptions, and manufacturers, then exit without opening any ports or starting
controller discovery. This uses the same USB-only default and port filters as
the bridge; add `--all-ports` to include non-USB serial devices, or
`--include-port-desc CP210` to preview a description filter.
- **macOS/Linux (terminal)**:
- Quick list with descriptions: `python -m serial.tools.list_ports -v`
- Then run the bridge with a filter, for example: `controller-uart-bridge --interactive --include-port-desc CP210`
@ -2653,6 +2659,7 @@ Options:
- `--map index:PORT` (repeatable) to pin controller index to serial (e.g., `--map 0:/dev/cu.usbserial-0001` or `--map 0:COM5`).
- `--ports PORTS...` or `--interactive` for auto/interactive pairing.
- `--all-ports` to include non-USB serial devices in discovery.
- `--list-ports` to print serial port names, descriptions, and manufacturers, then exit (respects port filters and `--all-ports`).
- `--ignore-port-desc SUBSTR` / `--include-port-desc SUBSTR` to filter serial ports by description (repeatable).
- `--include-controller-name SUBSTR` to only open controllers whose name matches (repeatable).
- `--list-controllers` to print detected controllers and their GUIDs, then exit (useful for GUID-based options).

View file

@ -32,6 +32,7 @@ import sdl3
from rich.console import Console
from rich.prompt import Prompt
from rich.table import Table
from rich.text import Text
from .switch_pico_uart import (
UART_BAUD,
@ -641,6 +642,11 @@ def build_arg_parser() -> argparse.ArgumentParser:
action="store_true",
help="Include non-USB serial ports when listing devices.",
)
parser.add_argument(
"--list-ports",
action="store_true",
help="List serial ports, descriptions, and manufacturers, then exit. Uses port filters and --all-ports.",
)
parser.add_argument(
"--frequency",
type=float,
@ -1002,6 +1008,32 @@ def list_controllers_with_guids(
console.print(table)
def list_serial_ports(console: Console, args: argparse.Namespace) -> None:
"""Show available UART ports without opening them or initializing SDL."""
ports = discover_serial_ports(
include_non_usb=args.all_ports,
ignore_descriptions=args.ignore_port_desc,
include_descriptions=args.include_port_desc,
include_manufacturers=args.include_port_manufacturer,
)
if not ports:
console.print("No matching serial ports found.")
if not args.all_ports:
console.print("Use --all-ports to include non-USB serial devices.")
return
table = Table(title="Serial Ports")
table.add_column("Port", no_wrap=True)
table.add_column("Description")
table.add_column("Manufacturer")
for port in sorted(ports, key=lambda info: info["device"]):
table.add_row(
Text(port["device"]),
Text(port["description"]),
Text(port["manufacturer"] or "Unknown"),
)
console.print(table)
def prepare_pairing_state(
args: argparse.Namespace,
console: Console,
@ -1665,6 +1697,9 @@ def main() -> None:
parser = build_arg_parser()
args = parser.parse_args()
console = Console()
if args.list_ports:
list_serial_ports(console, args)
return
config = build_bridge_config(console, args)
initialize_sdl(parser)
contexts: Dict[int, ControllerContext] = {}