近期在排查打开相机黑屏的问题,然后就跟了一下android camera的框架。根据log分析发现是camera个数为0,然后就进行代码流程跟踪。由于开发平台是mtk平台,log提示上层报错的对应代码逻辑如下图。
mCameraService是ICameraService接口类型。
获取服务的名称如下:
并且是通过aidl跟底层c++通信。
frameworks/base/core/java/android/hardware/ICameraService.aidl
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware;
import android.hardware.ICamera;
import android.hardware.ICameraClient;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.utils.BinderHolder;
import android.hardware.ICameraServiceListener;
import android.hardware.CameraInfo;
/**
* Binder interface for the native camera service running in mediaserver.
*
* @hide
*/
interface ICameraService
{
/**
* Keep up-to-date with frameworks/av/include/camera/ICameraService.h
*/
int getNumberOfCameras(int type);
// rest of 'int' return values in this file are actually status_t
int getCameraInfo(int cameraId, out CameraInfo info);
int connect(ICameraClient client, int cameraId,
String opPackageName,
int clientUid,
// Container for an ICamera object
out BinderHolder device);
int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
String opPackageName,
int clientUid,
// Container for an ICameraDeviceUser object
out BinderHolder device);
int addListener(ICameraServiceListener listener);
int removeListener(ICameraServiceListener listener);
int getCameraCharacteristics(int cameraId, out CameraMetadataNative info);
/**
* The java stubs for this method are not intended to be used. Please use
* the native stub in frameworks/av/include/camera/ICameraService.h instead.
* The BinderHolder output is being used as a placeholder, and will not be
* well-formatted in the generated java method.
*/
int getCameraVendorTagDescriptor(out BinderHolder desc);
// Writes the camera1 parameters into a single-element array.
int getLegacyParameters(int cameraId, out String[] parameters);
// Determines if a particular API version is supported; see ICameraService.h for version defines
int supportsCameraApi(int cameraId, int apiVersion);
int connectLegacy(ICameraClient client, int cameraId,
int halVersion,
String opPackageName,
int clientUid,
// Container for an ICamera object
out BinderHolder device);
int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
/**
* Notify the camera service of a system event. Should only be called from system_server.
*
* Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
*/
oneway void notifySystemEvent(int eventId, in int[] args);
// atc aosp enhancement: cvbs camera , cvbs format detect.
int atcSetCameraInfoUpdateFlag(int flag);
}
当时我们公司的应用开发工程师打开相机时会进行摄像头探测,通过调用framework的aidl接口去调用mCameraService.getNumberOfCameras()探测camera个数,总的流程会通过三部分讲解。分别为framework层,native层,driver层三部分。
一:framework层
注意:CarmerServiceDetector中的mCameraService是直接通过aidl调用到c++的CameraSevice服务的。具体代码如下:
private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
......//代表中间有很多代码
mCameraService = ICameraService.Stub.asInterface(ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME));
我们看下CameraSevice.cpp是如何启动注册服务以及完成ICameraService.aidl的接口调用的。
//代码路径:frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char** argv)
{
......//代表中间走过了很多代码
//相机服务开始初始化并注册
CameraService::instantiate();
.....
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
}
class CameraService :
public BinderService<CameraService>,
public BnCameraService,
public IBinder::DeathRecipient,
public camera_module_callbacks_t
{
friend class BinderService<CameraService>;
public:
class Client;
class BasicClient;
......
// 获取注册服务的名字,提供上层aidl找到该服务
static char const* getServiceName() { return "media.camera"; }
.....
}
注意:在instantiate函数中,将CameraService注册到系统的binder service列表中,这样以后上层java就可以通过aid调到CameraService提供的方法了。并且我们可以通过注册CameraService时会调用getServiceName名字注册跟上层ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME)时的名字都是media.camera可得知CameraService便正是上层通过aidl调用c++服务。
二:HAL层
经过上面的调用过程最终调用到mtk的carmer hal层,至于怎么调用到这里的,写过adroid hal层的都应该大概知道。
//path:vendor/mediatek/proprietary/hardware/mtkcam/legacy/module_hal/module/module.h
static
int
get_number_of_cameras(void)
{
return NSCam::getCamDeviceManager()->getNumberOfDevices();
}
//path:vendor/mediatek/proprietary/hardware/mtkcam/common/include/device/ICamDeviceManager.h
#ifndef _MTK_HARDWARE_INCLUDE_MTKCAM_DEVICE_ICAMDEVICEMANAGER_H_
#define _MTK_HARDWARE_INCLUDE_MTKCAM_DEVICE_ICAMDEVICEMANAGER_H_
//
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
//
#include <hardware/camera_common.h>
#include <common.h>
.....
namespace NSCam {
class ICamDevice;
class ICamDeviceManager
{
...
};
ICamDeviceManager* getCamDeviceManager();//返回一个ICamDeviceManager类型对象
}; //namespace NSCam
#endif //_MTK_HARDWARE_INCLUDE_MTKCAM_DEVICE_ICAMDEVICEMANAGER_H_
查看具体getCamDeviceManager实现,可知返回就只有返回CamDeviceManagerImp类型指针。
//path:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt3561m/devicemgr/CamDeviceManagerImp.cpp
namespace
{
CamDeviceManagerImp gCamDeviceManager;
} //namespace
namespace NSCam {
ICamDeviceManager*
getCamDeviceManager()
{
return &gCamDeviceManager;//返回CamDeviceManagerImp类型函数
}
}
CamDeviceManagerImp的声明,继承CamDeviceManagerBase
//path:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt3561m/devicemgr/CamDeviceManagerImp.h
class CamDeviceManagerImp : public CamDeviceManagerBase
{
public: Instantiation.
CamDeviceManagerImp();
protected: Operations.
virtual android::status_t validateOpenLocked(
int32_t i4OpenId,
uint32_t device_version
) const;
virtual int32_t enumDeviceLocked();
virtual android::status_t setTorchModeLocked(
int const deviceId,
bool enabled,
bool notifyEvent);
virtual android::status_t setTorchAvailableLocked(
int const deviceId,
bool available);
};
从上面CamDeviceManagerImp的类看出,其并没有定义方法getNumberOfDevices,但是继承了CamDeviceManagerBase,所以很有可能getNumberOfDevices是getNumberOfDevices的方法。跟踪代码发现如下,果然如此。
//path:vendor/mediatek/proprietary/hardware/mtkcam/legacy/module_hal/devicemgr/CamDeviceManagerBase.cpp
int32_t
CamDeviceManagerBase::
getNumberOfDevices()
{
RWLock::AutoWLock _l(mRWLock);
//
if ( 0 != mi4DeviceNum )
{
MY_LOGD("#devices:%d", mi4DeviceNum);//返回支持摄像头个数。一般来说初始化过一次后就得到支持的camera个数了。
}
else
{
//第一次开机启动一般通过走这里去获取支持camera的数量
Utils::CamProfile _profile(__FUNCTION__, "CamDeviceManagerBase");
mi4DeviceNum = enumDeviceLocked();
_profile.print("");
}
//
return mi4DeviceNum;
}
下面我们通过uml图来说明下调用流程:
最后camera hal层会通过ioctl去访问底层驱动,并且检测camera的sensor id是否有效,有效数目便是支持返回的camera个数。代码逻辑如下:
//path:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt3561m/hal/sensor/imgsensor_drv.cpp
MINT32
ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)
{
......
for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {
//end of driver list
if (m_pstSensorInitFunc[i].getCameraDefault == NULL) {
LOG_MSG("m_pstSensorInitFunc[i].getCameraDefault is NULL: %d \n", i);
break;
}
//set sensor driver
id[KDIMGSENSOR_INVOKE_DRIVER_0] = (SensorEnum << KDIMGSENSOR_DUAL_SHIFT) | i;
LOG_MSG("set sensor driver id =%x\n", id[KDIMGSENSOR_INVOKE_DRIVER_0]);
//通过ioctl初始化camera sensor驱动
err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
if (err < 0) {
LOG_ERR("ERROR:KDCAMERAHWIOC_X_SET_DRIVER\n");
}
//通过ioctl去检测camera sensor是否有效
//err = open();
err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
if (err < 0) {
LOG_MSG("[impSearchSensor] Err-ctrlCode (%s) \n", strerror(errno));
}
}
......
}
三:内核driver层
1.利用cmd命令KDIMGSENSORIOC_X_SET_DRIVER通过ioctl初始化sensor驱动,
//hal层的代码调用
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt3561/kd_sensorlist.c
err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
static long CAMERA_HW_Ioctl(struct file *a_pstFile,
unsigned int a_u4Command, unsigned long a_u4Param)
{
pIdx = (u32 *) pBuff;
switch (a_u4Command) {
case KDIMGSENSORIOC_X_SET_DRIVER:
i4RetValue = kdSetDriver((unsigned int *)pBuff);
}
}
int kdSetDriver(unsigned int *pDrvIndex)
{
......
//(1)初始化pSensorList指针,指向sensor驱动数组ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT //kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1]
if (0 != kdGetSensorInitFuncList(&pSensorList)) {
PK_ERR("ERROR:kdGetSensorInitFuncList()\n");
return -EIO;
}
//(2)调用pSensorList指向的ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT类型中的SensorInit进行初始化。
pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);
......
}
分两部讲,第一步就是(1)初始化pSensorList指针,指向sensor驱动数组ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] ,来看下实现具体过程
UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{
if (NULL == ppSensorList) {
PK_ERR("[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n");
return 1;
}
*ppSensorList = &kdSensorList[0];//执行kdSensorList数组的标号0,也就是开始地址。
return 0;
} /* kdGetSensorInitFuncList() */
可以看到传进来的参数指针指向了kdSensorList数组的标号0,也就是该数组的开始地址,kdSensorList的定义如下:
//path:kernel-3.18/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_define.h
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT的声明:
typedef struct {
MUINT32 SensorId;
MUINT8 drvname[32];
MUINT32(*SensorInit)(PSENSOR_FUNCTION_STRUCT *pfFunc);
} ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT, *PACDK_KD_SENSOR_INIT_FUNCTION_STRUCT;
//path:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt3561m/kd_sensorlist.h
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
{
#if defined(OV8825_MIPI_RAW)
{OV8825_SENSOR_ID, SENSOR_DRVNAME_OV8825_MIPI_RAW, OV8825_MIPI_RAW_SensorInit},
#endif
......
#if defined(RN6752_YUV)
{RN6752_SENSOR_ID, SENSOR_DRVNAME_RN6752_YUV, RN6752_YUV_SensorInit},
#endif
......
/* ADD sensor driver before this line */
{0,{0},NULL}, //end of list
};
可以看出kdSensorList是各个sensor型号驱动初始化结构体的数组。例如上面支持的RN6752_YUV型号的sensor驱动的初始化函数RN6752_YUV_SensorInit。
//RN6752_YUV sensor驱动的操作集合
SENSOR_FUNCTION_STRUCT SensorFuncRN6752 =
{
RN6752Open,
RN6752GetInfo,
RN6752GetResolution,
RN6752FeatureControl,
RN6752Control,
RN6752Close,
RN6752_Get_SignalStatus
};
//RN6752_YUV sensor 驱动初始化
UINT32 RN6752_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
{
/* To Do: check sensor status here */
//LOG_INF("Sensor init enter\n");
if (pfFunc != NULL)
*pfFunc = &SensorFuncRN6752;
return ERROR_NONE;
} /* SensorInit() */
(2)上面第一步对pSensorList赋值后,接下来就可以调用sensor驱动的初始化获取sensor驱动的操作集合,如下:
pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);
最终便会执行到上面kdSensorList数组里面对应初始化函数,例如RN6752_YUV型号的sensor驱动的初始化函数RN6752_YUV_SensorInit,从下面初始化函数的逻辑得出执行完初始化函数后参数g_pInvokeSensorFunc数组中将会储存者RN6752_YUV型号的sensor驱动操作集合SensorFuncRN6752的地址。记住g_pInvokeSensorFunc这个变量后面会用到。
UINT32 RN6752_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
{
/* To Do: check sensor status here */
//LOG_INF("Sensor init enter\n");
if (pfFunc != NULL)
*pfFunc = &SensorFuncRN6752;
return ERROR_NONE;
} /* SensorInit() */
2.利用KDIMGSENSORIOC_T_CHECK_IS_ALIVE命令通过ioctl来获取sensor id值。
上面说完了sensor驱动的初始化完后,将会调用KDIMGSENSORIOC_T_CHECK_IS_ALIVE命令通过ioctl来检测sensor id的值。
err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
驱动层代码如下:
case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
i4RetValue = adopt_CAMERA_HW_CheckIsAlive();
static inline int adopt_CAMERA_HW_CheckIsAlive(void)
{
......
if (g_pSensorFunc) {
for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
if (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) {
//次数通过sensorID变量获取sensor id的值
err = g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i], SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *)&sensorID, &retLen);
if (sensorID == 0) { /* not implement this feature ID */
PK_DBG(" Not implement!!, use old open function to check\n");
err = ERROR_SENSOR_CONNECT_FAIL;
} else if (sensorID == 0xFFFFFFFF) { /* fail to open the sensor */
PK_DBG(" No Sensor Found");
err = ERROR_SENSOR_CONNECT_FAIL;
} else {
PK_INF(" Sensor found ID = 0x%x\n", sensorID);
snprintf(mtk_ccm_name, sizeof(mtk_ccm_name), "%s CAM[%d]:%s;", mtk_ccm_name, g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);
err = ERROR_NONE;
}
if (ERROR_NONE != err) {
PK_DBG("ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n");
}
}
}
}
......
}
上面主要通过
err = g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i], SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *)&sensorID, &retLen);获取sensor id的值,查找g_pSensorFunc的定义赋值如下:
//path:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt3561/kd_sensorlist.c
static MULTI_SENSOR_FUNCTION_STRUCT2 *g_pSensorFunc = &kd_MultiSensorFunc;
MULTI_SENSOR_FUNCTION_STRUCT2 kd_MultiSensorFunc = {
kd_MultiSensorOpen,
kd_MultiSensorGetInfo,
kd_MultiSensorGetResolution,
kd_MultiSensorFeatureControl,
kd_MultiSensorControl,
kd_MultiSensorClose
};
//MULTI_SENSOR_FUNCTION_STRUCT2的类型声明
//path:kernel-3.18/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_define.h
typedef struct {
MUINT32(*SensorOpen)(void);
MUINT32(*SensorGetInfo)(MUINT32 *pScenarioId[2], MSDK_SENSOR_INFO_STRUCT * pSensorInfo[2], MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData[2]);
MUINT32(*SensorGetResolution)(MSDK_SENSOR_RESOLUTION_INFO_STRUCT * pSensorResolution[2]);
MUINT32(*SensorFeatureControl)(CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera, MSDK_SENSOR_FEATURE_ENUM FeatureId, MUINT8 *pFeaturePara, MUINT32 *pFeatureParaLen);
MUINT32(*SensorControl)(CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera, MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData);
MUINT32(*SensorClose)(void);
} MULTI_SENSOR_FUNCTION_STRUCT2, *PMULTI_SENSOR_FUNCTION_STRUCT2;
从上面可以的得知g_pSensorFunc->SensorFeatureControl调用的是kd_MultiSensorFeatureControl函数。kd_MultiSensorFeatureControl定义如下:
MUINT32
kd_MultiSensorFeatureControl(
CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera,
MSDK_SENSOR_FEATURE_ENUM FeatureId,
MUINT8 *pFeaturePara,
MUINT32 *pFeatureParaLen)
{
MUINT32 ret = ERROR_NONE;
u32 i = 0;
KD_MULTI_FUNCTION_ENTRY();
for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) {
if (InvokeCamera == g_invokeSocketIdx[i]) {
.....
//这里是主要的调用,获取sensor id值
ret = g_pInvokeSensorFunc[i]->SensorFeatureControl(FeatureId, pFeaturePara, pFeatureParaLen);
if (ERROR_NONE != ret) {
PK_ERR("[%s]\n", __func__);
return ret;
}
}
}
}
KD_MULTI_FUNCTION_EXIT();
return ERROR_NONE;
}
上面可以看出主要是通过ret = g_pInvokeSensorFunc[i]->SensorFeatureControl(FeatureId, pFeaturePara, pFeatureParaLen);来获取sensor id值,注意g_pInvokeSensorFunc这个指针是不是很熟悉,没错就是前面我们初始化sensor驱动的时候那个指针,所以这里调用 g_pInvokeSensorFunc[i]->SensorFeatureControl其实调用了具体的sensor型号的操作结合里面的SensorFeatureControl。上面我们所说的RN6752_YUV型号的sensor,那么这里调用的是RN6752FeatureControl。
//RN6752_YUV sensor驱动的操作集合
SENSOR_FUNCTION_STRUCT SensorFuncRN6752 =
{
RN6752Open,
RN6752GetInfo,
RN6752GetResolution,
RN6752FeatureControl,
RN6752Control,
RN6752Close,
RN6752_Get_SignalStatus
};
具体代码如下:这里在获取sensor id的时候传进来的FeatureId是SENSOR_FEATURE_CHECK_SENSOR_ID,因此会调用到RN6752GetSensorId(pFeatureData32)。
UINT32 RN6752FeatureControl(MSDK_SENSOR_FEATURE_ENUM FeatureId,
UINT8 *pFeaturePara,UINT32 *pFeatureParaLen)
{
UINT16 *pFeatureReturnPara16 = (UINT16 *) pFeaturePara;
UINT16 *pFeatureData16 = (UINT16 *) pFeaturePara;
UINT32 *pFeatureReturnPara32 = (UINT32 *) pFeaturePara;
UINT32 *pFeatureData32 = (UINT32 *) pFeaturePara;
//unsigned long long **pp64FeaturePara = (unsigned long long **)pFeaturePara;
MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData = (MSDK_SENSOR_CONFIG_STRUCT *) pFeaturePara;
MSDK_SENSOR_REG_INFO_STRUCT *pSensorRegData = (MSDK_SENSOR_REG_INFO_STRUCT *) pFeaturePara;
switch (FeatureId) {
case SENSOR_FEATURE_GET_RESOLUTION:
*pFeatureReturnPara16++ = input_source_width;
*pFeatureReturnPara16 = input_source_height;
*pFeatureParaLen = 4;
break;
case SENSOR_FEATURE_GET_PERIOD:
*pFeatureReturnPara16++ = input_source_width;
*pFeatureReturnPara16 = input_source_height;
*pFeatureParaLen = 4;
break;
case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ:
*pFeatureReturnPara32 = 27000000;
*pFeatureParaLen = 4;
break;
case SENSOR_FEATURE_SET_ESHUTTER:
break;
case SENSOR_FEATURE_SET_NIGHTMODE:
RN6752NightMode((BOOL) *pFeatureData16);
break;
case SENSOR_FEATURE_SET_GAIN:
break;
case SENSOR_FEATURE_SET_FLASHLIGHT:
break;
case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ:
RN6752_isp_master_clock = *pFeatureData32;
break;
case SENSOR_FEATURE_SET_REGISTER:
RN6752_write_cmos_sensor(pSensorRegData->RegAddr, pSensorRegData->RegData);
break;
case SENSOR_FEATURE_GET_REGISTER:
pSensorRegData->RegData = RN6752_read_cmos_sensor(pSensorRegData->RegAddr);
break;
case SENSOR_FEATURE_GET_CONFIG_PARA:
memcpy(pSensorConfigData, &RN6752SensorConfigData, sizeof(MSDK_SENSOR_CONFIG_STRUCT));
*pFeatureParaLen = sizeof(MSDK_SENSOR_CONFIG_STRUCT);
break;
case SENSOR_FEATURE_SET_CCT_REGISTER:
case SENSOR_FEATURE_SET_ENG_REGISTER:
case SENSOR_FEATURE_GET_REGISTER_DEFAULT:
case SENSOR_FEATURE_CAMERA_PARA_TO_SENSOR:
case SENSOR_FEATURE_SENSOR_TO_CAMERA_PARA:
case SENSOR_FEATURE_GET_GROUP_COUNT:
*pFeatureReturnPara32++ = 0;
*pFeatureParaLen = 4;
break;
case SENSOR_FEATURE_GET_GROUP_INFO:
case SENSOR_FEATURE_GET_ITEM_INFO:
case SENSOR_FEATURE_SET_ITEM_INFO:
case SENSOR_FEATURE_GET_ENG_INFO:
break;
case SENSOR_FEATURE_GET_LENS_DRIVER_ID:
// get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE
// if EEPROM does not exist in camera module.
*pFeatureReturnPara32 = LENS_DRIVER_ID_DO_NOT_CARE;
*pFeatureParaLen = 4;
break;
case SENSOR_FEATURE_SET_YUV_CMD:
RN6752YUVSensorSetting((FEATURE_ID)*pFeatureData32, *(pFeatureData32+1));
break;
case SENSOR_FEATURE_SET_VIDEO_MODE:
RN6752YUVSetVideoMode(*pFeatureData16);
case SENSOR_FEATURE_CHECK_SENSOR_ID:
RN6752GetSensorId(pFeatureData32);
break;
case SENSOR_FEATURE_GET_DELAY_INFO:
//LOG_INF("SENSOR_FEATURE_GET_DELAY_INFO\n");
//RN6752YUVGetDelayInfo((uintptr_t)*pp64FeaturePara);
break;
case SENSOR_FEATURE_GET_INTERLACE_FLAG:
if (source_format == PAL || source_format == NTSC){
*pFeatureReturnPara32 = 1;
} else {
*pFeatureReturnPara32 = 0;
}
*pFeatureParaLen = 8;
LOG_INF("*pFeatureReturnPara32: %d\n", *pFeatureReturnPara32);
break;
case SENSOR_FEATURE_SET_VIDEO_CHANNEL:
RN6752_Set_Video_Channel(*pFeatureData16);
LOG_INF("Richard *pFeatureData16: %d\n", *pFeatureData16);
break;
default:
break;
}
return ERROR_NONE;
}
RN6752GetSensorId(pFeatureData32);的实现:
UINT32 RN6752GetSensorId(UINT32 *sensorId)
{
int retry = 3;
do {
//获取sernsor id。主要是通过i2c获取0xfe寄存器的值与0xfd寄存器的值
*sensorId = ((RN6752_read_cmos_sensor(0xfe) << 8) | RN6752_read_cmos_sensor(0xfd));
LOG_ERR("WFH: sensor id = 0x%x", *sensorId);
if (*sensorId == SENSOR_ID)
break;
retry--;
} while (retry > 0);
if (*sensorId != SENSOR_ID) {
*sensorId = 0xFFFFFFFF;
return ERROR_SENSOR_CONNECT_FAIL;
}
if (false == bRN6752_Inputsource_Format_Detected) {
//RN6752ForceUpdateCVBSFormat();
RN6752_PrestoreFormat();
bRN6752_Inputsource_Format_Detected = true;
}
return ERROR_NONE;
}
也正是这里,因为获取sensor id的值失败,导致返回上层的camera个数为0,后来从log也能看出来,在进行i2c通信的时候出现i2c通信异常。