#!/usr/bin/env python3
"""
Raw diagnostic - see EXACTLY what the device sends back.
Run: sudo python3 /tmp/mtk_flash_tool/diag.py
"""
import serial, serial.tools.list_ports, glob, time, sys

def find_port():
    """Find MTK CDC port."""
    while True:
        for p in serial.tools.list_ports.comports():
            if p.vid == 0x0E8D:
                return p.device
        for pat in ["/dev/cu.usbmodem*", "/dev/tty.usbmodem*"]:
            m = glob.glob(pat)
            if m: return m[0]
        sys.stdout.write(".")
        sys.stdout.flush()
        time.sleep(0.05)

def dump(label, data):
    if data:
        hex_str = " ".join(f"{b:02X}" for b in data)
        ascii_str = "".join(chr(b) if 32 <= b < 127 else "." for b in data)
        print(f"  {label}: [{hex_str}]  '{ascii_str}'  ({len(data)} bytes)")
    else:
        print(f"  {label}: [empty]")

def read_all(port, timeout=0.3):
    """Read everything available."""
    port.timeout = timeout
    data = port.read(256)
    return bytes(data) if data else b""

print("=== MTK BROM Raw Diagnostic ===")
print("Waiting for device...")

port_name = find_port()
print(f"\nFound: {port_name}")

try:
    s = serial.Serial(port_name, 115200, timeout=0.5,
                      bytesize=8, parity='N', stopbits=1,
                      xonxoff=False, rtscts=False, dsrdtr=False)
except Exception as e:
    print(f"Open failed at 115200: {e}")
    print("Trying 921600...")
    s = serial.Serial(port_name, 921600, timeout=0.5,
                      bytesize=8, parity='N', stopbits=1)

print(f"Port open: {s.name} @ {s.baudrate}")

# Flush
s.reset_input_buffer()
s.reset_output_buffer()

# Read any initial data
init = read_all(s, 0.2)
if init:
    dump("INITIAL", init)

print("\n--- Step 1: Handshake (0xA0 0x0A 0x50 0x05) ---")
handshake = [(0xA0, 0x5F), (0x0A, 0xF5), (0x50, 0xAF), (0x05, 0xFA)]

for send_b, expect_b in handshake:
    s.write(bytes([send_b]))
    r = s.read(1)
    got = r[0] if r else None
    ok = "OK" if got == expect_b else "FAIL"
    print(f"  Sent 0x{send_b:02X} → Got 0x{got:02X} (expect 0x{expect_b:02X}) [{ok}]" if got is not None
          else f"  Sent 0x{send_b:02X} → Got NOTHING [FAIL]")
    if got != expect_b:
        # Read any extra
        extra = read_all(s, 0.1)
        if extra: dump("EXTRA", extra)
        print("Handshake failed, aborting.")
        s.close()
        sys.exit(1)

print("  Handshake complete!\n")

# Flush post-handshake
post = read_all(s, 0.1)
if post:
    dump("POST-HANDSHAKE", post)

print("--- Step 2: GET_HW_CODE (0xFD) ---")
s.write(bytes([0xFD]))
time.sleep(0.05)
resp = read_all(s, 0.5)
dump("RESPONSE", resp)

if len(resp) >= 1:
    print(f"\n  Analysis:")
    print(f"    Byte 0: 0x{resp[0]:02X} {'(echo)' if resp[0] == 0xFD else '(NOT echo!)'}")
    if len(resp) >= 3:
        if resp[0] == 0xFD:
            # Echo + data
            data = resp[1:]
            print(f"    After echo: {' '.join(f'0x{b:02X}' for b in data)}")
            if len(data) >= 4:
                import struct
                val = struct.unpack(">I", data[0:4])[0]
                hw_code = (val >> 16) & 0xFFFF
                hw_sub = val & 0xFFFF
                print(f"    → HW code: 0x{hw_code:04X}, HW sub: 0x{hw_sub:04X}")
            if len(data) >= 6:
                status = struct.unpack(">H", data[4:6])[0]
                print(f"    → Status: 0x{status:04X}")
        else:
            # No echo - data starts at byte 0
            print(f"    No echo detected, raw data starts at byte 0")
            if len(resp) >= 4:
                import struct
                val = struct.unpack(">I", resp[0:4])[0]
                print(f"    → As u32: 0x{val:08X}")

print("\n--- Step 3: GET_HW_SW_VER (0xFC) ---")
s.write(bytes([0xFC]))
time.sleep(0.05)
resp = read_all(s, 0.5)
dump("RESPONSE", resp)

print("\n--- Step 4: GET_TARGET_CONFIG (0xD8) ---")
s.write(bytes([0xD8]))
time.sleep(0.05)
resp = read_all(s, 0.5)
dump("RESPONSE", resp)

s.close()
print("\nDone!")
