83 lines
2.5 KiB
Python
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
|