android-unlock-and-more-box/aubox/usb.py

83 lines
2.5 KiB
Python

"""USB-Geräte-Erkennung über VID:PID.
Erkennt die wichtigsten Hersteller-Modi und ordnet sie einem semantischen
Status zu, damit Workflows wissen, in welchem Modus das Gerät gerade ist.
"""
from __future__ import annotations
from dataclasses import dataclass
import usb.core
import usb.util
@dataclass(frozen=True)
class DeviceMode:
label: str
vendor: str
notes: str = ""
# (vid, pid) -> Modus
KNOWN: dict[tuple[int, int], DeviceMode] = {
# Huawei / Kirin
(0x12D1, 0x1100): DeviceMode("kirin-dload", "Huawei",
"Kirin Download-Mode, wartet auf xloader via hisi-idt"),
(0x12D1, 0x1052): DeviceMode("huawei-fastboot-d", "Huawei",
"Erweiterter Fastboot-Mode (nach xloader)"),
(0x12D1, 0x3609): DeviceMode("kirin-dload-alt", "Huawei",
"Kirin DLOAD alternative PID"),
(0x12D1, 0x107E): DeviceMode("huawei-hisuite", "Huawei",
"HiSuite/MTP-Modus, kein Recovery-Zugriff"),
# Google / Android Standard
(0x18D1, 0x4EE0): DeviceMode("fastboot", "Google", "Standard-Fastboot"),
(0x18D1, 0x4EE7): DeviceMode("adb", "Google", "ADB"),
# MediaTek
(0x0E8D, 0x0003): DeviceMode("mtk-preloader", "MediaTek",
"Preloader (DA-Mode möglich)"),
(0x0E8D, 0x2000): DeviceMode("mtk-brom", "MediaTek",
"BROM — Ziel für mtkclient/kamakiri"),
# Qualcomm EDL
(0x05C6, 0x9008): DeviceMode("qc-edl", "Qualcomm",
"Emergency Download (Firehose-fähig)"),
}
@dataclass
class FoundDevice:
vid: int
pid: int
mode: DeviceMode
bus: int
address: int
def __str__(self) -> str:
return (f"[{self.bus:03d}:{self.address:03d}] "
f"{self.vid:04x}:{self.pid:04x} {self.mode.vendor} "
f"{self.mode.label}")
def scan() -> list[FoundDevice]:
"""Alle bekannten Hersteller-Modi auflisten, die gerade angeschlossen sind."""
found: list[FoundDevice] = []
for dev in usb.core.find(find_all=True):
key = (dev.idVendor, dev.idProduct)
mode = KNOWN.get(key)
if mode is None:
continue
found.append(FoundDevice(
vid=dev.idVendor,
pid=dev.idProduct,
mode=mode,
bus=dev.bus,
address=dev.address,
))
return found
def find_first(label: str) -> FoundDevice | None:
for d in scan():
if d.mode.label == label:
return d
return None