Files
chongming-plugins/aibox_sophon_adapter/diwatch/devicetree.py
T
2026-09-11 16:55:54 +08:00

67 lines
1.7 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""从设备树复算 gpio-in-N 对应的全局 GPIO 号。"""
from pathlib import Path
from .config import DEVICETREE_BASE
def _read_be32(path: Path, offset: int = 0):
try:
data = path.read_bytes()
except OSError:
return None
if len(data) < offset + 4:
return None
return int.from_bytes(data[offset:offset + 4], "big")
def derive_gpio(n: int, base_dir: str = DEVICETREE_BASE):
"""从设备树复算 IN<n> 的全局 GPIO 号。
返回 (gpio_num, label, pin) 或 None。
"""
base = Path(base_dir)
f = base / f"gpio-in-{n}" / "control-gpios"
if not f.exists():
return None
try:
data = f.read_bytes()
except OSError:
return None
if len(data) < 8:
return None
ph = int.from_bytes(data[0:4], "big")
pin = int.from_bytes(data[4:8], "big")
# phandle -> gpio-controller 节点
ctrl = None
for c in base.glob("gpio@*/gpio-controller@*"):
cph = _read_be32(c / "phandle")
if cph == ph:
ctrl = c
break
if ctrl is None:
return None
bank = ctrl.parent.name
if bank.startswith("gpio@"):
bank = bank[len("gpio@"):]
label = f"{bank}.gpio"
# label -> gpiochip base
gpio_class = Path("/sys/class/gpio")
if not gpio_class.exists():
return None
for g in gpio_class.glob("gpiochip*"):
try:
if (g / "label").read_text().strip() == label:
chip_base = int((g / "base").read_text().strip())
return chip_base + pin, label, pin
except (OSError, ValueError):
continue
return None