- 逆向:Ghidra/IDA 全量反编译 CoreSDKLib.dll/ThermalSDK.dll/libthermalSDK.so/ libcoresdk.so(ARM64)/libmagcore.so,导出 analysis/ida/export/ - 解码官方渲染管线:DDT 校准表加载->快门端点选择->Q12 插值->ref(4x type1 帧 均值)->NUC 查表->盲元补偿->窗口->LUT1024 重建->2x 升采样->调色板 - 逐像素验证:NUC+盲元 0/19200、插值 0 误差、2x 0/76800、窗口一致 - demo3 v5:完整复刻官方管线(含 DDT 解析、FFC 状态机、快门温度驱动), 修复 load_ddt 表错位导致的零像素问题 - 鬼影根因分析写入 analysis/reverse_20260813_full.md - 心跳/恢复机制:analysis/session_state.md + tools/resume_rev.ps1 - 新增 tsdk_pair3 增强采集工具;历史工具归档 csdk/tools/legacy/; 根目录抓帧残留删除,历史文档归档 analysis/history/ - csdk/README.md 完整使用文档;.gitignore/.gitattributes 补 LFS 规则
MAG160C C SDK (csdk/)
MAG160C 热像仪(160×120,USB VID 0x833C)的纯 C 重新实现,基于对原厂
Windows/Linux/Android SDK 的完整逆向(见 ../analysis/reverse_20260813_full.md)。
包含:USB 会话层、帧解析/流组装、温度换算、TCM 板通信、以及官方渲染管线的
逐像素复刻(demo3 v5)。
目录结构
csdk/
include/mag160c/
mag160c.h 公共 C ABI(错误域、协议常量、帧格式、温度、TCM)
mag160c_display.h FFC 调度器 + 显示辅助(ref rebase 等)
src/
mag160c_internal.h 内部共享(last-error)
mag160c_error.c TLS last-error + 错误名
mag160c_frame.c 0x1bb1b11b 帧解析 + 流组装器
mag160c_temp.c Calibration / ConvertResponse2Temperature / T2E
mag160c_tcm.c FTDICommand 0x7e 组帧 + 旋转/指示灯构建
mag160c_ir.c libusb 会话(link/start/stop/ffc/info/回调/FFC调度)
mag160c_display.c 显示辅助(FFC 调度器、ref rebase、坏点)
mag160c_tables.h T2E/E2TAccQ10 温度表(从二进制提取)
mag160c_official_*.h 官方调色板 / LUT1024 / T2E(从官方活体抓取导出)
tools/
mag160c_demo3.c 主程序:官方管线复刻(DDT+NUC+盲元+窗口+LUT+2x)
tsdk_pair2.c 官方 ThermalSDK 同帧抓帧工具(含表/盲元/快门)
tsdk_pair3.c 增强采集(DDT 复制、完整端点表、盲元、h1024/cdf)
mag160c_cli.c CLI:ir-info/ffc/start/stop/tcm-rotate/tcm-light 等
mag160c_csdk_stream_test.c csdk 流测试
legacy/ 历史探索工具(归档,勿用)
tests/ test_frame / test_temp / test_tcm / test_api / test_display
CMakeLists.txt CMake 构建(可选;当前环境直接用 gcc)
WINDOWS_TESTING.md Windows 硬件测试指南(USBPcap/Wireshark/MinGW)
构建
方式 A:直接 GCC(当前 Windows 环境)
# CLI 工具
gcc -O2 -w -DMAG160C_STATIC -I"csdk\third_party\libusb\win64" -I"csdk\include" -I"csdk\src" `
-o build-artifacts\mag160c_cli.exe csdk\tools\mag160c_cli.c `
csdk\src\mag160c_ir.c csdk\src\mag160c_frame.c csdk\src\mag160c_temp.c `
csdk\src\mag160c_tcm.c csdk\src\mag160c_error.c csdk\src\mag160c_display.c `
csdk\third_party\libusb\win64\libusb-1.0.x64.a
# 主程序 demo3(官方管线复刻)
gcc -O2 -w -DMAG160C_STATIC -I"csdk\third_party\libusb\win64" -I"csdk\include" -I"csdk\src" `
-o build-artifacts\mag160c_demo3.exe csdk\tools\mag160c_demo3.c `
csdk\src\mag160c_display.c csdk\src\mag160c_error.c `
csdk\third_party\libusb\win64\libusb-1.0.x64.a -lgdi32 -luser32
# 官方抓帧工具
gcc -O2 -w -o build-artifacts\tsdk_pair3.exe csdk\tools\tsdk_pair3.c
libusb 依赖:csdk/third_party/libusb/win64/(头文件 + DLL + MinGW 导入库)。
方式 B:CMake(有 CMake 时)
cmake -B build -S csdk
cmake --build build
ctest --test-dir build
无 libusb-1.0 时,IR 会话 API 返回 MAG160C_ERR_NOT_SUPPORTED;纯计算
(帧解析、温度、TCM)和对应测试无依赖可跑。
快速开始
1. 连接并启动(核心 API 流程)
#include <mag160c/mag160c.h>
#include <mag160c/mag160c_display.h>
static void on_frame(uint32_t idx, const uint8_t *data, size_t len, void *user) {
/* data: 完整帧(0x1c 头 + 像素)。用 mag160c_frame_parse 解析。 */
mag160c_frame_header_t hdr;
const uint16_t *pixels;
if (mag160c_frame_parse(data, len, &hdr, &pixels) == MAG160C_OK && hdr.frame_type == 0)
; /* pixels[19200] 小端 uint16,160×120 */
}
int main(void) {
mag160c_ctx_t *ctx = NULL;
mag160c_ir_t *ir = NULL;
mag160c_init(&ctx);
mag160c_ir_open(ctx, &ir); /* 自动找 VID 0x833c,config 2,interface 0 */
mag160c_ir_prepare(ir); /* 66b/66c/66f + FFC(0)x2 + 300ms */
mag160c_ir_set_frame_callback(ir, on_frame, NULL);
/* 官方 FFC 节律(周期 1800 帧 / 间隔 9),保持 type=0 流稳定 */
static mag160c_ffc_scheduler_t sched;
mag160c_ffc_scheduler_init(&sched, 1800, 9);
mag160c_ir_set_ffc_scheduler(ir, &sched, 0);
mag160c_ir_start(ir); /* 线程收帧 + 0x6bb6b673 */
/* ... 收帧 / 读温度 ... */
int32_t temp_mc = 0;
mag160c_ir_read_temperature(ir, 80, 60, &temp_mc);
mag160c_ir_stop(ir);
mag160c_ir_close(ir);
mag160c_shutdown(ctx);
return 0;
}
2. 关键 API
| API | 说明 |
|---|---|
mag160c_ir_open/close |
USB 设备会话 |
mag160c_ir_prepare |
官方初始化命令序列 |
mag160c_ir_start/stop |
起停流(0x6bb6b673 / 0x6bb6b674) |
mag160c_ir_trigger_ffc(param) |
手动 FFC(0 或 1) |
mag160c_ir_set_ffc_scheduler |
挂官方节律 FFC 调度器 |
mag160c_ir_set_frame_callback |
每帧回调(解析后数据) |
mag160c_ir_read_temperature(x,y,&t) |
探针温度(毫摄氏度×100) |
mag160c_frame_parse |
纯解析:marker/计数/类型/像素指针 |
mag160c_frame_stream_* |
流组装器(乱序/分包恢复) |
mag160c_temp_calibrate |
官方逐像素分段线性校准(NUC 温度域) |
mag160c_temp_convert_response |
自动增益线性换算 |
mag160c_temp_t2e_interp |
T2E 曲线 Q13 插值 |
mag160c_tcm_* |
TCM 板 FTDICommand 0x7e 帧(旋转/指示灯) |
错误码域 mag160c_error_t 与官方 errno 域 0xE4AE0001.. 对齐;
mag160c_last_error() 取线程局部最近错误字符串。
3. CLI 用法(mag160c_cli.exe,无硬件可跑纯计算)
build-artifacts\mag160c_cli.exe ir-info # 枚举/信息
build-artifacts\mag160c_cli.exe frame-test # 帧解析自测
build-artifacts\mag160c_cli.exe temp-test # 温度换算自测
build-artifacts\mag160c_cli.exe tcm-rotate 5 # TCM 旋转指令编码
build-artifacts\mag160c_cli.exe tcm-light green blink # TCM 指示灯指令编码
4. 主程序 demo3(官方渲染管线复刻)
tools/mag160c_demo3.c 是当前维护的 Windows 直连演示/研究程序,逐像素复刻
CoreSDKLib.dll 的完整链路:
USB帧(type=0) → 快门提取(帧尾字) → FFC状态机(0x9ee0)
→ 端点选择+Q12插值(0x16ae0/0x16dd0/0x16f10, 快门驱动)
→ ref = FFC窗口4个type=1帧均值(0x41ee0 mode=4)
→ NUC查表(0x17200) → 盲元补偿(0x17330, 32条固定记录)
→ 统计+窗口(0x10780/0x109c0, half=312) → LUT1024重建(0x11ee0)
→ 灰度+2x升采样(0x19740) → 官方调色板
运行(需要 build-artifacts/ 下的 DDT 表文件):
Stop-Process -Name mag160c_demo3 -Force -ErrorAction SilentlyContinue
Start-Process "C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe" -WorkingDirectory "C:\Project\MAG160C\build-artifacts"
依赖文件(放 exe 同目录):
| 文件 | 来源 |
|---|---|
mag160c_official.ddt |
官方 DDT 校准文件(%TEMP%\Core<序列号> 副本) |
mag160c_official_nuc_gain.bin |
官方 NUC gain/off 表(历史抓取,备用) |
mag160c_official_nuc_thr.bin |
官方 NUC 阈值表(历史抓取,备用) |
libusb-1.0.dll |
libusb 运行库 |
验证状态(2026-08-13):
- NUC+盲元 与官方同帧抓帧逐像素 0/19200 误差
- 阈值/gain 插值 0 误差;2x 升采样 0/76800 误差;窗口公式与官方一致
- 同静态场景 gray 直方图与官方相关性 0.92(跨会话)
- 输出日志:
demo3_diag.txt(每帧统计)、demo3_ffc.txt(FFC 事件)、demo3_auto_*.bmp(每 30 帧快照)
5. 官方抓帧工具(tsdk_pair2 / tsdk_pair3)
用途:对照验证 demo3 与官方管线。先停 demo3,再运行(同一设备独占):
# tsdk_pair2:官方 ThermalSDK 同帧抓帧(gray/rgb/raw/ref/f20/tables/win)
& build-artifacts\tsdk_pair2_fixed.exe C:\Project\MAG160C\analysis\pairs_xxx 12 6000
# tsdk_pair3:增强采集(+ 完整端点表/盲元记录/shutter/h1024/cdf/DDT 复制)
& build-artifacts\tsdk_pair3.exe C:\Project\MAG160C\analysis\pairs_xxx 8 6000
# 注意:config.txt 和 pair_*.meta/win 写在进程 CWD,跑完移回输出目录
参数:<输出目录> <抓帧对数> <官方SDK初始化等待ms>。
若报 "no channel":停止所有程序后重新插拔 USB。
测试
# 无硬件验证(纯计算)
build-artifacts\csdk_test_frame.exe
build-artifacts\csdk_test_temp.exe
build-artifacts\csdk_test_tcm.exe
build-artifacts\csdk_test_api.exe
build-artifacts\csdk_test_display.exe
协议要点(详见 analysis/protocol_spec.md)
- 端点:EP0x03 命令 OUT / 0x82 响应 IN / 0x81 帧流 IN / 0x84 大块读 IN
- 命令 4 字节
{magic},仅 FFC(0x6bb6b672) 用 8 字节{magic, param} - 帧:
0x1bb1b11b | counter | len | type(0/1) | ... | 像素 u16 LE | 0x1bb1b11c - 快门(设备温度代理)= 帧尾字
frame[len+0x24](width=160 时) - 温度:
temp_mC = T2E[3*nuc - C],C≈5797(会话相关)
文档索引
| 文档 | 内容 |
|---|---|
../analysis/protocol_spec.md |
USB 协议/帧/命令/温度完整规格 |
../analysis/reverse_20260813_full.md |
官方管线 Ghidra 全量逆向 + 鬼影根因 |
../analysis/session_state.md |
当前会话状态/恢复点(心跳) |
../交接_完整逆向工程说明_20260811.md |
项目总交接(目录/环境/历史) |
WINDOWS_TESTING.md |
Windows 抓包与硬件测试指南 |
legacy/ |
历史工具源码归档(早期探索,功能已被现工具取代) |