100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""keys1617 套件:TM1617 段落/导航键注入(RTT `tm1617 key N`).
|
||
|
||
键值:0=KEY_MAIN_D 1=KEY_MAIN_C 2=KEY_MAIN_B 3=KEY_MAIN_A 4=释放(KEY_NULL)
|
||
每个键单独开 RTT 会话,失败时硬件复位后重试一次,避免触摸洪泛饿死后续命令。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
import subprocess
|
||
import sys
|
||
import time
|
||
|
||
from ..paths import TOOLS_DIR
|
||
from ..transports.rtt_session import open_session
|
||
|
||
SUITE = "keys1617"
|
||
KEY_NAMES = {0: "MAIN_D", 1: "MAIN_C", 2: "MAIN_B", 3: "MAIN_A"}
|
||
|
||
|
||
def _hw_reset(device: str) -> None:
|
||
script = os.path.join(TOOLS_DIR, "rtt_reset.py")
|
||
subprocess.run(
|
||
[sys.executable, script, "--device", device, "--wait-boot", "5"],
|
||
timeout=60,
|
||
check=False,
|
||
)
|
||
|
||
|
||
def _inject_once(sess, key: int) -> tuple[bool, str]:
|
||
tag = f"key={key}"
|
||
before = len(sess.lines)
|
||
ok = sess.cmd_ack(f"tm1617 key {key}", "TM1617_KEY_OK", timeout_s=2.5, retries=3)
|
||
if ok:
|
||
return True, "TM1617_KEY_OK"
|
||
recent = sess.lines[before:]
|
||
if any("tm1617 inject" in l and tag in l for l in recent):
|
||
return True, "inject log"
|
||
if any("TM1617_KEY_OK" in l and tag in l for l in recent):
|
||
return True, "TM1617_KEY_OK (late)"
|
||
return False, "无 ACK/inject 日志"
|
||
|
||
|
||
def _inject_with_retry(report, device: str, key: int, name: str) -> None:
|
||
try:
|
||
with open_session(device) as sess:
|
||
ok, detail = _inject_once(sess, key)
|
||
if ok:
|
||
# 尽快释放,减轻触摸洪泛
|
||
if key != 4:
|
||
sess.cmd_ack("tm1617 key 4", "TM1617_KEY_OK", timeout_s=1.5, retries=2)
|
||
time.sleep(0.3)
|
||
report.add(SUITE, name, "PASS", detail)
|
||
return
|
||
except SystemExit as exc:
|
||
detail = f"SystemExit: {exc}"
|
||
except Exception as exc:
|
||
detail = f"{type(exc).__name__}: {exc}"
|
||
|
||
print(f"!! {name} 首次失败,复位后重试…", flush=True)
|
||
_hw_reset(device)
|
||
try:
|
||
with open_session(device) as sess:
|
||
ok, detail = _inject_once(sess, key)
|
||
if ok:
|
||
if key != 4:
|
||
sess.cmd_ack("tm1617 key 4", "TM1617_KEY_OK", timeout_s=1.5, retries=2)
|
||
report.add(SUITE, name, "PASS", detail + " (retry)")
|
||
return
|
||
report.add(SUITE, name, "FAIL", detail)
|
||
except SystemExit as exc:
|
||
report.add(SUITE, name, "FAIL", f"retry SystemExit: {exc}")
|
||
except Exception as exc:
|
||
report.add(SUITE, name, "FAIL", f"retry {type(exc).__name__}: {exc}")
|
||
|
||
|
||
def run(report, ctx) -> None:
|
||
# 探测命令是否存在
|
||
try:
|
||
with open_session(ctx.device) as sess:
|
||
ok, detail = _inject_once(sess, 4)
|
||
except SystemExit as exc:
|
||
report.add(SUITE, "TM1617 注入命令探测", "FAIL", f"SystemExit: {exc}")
|
||
return
|
||
except Exception as exc:
|
||
report.add(SUITE, "TM1617 注入命令探测", "FAIL", f"{type(exc).__name__}: {exc}")
|
||
return
|
||
|
||
if not ok:
|
||
report.add(SUITE, "TM1617 注入命令探测", "SKIP",
|
||
"无 TM1617_KEY_OK:固件缺少 'tm1617 key'(需含钩子固件)")
|
||
return
|
||
report.add(SUITE, "TM1617 注入命令探测", "PASS", detail)
|
||
|
||
for key, label in KEY_NAMES.items():
|
||
_inject_with_retry(report, ctx.device, key, f"tm1617 {label}")
|
||
_hw_reset(ctx.device) # 每键后复位,保证下一键 RTT 干净
|
||
|
||
_inject_with_retry(report, ctx.device, 4, "tm1617 释放(KEY_NULL)")
|