3. 打开摄像头设备
任务说明
本案例实现 Camera HAL 层设备打开的核心逻辑:编写 open 函数,完成 camera_device_t 实例的创建、硬件接口初始化,并返回设备指针供上层调用。该函数对应 HAL 模块中 hw_module_methods_t::open 的回调实现,是上层通过 hw_get_module 获取摄像头设备后的第一个调用入口。
核心代码实现
// camera_hal_device.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hardware/hardware.h>
#include <hardware/camera_common.h>
#include <cutils/log.h>
// 硬件接口操作集(本案例仅实现 open/close 的最小闭环)
static int camera_device_close(struct hw_device_t* device) {
if (device == NULL) return -EINVAL;
camera_device_t* cam_dev = (camera_device_t*)device;
camera_device_ops_t* ops = cam_dev->ops;
// 释放内部资源(此处为最小实现,仅做空指针保护)
if (ops != NULL) {
free(ops);
cam_dev->ops = NULL;
}
free(cam_dev);
ALOGI("camera device closed and freed");
return 0;
}
// 设备打开入口:创建实例、绑定 ops、初始化硬件接口
static int camera_device_open(const hw_module_t* module, const char* id,
hw_device_t** device) {
if (module == NULL || id == NULL || device == NULL) {
ALOGE("invalid argument: module=%p id=%p device=%p", module, id, device);
return -EINVAL;
}
// 1. 分配 camera_device_t 实例
camera_device_t* cam_dev = (camera_device_t*)calloc(1, sizeof(camera_device_t));
if (cam_dev == NULL) {
ALOGE("failed to alloc camera_device_t");
return -ENOMEM;
}
// 2. 分配并填充 ops 操作集(当前仅注册 close,其余按业务扩展)
camera_device_ops_t* ops = (camera_device_ops_t*)calloc(1, sizeof(camera_device_ops_t));
if (ops == NULL) {
ALOGE("failed to alloc camera_device_ops_t");
free(cam_dev);
return -ENOMEM;
}
ops->close = camera_device_close;
// 3. 初始化公共 hw_device_t 字段
cam_dev->common.tag = HARDWARE_DEVICE_TAG;
cam_dev->common.version = CAMERA_DEVICE_API_VERSION_1_0;
cam_dev->common.module = (hw_module_t*)module;
cam_dev->common.close = camera_device_close;
cam_dev->ops = ops;
// 4. 初始化硬件接口(此处以模拟寄存器基址为例,实际项目替换为真实硬件访问)
// 真实场景:映射寄存器地址、配置 I2C/CSI 引脚、上电时序等
cam_dev->priv = NULL; // 私有数据指针,可存放硬件上下文
ALOGI("camera device opened, id=%s", id);
*device = &cam_dev->common;
return 0;
}
// HAL 模块方法表(导出符号)
static hw_module_methods_t camera_module_methods = {
.open = camera_device_open,
};
// 模块实例(实际项目中由 hw_get_module 按名称加载)
struct camera_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = CAMERA_MODULE_API_VERSION_1_0,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "Camera HAL Module",
.author = "CodeCase",
.methods = &camera_module_methods,
},
};
关键实现说明
上述代码完成了 open 回调的完整链路:camera_device_open 接收上层传入的 module、设备 id 和输出参数 device。函数内部依次完成三件事:分配 camera_device_t 结构体内存;分配并填充 camera_device_ops_t 操作集(当前注册 close 回调);初始化公共 hw_device_t 字段(tag、version、module 指针、close 函数指针)。最后将 cam_dev->common 的地址写入 *device 返回给调用者。
硬件接口初始化在代码中以 priv 字段预留位置,并注释标明真实场景需要完成的寄存器映射、引脚配置等操作。这是刻意的最小化设计——本案例聚焦于 HAL 设备对象的创建与返回路径,不展开具体传感器驱动细节。
编译与验证
# 编译(假设 Android 源码环境已就绪)
mmm hardware/libhardware/modules/camera/
# 或直接编译当前目录
mm -j8
验证方法:在 Android 系统启动后,通过 adb shell 执行以下命令触发 HAL 模块加载与设备打开:
# 查看 HAL 模块是否被系统识别
adb shell ls /system/lib/hw/camera.*.so
# 使用 v4l2 或 CameraService 日志确认 open 被调用
adb logcat -s CameraHAL
判定标准:logcat 中出现 camera device opened 日志,且无 invalid argument 或 failed to alloc 报错,说明 open 函数成功创建了设备实例并返回了有效的 camera_device_t 指针。若上层继续调用 close,应看到 camera device closed and freed 日志,表明资源释放路径正常。