Skip to content

Commit

Permalink
snagrecover: utils: Fail on USB device address collisions
Browse files Browse the repository at this point in the history
Sometimes, USB devices can share a single address. For vid:pid addresses, this
is not uncommon, as two devices of the exact same model will most likely share
the same vendor and product IDs. For USB paths, this should not happen but in
some rare cases, libusb can incorrectly assign the same bus number to two
separate root hubs (refer to issue #1521 in the official libusb Github repo for
more details).

If this happens, get_usb() should not just take the first device found and
ignore the other, as this can lead to wildly unexpected behavior (e.g.
snagrecover recovers one device then attempts to flash a different device).

Modify get_usb() and parse_usb_addr() to fail when a USB path collision is
found.

Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
  • Loading branch information
rgantois committed Jul 1, 2024
1 parent 6f2e4ce commit 4dd5cd5
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/snagrecover/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import re
import usb
import time
import logging
logger = logging.getLogger("snagrecover")

import yaml
import os

Expand Down Expand Up @@ -73,6 +76,11 @@ def parse_usb_addr(usb_addr: str, find_all=False) -> tuple:
if find_all:
return usb_paths
else:
if len(usb_paths) > 1:
print(f"Found too many ({len(usb_paths)}) possible results matching {usb_addr}!")
logger.error(f"Too many results for address {usb_addr}!\{str(usb_paths)}")
access_error("USB", usb_addr)

return usb_paths[0]
else:
return parse_usb_path(usb_addr)
Expand All @@ -93,7 +101,7 @@ def get_usb(usb_path, error_on_fail=True) -> usb.core.Device:

nb_devs = len(dev_list)

if nb_devs > 0:
if nb_devs == 1:
dev = dev_list[0]

try:
Expand All @@ -102,6 +110,10 @@ def get_usb(usb_path, error_on_fail=True) -> usb.core.Device:
except usb.core.USBError:
logger.warning(f"Failed to get configuration descriptor for device at {pretty_addr}!")

elif nb_devs > 1:
print(f"Found too many ({nb_devs}) possible results matching {pretty_addr}!")
logger.warning(f"Too many results for address {pretty_addr}!\{str(dev_list)}")

print(f"USB retry {i + 1}/{USB_RETRIES}")
time.sleep(USB_INTERVAL)

Expand Down

0 comments on commit 4dd5cd5

Please sign in to comment.