Metadata-Version: 2.5
Name: hdmi-edid-emulator
Version: 1.0.0
Summary: HDMI EDID 模拟器的 Python 控制 SDK
Author: sannmizu
License-Expression: MIT
License-File: LICENSE
Keywords: DDC,E-EDID,EDID,HDMI,HPD,SCDC
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Topic :: System :: Hardware
Requires-Python: >=3.10
Requires-Dist: pyserial<4,>=3.5
Description-Content-Type: text/markdown

# HDMI EDID Emulator Python SDK

[![PyPI](https://img.shields.io/pypi/v/hdmi-edid-emulator)](https://pypi.org/project/hdmi-edid-emulator/)
[![Python](https://img.shields.io/pypi/pyversions/hdmi-edid-emulator)](https://pypi.org/project/hdmi-edid-emulator/)
[![License](https://img.shields.io/pypi/l/hdmi-edid-emulator)](https://pypi.org/project/hdmi-edid-emulator/)

用于通过 USB CDC 控制 HDMI EDID Emulator 硬件。SDK 提供 Python API 和
`hdmi-edid` 命令行工具，覆盖设备发现、EDID 读写和分析、HPD 控制、显示器侧
DDC/SCDC/DDC-CI 访问、链路诊断以及 USB CDC 固件升级。

当前 SDK 版本为 `1.0.0`，对应固件 `1.0.0` 和串口协议 `1.0`。要求 Python
3.10 或更高版本。

## 安装

作为命令行工具安装：

```sh
uv tool install hdmi-edid-emulator
```

作为项目依赖安装：

```sh
uv add hdmi-edid-emulator
```

也可以使用 pip：

```sh
python -m pip install hdmi-edid-emulator
```

升级到最新版本：

```sh
uv tool upgrade hdmi-edid-emulator
```

## 快速开始

连接设备后列出 USB CDC 端口，并读取固件和运行状态：

```sh
hdmi-edid list
hdmi-edid info
hdmi-edid status
```

不指定端口时，SDK 根据 `VID:PID 1A86:FE0C` 或 USB 产品名自动发现设备。
连接多台设备时，使用全局 `--serial` 或 `--port` 参数：

```sh
hdmi-edid --serial UNIT_0001 status
hdmi-edid --port /dev/cu.usbmodem101 info
```

Windows 端口示例为 `COM5`。Linux 用户需要确保当前账号有权访问对应的
`/dev/ttyACM*` 设备。

## Python API

```python
from hdmi_edid_emulator import HdmiEdidEmulator, analyze_edid

with HdmiEdidEmulator(serial_number="UNIT_0001") as device:
    print(device.get_info())
    print(device.get_status())

    edid = device.read_edid()
    report = analyze_edid(edid)
    print(report.manufacturer_id, report.product_name)

    device.set_edid_mode("EMU")
    device.set_hpd_mode("SERIAL")
    device.set_hpd_pulse_duration(1000)
    device.pulse_hpd()
```

设备对象支持上下文管理器，退出 `with` 块时会自动关闭串口。也可以显式传入
端口和超时：

```python
from hdmi_edid_emulator import HdmiEdidEmulator

with HdmiEdidEmulator(port="COM5", timeout=3.0) as device:
    print(device.get_serial_number())
```

## 常用命令

### SN 和持久化配置

```sh
hdmi-edid sn
hdmi-edid sn UNIT_0001
hdmi-edid config-save
hdmi-edid reboot
```

设置 SN 默认会写入双槽 Flash、软重启设备，并等待设备以新 SN 重新枚举。SN
必须为 1-16 位字母、数字、下划线或连字符。使用 `--temporary` 可只修改运行态，
使用 `--no-reboot` 可保存后暂不重启。

### EDID 读取、报告和写入

```sh
hdmi-edid edid-read current-edid.bin
hdmi-edid edid-report current-edid.bin
hdmi-edid edid-write replacement-edid.bin
hdmi-edid edid-write replacement-edid.bin --save
hdmi-edid edid-mode emu
```

SDK 支持 1-8 block E-EDID。写入前会校验长度、header、扩展计数、每块 checksum
和 EDID 1.3 Block Map。上传使用 64 字节分片；只有所有 block 校验成功后才会提交
为活动 EDID。`--save` 才会把结果持久化到 Flash。

分析本地 EDID 不需要连接硬件：

```python
from pathlib import Path

from hdmi_edid_emulator import analyze_edid, lint_edid

data = Path("display-edid.bin").read_bytes()
report = analyze_edid(data)
for warning in lint_edid(data):
    print(warning.code, warning.message)
```

### 读取真实显示器 EDID

```sh
hdmi-edid edid-mode emu
hdmi-edid sink-edid-read display-edid.bin
hdmi-edid sink-edid-report
hdmi-edid sink-edid-clone
hdmi-edid sink-edid-clone --save
```

`sink-edid-read` 通过显示器侧 DDC 读取真实显示器的 E-EDID。`sink-edid-clone`
会将捕获结果提交为本机活动模拟 EDID；只有带 `--save` 时才会断电保持。

### HPD 控制

```sh
hdmi-edid hpd-mode serial
hdmi-edid hpd-set 1
hdmi-edid hpd-pulse-duration 1000
hdmi-edid hpd-pulse
```

HPD 低脉冲可配置为 100-3000 ms。部分 Windows 主机需要约 1000 ms 才会执行
完整的显示器移除和重新枚举。

### DDC、SCDC 和 DDC/CI

```sh
hdmi-edid ddc-status
hdmi-edid emu-status
hdmi-edid ddc-trace
hdmi-edid sink-scdc-status
hdmi-edid sink-ddc-recover
hdmi-edid sink-ddcci-capabilities
hdmi-edid sink-ddcci-get 0x10
hdmi-edid sink-ddcci-set 0x10 50
```

显示器侧主动访问命令要求设备处于 `EMU` 模式。DDC/CI VCP `0x10` 通常表示
亮度，但具体功能和取值范围由显示器 capabilities 决定。

DDC 故障注入仅用于调试，默认关闭且不会写入 Flash：

```sh
hdmi-edid ddc-fault-nack 0x54
hdmi-edid ddc-fault-delay 0x54 1250
hdmi-edid ddc-fault-read 0x50 0xaa
hdmi-edid ddc-fault-clear
```

### 固件升级

```sh
hdmi-edid firmware-update CH32V203C8T.bin
```

该命令只接受链接到 `0x4000` 的应用原始 BIN，不接受 ELF、Intel HEX 或包含
bootloader 的首次烧录组合镜像。升级过程会自动进入 USB CDC bootloader、分片
写入、执行 CRC32 终检，并等待应用重新枚举。传输中断后可直接重新执行同一命令。

## 异常处理

```python
from hdmi_edid_emulator import (
    DeviceCommandError,
    DeviceNotFoundError,
    DeviceTimeoutError,
    EdidValidationError,
    HdmiEdidEmulator,
)

try:
    with HdmiEdidEmulator() as device:
        print(device.get_status())
except DeviceNotFoundError:
    print("未发现设备")
except DeviceTimeoutError:
    print("设备响应超时")
except DeviceCommandError as error:
    print(f"固件拒绝命令: {error}")
except EdidValidationError as error:
    print(f"EDID 校验失败: {error}")
```

主要异常均继承自 `EdidEmulatorError`，包括设备未找到、多设备冲突、串口超时、
协议格式错误、固件命令错误和 EDID 校验错误。

## 开发

源码采用标准 `src` 布局：

```text
sdk/python/
├── examples/                  # 显式实板示例
├── src/hdmi_edid_emulator/    # SDK、EDID 解析器和 CLI
├── tests/                     # 不连接硬件的自动测试
├── LICENSE
├── README.md
└── pyproject.toml
```

在源码目录运行：

```sh
uv sync
./run-tests.sh
uv run hdmi-edid --help
```

`examples/write_verified_edid.py` 会真实修改设备 EDID，必须显式执行，不会被自动
测试入口导入。

## 许可证

Python SDK 采用 [MIT License](https://opensource.org/license/mit)。硬件设计、固件及
第三方代码可能使用不同许可证，不包含在本 Python 分发包的许可范围内。
