From dcdeb7be78a79108d46afbf59a72dc5820c1f87c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 27 Jun 2024 09:41:30 -0400 Subject: [PATCH] apollo_fpga: Ignore devices not running Apollo When looking for devices running Apollo firmware, ignore those running Saturn-V or anything else that does not identify itself as "Apollo" with a vendor request. Because the USB VID/PID is shared between Saturn-V and Apollo, this is needed to prevent us from trying to communicate with a Saturn-V device as if it were running Apollo. --- apollo_fpga/__init__.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/apollo_fpga/__init__.py b/apollo_fpga/__init__.py index 710d398..e5b8238 100644 --- a/apollo_fpga/__init__.py +++ b/apollo_fpga/__init__.py @@ -8,6 +8,7 @@ import time import usb.core import platform +import errno from .jtag import JTAGChain from .spi import DebugSPIConnection @@ -47,6 +48,7 @@ class ApolloDebugger: if os.getenv("LUNA_USB_IDS"): LUNA_USB_IDS += [tuple([int(x, 16) for x in os.getenv("LUNA_USB_IDS").split(":")])] + REQUEST_GET_ID = 0xa0 REQUEST_SET_LED_PATTERN = 0xa1 REQUEST_GET_FIRMWARE_VERSION = 0xa2 REQUEST_GET_USB_API_VERSION = 0xa3 @@ -83,7 +85,7 @@ def __init__(self, force_offline=False): """ Sets up a connection to the debugger. """ # Try to create a connection to our Apollo debug firmware. - device = self._find_device(self.APOLLO_USB_IDS) + device = self._find_device(self.APOLLO_USB_IDS, custom_match=self._device_has_apollo_id) # If Apollo VID/PID is not found, try to find a gateware VID/PID with a valid Apollo stub # interface. If found, request the gateware to liberate the USB port. In devices with a @@ -106,7 +108,7 @@ def __init__(self, force_offline=False): # Wait for Apollo to enumerate and try again time.sleep(2) - device = self._find_device(self.APOLLO_USB_IDS) + device = self._find_device(self.APOLLO_USB_IDS, custom_match=self._device_has_apollo_id) if device is None: raise DebuggerNotFound("Handoff was requested, but Apollo is not available") @@ -162,6 +164,23 @@ def _device_has_stub_iface(device, return_iface=False): return stub_if if return_iface else True return None if return_iface else False + @staticmethod + def _device_has_apollo_id(device): + """ Checks if a device identifies itself as Apollo.""" + request_type = usb.ENDPOINT_IN | usb.RECIP_DEVICE | usb.TYPE_VENDOR + try: + response = device.ctrl_transfer(request_type, ApolloDebugger.REQUEST_GET_ID, data_or_wLength=256, timeout=500) + apollo_id = bytes(response).decode('utf-8').split('\x00')[0] + return True if "Apollo" in apollo_id else False + except usb.USBError as e: + if e.errno == errno.EPIPE: + # A pipe error occurs when the device does not implement a + # vendor request with a number matching REQUEST_GET_ID. This is + # the expected result if the device is running Saturn-V. + return False + else: + raise + def detect_connected_version(self): """ Attempts to determine the revision of the connected hardware.