Android6.0 camera个数探测

近期在排查打开相机黑屏的问题,然后就跟了一下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通信异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值