openharmony摄像头驱动到应用浏览显示 第3章 能力注入与流桥接(HDF/HDI/VDI)
本文为《开源鸿蒙相机:驱动到应用预览显示》系列发布版。
当前章节:第3章 能力注入与流桥接(HDF/HDI/VDI)
代码基线:~/work/ohos5.1/nt_backclip_vendor(基于 OpenHarmony 5.1.0 Release 移植)
发布说明:使用ai codex移植调试开源鸿蒙摄像头的任务全流程在链接https://github.com/chenlong3388/codex_fix_OpenHarmony_Camera
第3章 能力注入与流桥接(HDF/HDI/VDI)
本章目标
回答 5 个问题:
- HCS 到底有哪些参数,按原始分区怎么分。
- 每个参数干什么。
- 参数值从哪里来(驱动、DTS、defconfig、板级映射、运行时实测)。
- 参数如何起作用(读取函数 -> 生效函数 -> 失败信号)。
- 调用链是否完整,每个函数在链路里的职责是什么。
两份 HCS,不同职责(先定边界)
vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs
用于 UHDF/HDI/VDI 主链:逻辑相机映射 + CameraMetadata 能力注入。vendor/gkhos/nt_backclip_vendor/hdf_config/khdf/camera/camera_config.hcs
用于 KHDF model camera:设备分区开关、ctrl 能力表、stream 上限枚举。
一句话:camera_host_config.hcs 决定“上层看到什么能力并如何 open”,camera_config.hcs 决定“KHDF 设备层认为哪些模块/能力存在”。
总调用图(函数全注释版)
[UHDF 能力注入链]
camera_host_config.hcs
-> CameraHostService::GetVdiLibList
作用: 从 root 读取 vdiLibList,决定加载哪个 VDI so
-> CameraHostService::GetInstance
作用: HdfLoadVdi 动态装载 host vdi 实现
-> CameraHostConfig::ReadConfigFile
作用: 读取 camera_host_config.hcb,构建逻辑ID/能力缓存
-> HcsDeal::DealCameraAbility
作用: 解析 logicCameraId/physicsCameraIds/metadata
-> HcsDeal::DealMetadata
作用: 把 metadata 字段写入 CameraMetadata tag
-> CameraHostVdiImpl::GetCameraIds/GetCameraAbility/OpenCamera
作用: 枚举ID/返回能力/Open时按 physicsCameraIds 上电
-> HCameraHostManager::GetCameraAbility
作用: service 侧拉取并缓存能力向 framework 提供
-> CameraManager::ParseCapability
作用: 按 ProfileLevel > Extend > Basic 优先级生成 profile
-> ParseExtendCapability / ParseBasicCapability
作用: 转换 preview/photo/video 配置供上层输出创建
[KHDF 设备配置链]
camera_config.hcs
-> HdfCameraDriverInit
作用: camera core 启动时读取 device->property
-> HdfParseCameraConfig
作用: 解析 abilityConfig 根块
-> ParseCameraDeviceConfig(+Sensor/Isp/Vcm/Lens/Flash/Stream 分区)
作用: 把 mode/name/id/ctrlValue/formatType 等落到 g_configCameraRoot
-> CheckCameraDevice / CheckDeviceOps / CameraStreamEnumDevice
作用: 按分区 mode 与 stream 上限能力对外枚举和门禁
参数全景(按原始分区)
A. camera_host_config.hcs 分区全景(UHDF 主链)
| 原始分区 | 参数 | 含义 | 读取函数 | 生效函数 |
|---|---|---|---|---|
root |
module |
HCS 模块名 | HCS 编译阶段 | 配置组织用途 |
root |
vdiLibList[] |
要加载的 VDI 动态库列表 | CameraHostService::GetVdiLibList |
CameraHostService::GetInstance 调 HdfLoadVdi |
camera_host_config |
match_attr |
匹配 camera host 接口 | HDF 配置匹配阶段 | 决定节点是否被 host 看到 |
ability_xx |
logicCameraId |
对外逻辑相机 ID | HcsDeal::DealCameraAbility |
CameraHostConfig::cameraIdMap_ / GetCameraIds |
ability_xx |
physicsCameraIds[] |
逻辑 ID 对应物理相机枚举 | HcsDeal::DealPhysicsCameraId |
CameraHostVdiImpl::OpenCamera -> CameraPowerUp |
ability_xx.metadata |
aeAvailableAntiBandingModes[] |
AE 防频闪能力 | DealAeAvailableAntiBandingModes |
metadata 下发到 framework |
ability_xx.metadata |
aeAvailableModes[] |
AE 模式集合 | DealAeAvailableModes |
同上 |
ability_xx.metadata |
availableFpsRange |
能力范围 FPS | DealAvailableFpsRange |
ParseBasicCapability 组 video fps |
ability_xx.metadata |
cameraPosition |
前后摄位置标签 | DealCameraPosition |
framework 设备分组/展示 |
ability_xx.metadata |
cameraType |
广角等类型 | DealCameraType |
framework 选择策略 |
ability_xx.metadata |
cameraConnectionType |
内置/外接 | DealCameraConnectionType |
builtin/usb 分支策略 |
ability_xx.metadata |
cameraMemoryType |
buffer 内存类型语义 | DealCameraMemoryType |
stream 相关约束 |
ability_xx.metadata |
faceDetectMaxNum |
最大人脸数 | DealCameraFaceDetectMaxNum |
人脸能力报告 |
ability_xx.metadata |
aeCompensationRange |
曝光补偿范围 | DealAeCompensationRange |
AE UI/算法范围 |
ability_xx.metadata |
aeCompensationSteps |
曝光补偿步长 | DealAeCompensationSteps |
AE 调节粒度 |
ability_xx.metadata |
availableAwbModes[] |
AWB 模式集合 | DealAvailableAwbModes |
AWB 能力报告 |
ability_xx.metadata |
sensitivityRange |
ISO 范围 | DealSensitivityRange |
传感器能力报告 |
ability_xx.metadata |
faceDetectMode |
人脸检测模式 | DealFaceDetectMode |
统计能力 |
ability_xx.metadata |
focalLength |
焦距 | DealFocalLength |
相机信息展示 |
ability_xx.metadata |
focusAvailableModes[] |
对焦模式 | DealAvailableFocusModes |
AF 能力 |
ability_xx.metadata |
exposureAvailableModes[] |
曝光模式 | DealAvailableExposureModes |
AE 能力 |
ability_xx.metadata |
meterAvailableModes[] |
测光模式 | DealAvailableMetereModes |
测光能力 |
ability_xx.metadata |
flashAvailableModes[] |
闪光灯模式 | DealAvalialbleFlashModes |
闪光控制能力 |
ability_xx.metadata |
mirrorSupported |
是否支持镜像 | DealMirrorSupported |
前摄镜像能力 |
ability_xx.metadata |
basicAvailableConfigurations |
基础流能力(格式/宽/高) | DealAvaliableBasicConfigurations |
ParseBasicCapability |
ability_xx.metadata |
extendAvailableConfigurations |
模式化流能力(mode/stream/fps) | DealAvaliableExtendConfigurations |
ParseExtendCapability |
ability_xx.metadata |
sensorOrientationSupported |
sensor 方向 | DealSensorOrientation |
旋转策略 |
ability_xx.metadata |
videoStabilizationAvailableModes[] |
防抖模式 | DealAvalialbleVideoStabilizationModes |
视频防抖能力 |
ability_xx.metadata |
flashAvailable |
是否存在闪光灯 | DealAvalialbleFlash |
闪光灯开关可用性 |
ability_xx.metadata |
afAvailable[] |
AF 可用模式 | DealAvalialbleAutoFocus |
AF 能力 |
ability_xx.metadata |
zoomRatioRange |
变焦范围 | DealZoomRationRange |
zoom 能力 |
ability_xx.metadata |
jpegOrientation |
JPEG 方向 | DealJpegOrientation |
拍照方向元数据 |
ability_xx.metadata |
jpegQuality |
JPEG 质量等级 | DealJpegQuality |
拍照质量策略 |
ability_xx.metadata |
availableCharacteristicsKeys[] |
对外能力键集合 | HCS 提供 | framework 查询可见键 |
ability_xx.metadata |
availableRequestKeys[] |
可设置请求键集合 | HCS 提供 | request 下发可见键 |
ability_xx.metadata |
availableResultKeys[] |
结果可见键集合 | HCS 提供 | result 上报可见键 |
B. camera_config.hcs 分区全景(KHDF model camera)
| 原始分区 | 参数 | 含义 | 读取函数 | 生效函数 |
|---|---|---|---|---|
abilityConfig |
uvcMode |
是否支持 UVC | ParseCameraConfig |
CheckSwitchType(UVC_TYPE) |
device |
deviceName |
相机设备名 | ParseCameraDeviceConfig |
HdfCameraInitDevice(deviceName) |
SensorConfig |
mode |
sensor 分区开关 | ParseCameraSensorConfig |
CheckSwitchType(SENSOR_TYPE) |
SensorDevice |
name/id/exposure/mirror/gain/ctrlValue |
sensor 能力与控制项 | ParseCameraSensorDeviceConfig |
SetCtrlCapInfo + 设备门禁 |
IspConfig |
mode + name/id/brightness/contrast/saturation/hue/sharpness/gain/gamma/whiteBalance/ctrlValue |
ISP 分区能力 | ParseCameraIspConfig / ParseCameraIspDeviceConfig |
CheckSwitchType(ISP_TYPE) |
VcmConfig |
mode + focus/autoFocus/zoom/zoomMaxNum/ctrlValue |
VCM 能力 | ParseCameraVcmConfig |
CheckSwitchType(VCM_TYPE) |
LensConfig |
mode + aperture/ctrlValue |
Lens 能力 | ParseCameraLensConfig |
CheckSwitchType(LENS_TYPE) |
FlashConfig |
mode + flashMode/flashIntensity/ctrlValue |
Flash 能力 | ParseCameraFlashConfig |
CheckSwitchType(FLASH_TYPE) |
StreamConfig |
mode + heightMaxNum/widthMaxNum/frameRateMaxNum/bufferCount/bufferType/formatType |
流上限与格式能力 | ParseCameraStreamDeviceConfig |
CameraStreamEnumDevice 返回给上层 |
参数值从哪里来(配置来源方法)
| 参数组 | 推荐来源 | 当前源码锚点示例 |
|---|---|---|
physicsCameraIds |
板级硬件映射(枚举 ID 到硬件名) | device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h:20-27 |
前后摄位置类(cameraPosition、lensFacing) |
DTS 的 rockchip,camera-module-facing + 模组安装方向 |
device/board/gkhbd/nt_backclip_5cun_v1/kernel/dts/nt_backclip_vendor/rk3568-gkh-nt_backclip_5cun.dtsi:239-241 |
| 驱动启用关系 | defconfig 的 CONFIG_VIDEO_* |
device/board/gkhbd/nt_backclip_5cun_v1/kernel/configs/nt_backclip_vendor_oh_defconfig:3759,3798 |
| 分辨率/FPS 能力 | sensor 驱动 mode 表 + frame_interval | kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c:863-943 |
| lane/link 速率 | DTS endpoint + 驱动 link-freq 回退机制 | device/board/gkhbd/nt_backclip_5cun_v1/kernel/dts/nt_backclip_vendor/rk3568-gkh-nt_backclip_5cun.dtsi:244-249,283-289 + kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c:953-975 |
| stream 上限(KHDF) | camera_config.hcs StreamConfig + 驱动可实现能力交叉 |
vendor/gkhos/nt_backclip_vendor/hdf_config/khdf/camera/camera_config.hcs:166-177 |
参数值从哪里来(细化到代码与实操)
本节整体规划(A-B-C-D)
A. 全量参数总览:先把“所有参数”放进统一对照框架(来源/HCS/读取函数/驱动生效点/日志旁证)。
B. 映射链深挖:重点讲清 physicsCameraIds -> rkisp_v5/Imx600 -> SensorManager/IspManager -> Linux。
C. 流能力深挖:basic/extend/fps/orientation 的数组位语义、解析函数、驱动上限与实测闭环。
D. 控制与分区深挖:AE/AWB/ISO/ctrlValue 与 KHDF 分区开关如何真正影响可用能力。
一句话规则:每个参数都按“来源 -> HCS -> 读取 -> 生效 -> 日志”五步闭环,不允许只停在 HCS 文本层。
A) 全量参数总览(所有参数统一入表)
A.1 UHDF camera_host_config.hcs (ability_01) 参数全集对照
| 参数 | HCS当前值(摘要) | 读取函数 | 来源(应对齐) | 驱动/运行时生效锚点 |
|---|---|---|---|---|
logicCameraId |
lcam001 |
DealCameraAbility |
产品逻辑ID规划 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:94-117 |
physicsCameraIds |
CAMERA_FIRST |
DealPhysicsCameraId |
板级映射 device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h |
drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_vdi_impl.cpp:196-203,248-273 |
aeAvailableAntiBandingModes |
OFF |
DealAeAvailableAntiBandingModes |
驱动可支持模式 + 策略 | tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt:61-64 |
aeAvailableModes |
ON/OFF |
DealAeAvailableModes |
驱动 AE 能力 | 同上 |
availableFpsRange |
[15,15] |
DealAvailableFpsRange |
sensor mode + 实测 fps | kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c:863-931 + tmp_test/v4l2_compare_stable_tail_0402_182338/99_report.txt:32-45 |
cameraPosition |
FRONT |
DealCameraPosition |
DTS camera-module-facing |
device/board/gkhbd/nt_backclip_5cun_v1/kernel/dts/nt_backclip_vendor/rk3568-gkh-nt_backclip_5cun.dtsi:239-241 |
cameraType |
WIDE_ANGLE |
DealCameraType |
产品定义 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:299-322 |
cameraConnectionType |
BUILTIN |
DealCameraConnectionType |
板级连接形态 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:324-347 |
cameraMemoryType |
USERPTR |
DealCameraMemoryType |
V4L2 buffer 策略 | drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp:90-118 |
faceDetectMaxNum |
10 |
DealCameraFaceDetectMaxNum |
算法策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:374-397 |
aeCompensationRange |
[0,0] |
DealAeCompensationRange |
AE 补偿能力 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:399-420 |
aeCompensationSteps |
[0,0] |
DealAeCompensationSteps |
AE 步进能力 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:422-443 |
availableAwbModes |
AUTO/OFF |
DealAvailableAwbModes |
AWB 控件能力 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:445-469 |
sensitivityRange |
[32,2400] |
DealSensitivityRange |
驱动 gain/iso 范围 | tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt:53-55 |
faceDetectMode |
OFF |
DealFaceDetectMode |
算法能力 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:494-516 |
availableCharacteristicsKeys |
一组 tag | HCS透传 | framework 可见键策略 | vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs:154-183 |
availableRequestKeys |
一组 tag | HCS透传 | request 可下发键 | vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs:184-192 |
availableResultKeys |
一组 tag | HCS透传 | result 可回传键 | vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs:193-200 |
focalLength |
24.0 |
DealFocalLength |
模组参数 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:518-538 |
focusAvailableModes |
MANUAL/CAF/AF/LOCKED |
DealAvailableFocusModes |
AF 能力 + 策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:540-566 |
exposureAvailableModes |
MANUAL/CAF/LOCKED/AUTO |
DealAvailableExposureModes |
AE 能力 + 策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:568-594 |
meterAvailableModes |
SPOT/REGION/OVERALL |
DealAvailableMetereModes |
测光策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:596-621 |
flashAvailableModes |
CLOSE/OPEN/AUTO/ALWAYS_OPEN |
DealAvalialbleFlashModes |
闪光策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:623-648 |
mirrorSupported |
ON |
DealMirrorSupported |
前摄镜像策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:650-673 |
basicAvailableConfigurations |
[3,640,480,3,1280,960,4,1280,960] |
DealAvaliableBasicConfigurations |
格式/尺寸来源于驱动能力 | tmp_test/color_fullpack_0402_181021/07_v4l2_formats.txt:14-25 |
extendAvailableConfigurations |
mode/stream/detail 数组 | DealAvaliableExtendConfigurations |
mode 输出策略 + basic细化 | foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/camera_stream_info_parse.h:49-109 |
sensorOrientationSupported |
180 |
DealSensorOrientation |
模组安装方向 | DTS朝向 + UI旋转链 |
videoStabilizationAvailableModes |
OFF |
DealAvalialbleVideoStabilizationModes |
算法/ISP能力 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:760-784 |
flashAvailable |
FALSE |
DealAvalialbleFlash |
板级闪光器件是否存在 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:786-809 |
afAvailable |
OFF |
DealAvalialbleAutoFocus |
AF 控件是否可用 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:811-835 |
zoomRatioRange |
[1.0,1.0] |
DealZoomRationRange |
光学/数字变焦能力 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:837-868 |
jpegOrientation |
180 |
DealJpegOrientation |
编码旋转策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:870-903 |
jpegQuality |
2 |
DealJpegQuality |
编码质量策略 | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:928-953 |
A.2 KHDF camera_config.hcs 参数对照
| 参数 | HCS当前值(摘要) | 来源(应对齐) | 生效锚点 |
|---|---|---|---|
abilityConfig.uvcMode |
true |
是否支持 UVC 热插拔策略 | drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:494-522 |
SensorConfig.mode |
true |
sensor 分区开关 | drivers/hdf_core/framework/model/camera/utils/src/camera_utils.c:120-166 |
SensorDevice.name |
rkisp_v5 |
与 VDI 硬件映射一致 | device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h:21 + drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:215-352 |
SensorDevice.exposure |
true |
曝光能力声明 | tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt:53,61-64 |
SensorDevice.ctrlValue |
id/min/max/step/default 数组 |
控件能力范围 | drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:215-352 |
IspConfig.mode/name |
true/ISP0 |
ISP 分区与命名策略 | drivers/hdf_core/framework/model/camera/utils/src/camera_utils.c:120-166 + drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/isp_manager.cpp:25-37 |
StreamConfig.mode |
true |
流能力分区开关 | drivers/hdf_core/framework/model/camera/utils/src/camera_utils.c:120-166 |
StreamDevice.name |
rkisp_v5 |
与 sensor 链路一致性 | device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h:21 |
widthMaxNum/heightMaxNum |
2592/1944 |
驱动支持上限 | tmp_test/color_fullpack_0402_181021/07_v4l2_formats.txt:14-25 |
frameRateMaxNum |
15 |
mode表+实测帧率 | kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c:863-931 + tmp_test/v4l2_compare_stable_tail_0402_182338/99_report.txt:32-45 |
bufferType |
[2] |
USERPTR 策略 | vendor/gkhos/nt_backclip_vendor/hdf_config/khdf/camera/camera_config.hcs:110-114,191 |
formatType |
[1,2,204,300] |
YUV/Bayer/JPEG 格式集合 | vendor/gkhos/nt_backclip_vendor/hdf_config/khdf/camera/camera_config.hcs:115-139,192 |
A.3 关键源码摘选(A段补强:总入口 + 数字位语义)
源码摘选A-1(UHDF 参数总入口):
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:94-117,145-192
int32_t ret = pDevResIns->GetString(&node, "logicCameraId", &cameraId, nullptr);
(void)DealPhysicsCameraId(node, phyCameraIds);
...
const struct DeviceResourceNode *metadataNode = pDevResIns->GetChildNode(&node, "metadata");
RetCode rc = DealMetadata(cameraId, *metadataNode);
...
DealAvaliableBasicConfigurations(node, metadata);
DealAvaliableExtendConfigurations(node, metadata);
cameraMetadataMap_.insert(std::make_pair(cameraId, metadata));
逐行解释:
logicCameraId是逻辑入口,决定 framework 看见的相机 ID。DealPhysicsCameraId把physicsCameraIds读成枚举字符串数组。metadata子节点是能力池,后续DealXxx全在这里取值。basic/extend都是由这里注入cameraMetadataMap_,不是 framework 直接读 HCS。
源码摘选A-2(KHDF 参数总入口):
// drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:494-522,218-254
cameraConfigNode = drsOps->GetChildNode(node, "abilityConfig");
ret = ParseCameraConfig(cameraConfigNode, drsOps, &g_configCameraRoot);
...
ret = drsOps->GetUint32(node, "heightMaxNum", &streamConfig->heightMaxNum, 0);
ret = drsOps->GetUint32(node, "widthMaxNum", &streamConfig->widthMaxNum, 0);
ret = drsOps->GetUint32(node, "frameRateMaxNum", &streamConfig->frameRateMaxNum, 0);
ret = drsOps->GetUint32Array(node, "bufferType", streamConfig->bufferType, streamConfig->bufferTypeNum, 0);
ret = drsOps->GetUint32Array(node, "formatType", streamConfig->formatType, streamConfig->formatTypeNum, 0);
逐行解释:
- KHDF 统一从
abilityConfig进入,不会跳过根节点直读子段。 width/height/fps是显式字段,不是推导值。bufferType/formatType是数组字段,元素数量先做上限校验再读取。
源码摘选A-3(ctrlValue 五元组位语义):
// drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:23-37
for (i = 0; i < ctrlValueNum; i += CTRL_INFO_COUNT) {
ctrlCap[i / CTRL_INFO_COUNT].ctrlId = ctrlValue[i + CTRL_ID_INDEX];
ctrlCap[i / CTRL_INFO_COUNT].max = ctrlValue[i + CTRL_MAX_INDEX];
ctrlCap[i / CTRL_INFO_COUNT].min = ctrlValue[i + CTRL_MIN_INDEX];
ctrlCap[i / CTRL_INFO_COUNT].step = ctrlValue[i + CTRL_STEP_INDEX];
ctrlCap[i / CTRL_INFO_COUNT].def = ctrlValue[i + CTRL_DEF_INDEX];
}
数字串位定义(你关心的“第一位第二位”):
- 第1位:
ctrlId。 - 第2位:
min。 - 第3位:
max。 - 第4位:
step。 - 第5位:
default。
注意:代码先写max再写min,但索引常量仍对应“五元组语义”;检查时以常量定义与日志双证据为准。
A.4 参数总表升级:函数入口编号(F)+ 检查命令模板
| 编号 | 入口函数(源码锚点) | 覆盖参数组 | 检查命令模板(仓内可直接执行) | 通过判据(双证据) |
|---|---|---|---|---|
F1 |
DealCameraAbility (drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:94-131) |
logicCameraId、physicsCameraIds |
`rg -n "logicCameraId | physicsCameraIds" vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs` |
F2 |
DealPhysicsCameraId (drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:133-143) |
physicsCameraIds[] |
`rg -n "CAMERA_FIRST | CAMERA_SECOND" device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h` |
F3 |
DealMetadata (drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:145-192) |
全部 metadata 参数 | rg -n "Deal[A-Za-z]+\\(" drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp |
目标参数对应 DealXxx 已被调用 |
F4 |
DealAvaliableBasicConfigurations (drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:704-733) |
basicAvailableConfigurations |
`rg -n "basicAvailableConfigurations | STREAM_INFO_ITEM_LENGTH |
F5 |
DealAvaliableExtendConfigurations (drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp) |
extendAvailableConfigurations |
rg -n "extendAvailableConfigurations" vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs |
HCS 数组结构完整且含 -1 分隔 |
F6 |
ParseCapability (foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2253-2268) |
profile/extend/basic 解析优先级 |
`rg -n "ParseCapability | OHOS_ABILITY_STREAM_AVAILABLE_EXTEND_CONFIGURATIONS |
F7 |
ParseExtendCapability (foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2103-2134) |
mode-stream-detail 到 profile | `rg -n "ParseExtendCapability | getModeInfo |
F8 |
CameraStreamInfoParse::getDetailAbilityInfo (foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/camera_stream_info_parse.h:144-176) |
format/width/height/fixed/min/max/abilityId 位语义 |
`rg -n "formatOffset | widthOffset |
F9 |
HdfParseCameraConfig + ParseCameraConfig (drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:494-522,466-492) |
KHDF 总入口/uvcMode |
`rg -n "HdfParseCameraConfig | ParseCameraConfig |
F10 |
ParseCameraStreamDeviceConfig (drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:218-254) |
widthMaxNum/heightMaxNum/frameRateMaxNum/bufferType/formatType |
`rg -n "heightMaxNum | widthMaxNum |
F11 |
SetCtrlCapInfo (drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:23-37) |
ctrlValue 五元组 |
`rg -n "SetCtrlCapInfo | CTRL_ID_INDEX |
F12 |
V4L2GetCapability (drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/driver_adapter/src/v4l2_fileformat.cpp:119-149) |
cameraId -> /dev/videoX 匹配 |
`rg -n "cameraId != | cap.driver |
补充:实机采样命令模板(板端)
v4l2-ctl -d /dev/video0 --all
v4l2-ctl -d /dev/video0 --list-formats-ext
media-ctl -p
补充:仓内日志回放模板(离线复核)
rg -n "Driver name|Pixel Format|exposure|gain|auto_exposure" tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt
rg -n "2592x1944|Stepwise|NV12|NV21" tmp_test/color_fullpack_0402_181021/07_v4l2_formats.txt
rg -n "15\\.03 fps|15\\.04 fps" tmp_test/v4l2_compare_stable_tail_0402_182338/99_report.txt
A.5 F1~F12 失败分流(每条一行,现场直接照做)
| 编号 | 常见失败信号 | 一行分流顺序(固定) |
|---|---|---|
F1 |
cameraId 枚举不到/打开失败 | 先查 camera_host_config.hcs 的 logicCameraId/physicsCameraIds,再查 DealCameraAbility 是否读到,最后查 OpenCamera 日志是否进入 CameraPowerUp。 |
F2 |
physicsCameraIds 配了但不生效 |
先查 project_hardware.h 是否有该枚举,再查 CameraIdToHardware 映射,最后对 v4l2-ctl --all 的 Driver name。 |
F3 |
单个 metadata 参数“声明了但没出现在能力里” | 先查 HCS metadata{} 字段拼写,再查 DealMetadata 内是否调用对应 DealXxx,最后查 framework 侧是否读到该 tag。 |
F4 |
basic 能力格式/尺寸异常 | 先按三元组切 basicAvailableConfigurations,再查 formatArray 映射,最后用 v4l2-ctl --list-formats-ext 校对尺寸上限。 |
F5 |
extend 解析失败或 profile 缺项 | 先查 extendAvailableConfigurations 的 -1/-1/-1 分隔,再查 ParseExtendCapability 是否命中 mode,最后查输出 profile 列表。 |
F6 |
实际走了 basic 没走 extend | 先查 metadata 是否带 OHOS_ABILITY_STREAM_AVAILABLE_EXTEND_CONFIGURATIONS,再看 ParseCapability 分支命中,最后核对 profile 结果。 |
F7 |
指定模式(如 VIDEO)无对应 profile | 先查 extend 数组首位 mode 是否有目标模式,再查 ConvertMetaToFwkMode 映射,最后看 CreateProfile4StreamType 是否被调用。 |
F8 |
一串数字解释不清或解析错位 | 先按 format,width,height,fixed,min,max 六元头切块,再按 ABILITY_FINISH=-1 收尾,最后核对 abilityId 列表。 |
F9 |
KHDF 配置整体不生效 | 先查 abilityConfig 根节点是否存在,再查 HdfParseCameraConfig 是否成功返回,最后查各分区 mode 是否被短路。 |
F10 |
widthMaxNum/frameRateMaxNum 与运行时不一致 |
先查 camera_config.hcs 数值,再查 ParseCameraStreamDeviceConfig 读取日志,最后对比 v4l2-ctl 与 sensor 驱动 mode 表。 |
F11 |
ctrlValue 数字串语义混乱 |
先每5位切组(id/min/max/step/default),再查 SetCtrlCapInfo 索引常量,最后对照 v4l2-ctl --all 的控件范围。 |
F12 |
cameraId 与 /dev/videoX 绑定失败 |
先查 cap.driver 是否等于期望 cameraId,再查 deviceMatch 是否插入,最后查 Driver name 与板级映射是否一致。 |
B) 映射参数族深挖:physicsCameraIds 到 Linux 驱动
源码摘选1(HCS设定):
// vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs:127-131
logicCameraId = "lcam001";
physicsCameraIds = ["CAMERA_FIRST"];
逐行解释:
- 这里只声明“逻辑相机绑哪一路枚举”。
- 没有直接出现
ov5648/rkisp字符串。
源码摘选2(枚举到硬件名来源):
// device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h:20-26
{CAMERA_FIRST, DM_M_SENSOR, DM_C_SENSOR, (std::string) "rkisp_v5"},
{CAMERA_FIRST, DM_M_ISP, DM_C_ISP, (std::string) "isp"},
{CAMERA_SECOND,DM_M_SENSOR, DM_C_SENSOR, (std::string) "Imx600"},
逐行解释:
CAMERA_FIRST在 sensor 维度对应rkisp_v5。- ISP 维度固定是
isp,单独 manager。 CAMERA_SECOND -> Imx600当前是模板链路。
源码摘选3(实际生效函数链):
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_vdi_impl.cpp
config->GetPhysicCameraIds(cameraId, phyCameraIds);
CameraPowerUp(cameraId, phyCameraIds);
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/v4l2_device_manager.cpp
(*iter)->PowerUp(CameraIdToHardware(cameraId, (*iter)->GetManagerId()));
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/sensor_controller.cpp
sensorVideo_->start(GetName());
逐行解释:
- HCS 的
CAMERA_FIRST先在 host 层取出。 - 到 device manager 按 manager 维度翻译成硬件名。
- sensor controller 用该名走 V4L2 打开设备并开始流。
源码摘选4(如何连到 Linux 节点):
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/driver_adapter/src/v4l2_fileformat.cpp
V4L2MatchDevice(cameraIDs); // 遍历 /dev/videoX
V4L2GetCapability(..., cameraId) {
if (cameraId != (char*)cap.driver) return RC_ERROR;
}
逐行解释:
- VDI 用
cap.driver == cameraID做匹配。 - 匹配成功后才建立
cameraID -> /dev/videoX映射。 - 后续
VIDIOC_S_FMT/REQBUFS/STREAMON都落在这个节点。
运行时旁证:
// tmp_test/color_fullpack_0402_181021/05_media_ctl_p.txt:117-126
... "m00_f_ov5648 4-0036" -> "rockchip-csi2-dphy0" [ENABLED]
... fmt:SBGGR10_1X10/2592x1944@1/15
结论:实际物理 sensor 是 ov5648;rkisp_v5 是 VDI 侧匹配入口名,不是最终日志里 sensor 节点名。
B.1 rkisp_v5/Imx600 与 HCS/DTS 并排对照(补强)
| 维度 | 配置值 | 配置来源 | 代码生效点 | 运行时可见信号 |
|---|---|---|---|---|
| UHDF 逻辑映射 | physicsCameraIds=["CAMERA_FIRST"] |
vendor/gkhos/nt_backclip_vendor/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs:128-131 |
DealPhysicsCameraId -> CameraPowerUp |
OpenCamera 后进入 deviceManager->PowerUp |
| 板级硬件映射 | CAMERA_FIRST->rkisp_v5、CAMERA_SECOND->Imx600 |
device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h:20-26 |
CameraIdToHardware(cameraId, managerId) |
v4l2-ctl --all 看到 Driver name : rkisp_v5 |
| 真实 sensor 驱动 | compatible = "ovti,ov5648" |
device/board/gkhbd/nt_backclip_5cun_v1/kernel/dts/nt_backclip_vendor/rk3568-gkh-nt_backclip_5cun.dtsi:223-241 |
Linux i2c sensor probe | media-ctl -p 显示 m00_f_ov5648 |
B.2 SensorManager/IspManager 分轨代码摘选与逐行解释
源码摘选B-1(IspManager/IspController):
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/isp_manager.cpp:25-40,57-64
if (controllerId == DM_C_ISP) {
std::shared_ptr<IspController> isp = std::make_shared<IspController>(hardwareName);
rc = isp->Init();
if (rc == RC_OK) { ispList_.push_back(isp); }
}
...
if ((*iter)->GetName() == hardwareName) {
return (*iter)->PowerUp();
}
逐行解释:
- ISP 轨只处理
DM_C_ISP控制器。 hardwareName来自CameraIdToHardware(..., DM_M_ISP),即project_hardware.h的isp。PowerUp/PowerDown是 ISP 侧生命周期门禁。
源码摘选B-2(SensorController):
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/sensor_controller.cpp:104-143
rc = sensorVideo_->start(GetName());
sensorVideo_->ConfigSys(GetName(), CMD_V4L2_SET_FORMAT, format);
sensorVideo_->ReqBuffers(GetName(), buffCont_);
逐行解释:
- Sensor 轨最终进入
HosV4L2Dev,GetName()就是rkisp_v5/Imx600这类硬件名。 ConfigSys(...SET_FORMAT...)对应VIDIOC_S_FMT。ReqBuffers对应VIDIOC_REQBUFS,真正申请视频缓冲。
B.3 与 Linux 节点绑定的双证据
- 代码锚点:
V4L2GetCapability里if (cameraId != cap.driver) return RC_ERROR;(drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/driver_adapter/src/v4l2_fileformat.cpp:136-141)。 - 实际日志:
tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt中Driver name : rkisp_v5与 HCS/板级映射一致;同时tmp_test/color_fullpack_0402_181021/05_media_ctl_p.txt出现ov5648,证明最终链路落到真实 Linux sensor 驱动。
C) 流能力参数族深挖:basic/extend/fps/orientation
C.1 basicAvailableConfigurations 位定义 + 生效链
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:704-733
if (i % 3 == 0) {
basicConfigAvaliableInt32s.push_back(formatArray[(int32_t)nodeValue - 1]);
} else {
basicConfigAvaliableInt32s.push_back((int32_t)nodeValue);
}
逐行解释:
- basic 固定三元组:
format,width,height。 - format 位会被重映射,不是原值直通。
- 这就是“为什么 HCS 写 3/4/5,framework 看到的枚举会变”。
C.2 extendAvailableConfigurations 位定义 + 解析器
// foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/camera_stream_info_parse.h
formatOffset=0; widthOffset=1; heightOffset=2;
fixedFpsOffset=3; minFpsOffset=4; maxFpsOffset=5;
ABILITY_FINISH=-1; STREAM_FINISH=-1; MODE_FINISH=-1;
逐行解释:
- detail 前 6 位固定语义:
format,width,height,fixed,min,max。 - 后续可跟
abilityId...。 -1既是 detail 结束,也是 stream/mode 的分隔语义。
最小合法结构:
[mode, streamType, format, width, height, fixedFps, minFps, maxFps, -1, -1, -1]
C.3 与驱动上限对齐(必须双证据)
- 驱动 mode 表给出上限:
kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c中2592x1944@15。 - 实测格式上限:
tmp_test/color_fullpack_0402_181021/07_v4l2_formats.txt到2592x1944。 - 实测 fps 稳定:
tmp_test/v4l2_compare_stable_tail_0402_182338/99_report.txt在15.03/15.04 fps。 - 因此
availableFpsRange=[15,15]、extend 里2592x1944@15是可闭环的。
C.4 ParseExtendCapability + getDetailAbilityInfo 联合逐行解释
源码摘选C-1(framework 选择 extend 解析):
// foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2253-2268
if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_AVAILABLE_PROFILE_LEVEL)) {
ParseProfileLevel(...);
} else if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_STREAM_AVAILABLE_EXTEND_CONFIGURATIONS)) {
ParseExtendCapability(profilesWrapper, mode, item);
} else if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS)) {
ParseBasicCapability(...);
}
逐行解释:
- 优先级是
profile_level > extend > basic。 - 设备只要带 extend tag,默认走
ParseExtendCapability。 - 这就是“为什么 basic 配了但 profile 仍异常”的常见根因。
源码摘选C-2(extend 数组拆解):
// foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2103-2134
modeStreamParse->getModeInfo(item.data.i32, item.count, extendInfo);
...
if (modeName == scMode) {
CreateProfile4StreamType(profilesWrapper, streamType, i, j, extendInfo);
}
逐行解释:
- 先把一维
int32[]数组拆成mode->stream->detail三层结构。 - 再按
modeName过滤,只有匹配模式会生成 profile。 CreateProfile4StreamType最终产出 preview/photo/video 能力集合。
源码摘选C-3(detail 六元头 + ability 列表):
// foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/camera_stream_info_parse.h:146-169
uint32_t allOffset = 6;
format = originInfo[m + 0];
width = originInfo[m + 1];
height = originInfo[m + 2];
fixedFps = originInfo[m + 3];
minFps = originInfo[m + 4];
maxFps = originInfo[m + 5];
for (n = m + allOffset; n < abilityEndIndex_.front(); n++) {
abilityId.push_back(originInfo[n]);
}
逐行解释:
- 每个 detail 前 6 位是固定头,不能改顺序。
- 第 7 位开始是可选
abilityId列表,直到遇到-1。 - 所以你看到的长数字串,先按
6+N一组切,再看分隔-1。
C.5 终端工具与实际日志(实操证据)
推荐命令:
v4l2-ctl -d /dev/video0 --all
v4l2-ctl -d /dev/video0 --list-formats-ext
media-ctl -p
当前仓证据摘录:
tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt显示Driver name : rkisp_v5、Pixel Format : 'NV21'。- 同文件显示控件范围:
exposure min=4 max=1980、gain min=16 max=248。 tmp_test/color_fullpack_0402_181021/07_v4l2_formats.txt显示 stepwise 上限到2592x1944。tmp_test/v4l2_compare_stable_tail_0402_182338/99_report.txt显示采集稳定在15.03~15.04 fps。
D) 控制与分区参数族深挖:AE/AWB/ISO/ctrlValue/mode
D.1 UHDF 控制参数如何起作用
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp
DealAeAvailableModes(...)
DealAvailableAwbModes(...)
DealSensitivityRange(...)
metadata->addEntry(...)
逐行解释:
- HCS 控制参数先写入 metadata。
- framework/服务端据此决定“哪些控制可下发、可回传”。
- 日志侧需要看到对应控件存在和值变化,否则就是“声明未落地”。
日志旁证:
// tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt
exposure: min=4 max=1980 value=500
gain: min=16 max=248 value=96
auto_exposure: Auto Mode
解释:曝光/增益控制项真实存在并有范围,不是仅 HCS 文本声明。
D.2 KHDF mode 和 ctrlValue 如何起作用
// drivers/hdf_core/framework/model/camera/utils/src/camera_utils.c (CheckSwitchType)
// drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c (ParseCamera*Config)
逐行解释:
mode=true/false是门禁开关;关掉后分区能力不参与枚举。ctrlValue数组语义是五元组:id,min,max,step,default。- 这些值用于构建设备能力边界,不应脱离驱动真实控件范围。
D.3 控制项从 OHOS tag 到 V4L2 CID 的实际函数链
源码摘选D-1(Tag -> CID 映射):
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/sensor_controller.cpp:21-27
{OHOS_SENSOR_EXPOSURE_TIME, V4L2_CID_EXPOSURE_AUTO},
{OHOS_CONTROL_AWB_MODE, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE},
{OHOS_CONTROL_FOCUS_MODE, V4L2_CID_FOCUS_AUTO},
{OHOS_CONTROL_EXPOSURE_MODE, V4L2_CID_EXPOSURE_AUTO},
{OHOS_CONTROL_FLASH_MODE, V4L2_CID_FLASH_LED_MODE},
逐行解释:
- framework 传的是 OHOS tag,不是直接传 V4L2 CID。
SensorController内部完成 tag 到 CID 的桥接。- 桥接表缺项时,控制项会“声明存在但下发无效”。
源码摘选D-2(配置下发链):
// drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/device_manager/sensor_controller.cpp:81-102,104-117
RetCode SensorController::Configure(std::shared_ptr<CameraMetadata> meta)
{
return SendSensorMetaData(meta);
}
...
RetCode SensorController::ConfigFps(std::shared_ptr<CameraMetadata> meta)
{
RetCode rc = SendFpsMetaData(data);
return rc;
}
...
rc = sensorVideo_->start(GetName());
逐行解释:
Configure入口处理通用控制(AE/AWB/AF 等)。ConfigFps单独处理帧率元数据。ConfigStart开启设备后,控制值才会在流上体现。
D.4 mode 门禁与 ctrlValue 位定义的代码双证据
源码摘选D-3(mode 门禁):
// drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:264-270,293-299
ret = drsOps->GetUint8(node, "mode", &sensorConfig->mode, 0);
if (sensorConfig->mode == DEVICE_NOT_SUPPORT) { return HDF_SUCCESS; }
...
ret = drsOps->GetUint8(node, "mode", &ispConfig->mode, 0);
if (ispConfig->mode == DEVICE_NOT_SUPPORT) { return HDF_SUCCESS; }
逐行解释:
mode=false不会报错,但该分区直接短路退出。- 这就是“配置文件看起来有字段,但运行时没有能力”的第一检查点。
源码摘选D-4(ctrlValue 五元组解析):
// drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:27-36
ctrlCap[...].ctrlId = ctrlValue[i + CTRL_ID_INDEX];
ctrlCap[...].max = ctrlValue[i + CTRL_MAX_INDEX];
ctrlCap[...].min = ctrlValue[i + CTRL_MIN_INDEX];
ctrlCap[...].step = ctrlValue[i + CTRL_STEP_INDEX];
ctrlCap[...].def = ctrlValue[i + CTRL_DEF_INDEX];
位定义(检查模板):
- 第1位
id:控件 ID。 - 第2位
min:最小值。 - 第3位
max:最大值。 - 第4位
step:步进。 - 第5位
default:默认值。
检查动作:将camera_config.hcs中每 5 个数切一组,与v4l2-ctl --all的控件范围逐组对齐。
D.5 HCS 与实测日志并排示例(曝光/增益)
- HCS 侧:
vendor/gkhos/nt_backclip_vendor/hdf_config/khdf/camera/camera_config.hcs:150-154声明了ctrlValue。 - 解析侧:
SetCtrlCapInfo把五元组写入ctrlCap(drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:23-37)。 - 运行侧:
tmp_test/color_fullpack_0402_181021/06_v4l2_all.txt实测exposure min=4 max=1980、gain min=16 max=248。 - 判据:若 HCS 声明与 V4L2 范围不一致,以驱动实测范围为最终约束,回写 HCS。
本节收口(你要求的“整体规划”落地检查)
- 是否先有全参数总表:有(A.1 + A.2)。
- 是否每组都连到驱动生效点:有(B/C/D 的函数链 + ioctl/日志)。
- 是否有源码摘选+逐行分析+hcs对比:有(A/B/C/D 都覆盖)。
- 是否可实操复核:可,按“五步法”逐参数复用。
关键源码摘选与分析
1) vdiLibList 决定是否能装载 VDI
// drivers/peripheral/camera/hdi_service/v1_0/src/camera_host_service.cpp
int32_t elemNum = pDevResIns->GetElemNum(pRootNode, "vdiLibList");
for (int i = 0; i < elemNum; i++) {
pDevResIns->GetStringArrayElem(pRootNode, "vdiLibList", i, &vdiLib, nullptr);
vdiLibList.push_back(std::string(vdiLib));
}
...
struct HdfVdiObject *cameraHostVdiLoader = HdfLoadVdi(vdiLib.c_str());
分析:
vdiLibList为空会直接返回INVALID_ARGUMENT,host 起不来。- 这是 UHDF 主链最前置门禁,后面所有
GetCameraIds/OpenCamera都依赖它。
2) logic/physics + metadata 的统一解析入口
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp
int32_t ret = pDevResIns->GetString(&node, "logicCameraId", &cameraId, nullptr);
(void)DealPhysicsCameraId(node, phyCameraIds);
...
RetCode rc = DealMetadata(cameraId, *metadataNode);
分析:
- 先建
cameraIdMap_,再建cameraMetadataMap_,两者缺一不可。 logicCameraId配错是“枚举/打开找不到”,metadata配错是“能力解析错配”。
3) basicAvailableConfigurations 的格式重映射
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp
if (i % STREAM_INFO_ITEM_LENGTH == 0) {
basicConfigAvaliableInt32s.push_back(formatArray[static_cast<int32_t>(nodeValue) - 1]);
} else {
basicConfigAvaliableInt32s.push_back(static_cast<int32_t>(nodeValue));
}
分析:
- HCS 里的格式号不是直接下发,先经过
formatArray映射。 - 这就是“看起来填了 3/4/5,但 framework 实际看到的是映射后值”的根因。
4) OpenCamera 真正用到 physicsCameraIds 上电
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_vdi_impl.cpp
RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds);
if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) {
CAMERA_LOGE("camera powerup failed.");
CameraPowerDown(phyCameraIds);
return DEVICE_ERROR;
}
分析:
physicsCameraIds是 open 阶段真实执行参数,不是“展示字段”。- 多映射或错映射会直接表现为
camera powerup failed。
5) framework 能力解析优先级
// foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp
if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_AVAILABLE_PROFILE_LEVEL)) {
ParseProfileLevel(...);
} else if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_STREAM_AVAILABLE_EXTEND_CONFIGURATIONS)) {
ParseExtendCapability(...);
} else if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS)) {
ParseBasicCapability(...);
}
分析:
- 同时存在时优先走
ProfileLevel,其次Extend,最后Basic。 - 所以
extendAvailableConfigurations结构错误会优先污染 profile,不会自动回到 basic。
6) KHDF camera_config.hcs 的真实解析入口
// drivers/hdf_core/framework/model/camera/core/src/camera_core.c
if (HdfParseCameraConfig(device->property) != HDF_SUCCESS) {
return HDF_FAILURE;
}
...
for (i = 0; i < rootConfig->deviceNum; i++) {
ret = HdfCameraInitDevice(rootConfig->deviceConfig[i].deviceName);
}
分析:
camera_config.hcs在 core init 就会解析,不是“文档参数”。mode开关直接影响对应分区是否被认作支持设备。
函数逐行解释:DealMetadata
目标函数:drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:145-193
源码摘选:
// drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:145-193
RetCode HcsDeal::DealMetadata(const std::string &cameraId, const struct DeviceResourceNode &node)
{
struct DeviceResourceAttr *drAttr = nullptr;
DEV_RES_NODE_FOR_EACH_ATTR(&node, drAttr) {}
const int ENTRY_CAPACITY = 30;
const int DATA_CAPACITY = 2000;
std::shared_ptr<CameraMetadata> metadata = std::make_shared<CameraMetadata>(ENTRY_CAPACITY, DATA_CAPACITY);
if (metadata == nullptr) {
return RC_ERROR;
}
DealAvailableFpsRange(node, metadata);
DealCameraPosition(node, metadata);
...
DealAvaliableBasicConfigurations(node, metadata);
...
DealAvaliableExtendConfigurations(node, metadata);
...
cameraMetadataMap_.insert(std::make_pair(cameraId, metadata));
return RC_OK;
}
逐行解释:
DEV_RES_NODE_FOR_EACH_ATTR:先扫描 metadata 节点属性,确认节点结构可遍历。ENTRY_CAPACITY/DATA_CAPACITY:为 metadata 容器预分配空间。make_shared<CameraMetadata>:创建能力容器实例。if (metadata == nullptr):创建失败立即终止,避免写空指针。DealAvailableFpsRange/DealCameraPosition/...:把 HCS 文本和数组逐项转成标准 metadata tag。DealAvaliableBasicConfigurations:注入 basic 三元组能力。DealAvaliableExtendConfigurations:注入 extend 模式化能力。cameraMetadataMap_.insert(...):把能力绑定到cameraId,这是上层可见的最终落点。return RC_OK:函数成功返回,后续GetCameraAbility才能读到完整结果。
函数逐行解释:ParseCapability
目标函数:foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2253-2279
源码摘选:
// foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2253-2279
void CameraManager::ParseCapability(..., const int32_t modeName, camera_metadata_item_t& item, ...)
{
if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_AVAILABLE_PROFILE_LEVEL)) {
...
ParseProfileLevel(profilesWrapper, mode, item);
} else if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_STREAM_AVAILABLE_EXTEND_CONFIGURATIONS)) {
...
ParseExtendCapability(profilesWrapper, mode, item);
} else if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS)) {
ParseBasicCapability(profilesWrapper, metadata, item);
} else {
MEDIA_ERR_LOG("Failed get stream info");
}
if (g_isCapabilitySupported(metadata, item, OHOS_ABILITY_DEPTH_DATA_PROFILES)) {
...
ParseDepthCapability(mode, item);
}
}
逐行解释:
- 第一个
if:优先检查PROFILE_LEVEL,这是最高优先级路径。 - 命中后
ParseProfileLevel:直接按 profile-level 生成能力,不再进入 extend/basic。 - 第二个
else if:如果没有 profile-level,才看EXTEND_CONFIGURATIONS。 - 命中后
ParseExtendCapability:解析mode->stream->detail结构。 - 第三个
else if:前两者都缺失才回退ParseBasicCapability。 else错误日志:三条主能力标签都没有时,报Failed get stream info。- 尾部独立
if:深度能力DEPTH_DATA_PROFILES是并行解析,不受主分支互斥影响。
函数逐行解释:DealAvaliableBasicConfigurations
目标函数:drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:704-733
- 第 707-708 行:声明
nodeValue与basicConfigAvaliableInt32s。
重点:后者就是最终写入 metadata 的 basic 配置数组。 - 第 710 行:读取
basicAvailableConfigurations元素个数。
重点:这里拿的是 HCS 原始数组长度,不做组数校验。 - 第 713 行:
STREAM_INFO_ITEM_LENGTH=3。
重点:basic 语义固定为 3 元组:format,width,height。 - 第 714-723 行:逐元素读取并重写。
重点A:i%3==0时认定当前元素是格式位,会执行formatArray[nodeValue-1]映射。
重点B:非格式位(宽高)直接原样写入。
重点C:这就是“写 3/4/5,框架看到的是映射后枚举”的直接代码证据。 - 第 725-726 行:将重写后的数组写入 tag
OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS。
重点:这是 basic 能力最终生效点。 - 第 727-730 行:写入失败返回
RC_ERROR。
重点:这一段失败时,framework 只能尝试 extend/profile-level 分支。 - 第 731-732 行:日志成功并返回
RC_OK。
重点:只代表“写入 metadata 成功”,不代表上层一定会选中该 profile。
函数逐行解释:ParseExtendCapability
目标函数:foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2103-2137
- 第 2106 行:初始化
ExtendInfo。
重点:这是解析后 mode/stream/detail 的结构化承载对象。 - 第 2107 行:创建
CameraStreamInfoParse解析器。
重点:后续解析完全依赖这个对象对-1分隔语义的理解。 - 第 2108 行:
getModeInfo(item.data.i32, item.count, extendInfo)。
重点:把 metadata 原始 int32 数组解包成mode -> streamType -> detail三级结构。 - 第 2109-2123 行:
modeName==VIDEO时先额外扫描HIGH_FRAME_RATE。
重点:视频模式会先补一轮高帧率能力,这是 video 特有分支。 - 第 2112-2113 行:
ConvertMetaToFwkMode做元数据 mode 到 framework mode 映射。
重点:映射失败时会打印错误,常见原因是 extend 里 mode 编码不合法。 - 第 2117-2121 行:遍历 streamType 并
CreateProfile4StreamType。
重点:真正把 detail 生成 preview/photo/video profile 的地方。 - 第 2124-2135 行:常规模式匹配分支。
重点A:逐个 mode 找与modeName相等的分组。
重点B:命中后生成 profile 并break,不会继续扫后续 mode。 - 第 2137 行:函数结束。
重点:该函数不显式返回错误码,异常多靠日志和 profile 结果侧面体现。
两个函数的高频坑位(配套)
| 函数 | 常见坑位 | 直接信号 | 最小验证动作 |
|---|---|---|---|
DealAvaliableBasicConfigurations |
format 填值和 formatArray 映射预期不一致 |
preview/profile 格式看起来“变了” | 对照 drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:718-721 + 打印 cameraAbility |
DealAvaliableBasicConfigurations |
数组长度不是 3 的倍数(隐式脏数据) | 上层 profile 维度异常 | 检查 HCS 数组是否严格三元组 |
ParseExtendCapability |
-1 分隔语义破坏(mode/stream/detail 边界错) |
ValidateOutputProfile ... fail 或 profile 缺失 |
用 CameraStreamInfoParse 路径核对原始数组结构 |
ParseExtendCapability |
mode 编码无法映射到 framework scene mode | 日志出现 ConvertMetaToFwkMode 相关异常 |
对照 mode 值与实际枚举定义 |
参数如何起作用(按流程拆解)
轨道A:映射与上电
logicCameraId/physicsCameraIds被DealCameraAbility解析进cameraIdMap_。
锚点:drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:94-143OpenCamera通过逻辑 ID 取物理 ID,逐个PowerUp。
锚点:drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_vdi_impl.cpp:195-205,266-277- 上层只看到逻辑 ID,实际供电和驱动匹配用的是物理枚举。
锚点:drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_config.cpp:98-106
轨道B:能力注入与 profile 构造
metadata字段经DealMetadata一次性入CameraMetadata。
锚点:drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:145-193- service 通过 HDI 拉取能力并缓存。
锚点:foundation/multimedia/camera_framework/services/camera_service/src/hcamera_host_manager.cpp:251-279 - framework 依据优先级解析
profile,最后用于 preview/photo/video 输出创建。
锚点:foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2253-2268,2055-2137
轨道C:KHDF 分区门禁
abilityConfig被解析到g_configCameraRoot。
锚点:drivers/hdf_core/framework/model/camera/parser/src/camera_config_parser.c:494-522mode字段被CheckSwitchType作为开关门禁。
锚点:drivers/hdf_core/framework/model/camera/utils/src/camera_utils.c:120-166StreamConfig上限会通过CameraStreamEnumDevice返回。
锚点:drivers/hdf_core/framework/model/camera/device_impl/src/camera_stream.c:472-483
双证据检查模板(本章强制)
| 检查项 | 前序知识点判据 | 实际源码锚点 | 结论写法 |
|---|---|---|---|
physicsCameraIds 是否正确 |
“Open 失败优先查逻辑到物理映射” | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_vdi_impl.cpp:195-205,266-277 + device/board/gkhbd/nt_backclip_5cun_v1/camera/vdi_impl/v4l2/device_manager/include/project_hardware.h:20-27 |
判据+锚点一致/不一致 |
| 朝向是否一致 | “UI前后摄异常先查 metadata 与 DTS 朝向一致性” | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:274-297 + device/board/gkhbd/nt_backclip_5cun_v1/kernel/dts/nt_backclip_vendor/rk3568-gkh-nt_backclip_5cun.dtsi:239-241 |
cameraPosition 与 DTS facing 对齐/错配 |
| 能力表是否可解析 | “preview/profile 异常先查 extend/basic 结构” | drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp:704-733,967-999 + foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp:2055-2137 |
能解析/分隔符或结构异常 |
| 驱动能力是否支撑 HCS | “HCS 分辨率/FPS 不应超过驱动 mode 表” | kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c:863-943 |
能力覆盖/超配 |
配置改动影响范围速查
| 参数 | 第一生效函数 | 第二影响函数 | 常见失败信号 |
|---|---|---|---|
vdiLibList |
CameraHostService::GetInstance |
host 初始化整体失败 | Vdi library list is empty |
logicCameraId |
CameraHostConfig::GetCameraIds |
framework 枚举设备 ID | GetCameraIds 不含目标 ID |
physicsCameraIds |
CameraHostVdiImpl::OpenCamera |
CameraPowerUp |
camera powerup failed |
basicAvailableConfigurations |
ParseBasicCapability |
preview/video profile 列表 | profile 稀疏/缺失 |
extendAvailableConfigurations |
ParseExtendCapability |
mode 输出匹配 | ValidateOutputProfile ... fail |
cameraPosition |
DealCameraPosition |
GetSupportedCameras 选择与展示 |
前后摄分组异常 |
camera_config.hcs 的各分区 mode |
CheckSwitchType |
KHDF dispatch 开放能力 | not supported |
为什么这样设计(优点与取舍)
| 设计点 | 优点 | 取舍 |
|---|---|---|
| 逻辑 ID 与物理 ID 分离 | 上层接口稳定,底层硬件可换 | 需要维护映射一致性 |
| metadata 驱动能力注入 | 板级差异尽量配置化 | 参数语义复杂,错误不易一眼看出 |
| Extend 优先 Basic 兜底 | 能表达 mode/stream/fps 细粒度能力 | extend 写坏会优先影响能力解析 |
| KHDF 分区化开关 | 模块可裁剪、可按硬件能力启停 | 双 HCS 并存带来理解成本 |
知识点依赖与跨章连接
| 本章知识点 | 依赖 | 下一跳 |
|---|---|---|
| HCS 参数来源方法 | 第2章(DTS/驱动基线) | 第4章(会话门禁如何消费这些能力) |
OpenCamera 上电链 |
第1章(全链路时序) | 第6章(函数级失败点) |
| Extend/Basic 优先级 | 第1章(能力解析时序) | 第5章(ArkTS 输出创建失败机制) |
信号 -> 判断 -> 动作
| 信号 | 判断 | 动作 |
|---|---|---|
GetCameraIds 正常但预览创建失败 |
映射轨大概率正常,能力轨异常 | 查 extend/basic + ParseCapability |
camera powerup failed |
物理映射或硬件枚举不一致 | 对齐 physicsCameraIds 与 project_hardware.h |
| 前后摄展示错位 | metadata 位置标签与 DTS 不一致 | 对齐 cameraPosition/lensFacing 与 DTS facing |
KHDF 报 not supported |
对应分区 mode=0 或解析失败 |
查 camera_config.hcs 分区开关与解析日志 |
四函数流程卡(每一步都有说明)
1) DealMetadata 流程
| 步骤 | 做什么 | 为什么重要 | 下一跳/失败信号 |
|---|---|---|---|
| Step 1 | 创建 CameraMetadata(ENTRY_CAPACITY, DATA_CAPACITY) |
建立能力容器,后续字段都写入这里 | 失败返回 RC_ERROR |
| Step 2 | 顺序调用各 DealXXX 子函数(AE/AWB/FPS/position/basic/extend...) |
把 HCS 每个字段转成标准 metadata tag | 某字段解析失败会留下“部分能力”风险 |
| Step 3 | 执行 DealAvaliableBasicConfigurations |
注入 basic 流能力(格式/分辨率) | basic 错会导致 profile 稀疏 |
| Step 4 | 执行 DealAvaliableExtendConfigurations |
注入 mode/stream/fps 细粒度能力 | extend 错会优先污染解析路径 |
| Step 5 | cameraMetadataMap_.insert(cameraId, metadata) |
这是能力真正对外可见的落点 | 未插入则上层拿不到能力 |
2) DealAvaliableBasicConfigurations 流程
| 步骤 | 做什么 | 为什么重要 | 下一跳/失败信号 |
|---|---|---|---|
| Step 1 | 读取 basicAvailableConfigurations 原始数组 |
拿到 HCS 的 basic 输入 | 数组为空或脏数据会影响后续 |
| Step 2 | 按每 3 个为一组遍历(format,width,height) |
维持 basic 语义一致 | 长度异常会造成维度错位 |
| Step 3 | 对格式位做 formatArray[value-1] 映射 |
HCS 格式号转 framework 可识别枚举 | 格式不在映射内会导致 profile 异常 |
| Step 4 | 宽高位原样写入 | 保留真实尺寸参数 | 尺寸超驱动能力会在后续失败 |
| Step 5 | addEntry(OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS, ...) |
完成 basic 能力注入 | 写入失败返回 RC_ERROR |
3) ParseCapability 流程
| 步骤 | 做什么 | 为什么重要 | 下一跳/失败信号 |
|---|---|---|---|
| Step 1 | 先查 OHOS_ABILITY_AVAILABLE_PROFILE_LEVEL |
最高优先级解析入口 | 命中则直接 ParseProfileLevel |
| Step 2 | 未命中时查 OHOS_ABILITY_STREAM_AVAILABLE_EXTEND_CONFIGURATIONS |
extend 优先于 basic | 命中则走 ParseExtendCapability |
| Step 3 | 再未命中时查 OHOS_ABILITY_STREAM_AVAILABLE_BASIC_CONFIGURATIONS |
basic 兜底路径 | 命中则走 ParseBasicCapability |
| Step 4 | 三者都不命中则报错 | 表示主流能力标签缺失 | Failed get stream info |
| Step 5 | 额外独立检查 OHOS_ABILITY_DEPTH_DATA_PROFILES |
深度流与主流并行解析 | 命中则走 ParseDepthCapability |
4) ParseExtendCapability 流程
| 步骤 | 做什么 | 为什么重要 | 下一跳/失败信号 |
|---|---|---|---|
| Step 1 | getModeInfo(item.data.i32, item.count, extendInfo) |
把原始 int32 数组按 -1 语义拆成结构 |
分隔错会导致 mode/stream/detail 乱序 |
| Step 2 | 若 modeName == VIDEO,先扫 HIGH_FRAME_RATE |
视频模式特有补充分支 | 该分支可解释 video profile 差异 |
| Step 3 | ConvertMetaToFwkMode 做 mode 映射 |
元数据 mode 需转 framework scene mode | 映射失败会打印错误并跳过 |
| Step 4 | 找到目标 mode 后遍历 streamType | 锁定当前会话模式可用输出流 | 找不到 mode 会导致 profile 为空 |
| Step 5 | 调 CreateProfile4StreamType 生成 profile |
这是 preview/photo/video 产出点 | 异常常表现为 ValidateOutputProfile ... fail |
一页速记卡(现场排障可直接照抄)
| 主题 | 速记 |
|---|---|
| 首查顺序 | GetCameraIds -> OpenCamera(powerup) -> ParseCapability |
| 能力优先级 | ProfileLevel > Extend > Basic(不是 Basic 优先) |
| basic 三元组 | format,width,height,格式位会做 formatArray 映射 |
| extend 结构 | mode -> streamType -> detail,靠 -1 分隔 |
| 朝向双证据 | HCS cameraPosition/lensFacing + DTS camera-module-facing |
| 映射双证据 | HCS physicsCameraIds + project_hardware.h |
| 分辨率/FPS 双证据 | HCS basic/extend + ov5648_modes[]/frame_interval |
| Linux 工具 | media-ctl -p(拓扑)/ v4l2-ctl --list-formats-ext(格式)/ --list-subdev-frameintervals(fps) |
| 典型错误1 | camera powerup failed -> 先核 physicsCameraIds |
| 典型错误2 | ValidateOutputProfile ... fail -> 先核 extend 分隔与 mode 映射 |
| 典型错误3 | 前后摄错位 -> 先核 HCS 朝向与 DTS 朝向一致性 |
本章最小动作(10分钟)
- 对照
camera_host_config.hcs抽查 4 项:physicsCameraIds、cameraPosition、basic、extend。 - 用源码确认读取点和生效点:
drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/hcs_deal.cpp+drivers/peripheral/camera/vdi_base/v4l2/src/camera_host/camera_host_vdi_impl.cpp+foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp。 - 再对照 DTS/驱动:
device/board/gkhbd/nt_backclip_5cun_v1/kernel/dts/nt_backclip_vendor/rk3568-gkh-nt_backclip_5cun.dtsi与kernel/linux/linux-6.6-nt_backclip_5cun_v1/drivers/media/i2c/ov5648.c,确认参数值来源有证据。
一句话小结
这章的核心不是“背字段”,而是把每个参数放进“来源 -> 读取函数 -> 生效函数 -> 失败信号”的闭环里做双证据验证。
发布后补链
- 上一篇:https://laval.csdn.net/69d8b7fd0a2f6a37c59e6f33.html
- 下一篇:https://laval.csdn.net/69d8b8d154b52172bc6860ae.html
全章导航
- 第0章 导读学习指南:https://laval.csdn.net/69d77a0554b52172bc6802aa.html
- 第1章 主链调用总览(图表):https://laval.csdn.net/69d8b75f54b52172bc686020.html
- 第2章 驱动与硬件基线:https://laval.csdn.net/69d8b7fd0a2f6a37c59e6f33.html
- 第3章 能力注入与流桥接(HDF/HDI/VDI):https://laval.csdn.net/69d8b86154b52172bc68609a.html
- 第4章 会话编排与门禁(Framework/Service):https://laval.csdn.net/69d8b8d154b52172bc6860ae.html
- 第5章 输出创建与显示绑定(ArkTS/HAP):https://laval.csdn.net/69d8b91954b52172bc6860be.html
- 第6章 函数级链路走读(驱动到显示):https://laval.csdn.net/69d8b96854b52172bc6860cd.html
- 第7章 异常挂点与主链归因:https://laval.csdn.net/69d8b9d054b52172bc6860dc.html
- 第8章 调试方法与证据模板:https://laval.csdn.net/69d8ba1454b52172bc6860e4.html
- 第9章 实战演练与复盘:https://laval.csdn.net/69d8ba4754b52172bc6860f3.html
更多推荐
所有评论(0)