120 lines
3.7 KiB
Python
120 lines
3.7 KiB
Python
"""CLI-Einstiegspunkt: `python -m aubox <command>`."""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import sys
|
|
import time
|
|
|
|
from . import p10lite, usb
|
|
from .kirin import KirinDload
|
|
|
|
|
|
def cmd_detect(_args: argparse.Namespace) -> int:
|
|
devs = usb.scan()
|
|
if not devs:
|
|
print("Kein bekanntes Hersteller-Gerät angeschlossen.")
|
|
print("Probiere `lsusb` für die rohe Liste.")
|
|
return 1
|
|
for d in devs:
|
|
print(d)
|
|
if d.mode.notes:
|
|
print(f" {d.mode.notes}")
|
|
return 0
|
|
|
|
|
|
def cmd_p10lite_frp(args: argparse.Namespace) -> int:
|
|
if args.method == "erecovery":
|
|
print(p10lite.erecovery_instructions())
|
|
return 0
|
|
|
|
if args.method == "dload-erase":
|
|
try:
|
|
plan = p10lite.dload_erase_plan()
|
|
except FileNotFoundError as e:
|
|
print(str(e), file=sys.stderr)
|
|
return 2
|
|
|
|
print("Plan:")
|
|
for stage in plan["stages"]:
|
|
print(f" - {stage['label']}: {stage['file']} -> 0x{stage['addr']:08x}")
|
|
print()
|
|
print("Bitte jetzt Testpoint setzen und USB anschließen.")
|
|
print("Warte auf Kirin DLOAD (12d1:1100)...")
|
|
|
|
for _ in range(60):
|
|
if usb.find_first("kirin-dload") is not None:
|
|
break
|
|
time.sleep(0.5)
|
|
else:
|
|
print("Timeout: kein Kirin DLOAD erschienen.", file=sys.stderr)
|
|
return 3
|
|
|
|
print("Gerät erkannt. Sende Loader-Stages...")
|
|
with KirinDload() as k:
|
|
for stage in plan["stages"]:
|
|
print(f" -> {stage['label']}")
|
|
k.send_loader(stage["file"], stage["addr"])
|
|
# Zwischen den Stages re-enumeriert das Gerät evtl.
|
|
time.sleep(2)
|
|
|
|
print("Loader-Stages gesendet. Erwarteter Folgemodus:",
|
|
plan["post"])
|
|
print("Nächster Schritt (manuell, bis Workflow ausgereift):")
|
|
print(" fastboot devices")
|
|
print(f" fastboot erase {plan['frp_partition']}")
|
|
return 0
|
|
|
|
print(f"Methode {args.method!r} noch nicht implementiert.", file=sys.stderr)
|
|
return 2
|
|
|
|
|
|
def cmd_web(args: argparse.Namespace) -> int:
|
|
import uvicorn
|
|
uvicorn.run(
|
|
"aubox.web.app:app",
|
|
host=args.host,
|
|
port=args.port,
|
|
reload=args.reload,
|
|
log_level="info",
|
|
)
|
|
return 0
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
p = argparse.ArgumentParser(prog="aubox")
|
|
sub = p.add_subparsers(dest="cmd", required=True)
|
|
|
|
sp_detect = sub.add_parser("detect", help="Angeschlossene Geräte erkennen")
|
|
sp_detect.set_defaults(func=cmd_detect)
|
|
|
|
sp_web = sub.add_parser("web", help="Lokale Web-UI starten")
|
|
sp_web.add_argument("--host", default="127.0.0.1",
|
|
help="Bind-Adresse (Default: 127.0.0.1, im Container 0.0.0.0)")
|
|
sp_web.add_argument("--port", type=int, default=8080)
|
|
sp_web.add_argument("--reload", action="store_true",
|
|
help="Auto-Reload bei Code-Änderungen (Entwicklung)")
|
|
sp_web.set_defaults(func=cmd_web)
|
|
|
|
sp_p10 = sub.add_parser("p10lite", help="Workflows für Huawei P10 Lite")
|
|
p10_sub = sp_p10.add_subparsers(dest="p10_cmd", required=True)
|
|
|
|
sp_frp = p10_sub.add_parser("frp-remove", help="Google-Account-Sperre entfernen")
|
|
sp_frp.add_argument(
|
|
"--method",
|
|
choices=["erecovery", "dload-erase", "dload-flash"],
|
|
default="erecovery",
|
|
help="Welcher Pfad? Default: erecovery (sicherster, kein Loader nötig)",
|
|
)
|
|
sp_frp.set_defaults(func=cmd_p10lite_frp)
|
|
|
|
return p
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
args = build_parser().parse_args(argv)
|
|
return args.func(args)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|