Skip to content

Commit

Permalink
feat(esptool): allow picking UART by VID/PID/Name
Browse files Browse the repository at this point in the history
Enable user to specify USB VID, USB PID, or port name
to filter the com port list before checking for ESP chips.

Implements espressif#987
  • Loading branch information
bryghtlabs-richard committed Jul 30, 2024
1 parent 3731e11 commit 5dd3dcc
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 10 deletions.
18 changes: 18 additions & 0 deletions docs/en/esptool/advanced-options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,21 @@ An example of this is available in the :ref:`merge_bin <merge-bin>` command desc
.. note:: PowerShell users

Because of `splatting <https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-7.3>`__ in PowerShell (method of passing a collection of parameter values to a command as a unit) there is a need to add quotes around @filename.txt ("@filename.txt") to be correctly resolved.

Filtering serial ports
----------------------
.. _filtering_serial_ports:

``--port-filter <FilterType>=<FilterValue>`` allows limiting ports that will be tried. This can be useful when esptool is run on a system
with many serial ports. There are a few different types that can be combined. A port must match all specified FilterTypes, and must match
at least one FilterValue for each specified FilterType to be considered. Example filter configurations:

.. list::

* ``--port-filter vid=0x303A`` matches ports with the Espressif USB VID.
* ``--port-filter vid=0x303A --port-filter vid=0x0403`` matches Espressif and FTDI ports by VID.
* ``--port-filter vid=0x303A --port-filter pid=0x0002`` matches Espressif ESP32-S2 in USB-OTG mode by VID and PID.
* ``--port-filter vid=0x303A --port-filter pid=0x1001`` matches Espressif USB-Serial/JTAG unit used by multiple chips by VID and PID.
* ``--port-filter name=ttyUSB`` matches ports where the port name contains the specified text.

See also the `Espressif USB customer-allocated PID repository <https://github.com/espressif/usb-pids>`_
53 changes: 43 additions & 10 deletions esptool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ def main(argv=None, esp=None):
default=os.environ.get("ESPTOOL_BAUD", ESPLoader.ESP_ROM_BAUD),
)

parser.add_argument(
"--port-filter",
action="append",
help="Serial port device filter, can be vid=NUMBER, pid=NUMBER, name=SUBSTRING",
type=str,
default=[],
)

parser.add_argument(
"--before",
help="What to do before connecting to the chip",
Expand Down Expand Up @@ -690,6 +698,23 @@ def add_spi_flash_subparsers(

StubFlasher.set_preferred_stub_subdir(args.stub_version)

# Parse filter arguments into separate lists
args.filterVids = []
args.filterPids = []
args.filterNames = []
for f in args.port_filter:
kvp = f.split("=")
if len(kvp) != 2:
raise FatalError("Option --port-filter argument must consist of key=value")
if kvp[0] == "vid":
args.filterVids.append(arg_auto_int(kvp[1]))
elif kvp[0] == "pid":
args.filterPids.append(arg_auto_int(kvp[1]))
elif kvp[0] == "name":
args.filterNames.append(kvp[1])
else:
raise FatalError("Option --port-filter argument key not recognized")

# operation function can take 1 arg (args), 2 args (esp, arg)
# or be a member function of the ESPLoader class.

Expand Down Expand Up @@ -725,7 +750,7 @@ def add_spi_flash_subparsers(
initial_baud = args.baud

if args.port is None:
ser_list = get_port_list()
ser_list = get_port_list(args.filterVids, args.filterPids, args.filterNames)
print("Found %d serial ports" % len(ser_list))
else:
ser_list = [args.port]
Expand Down Expand Up @@ -1010,21 +1035,29 @@ def arg_auto_chunk_size(string: str) -> int:
return num


def get_port_list():
def get_port_list(vids=[], pids=[], names=[]):
if list_ports is None:
raise FatalError(
"Listing all serial ports is currently not available. "
"Please try to specify the port when running esptool.py or update "
"the pyserial package to the latest version"
)
port_list = sorted(ports.device for ports in list_ports.comports())
if sys.platform == "darwin":
port_list = [
port
for port in port_list
if not port.endswith(("Bluetooth-Incoming-Port", "wlan-debug"))
]
return port_list
ports = []
for port in list_ports.comports():
if sys.platform == "darwin" and port.device.endswith(
("Bluetooth-Incoming-Port", "wlan-debug")
):
continue
if vids and (port.vid is None or port.vid not in vids):
continue
if pids and (port.pid is None or port.pid not in pids):
continue
if names and (
port.name is None or all(name not in port.name for name in names)
):
continue
ports.append(port.device)
return sorted(ports)


def expand_file_arguments(argv):
Expand Down

0 comments on commit 5dd3dcc

Please sign in to comment.