diff --git a/tools/recover.sh b/tools/recover.sh new file mode 100755 index 0000000..0989abd --- /dev/null +++ b/tools/recover.sh @@ -0,0 +1,152 @@ +#!/bin/bash +# Quick recovery script — run after physical intervention (SDA pull-up / SOIC clip) +# Waits for bare FX2 or SkyWalker enumeration, loads firmware, runs full test +set -euo pipefail + +TOOLS="$(cd "$(dirname "$0")" && pwd)" +FW="$TOOLS/../firmware/build/skywalker1.ihx" + +if [ ! -f "$FW" ]; then + echo "ERROR: Firmware not found at $FW" + echo "Run: cd firmware && make" + exit 1 +fi + +echo "=== SkyWalker-1 Recovery ===" +echo "Waiting for device to appear... (plug in now, Ctrl+C to stop)" +echo "" + +# Poll for up to 60 seconds +for i in $(seq 1 120); do + DEV=$(lsusb -d 09c0:0203 2>/dev/null || true) + BARE=$(lsusb -d 04b4:8613 2>/dev/null || true) + + if [ -n "$DEV" ]; then + echo "FOUND SkyWalker-1 (09c0:0203): $DEV" + echo "Device already has firmware — skipping load" + break + elif [ -n "$BARE" ]; then + echo "FOUND bare FX2 (04b4:8613): $BARE" + sleep 0.5 + echo "Loading firmware..." + python3 "$TOOLS/fw_load.py" load "$FW" + echo "Waiting 3s for re-enumeration..." + sleep 3 + # Verify it came back + DEV=$(lsusb -d 09c0:0203 2>/dev/null || true) + if [ -z "$DEV" ]; then + echo "WARNING: Device did not re-enumerate as SkyWalker-1" + echo "Check dmesg for errors" + exit 1 + fi + echo "Re-enumerated: $DEV" + break + fi + + [ $((i % 20)) -eq 0 ] && printf "." + sleep 0.5 +done + +# If we got here without finding anything +DEV=$(lsusb -d 09c0:0203 2>/dev/null || true) +if [ -z "$DEV" ]; then + echo "" + echo "Timeout — no device detected in 60s" + echo "Check physical connections and try again" + exit 1 +fi + +echo "" +echo "--- Running post-recovery test ---" +python3 -c " +import usb.core, usb.util, time, sys + +dev = usb.core.find(idVendor=0x09C0, idProduct=0x0203) +if not dev: + print('Device not found'); sys.exit(1) +print(f'Product: {dev.product}') + +# Detach kernel drivers +for c in dev: + for i in c: + if dev.is_kernel_driver_active(i.bInterfaceNumber): + dev.detach_kernel_driver(i.bInterfaceNumber) +try: dev.set_configuration() +except: pass + +A0 = 0xA0 +VIN = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_IN + +# Read FX2 registers +def read_reg(addr, n=1): + return bytes(dev.ctrl_transfer(VIN, A0, addr, 0, n, 2000)) + +cpucs = read_reg(0xE600)[0] +i2cs = read_reg(0xE678)[0] +print(f'CPUCS=0x{cpucs:02X} I2CS=0x{i2cs:02X}') + +# Test BCM3440 I2C gateway +print() +print('--- I2C Gateway Test ---') +try: + d = dev.ctrl_transfer(VIN, 0x84, 0x10, 0xA7, 1, 3000) + print(f'BCM3440 gateway (A7): 0x{d[0]:02X} -- OK') +except Exception as e: + print(f'BCM3440 gateway: FAIL ({e})') + +# Boot BCM4500 (wValue=1 = full boot, wIndex=0 = normal) +print() +print('--- BOOT_8PSK (wValue=1) ---') +try: + d = dev.ctrl_transfer(VIN, 0x89, 1, 0, 3, 15000) + config = d[0] + stage = d[1] + print(f'config_status=0x{config:02X} boot_stage=0x{stage:02X}') + if config & 0x03 == 0x03: + print('Boot: SUCCESS (started + fw_loaded)') + elif stage == 0xFF: + print('Boot: SUCCESS (stage=0xFF = complete)') + else: + print(f'Boot: INCOMPLETE (check stage 0x{stage:02X})') +except Exception as e: + print(f'Boot: FAIL ({e})') + +# Wait for demod to settle +time.sleep(3) + +# Signal check +print() +print('--- Signal Monitor ---') +try: + d = dev.ctrl_transfer(VIN, 0x90, 0, 0, 8, 3000) + snr = (d[0] << 8) | d[1] + agc1 = (d[2] << 8) | d[3] + agc2 = (d[4] << 8) | d[5] + lock = d[6] + status = d[7] + print(f'SNR={snr} AGC1={agc1} AGC2={agc2} Lock=0x{lock:02X} Status=0x{status:02X}') +except Exception as e: + print(f'Signal: FAIL ({e})') + +# GET_8PSK_CONFIG +print() +print('--- Config Status ---') +try: + d = dev.ctrl_transfer(VIN, 0x80, 0, 0, 1, 2000) + print(f'config_status: 0x{d[0]:02X}') + flags = [] + if d[0] & 0x01: flags.append('STARTED') + if d[0] & 0x02: flags.append('FW_LOADED') + if d[0] & 0x04: flags.append('INTERSIL') + if d[0] & 0x08: flags.append('DVB_MODE') + if d[0] & 0x80: flags.append('ARMED') + print(f'Flags: {\" | \".join(flags) if flags else \"(none)\"}') +except Exception as e: + print(f'Config: FAIL ({e})') + +print() +print('=== Recovery test complete ===') +" 2>&1 + +echo "" +echo "=== Done ==="