"""Host OS/arch detection and Snowsky-Disc device presence checks. Device USB identities we care about: - Ingenic X2000 mask-ROM (flashing mode): VID:PID 0a108:eaef (a108:eaef) - normal running device (not used for flashing) is a different id. We enumerate USB via pyusb (bundled) so we don't depend on `lsusb` being present. """ import platform import sys MASKROM_VID = 0x0a108 & 0xFFFF # printed as a108 by lsusb; VID field is 0xa108 MASKROM_PID = 0xeaef # lsusb shows "a108:eaef"; libusb reports idVendor=0xa108 idProduct=0xeaef MASKROM_VID = 0xa108 def host(): """Return (os_key, arch_key) e.g. ('linux','x86_64') / ('macos','arm64').""" sysname = platform.system().lower() if sysname == "darwin": os_key = "macos" elif sysname == "linux": os_key = "linux" else: os_key = sysname # 'windows' etc. - unsupported for now machine = platform.machine().lower() arch = { "x86_64": "x86_64", "amd64": "x86_64", "arm64": "arm64", "aarch64": "arm64", }.get(machine, machine) return os_key, arch def host_tag(): o, a = host() return f"{o}-{a}" def is_supported(): o, _ = host() return o in ("linux", "macos") def _bundled_libusb_backend(): """A pyusb libusb1 backend pointed at OUR bundled libusb, so USB enumeration works in the frozen app even when the system has no libusb. Returns a backend or None (caller falls back to pyusb's default search).""" try: import glob import os import usb.backend.libusb1 as libusb1 from . import bundle libdir = os.path.join(bundle.vendor_dir(), "lib") # macOS dylib or Linux .so, whatever we bundled for pat in ("libusb-1.0*.dylib", "libusb-1.0.so*", "libusb-1.0*"): hits = sorted(glob.glob(os.path.join(libdir, pat))) if hits: return libusb1.get_backend(find_library=lambda _n, _p=hits[0]: _p) except Exception: pass return None def _maskrom_count_pyusb(): """Count devices in Ingenic mask-ROM mode via pyusb. Returns int or None if pyusb/backend is unavailable.""" try: import usb.core # pyusb (bundled) except Exception: return None try: backend = _bundled_libusb_backend() # prefer our bundled libusb devs = list(usb.core.find(find_all=True, idVendor=MASKROM_VID, idProduct=MASKROM_PID, backend=backend)) return len(devs) except Exception: return None def _maskrom_count_lsusb(): """Fallback: parse `lsusb` if present (Linux).""" import shutil import subprocess if not shutil.which("lsusb"): return None try: out = subprocess.run(["lsusb"], capture_output=True, text=True, timeout=10).stdout except Exception: return None return sum(1 for ln in out.splitlines() if "a108:eaef" in ln.lower()) def maskrom_count(): """How many devices are currently in mask-ROM mode. Prefers pyusb, falls back to lsusb, returns -1 if neither is available (caller should warn).""" n = _maskrom_count_pyusb() if n is not None: return n n = _maskrom_count_lsusb() if n is not None: return n return -1