#!/usr/bin/env python3 """I2C debug tool for SkyWalker-1. First powers on the BCM4500 via GPIO debug mode (0x81), then: 1. Runs I2C bus scan (0xB4) to find any devices 2. Tries raw I2C reads (0xB5) to common BCM4500 addresses 3. Tests different post-reset delays """ import usb.core import usb.util import sys import time BOOT_8PSK = 0x89 def find_device(): dev = usb.core.find(idVendor=0x09C0, idProduct=0x0203) if not dev: print("Device not found!") sys.exit(1) return dev def setup_device(dev): try: if dev.is_kernel_driver_active(0): dev.detach_kernel_driver(0) except Exception: pass try: dev.set_configuration() except usb.core.USBError: pass def main(): dev = find_device() setup_device(dev) # Verify firmware ret = dev.ctrl_transfer(0xC0, 0x92, 0, 0, 6, timeout=2000) major, minor, patch = ret[2], ret[1], ret[0] print(f"Firmware: v{major}.{minor:02d}.{patch}") # Step 1: Power on BCM4500 via GPIO-only debug mode print("\n--- Step 1: Power on BCM4500 (GPIO mode 0x81) ---") ret = dev.ctrl_transfer(0xC0, BOOT_8PSK, 0x81, 0, 3, timeout=3000) print(f" GPIO setup: stage=0x{ret[1]:02X}") # Step 2: I2C bus scan immediately print("\n--- Step 2: I2C bus scan (immediately after power-on) ---") try: ret = dev.ctrl_transfer(0xC0, 0xB4, 0, 0, 16, timeout=5000) addrs = [] for bi in range(16): for bit in range(8): if ret[bi] & (1 << bit): addrs.append(bi * 8 + bit) if addrs: print(f" Found devices at: {[f'0x{a:02X}' for a in addrs]}") else: print(" No I2C devices found!") except usb.core.USBError as e: print(f" Bus scan error: {e}") # Step 3: Wait longer and scan again print("\n--- Step 3: Wait 500ms and scan again ---") time.sleep(0.5) try: ret = dev.ctrl_transfer(0xC0, 0xB4, 0, 0, 16, timeout=5000) addrs = [] for bi in range(16): for bit in range(8): if ret[bi] & (1 << bit): addrs.append(bi * 8 + bit) if addrs: print(f" Found devices at: {[f'0x{a:02X}' for a in addrs]}") else: print(" No I2C devices found!") except usb.core.USBError as e: print(f" Bus scan error: {e}") # Step 4: Try raw I2C reads to various addresses print("\n--- Step 4: Raw I2C reads (0xB5) to likely BCM4500 addresses ---") # BCM4500 could be at different addresses depending on pin strapping # Common: 0x08 (AD=low), 0x0A (AD=high), or even other addresses candidates = [0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x68, 0x69, 0x60, 0x61] for addr in candidates: for reg in [0xA2, 0x00]: try: r = dev.ctrl_transfer(0xC0, 0xB5, addr, reg, 1, timeout=1000) print(f" Addr 0x{addr:02X} Reg 0x{reg:02X} = 0x{r[0]:02X} <--- RESPONDS!") except usb.core.USBError: print(f" Addr 0x{addr:02X} Reg 0x{reg:02X} = (no response)") # Step 5: Check I2C bus state print("\n--- Step 5: I2C controller state ---") try: # Read I2CTL and I2CS by inspecting them through a known-working address # Actually, we can just observe what happens when we try reads print(" (Bus scan and raw reads above show bus health)") except Exception as e: print(f" Error: {e}") # Step 6: Try I2C probe via debug mode 0x82 again with a delay print("\n--- Step 6: Debug probe (0x82) after additional 1s delay ---") time.sleep(1.0) ret = dev.ctrl_transfer(0xC0, BOOT_8PSK, 0x82, 0, 3, timeout=3000) stage = ret[1] probe = ret[2] if stage == 0xA2: print(f" PROBE SUCCESS! BCM4500 status = 0x{probe:02X}") else: print(f" Probe failed: stage=0x{stage:02X} probe=0x{probe:02X}") print("\nDone.") if __name__ == "__main__": main()