Skip to content

Commit

Permalink
Merge pull request #8 from Neradoc/add-vidpid-filter
Browse files Browse the repository at this point in the history
Add devices_by_vidpid to filter devices by vid and pid.
  • Loading branch information
Neradoc authored Mar 18, 2022
2 parents a109ea3 + 33515e9 commit cca02a0
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 36 deletions.
1 change: 1 addition & 0 deletions discotool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
devices_by_name,
devices_by_drive,
devices_by_serial,
devices_by_vidpid,
)

try:
Expand Down
25 changes: 7 additions & 18 deletions discotool/discotool.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import sys
import time
from . import usbinfos
from .usbinfos import port_is_repl, port_is_data


DEFAULT_WINDOWS_SERIAL_TOOLS = {
"ttermpro": "ttermpro.exe /C={portnum}",
Expand Down Expand Up @@ -73,19 +75,6 @@ def setup_command_tools():
echo(f"{environ_var}={os.environ[environ_var]}", underline=True)


# string description of the circuitpython REPL and secondary serial port
# generic, stringcar_m0_express, winterbloom_sol
SERIAL_NAMES = ["CircuitPython","StringCarM0Ex","Sol"]
EXT_REPL = " CDC "
EXT_CDC2 = " CDC2 "

def IS_REPL(iface):
return any([(n + EXT_REPL).lower() in iface.lower() for n in SERIAL_NAMES])

def IS_CDC2(iface):
return any([(n + EXT_CDC2).lower() in iface.lower() for n in SERIAL_NAMES])


# print the text from main
def displayTheBoardsList(bList, ports=[]):
if len(bList) == 0 and len(ports) == 0:
Expand All @@ -110,9 +99,9 @@ def displayTheBoardsList(bList, ports=[]):
)
for portInfo in dev_ports:
iface = portInfo['iface']
if IS_REPL(iface):
if port_is_repl(iface):
iface = "REPL"
elif IS_CDC2(iface):
elif port_is_data(iface):
iface = "DATA"
click.echo(f"\t{portInfo['dev']} ({iface})")
# volumes and main files
Expand Down Expand Up @@ -333,7 +322,7 @@ def repl(ctx):
port = device['ports'][0]
else:
potential_ports = [pp for pp in device['ports']
if IS_REPL(pp['iface'])]
if port_is_repl(pp['iface'])]
if len(potential_ports) == 0:
port = device['ports'][0]
else:
Expand Down Expand Up @@ -583,12 +572,12 @@ def get(ctx, key):
if 'ports' in device:
device['ports'].sort(key = lambda port: port['dev'])
values += [pp['dev'] for pp in device['ports']
if IS_REPL(pp['iface'])]
if port_is_repl(pp['iface'])]
elif key in ("cdc2", "data"):
if 'ports' in device:
device['ports'].sort(key = lambda port: port['dev'])
values += [pp['dev'] for pp in device['ports']
if IS_CDC2(pp['iface'])]
if port_is_data(pp['iface'])]
elif key == "vid":
values.append(device['vendor_id'])
elif key == "pid":
Expand Down
34 changes: 32 additions & 2 deletions discotool/usbinfos/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@
raise ImportError("Platform not supported")


############################################################
# identify serial ports for Circuitpython
############################################################

# string description of the circuitpython REPL and secondary serial port
# generic, stringcar_m0_express, winterbloom_sol
SERIAL_NAMES = ["CircuitPython","StringCarM0Ex","Sol"]
EXT_REPL = " CDC "
EXT_CDC2 = " CDC2 "

def port_is_repl(iface):
return any([(n + EXT_REPL).lower() in iface.lower() for n in SERIAL_NAMES])

def port_is_data(iface):
return any([(n + EXT_CDC2).lower() in iface.lower() for n in SERIAL_NAMES])


############################################################
# device information class
############################################################
Expand Down Expand Up @@ -64,10 +81,14 @@ def __init__(self, device_info):
self.data = None
self.repl = None
for port in self["ports"]:
if port["iface"].find("CDC2") >= 0:
if port_is_repl(port["iface"]):
self.repl = port["dev"]
elif port_is_data(port["iface"]):
self.data = port["dev"]
else:
self.repl = port["dev"]
# whatever is left is repl if repl not found
if self.repl is None:
self.repl = port["dev"]


############################################################
Expand All @@ -91,6 +112,15 @@ def get_unidentified_ports():
############################################################
# get filtered lists
############################################################
def devices_by_vidpid(vid, pid=None):
out = []
liste = get_identified_devices()
for dev in liste:
if (dev.vid == vid and (pid is None or dev.pid == pid)):
out.append(dev)
return out


def devices_by_name(name):
out = []
liste = get_identified_devices()
Expand Down
25 changes: 9 additions & 16 deletions examples/find_boards_by_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,30 @@
- finds a board by volume name
- sends some data to the board's data serial port
python3 find_boards_by_volume.py -m CIRCUITPY -d "Hi there"
python3 find_boards_by_volume.py --mount QTPY2040 ---data "Hi there"
"""
import argparse
import discotool
import os
import serial

BOARD_DRIVE_NAME = "QTPY2040"
BOARD_DRIVE_NAME = "CIRCUITPY"
DATA_STRING = "Hello World"

# This lets you specify the drive name and data to send in the command line
parser = argparse.ArgumentParser()
parser.add_argument(
"--mount",
"-m",
type=str,
help="Name of the board's mount",
default=BOARD_DRIVE_NAME,
)
parser.add_argument(
"--data",
"-d",
type=str,
help="The data string to send",
default=DATA_STRING,
)
parser.add_argument("--mount", type=str, help="Drive name", default=BOARD_DRIVE_NAME)
parser.add_argument("--data", type=str, help="Data to send", default=DATA_STRING)
args = parser.parse_args()

# prepare the parameters
mount_name = os.path.basename(args.mount)
data_string = args.data.encode("utf8")

# find all the devices
devs = discotool.get_identified_devices()

# and now drill into it to the the correct one
for dev in devs:
volume = dev.volume_name
data_port = dev.data
Expand Down
43 changes: 43 additions & 0 deletions examples/find_boards_with_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
A demo host-side script that
- finds a board by product name ("pico", "macropad", "featherS3"...)
- sends some data to the board's data serial port
python3 find_boards_with_filters.py --name FeatherS3 ---data "Hi there"
"""
import argparse
import discotool
import os
import serial

PRODUCT_NAME = "QT PY" # not case sensitive
DATA_STRING = "Hello World"

# This lets you specify the drive name and data to send in the command line
parser = argparse.ArgumentParser()
parser.add_argument("--name", type=str, help="Product name", default="")
parser.add_argument("--data", type=str, help="Data to send", default=DATA_STRING)
parser.add_argument("--vid", type=int, help="Product name", default=0)
args = parser.parse_args()

# prepare the parameters
product_name = args.name
data_string = args.data.encode("utf8")
vid = args.vid

# use filters based on given parameters
if vid != 0 and product_name == "":
pad = discotool.devices_by_vidpid(vid)
elif not product_name:
pad = discotool.devices_by_name(PRODUCT_NAME)
else:
pad = discotool.devices_by_name(product_name)

# send data to whatever is found
if pad and (data_port := pad[0].data):
print(f"Board found: {pad[0].name}")
print(f"Send {data_string} to {data_port}")
with serial.Serial(data_port) as pp:
pp.write(data_string)
else:
print(f"Could not find a {product_name} with an open data port.")

0 comments on commit cca02a0

Please sign in to comment.