Files
MAG160C/analysis/magcx_official_flow.md

104 lines
6.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MAG160C 官方 MAG-Cx 完整逆向结论(2026-09-10jadx + Ghidra 全量解包)
> 产物来源:
> - Java 层:`analysis/sdk_re/android_app/jadx_magcx/`jadx 1.5.1 反编译官方普通版 MAG-Cx.apk 全量源码)
> - Native 层:`analysis/sdk_re/android_app/libcxsdk_decomp.txt`
> Ghidra 11.3.2 headless 全量反编译 lib/armeabi/libcxsdk.so1290 函数)
> - libcoresdk(arm64) 反编译已在 `analysis/sdk_re/android_app/`(专业版/网络路径)
> - 本文结论全部来自以上反编译源码,与真机日志交叉验证(vivo V2509A, Android 16)。
## 1. USB 协议权威版(以官方 Java UsbCommunication.java 为准)
### 1.1 端点与超时
| 端点 | 方向 | 用途 | 超时 |
|---|---|---|---|
| 0x03 | OUT | 命令(4B 小端 magicFFC/激光/帧率带参数) | 800ms |
| 0x82 | IN | 命令响应/ack(读 ≤64B | 800ms |
| 0x81 | IN | 图像流(28B 头 + 38400B + 28B 尾) | 800ms |
| 0x84 | IN | 标定文件下载(16KB 块) | 800ms/块 |
| 0x05 | OUT | 向相机发送标定(SendCaliFile 上传方向,本项目暂不用) | 800ms |
**全部 800ms**(官方 `TIMEOUT` 常量)。响应缓冲 64B。
### 1.2 命令集(P2DCmd,全部 4 字节小端)
| 值 | 官方名 | 说明 |
|---|---|---|
| 0x6BB6B66B | GetParameter1 | → 0x5BB5B55B BasePara160B |
| 0x6BB6B66C | GetParameter2 | → 0x5BB5B55C BasePara260B |
| 0x6BB6B66D | SetParameter1 | 带 ack64B 读) |
| 0x6BB6B66E | SetParameter2 | 带 ack |
| 0x6BB6B66F | GetCaliInfo | → 0x5BB5B55E {i32 size, i32 reserved, i64 date} |
| 0x6BB6B670 | GetCaliFile | ack 0x5BB5B55D,随后相机在 0x84 推标定文件 |
| 0x6BB6B671 | SendCaliFile | 上传方向(配 0x05 OUT |
| 0x6BB6B672 | SetShutterState | FFC8B {magic LE, u32 on LE} |
| 0x6BB6B673 | StartTransferImg | 开始推流,带 ack |
| 0x6BB6B674 | StopTransferImg | 停流,带 ack |
| 0x6BB6B675 | GetLifeTime | → 0x5BB5B561 {magic, i32 开机毫秒} |
| 0x6BB6B676 | SetLaserState | 8B(激光,非省电!) |
| 0x6BB6B677 | PowerSave | 8B |
| 0x6BB6B678 | GetFPAState | → 0x5BB5B562 |
| 0x6BB6B679 | SetFrameRate | 12B {magic, i32 interFrame, i32 interLine} |
D2P 响应魔数:5B=SendParameter1、5C=SendParameter2、5D=SendCaliFile、
5E=SendCaliInfo、61=SendLifeTime(均在 0x5BB5B5xx 空间)。
**注意**0x6BB6B66B 是回文数(字节对称),因此历史上"66b 有响应、其余全无"
正是字节序反了的特征——非回文命令全部变成无效字节。`MagProtocolTest` 已锁死。
### 1.3 BasePara10x5BB5B55B payload14×i32 = 56B
int[0] serialNumberint[1] hwVersion(低24位)|devType(高8位)
int[2] swVersionint[4] fpaWidthint[5] fpaHeightint[6] fps
int[8] fpaGainint[9] fpaFlipint[10] interFrameint[11] interLine。
devType0=c1, 1=c3, 2=c3p, **3=core160(MAG160C)**, 5=c1pro, 6=c1prolite。
### 1.4 官方连接序列(connect() + startTransfer()
```
1. write GetParameter1 → read 64B → BasePara1(失败则整个 connect 放弃)
2. write GetParameter2 → read → BasePara2
3. write GetCaliInfo → read → {size, reserved, date}
4. 缓存判定:{caliDir}/{productType}.{serial}.{date} 存在且长度==size
├─ 命中:直接 startTransfer()
└─ 未命中:启动 ThreadCaliRecv0x84 连续读,16KB/块,无数据 5s 放弃)
→ sleep 50ms → write GetCaliFile(670)waitForCmdAck 读 ack
→ 收满 size 字节存盘 → startTransfer(caliPath)
5. startTransfer
a. native startProcess(w, h, serial, devType, shutterClose/OpenSpeed,
ffcTriggerFrame, ffcTriggerTemperature, paletteIndex, baseLineAcc,
caliPath) ← libcxsdk Controller::StartProcess → LoadCalibrationTable
(caliPath),加载失败即 startProcess 失败并删除缓存文件
b. native setEX / getExtParameter+setExtParameter(dwFlip) / setAutoEnlarge
(全部 native,不占 USB
c. 启动 ThreadImgRecv + ThreadImgProcess → sleep 5ms
→ write StartTransferImg(673)waitForCmdAck 读 ack
```
### 1.5 图像流帧结构(与 FrameStream/管线一致)
28B 头:0x1BB1B11B, frameIndex, dataLen(=w*h*2), type(0/1), period, 保留×3。
38400B u16LE 像素。
28B 尾:0x1BB1B11C, frameIndex, fpaTemp, intDrop(=type), reserved[2]。
官方 ThreadImgRecv:搜头→凑满 frameBytes→校验尾→drop∈{0,1} 才交给处理线程;
fpaTemp 在尾 +8devType0/5/6/3),camTemp=fpaTemp-500。
### 1.6 FFC 触发(官方逻辑)
- 双击/消息(MSG_TRIGGER_FFC)→ SetShutterState(672)
- 每 16 帧查 GetLifeTime(675)devType1/2 按 6.5s/13s/19.5s/26s 档位触发 FFC
**devType0/5/6/3(含 core160)该路径不自动 FFC**(仅温度稳定标志)。
- 本项目管线内部 FFC 调度(onFfc→672)为等效实现,且 672 相机随时接受。
## 2. 本项目复刻状态(IrSession.kt = 官方 UsbCommunication 等价物)
- 连接序列 1-5 已逐行复刻(含 0x84 拉取、缓存 files/cali/{product}.{serial}.{date});
- 命令打包小端(与官方 intToByteArray 一致)——**历史上 cmd4/cmd8 用
ByteBuffer.putInt 默认大端导致非回文命令全部反转**(16 轮黑屏的根因,
MagProtocolTest 锁死);
- usfs 坑:bulk 读超时后端点被标 halted,后续传输全部瞬间失败,须每次失败后
CLEAR_HALTIrSession.diagnoseEndpoint);
- 会话互斥(同一时刻仅一个 IrSession 持有相机)+ DETACHED 释放 + 去抖。
## 3. 工具与环境(2026-09-10 本机)
- jadx 1.5.1C:\Tools\jadx-1.5.1(反编译产物 C:\Tools\jadx-out,已拷贝入库
analysis/sdk_re/android_app/jadx_magcx/
- Ghidra 11.3.2C:\Tools\ghidra_11.3.2_PUBLIC;工程 C:\Tools\ghidra_proj\MagCX
全量反编译脚本 C:\Tools\ghidra_scripts_user\DumpAllDecomp.java
- 重跑命令(PowerShell/cmd):
`set JAVA_HOME=C:\Tools\jdk-21&& C:\Tools\ghidra_11.3.2_PUBLIC\support\analyzeHeadless.bat C:\Tools\ghidra_proj MagCX -process libcxsdk.so -scriptPath C:\Tools\ghidra_scripts_user -postScript DumpAllDecomp.java <输出文件>`