前言
最近在搞8581的camera问题,作为一个新手从没有做过camera部分,希望通过这一系列的文章记录自己学习过程。
大量参考大神的文章:【Camera专题】你应该熟悉的Camera驱动框架一(Hal层->kernel层)_justXiaoSha的博客-CSDN博客
一、hal层open流程
我们首先从 CameraDevice::open 开始
idh.code\vendor\sprd\interfaces\camera\device\3.2\default
Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback,
ICameraDevice::open_cb _hidl_cb) {
Status status = initStatus();
sp<CameraDeviceSession> session = nullptr;
/** Open HAL device */
status_t res;
camera3_device_t *device;
res = mModule->open(mCameraId.c_str(),
reinterpret_cast<hw_device_t**>(&device));
struct camera_info info;
res = mModule->getCameraInfo(mCameraIdInt, &info);
//mModule 的初始化在文章1中有介绍 bool LegacyCameraProviderImpl_2_4::initialize()中初始化
session = createSession(
device, info.static_camera_characteristics, callback);
mSession = session;
}
这里主要是:
1)、mModule->open 就是 open camera 的 hal,要注意这参数 device 是把 camera3_device_t * 强转成 hw_device_t**。
2)、createSession 创建一个sp的对象,这里会调用 initialize 接口。
这一篇主要介绍 open 的流程
vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3Factory.cpp
vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3Factory.cpp
struct hw_module_methods_t SprdCamera3Factory::mModuleMethods = {
.open = SprdCamera3Factory::camera_device_open,
};
int SprdCamera3Factory::camera_device_open(const struct hw_module_t *module,
const char *id,
struct hw_device_t **hw_device) {
if (isSingleIdExposeOnMultiCameraMode(atoi(id))) {
return gSprdCamera3Wrapper->cameraDeviceOpen(module, id, hw_device);
} else {
return gSprdCamera3Factory.cameraDeviceOpen(atoi(id), hw_device);
}
}
这里open a camera device by its ID,通过ID来打开摄像头(后主摄:0 后副摄:2 前主摄:1 前副摄:3)
接着继续调用gSprdCamera3Factory.cameraDeviceOpen();
int SprdCamera3Factory::cameraDeviceOpen(int camera_id,
struct hw_device_t **hw_device) {
SprdCamera3HWI *hw =
new SprdCamera3HWI(multiCameraModeIdToPhyId(camera_id));
//这里new一个对象,在构造函数里面初始化这个common
//mCameraDevice.common.tag = HARDWARE_DEVICE_TAG;
//mCameraDevice.common.version = CAMERA_DEVICE_API_VERSION_3_2;
//mCameraDevice.common.close = close_camera_device;
//mCameraDevice.ops = &mCameraOps;
//mCameraDevice.priv = this;
//这ops很重要
rc = hw->openCamera(hw_device);
return rc;
}
这里new了一个 SprdCamera3HWI 的实例,然后调用 openCamera(hw_device) 方法。
这里有个注意点就是 new SprdCamera3HWI时会初始化 mCameraDevice,通过参数返回 common成员的地址,这个 common 是 struct camera3_device_t 的第一个成员变量,
所以做一下类型转换就相当于传了一个 camera3_device_t 回去。还一个比较重要的是获取到了mCameraOps 操作函数集。
vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3HWI.cpp
int SprdCamera3HWI::openCamera(struct hw_device_t **hw_device) {
ret = openCamera();
if (ret == 0) {
//mCameraDevice 的初始化是在 SprdCamera3HWI 的构造函数里面
*hw_device = &mCameraDevice.common;
mCameraSessionActive++;
} else
*hw_device = NULL;
return ret;
}
接着继续调用空构造方法openCamera();
int SprdCamera3HWI::openCamera() {
···
//new SprdCamera3Setting的实例
mSetting = new SprdCamera3Setting(mCameraId);
//new SprdCamera3OEMIf的实例,这里会加载libcamoem.so库,同时mHalOem->ops = omi->ops = oem_module_ops;
mOEMIf = new SprdCamera3OEMIf(mCameraId, mSetting);
mOEMIf->camera_ioctrl(CAMERA_IOCTRL_SET_MULTI_CAMERAMODE, &mMultiCameraMode,
NULL);
//打开mOEMIf->openCamera()方法
ret = mOEMIf->openCamera();
mCameraOpened = true;
···
return NO_ERROR;
}
这里new SprdCamera3OEMIf的实例,继续调用mOEMIf->openCamera()方法。
vendor/sprd/modules/libcamera/hal3_2v6/SprdCamera3OEMIf.cpp
int SprdCamera3OEMIf::openCamera() {
//获取宽和高
mSetting->getLargestPictureSize(mCameraId, &picW, &picH);
mSetting->getLargestSensorSize(mCameraId, &snsW, &snsH);
if (picW * picH > snsW * snsH) {
mLargestPictureWidth = picW;
mLargestPictureHeight = picH;
} else {
mLargestPictureWidth = snsW;
mLargestPictureHeight = snsH;
}
//设置最大尺寸
mHalOem->ops->camera_set_largest_picture_size(
mCameraId, mLargestPictureWidth, mLargestPictureHeight);
//进行初始化,初始化mCameraHandle,mCameraHandle相当于libcamoem.so或者cmr的一个句柄
ret = mHalOem->ops->camera_init(mCameraId, camera_cb, this, 0,
&mCameraHandle, (void *)Callback_Malloc,
(void *)Callback_Free);
//获取抓取能力,包含3dnr能力
mHalOem->ops->camera_ioctrl(
mCameraHandle, CAMERA_IOCTRL_GET_GRAB_CAPABILITY, &grab_capability);
/*从oem层获取传感器和镜头信息*/
mHalOem->ops->camera_get_sensor_exif_info(mCameraHandle, &exif_info);
mSetting->getLENSTag(&lensInfo);
lensInfo.aperture = exif_info.aperture;
mSetting->setLENSTag(lensInfo);
//从oem层获取传感器otp
mSetting->getOTPTag(&otpInfo);
mHalOem->ops->camera_get_sensor_otp_info(mCameraHandle, dual_flag,
&otp_info);
/**添加3d校准,获取最大传感器尺寸*/
sprddefInfo = mSetting->getSPRDDEFTagPTR();
mHalOem->ops->camera_get_sensor_info_for_raw(mCameraHandle, mode_info);
//零延时模式线程初始化
ZSLMode_monitor_thread_init((void *)this);
#ifdef CONFIG_CAMERA_GYRO
gyro_monitor_thread_init((void *)this);
#endif
property_get("persist.sys.camera.raw.mode", value, "jpeg");
if (!strcmp(value, "raw") || !strcmp(value, "bin")) {
is_raw_capture = 1;
}
}
SprdCamera3OEMIf::openCamera主要做了以下事情:
mHalOem->ops = oem_module_ops,vendor/sprd/modules/libcamera/oem2v6/src/SprdOEMCamera.c
设置图像的最大尺寸
调用 camera_init 继续启动摄像头,mCameraHandle初始化
零延时模式线程初始化
根据 persist.sys.camera.raw.mode 设置属性
通过mHalOem->ops->camera_init最终会调用到SprdOEMCamera.c代码的camera_init进行初始化
vendor/sprd/modules/libcamera/oem2v6/src/SprdOEMCamera.c
cmr_int camera_init(cmr_u32 camera_id, camera_cb_of_type callback,
void *client_data, cmr_uint is_autotest,
cmr_handle *camera_handle, void *cb_of_malloc,
void *cb_of_free) {
//调用camera_local_int继续进行初始化
ret = camera_local_int(camera_id, callback, client_data, is_autotest,
camera_handle, cb_of_malloc, cb_of_free);
//其他的一些初始化
camera_lls_enable(*camera_handle, 0);
camera_set_lls_shot_mode(*camera_handle, 0);
camera_vendor_hdr_enable(*camera_handle, 0);
return ret;
}
vendor/sprd/modules/libcamera/oem2v6/src/cmr_oem.c
cmr_int camera_local_int(cmr_u32 camera_id, camera_cb_of_type callback,
void *client_data, cmr_uint is_autotest,
cmr_handle *oem_handle, void *cb_of_malloc,
void *cb_of_free) {
···
//内存申请
struct camera_context *cxt = NULL;
*oem_handle = (cmr_handle)0;
cxt = (struct camera_context *)malloc(sizeof(struct camera_context));
//参数赋值
cmr_bzero(cxt, sizeof(*cxt));
cxt->camera_id = camera_id;
cxt->camera_cb = callback; //后面上送数据的回调要使用
cxt->client_data = client_data; //client_data是SprdCamera3OEMIf的对象
cxt->hal_malloc = cb_of_malloc;
cxt->hal_free = cb_of_free;
cxt->hal_gpu_malloc = NULL;
cxt->is_multi_mode = is_multi_camera_mode_oem;
cxt->blur_facebeauty_flag = 0;
//调用camera_init_internal进行下一步初始化
ret = camera_init_internal((cmr_handle)cxt, is_autotest);
*oem_handle = (cmr_handle)cxt;
···
return ret;
}
这里重点关注一下 oem_handle 的初始化,就是赋值struct camera_context *cxt,还有回调函数camera_cb。
调用camera_init_internal进行下一步初始化
cmr_int camera_init_internal(cmr_handle oem_handle, cmr_uint is_autotest) {
···
//sensor初始化
ret = camera_sensor_init(oem_handle, is_autotest);
//grab初始化
ret = camera_grab_init(oem_handle);
//res初始化
ret = camera_res_init(oem_handle);
//isp初始化
ret = camera_isp_init(oem_handle);
//初始化完成
ret = camera_res_init_done(oem_handle);
//前置摄像头,lcd屏幕可以作为补光灯
camera_front_lcd_enhance_module_init(oem_handle);
···
return ret;
}
该函数主要做了以下事情:
sensor初始化
grab初始化
res初始化
isp初始化
我们先关注camera_sensor_init这个函数,其他的以后在分析
cmr_int camera_sensor_init(cmr_handle oem_handle, cmr_uint is_autotest) {
struct sensor_context *sn_cxt = NULL;
sn_cxt = &cxt->sn_cxt;
···
init_param.oem_handle = oem_handle;
//这里出现第二个context,sensor_context
ret = cmr_sensor_init(&init_param, &sensor_handle);
//这里可以看到senor_handle最终传到sn_cxt,通过camera_handle能找到sensor_handle
sn_cxt->sensor_handle = sensor_handle;
//这里继续open sensor
ret = cmr_sensor_open(sensor_handle, camera_id_bits);
cmr_sensor_event_reg(sensor_handle, cxt->camera_id, camera_sensor_evt_cb);
//struct cmr_sensor_handle *handle = (struct cmr_sensor_handle *)sensor_handle;
//handle->sensor_event_cb = event_cb;
cxt->sn_cxt.sensor_handle = sensor_handle;
sns_ex_info_ptr = &sn_cxt->cur_sns_ex_info;
ret = cmr_sensor_init_static_info(cxt);
···
}
该函数分别调用了 cmr_sensor_init 初始化和 cmr_sensor_open 打开Camera,下面分别介绍这几个函数。
这里出现一个常见的组合xxx_init和xxx_open,在init中设置一个工作函数,在open中传递信息,启动工作线程执行这个函数
1)cmr_sensor_init
vendor/sprd/modules/libcamera/oem2v6/src/cmr_sensor.c
cmr_int cmr_sensor_init(struct sensor_init_param *init_param_ptr,
cmr_handle *sensor_handle) {
struct cmr_sensor_handle *handle = NULL;
···
/*save init param*/
handle->oem_handle = init_param_ptr->oem_handle;
handle->sensor_bits = init_param_ptr->sensor_bits;
handle->private_data = init_param_ptr->private_data;
handle->is_autotest = init_param_ptr->is_autotest;
/*create thread*/
ret = cmr_sns_create_thread(handle);
*sensor_handle = (cmr_handle)handle;
···
return ret;
}
该函数 对一些参数进行赋值,然后调用cmr_sns_create_thread方法创建 cmr_sns_thread_proc 线程。
如下:
ret = cmr_thread_create(&handle->thread_cxt.thread_handle,
SENSOR_MSG_QUEUE_SIZE,cmr_sns_thread_proc,
(void *)handle)
通过handle->thread_cxt.thread_handle调用 cmr_sns_thread_proc
struct camera_context -----> struct sensor_context -----> (cmr_handle)struct cmr_sensor_handle
同时struct cmr_sensor_handle 也指向 struct camera_context
2)cmr_sensor_open
cmr_int cmr_sensor_open(cmr_handle sensor_handle, cmr_u32 sensor_id_bits) {
···
struct cmr_sensor_handle *handle =
(struct cmr_sensor_handle *)sensor_handle;
/*the open&close function should be sync*/
message.msg_type = CMR_SENSOR_EVT_OPEN;
message.sync_flag = CMR_MSG_SYNC_PROCESSED;
message.data = (void *)((unsigned long)sensor_id_bits);
//这里发送msg消息,去启动在cmr_sensor_init创建的
ret = cmr_thread_msg_send(handle->thread_cxt.thread_handle, &message);
···
return ret;
}
3)cmr_sensor_init_static_info
cmr_int cmr_sensor_init_static_info(cmr_handle oem_handle) {
...
val.type = SENSOR_VAL_TYPE_GET_STATIC_INFO;
val.pval = sns_ex_info_ptr;
ret = cmr_sensor_ioctl(cxt->sn_cxt.sensor_handle, cxt->camera_id,
SENSOR_ACCESS_VAL, (cmr_uint)&val);
...
}
cmr_int cmr_sensor_ioctl(cmr_handle sensor_handle, cmr_u32 sensor_id,
cmr_uint cmd, cmr_uint arg) {
...
ioctl_param.cmd = cmd;
ioctl_param.arg = arg;
/*the set mode function can be async control*/
message.msg_type = CMR_SENSOR_EVT_IOCTL;
message.sub_msg_type = sensor_id;
message.sync_flag = CMR_MSG_SYNC_PROCESSED;
message.data = (void *)malloc(sizeof(struct cmr_sns_ioctl_param));
cmr_copy(message.data, &ioctl_param, sizeof(struct cmr_sns_ioctl_param));
ret = cmr_thread_msg_send(handle->thread_cxt.thread_handle, &message);
...
}
在cmr_sensor_open中,发送了msg消息,去启动在cmr_sensor_init创建的线程cmr_sns_thread_proc。
这里的消息类型是message.msg_type = CMR_SENSOR_EVT_OPEN;
cmr_sensor_init_static_info中,发送了msg消息,去启动在cmr_sensor_init创建的线程cmr_sns_thread_proc。
这里的消息类型是message.msg_type = CMR_SENSOR_EVT_IOCTL;
cmr_int cmr_sns_thread_proc(struct cmr_msg *message, void *p_data) {//这个p_data就是creat这个proc时传递的p_data
···
switch (evt) {
case CMR_SENSOR_EVT_OPEN:
/*camera sensor open for every bits*/
ops_param = (cmr_u32)((unsigned long)message->data);
ret = cmr_sns_open(handle, ops_param);
case CMR_SENSOR_EVT_IOCTL: {
struct cmr_sns_ioctl_param *p_ioctl_param =
(struct cmr_sns_ioctl_param *)message->data;
camera_id = (cmr_u32)message->sub_msg_type;
CMR_LOGV("camera_id=%d", camera_id);
sensor_set_cxt_common(&handle->sensor_cxt[camera_id]);
cmr_sns_ioctl(&handle->sensor_cxt[camera_id], p_ioctl_param->cmd, p_ioctl_param->arg);
sns_ops = sensor_cxt->sensor_info_ptr->sns_ops;//这个sns_ops是镜头驱动的 static struct sensor_ic_ops s_se4770_ops_tab
sns_ops->ext_ops[sns_cmd].ops(sensor_cxt->sns_ic_drv_handle, arg);
se4770_drv_access_val
} break;
}
···
}
我们继续看cmr_sns_open方法。
cmr_int cmr_sns_open(struct cmr_sensor_handle *handle, cmr_u32 sensor_id_bits) {
/*open all signed camera sensor*/
for (cameraId = 0; cameraId < CAMERA_ID_MAX; cameraId++) {
if (0 != (sensor_id_bits & (1 << cameraId))) {
ret = sensor_open_common(&handle->sensor_cxt[cameraId], cameraId,
handle->is_autotest);
if (ret) {
CMR_LOGE("camera %u open failed!", cameraId);
} else {
handle->sensor_bits |= (1 << cameraId);
}
}
}
}
这里出现一个 sensor_cxt 类型是 struct sensor_drv_context
cmr_sns_open方法又继续调用 sensor_open_common 函数,初始化handle->sensor_cxt[cameraId],这个函数比较复杂,主要工作如下:
vendor/sprd/modules/libcamera/sensor/sensor_drv_u.c
cmr_int sensor_open_common(struct sensor_drv_context *sensor_cxt,
cmr_u32 sensor_id, cmr_uint is_autotest) {
···
ret = sensor_context_init(sensor_cxt, slot_id, is_autotest, 1);
ret = sensor_drv_open(sensor_cxt, slot_id);
···
return ret;
}
初始化ctx(sensor_drv_context)这个结构体
加载sensor file文件,里面保存了camera的id
根据sensor file里保存的camera 的id打开摄像头
1)、sensor_context_init
cmr_int sensor_context_init(struct sensor_drv_context *sensor_cxt,
cmr_u32 sensor_id, cmr_uint is_autotest,
cmr_int open_phase) {
//创建一个线程,通过sensor_cxt->ctrl_thread_cxt.thread_handle访问
ret = sensor_create_ctrl_thread(sensor_cxt);
//ret = cmr_thread_create(&sensor_cxt->ctrl_thread_cxt.thread_handle,
// SENSOR_CTRL_MSG_QUEUE_SIZE,
// sensor_ctrl_thread_proc, (void *)sensor_cxt);
input_ptr.sensor_id = sensor_id;
input_ptr.caller_handle = sensor_cxt;
//获取到驱动sprd_sensor的句柄hw_drv_handle,struct hw_drv_cxt
fd_sensor = hw_sensor_drv_create(&input_ptr, &hw_drv_handle);
//hw_drv_cxt = *hw_drv_handle;
//hw_drv_cxt->fd_sensor = SENSOR_FD_INIT;
//hw_drv_cxt->sensor_id = input_ptr->sensor_id;
//hw_drv_cxt->caller_handle = input_ptr->caller_handle;
//ret = _hw_sensor_dev_init(*hw_drv_handle, input_ptr->sensor_id);
//hw_drv_cxt->fd_sensor = open(HW_SENSOR_DEV_NAME, O_RDWR, 0);
//#define HW_SENSOR_DEV_NAME "/dev/sprd_sensor"
sensor_cxt->fd_sensor = fd_sensor;
sensor_cxt->hw_drv_handle = hw_drv_handle;
sensor_cxt->sensor_hw_handler = hw_drv_handle;
//这里是xml文件等配置信息
sensor_cxt->sensor_index = &devPtr->drv_idx[sensor_id];
sensor_cxt->xml_info = &xml_cfg_tab[sensor_id];
sensor_cxt->current_module = &sensor_cfg_tab[sensor_id];
sns_module = (SENSOR_INFO_T *)sensor_cxt->current_module;
sensor_cxt->sensor_info_ptr = sns_module->sensor_info;
}
这函数中有一个新的context,struct hw_drv_cxt sensor_cxt 这个是包含驱动节点sprd_sensor的句柄。这个函数在文章1中有介绍,在读取sensor id时,不过那时没有注册工作线程程序。还有这些静态变量就是在那个时候初始化的,现在就被用上了不用再来一遍。
static cmr_int sensor_drv_open(struct sensor_drv_context *sensor_cxt,
cmr_u32 sensor_id) {
//sns_ops = s_gc5035_ops_tab,
sns_ops = sensor_cxt->sensor_info_ptr->sns_ops;
sensor_cxt->sensor_isInit = SENSOR_TRUE;
//验证id,函数栈文章1中分析过就不再分析了
ret = sensor_drv_ic_identify(sensor_cxt, sensor_id, 0);
//对焦马达初始化
sensor_af_init(sensor_cxt);
ret = sensor_set_mode_msg(sensor_cxt, SENSOR_MODE_COMMON_INIT, is_inited);
//OTP的读取
sensor_otp_module_init(sensor_cxt);
module = sensor_cxt->current_module;
sensor_otp_rw_ctrl(sensor_cxt, OTP_READ_PARSE_DATA, 0, NULL);
sensor_set_otp_data(sensor_cxt);
sensor_otp_ops_t *otp_ops = PNULL;
otp_ops = &module->otp_drv_info.otp_drv_entry->otp_ops;
otp_ops->sensor_otp_ioctl(sensor_cxt->otp_drv_handle,
CMD_SNS_OTP_GET_VENDOR_ID,
(void *)&vendor_id);
sensor_set_raw_infor(sensor_cxt, vendor_id);
sensor_set_export_Info(sensor_cxt);
sensor_cxt->stream_on = 1;
sensor_stream_off(sensor_cxt);
//关流,防止上一次没有关流导致的影响
char value[PROPERTY_VALUE_MAX];
property_get("ro.fac.cfg.CAMERA_NUMBER", value, "2");
if(sensor_id < atoi(value))
property_set( "sys.camera.running", "1" );
};
这个函数主要时操作和很多sensor、af、otp的相关驱动,这里暂时不分析了。
到这里整个open的流程就结束了。
补充知识:给线程传递数据的同步标志sync_flag的作用
enum {
CMR_MSG_SYNC_NONE = 0, 数据送出继续执行
CMR_MSG_SYNC_RECEIVED, 线程收到数据再继续
CMR_MSG_SYNC_PROCESSED, 线程执行完成在继续
};
总结
这一篇主要是沿着open 这条主线在分析代码,这里有很多context 很容易弄的头晕。