camera_sensor_driver
image_sensr
首先要进行板极设备的初始化的工作:代码路径是在:
/mediatek/platform/mt6577/kernel/core/mt6577_devs.c
里面
#if1 ///defined(CONFIG_VIDEO_CAPTURE_DRIVERS)
retval =platform_device_register(&sensor_dev);
if (retval != 0){
return retval;
}
sensor_dev
的实现如下:
staticstruct platform_device sensor_dev = {
.name = “image_sensor”,
.id = -1,
};
上面是以
platformbus
方式进行注册设备的,
platformbus
的
match
的规则是名字相同,所以我们要找到
imagesensor
的
driver
就要找到以
Platform
方式进行注册,名字是”
image_sensor”
的驱动。
我们下
grepcmd ,
找到了
driver
的路径:
/mediatek/custom/common/kernel/imgsensor/src/kd_sensorlist.c
文件中:
staticstruct platform_driver g_stCAMERA_HW_Driver = {
.probe = CAMERA_HW_probe,
.remove =CAMERA_HW_remove,
.suspend = CAMERA_HW_suspend,
.resume =CAMERA_HW_resume,
.driver = {
.name = “image_sensor”,
.owner = THIS_MODULE,
}
};
发现没有,上面的
name
是
image_sensor,
看下
driver
在哪里进行注册的?
/*=======================================================================
* CAMERA_HW_i2C_init()
*=======================================================================*/
staticint __init CAMERA_HW_i2C_init(void)
{
struct proc_dir_entry*prEntry;
i2c_register_board_info(CAMERA_I2C_BUSNUM,&kd_camera_dev, 1);//
这里是注册一个
i2c
设备
if(platform_driver_register(&g_stCAMERA_HW_Driver)){//
这里就是我们以
platform
方式注册的驱动函数
PK_ERR(“failed toregister CAMERA_HW driver\n”);
return -ENODEV;
}
//Register proc file forsensor register debug
prEntry =create_proc_entry(“driver/camsensor”, 0,NULL);//
这里是注册
Image_sensor
的
proc
口,主要用于调试。
if (prEntry) {
prEntry->read_proc =CAMERA_HW_DumpReg_To_Proc;
prEntry->write_proc =CAMERA_HW_Reg_Debug;
}
else {
PK_ERR(“add/proc/driver/camsensor entry fail \n”);
}
atomic_set(&g_CamHWOpend,0);
atomic_set(&g_CamDrvOpenCnt,0);
atomic_set(&g_CamHWOpening,0);
return 0;
}
当我们
platformbus
的
deivice
和
drivermatch
成功后,就会调用
drver
的
probe
函数。
.probe =CAMERA_HW_probe,
staticint CAMERA_HW_probe(struct platform_device *pdev)
{
init_waitqueue_head(&kd_sensor_wait_queue);
returni2c_add_driver(&CAMERA_HW_i2c_driver);//
这里是以
i2c
的方式进行注册
cameradriver
整好和上上面的
i2c
方式注册设备一样。
}
其实
image_sensor
以
platform
方式注册,只是一个虚拟的方式进行注册的,主要好是以
i2c
方式进行注册的,下面就进入我们的主角,我们的
i2c
方式注册的
driver
和
platformbus
一样,
i2c
同样有自己的一套匹配方式,他的匹配方式就是匹配
id_table
里面的名字和以
i2c_register_board_info(CAMERA_I2C_BUSNUM,&kd_camera_dev, 1);
方式进行注册到
i2c
上面的设备的名字进行匹配,匹配成功后,同样也会调用对应的
probe
函数:
*I2C Driver structure
********************************************************************************/
structi2c_driver CAMERA_HW_i2c_driver = {
.probe = CAMERA_HW_i2c_probe,
.remove =CAMERA_HW_i2c_remove,
.driver.name =CAMERA_HW_DRVNAME,
.id_table = CAMERA_HW_i2c_id,
};
看下这个
Probe
函数的实现:
staticint CAMERA_HW_i2c_probe(struct i2c_client *client, const structi2c_device_id *id)
{
int i4RetValue = 0;
PK_DBG(“[CAMERA_HW]Attach I2C \n”);
//get sensor i2c client
spin_lock(&kdsensor_drv_lock);
g_pstI2Cclient =client;//
这里是获得我们的
clientdevice
,并且以
platform
方式进行注册
//set I2C clock rate
g_pstI2Cclient->timing =200;//200k
spin_unlock(&kdsensor_drv_lock);
//Register char driver
i4RetValue =RegisterCAMERA_HWCharDrv();
if(i4RetValue){
PK_ERR(“[CAMERA_HW]register char device failed!\n”);//
调用这个函数进行注册
char
类型的设备,下面
trace
下这个函数是如何实现的
return i4RetValue;
}
//spin_lock_init(&g_CamHWLock);
PK_DBG(“[CAMERA_HW]Attached!! \n”);
return 0;
}
trace
下
registerCAMERA_HWCharDrv
函数的实现:
*RegisterCAMERA_HWCharDrv
********************************************************************************/
inlinestatic int RegisterCAMERA_HWCharDrv(void)
{
struct device* sensor_device =NULL;
#ifCAMERA_HW_DYNAMIC_ALLOCATE_DEVNO
if(alloc_chrdev_region(&g_CAMERA_HWdevno, 0, 1,CAMERA_HW_DRVNAME))//
分配一个字符设备
{
PK_DBG(“[CAMERASENSOR] Allocate device no failed\n”);
return -EAGAIN;
}
#else
if( register_chrdev_region( g_CAMERA_HWdevno , 1 , CAMERA_HW_DRVNAME) )//
注册一个字符设备
{
PK_DBG(“[CAMERASENSOR] Register device no failed\n”);
return -EAGAIN;
}
#endif
//Allocate driver
g_pCAMERA_HW_CharDrv =cdev_alloc();
if(NULL ==g_pCAMERA_HW_CharDrv)
{
unregister_chrdev_region(g_CAMERA_HWdevno,1);
PK_DBG(“[CAMERASENSOR] Allocate mem for kobject failed\n”);
return -ENOMEM;
}
//Attatch file operation.
cdev_init(g_pCAMERA_HW_CharDrv,&g_stCAMERA_HW_fops);//
关联到
file_operation
进入字符设备
g_pCAMERA_HW_CharDrv->owner= THIS_MODULE;
//Add to system
if(cdev_add(g_pCAMERA_HW_CharDrv,g_CAMERA_HWdevno, 1))//
将我们分配的字符设备,
attach
上
file_operation
添加到
system
{
PK_DBG(“[mt6516_IDP]Attatch file operation failed\n”);
unregister_chrdev_region(g_CAMERA_HWdevno,1);
return -EAGAIN;
}
sensor_class =class_create(THIS_MODULE, “sensordrv”);//
创建一个
sensordrv
类
if (IS_ERR(sensor_class)) {
int ret =PTR_ERR(sensor_class);
PK_DBG(“Unable tocreate class, err = %d\n”, ret);
return ret;
}
sensor_device =device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL,CAMERA_HW_DRVNAME);
在
sensordrv
类里面创建一个
CAMERA_HW_DRVNAME
设备文件。
return 0;
}
上面只是一个虚拟的注册过程,我们还没有真正的到到我们的
image_sensor
设备。
看这个
image_sensor
的
file_operation
是如何实现的:
staticconst struct file_operations g_stCAMERA_HW_fops =
{
.owner = THIS_MODULE,
.open = CAMERA_HW_Open,
.release = CAMERA_HW_Release,
#ifdef USE_NEW_IOCTL
.unlocked_ioctl =CAMERA_HW_Ioctl
#else
.ioctl = CAMERA_HW_Ioctl
#endif
};
其实我最关注的就是我们手机上面有很多很多的
driver
,代码中是在哪里判断我们使用的是什么
IC
厂商的
imagesensor
。我找了很多代码,在
mediatek
的代码中我并没找到。
上层在操作设备的时候都是先
open
设备,获得文件指针以后就可以进行接下来的事情。
我们先分析
open
函数:
1
、
.open= CAMERA_HW_Open,
********************************************************************************/
staticint CAMERA_HW_Open
(
struct
inode * a_pstInode,
struct
file * a_pstFile)
{
//
atomic_inc(&g_CamDrvOpenCnt);
return
0;
}
//
open
函数里面没有进行任何的操作,就只是一个锁,防止多个
既然我们的
open
函数里面没有进行别的操作,而我们的
file_operation
里面就只有
open
和
ioctl
成员函数,所以说我们的任何操作
imagesensor
的操作函数都是通过
ioctl
进行操作设备的。
2
、
.unlocked_ioctl= CAMERA_HW_Ioctl
看下
unlocked_ioctl
:
上面的两种
ioctl
的函数都是
CAMERA_HW_Ioctl
看下
CAMERA_HW_Ioctl
函数的实现:
staticint CAMERA_HW_Ioctl(struct inode * a_pstInode,
structfile * a_pstFile,
unsignedint a_u4Command,
unsignedlong a_u4Param)
#endif
{
int i4RetValue = 0;
void * pBuff = NULL;
u32 *pIdx = NULL;
//PK_DBG(“%x, %x\n”,a_u4Command,a_u4Param);
mutex_lock(&kdCam_Mutex);
if(_IOC_NONE ==_IOC_DIR(a_u4Command))
{
}
else
{
pBuff =kmalloc(_IOC_SIZE(a_u4Command),GFP_KERNEL);//
分配一个
buffer,
if(NULL == pBuff)
{
PK_DBG(“[CAMERASENSOR] ioctl allocate mem failed\n”);
i4RetValue = -ENOMEM;
gotoCAMERA_HW_Ioctl_EXIT;
}
if(_IOC_WRITE &_IOC_DIR(a_u4Command))
//判断是否可写?
{
if(copy_from_user(pBuff, (void *) a_u4Param,_IOC_SIZE(a_u4Command)))//
将用户传递过来的命令参数复制到内核空间,接下来我们会根据这个数据进行选择
{
kfree(pBuff);
PK_DBG(“[CAMERASENSOR] ioctl copy from user failed\n”);
i4RetValue = -EFAULT;
gotoCAMERA_HW_Ioctl_EXIT;
}
}
}
pIdx = (u32*)pBuff;
switch(a_u4Command)
{
#if0
caseKDIMGSENSORIOC_X_POWER_ON:
i4RetValue =kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, true,CAMERA_HW_DRVNAME);//
进行
imagesensor
上电的工作,具体如何上电,我们会在下面进行讲解。
break;
caseKDIMGSENSORIOC_X_POWER_OFF:
i4RetValue =kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, false,CAMERA_HW_DRVNAME)
;
//
进行
imagesensor power off
的动作
break;
#endif
caseKDIMGSENSORIOC_X_SET_DRIVER:
i4RetValue =kdSetDriver((unsigned int*)pBuff);//
执行到这个
cmd
,将会调用
kdSetDriver
//
其实这个函数很重要,就是为我们对应的
imagesensor
设置
driver
,就是设置提供给上层操作底层的
interface
…
………………..
…
………………….
default :
PK_DBG(“No such command\n”);
i4RetValue = -EPERM;
break;
}
上层就是通过下
ioctl
的
cmd
进行操作底层的,我们就选几个
cmd
进行讲解下。
case
KDIMGSENSORIOC_T_OPEN:
i4RetValue= adopt_CAMERA_HW_Open();//
当执行上面的
cmd
的时候,我们就会执行这个函数
inline
static
int
adopt_CAMERA_HW_Open
(
void
)
{
UINT32
err = 0;
#ifdef
CONFIG_ARCH_MT6577
int
ret = 0;
//DDR2DRAM clock bug work around
if
(2 == get_ddr_type()) {
//DDR2
ret =set_dram_clk_gating(1);//
设置
dram
寄存器
if
(-1== ret) {
PK_ERR(
“ERROR: DRAM CLOCK GATING ERROR\n”
);
}
}
#endif
KD_IMGSENSOR_PROFILE_INIT();//
返回当前的时间
//poweron sensor
if
(atomic_read(&g_CamHWOpend) == 0) {
//turn on power
atomic_set(&g_CamHWOpening,1);
kdModulePowerOn((
CAMERA_DUAL_CAMERA_SENSOR_ENUM
)g_currDualSensorIdx, g_currSensorName,
true
,CAMERA_HW_DRVNAME);//
为
sensor
上电,这个上电函数我们在下面进行讲解
//waitfor power stable
mDELAY(10);
KD_IMGSENSOR_PROFILE(
“kdModulePowerOn”
);
//
if
(g_pSensorFunc) {//
判断我们
imagesensor
操作函数指针是否为
NULL
,如果为
NULL
,报错,因为我们就是靠这个操作函数集合去操作
imagesensor
的,
//
如果上层先下这个
cmd
的话,那么肯定是不行的,因为我们的
g_pSensorFunc
是
NULL
,并没有赋值,通过查询代码,发现是
case
KDIMGSENSORIOC_X_SET_DRIVER:
这个
case;
里面在做,所以上层肯定是先下这个
cmd
,然后才能执行我们现在讲解的
cmd.
这个
cmd
我们下面会进行讲解。
err =g_pSensorFunc->
SensorOpen
();//
调用使用的
imagesensor
的
open
函数
,
我们会对一个
imagesensor
的接口函数进行举例讲解。
if
(
ERROR_NONE
!= err) {
PK_DBG(
“ERROR:SensorOpen(), turn off power \n”
);
kdModulePowerOn((
CAMERA_DUAL_CAMERA_SENSOR_ENUM
)g_currDualSensorIdx, NULL,
false
,CAMERA_HW_DRVNAME);
}
//kaka_12_0112_2 add
else
// Add for sensor provider HW infomodule
{
if
(
DUAL_CAMERA_MAIN_SENSOR
== g_currDualSensorIdx){
memcpy(mainCameraName,g_currSensorName,CAM_NAME_LEN);
g_main_camera =mainCameraName;
}
else
if
(
DUAL_CAMERA_SUB_SENSOR
== g_currDualSensorIdx) {
memcpy(subCameraName,g_currSensorName,CAM_NAME_LEN);
g_sub_camera =subCameraName;
}
}
//kaka_12_0112_2end
}
else
{
PK_DBG(
“ERROR:NULL g_pSensorFunc\n”
);
}
KD_IMGSENSOR_PROFILE(
“SensorOpen”
);
}
if
(err == 0 ) {
atomic_set(&g_CamHWOpend,1);
}
return
err?-EIO:err;
}
/*adopt_CAMERA_HW_Open() */
2.1
、
kdModulePowerOn((
CAMERA_DUAL_CAMERA_SENSOR_ENUM
)g_currDualSensorIdx, g_currSensorName,
true
,CAMERA_HW_DRVNAME);
—-
-----
>
kdCISModulePowerOn(SensorIdx,currSensorName,On,mode_name)//
这个就是
camera
的上电函数,函数定义在
/mediatek/custom/common/kernel/camera/camera/kd_camera_hw.c
里面。这个文件里面就是
camera
的上电函数,在
mediatek
平台下都共用这个函数。
3
、
Case: KDIMGSENSORIOC_X_SET_DRIVER
kdSetDriver
函数的实现如下:
int
kdSetDriver
(
unsigned
int
*pDrvIndex)
{
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT
*pSensorList = NULL;
unsigned
int
drvIdx = (*pDrvIndex &KDIMGSENSOR_DUAL_MASK_LSB);//
这里根据我们用户传递进来的参数转化为
drvIdx
,就是
driverindex
的选择
//setdriver for MAIN or SUB sensor
spin_lock(&kdsensor_drv_lock);
g_currDualSensorIdx =(
CAMERA_DUAL_CAMERA_SENSOR_ENUM
)((*pDrvIndex& KDIMGSENSOR_DUAL_MASK_MSB)>>KDIMGSENSOR_DUAL_SHIFT);
spin_unlock(&kdsensor_drv_lock);
if
(0 != kdGetSensorInitFuncList(&pSensorList))//
调用这个函数,取得所有添加的
sensor
的结构的首地址。下面看下他的实现:
{
PK_ERR(
“ERROR:kdGetSensorInitFuncList()\n”
);
return
-EIO;
}
if
(drvIdx < MAX_NUM_OF_SUPPORT_SENSOR)
{
if
(NULL == pSensorList[drvIdx].
SensorInit
)
{
PK_ERR(
“ERROR:kdSetDriver()\n”
);
return
-EIO;
}
pSensorList[drvIdx].
SensorInit
(&g_pSensorFunc);//
调用我们所取得
snsor
的
SensorInit
函数,下面会进行看看这个
Init
函数的执行过程
if
(NULL == g_pSensorFunc)
{
PK_ERR(
“ERROR:NULLg_pSensorFunc\n”
);
return
-EIO;
}
//getsensor name
memcpy((
char
*)g_currSensorName,(
char
*)pSensorList[drvIdx].
drvname
,
sizeof
(pSensorList[drvIdx].
drvname
));
//returnsensor ID
*pDrvIndex = (
unsigned
int
)pSensorList[drvIdx].
SensorId
;
PK_DBG(
“[kdSetDriver]:%d,%d,%s,%d\n”
,g_currDualSensorIdx,drvIdx,g_currSensorName,
sizeof
(pSensorList[drvIdx].drvname));
}
return
0;
}
kdGetSensorInitFuncList
:
UINT32
kdGetSensorInitFuncList
(
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT
**ppSensorList)
{
if
(
NULL
== ppSensorList)
{
printk(
“[kdGetSensorInitFuncList]ERROR:NULL ppSensorList\n”
);
return
1;
}
*ppSensorList =&kdSensorList[0];//
这里取出
kdSensorList
数组的第一个参数,这个
KdSensorList
很重要,当我们要添加一个新的
sensor
的时候,我们就会在这个数组里面进行填写。,这个添加的路径是在
/mediatek/custom/common/kernel/imagesensor/src/kd_sensor_list.h
这个头文件中
return
0;
}
// kdGetSensorInitFuncList()
上面我们是取得了整个数组的首地址:
下面会调用我们上层所应该调用的
imagesensor
pSensorList[drvIdx].
SensorInit:
调用
SensorInit
函数:
我们有很多的
imagesensor
,我这里我只选取其中一个进行讲解:
看下这个
init
函数在干嘛?代码的路径是在
/mediatek/custom/common/kernel/imagesensor/hi253_yuv_Sensor.c
里面
4
、
UINT32
HI253_YUV_SensorInit
(
PSENSOR_FUNCTION_STRUCT
*pfFunc)
{
static
SENSOR_FUNCTION_STRUCT
SensorFuncHI253=
{
HI253Open,
HI253GetInfo,
HI253GetResolution,
HI253FeatureControl,
HI253Control,
HI253Close
};
/*To Do : Check Sensor status here */
if
(pfFunc!=NULL)
*pfFunc=&SensorFuncHI253;
return
ERROR_NONE
;
}
/* SensorInit() */
上面我加红的函数就是
driver
里面提供的接口
4.1
、
HI253Open
:
UINT32
HI253Open
(
void
)
{
kal_uint16
SensorId = 0;
//1software reset sensor and wait (to sensor)
HI253SetPage(0x00);
HI253WriteCmosSensor(0x01,0xf1);
HI253WriteCmosSensor(0x01,0xf3);
HI253WriteCmosSensor(0x01,0xf1);
SensorId =HI253ReadCmosSensor(0x04);
Sleep(3);
SENSORDB(
“[HI253]HI253Open:Sensor ID %x\n”
,SensorId);
if
(SensorId!= HI253_SENSOR_ID)
{
return
ERROR_SENSOR_CONNECT_FAIL
;
}
HI253InitSetting();
HI253InitPara();
return
ERROR_NONE
;
}
通过函数实现就可以看出来,这里是在通过
i2c
控制
imagesensor
的
register
,读取
deivceid ,
看是否链接上对应的
imagesensor
4.2:HI253GetInfo
UINT32
HI253GetInfo
(MSDK_SCENARIO_ID_ENUMScenarioId,
MSDK_SENSOR_INFO_STRUCT*pSensorInfo,
MSDK_SENSOR_CONFIG_STRUCT*pSensorConfigData)
{
pSensorInfo->
SensorPreviewResolutionX
=HI253_PV_WIDTH;
pSensorInfo->
SensorPreviewResolutionY
=HI253_PV_HEIGHT;
pSensorInfo->
SensorFullResolutionX
=HI253_FULL_WIDTH;
pSensorInfo->
SensorFullResolutionY
=HI253_FULL_HEIGHT;
…
…………….
…
………………
switch
(ScenarioId)
{
case
MSDK_SCENARIO_ID_CAMERA_PREVIEW:
case
MSDK_SCENARIO_ID_VIDEO_PREVIEW:
case
MSDK_SCENARIO_ID_VIDEO_CAPTURE_MPEG4:
case
MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG:
case
MSDK_SCENARIO_ID_CAMERA_CAPTURE_MEM:
default
:
pSensorInfo->
SensorClockFreq
=26;
pSensorInfo->
SensorClockDividCount
=3;
pSensorInfo->
SensorClockRisingCount
=0;
pSensorInfo->
SensorClockFallingCount
=2;
pSensorInfo->
SensorPixelClockCount
=3;
pSensorInfo->
SensorDataLatchCount
=2;
pSensorInfo->
SensorGrabStartX
= HI253_GRAB_START_X;
pSensorInfo->
SensorGrabStartY
= HI253_GRAB_START_Y;
break
;
}
return
ERROR_NONE
;
}
上面的函数一共传递进来了
3
个变量,第一个变量:是控制
camera
的工作模式,
(
拍照、摄像等等
)
第
2
个参数:主要设置
imagesensor
的频率的
(
时钟频率、预览频率、以及同步频率
)
;第
3
个参数同样也是
camera
的设置,其实要看到底是在干嘛,只要看看这个参数是如何定义的就可以了。
4.3
、
HI253GetResolution
UINT32
HI253GetResolution
(MSDK_SENSOR_RESOLUTION_INFO_STRUCT*pSensorResolution)
{
pSensorResolution->
SensorFullWidth
= HI253_FULL_WIDTH;
pSensorResolution->
SensorFullHeight
= HI253_FULL_HEIGHT;
pSensorResolution->
SensorPreviewWidth
= HI253_PV_WIDTH;
pSensorResolution->
SensorPreviewHeight
= HI253_PV_HEIGHT;
return
ERROR_NONE
;
}
/* HI253GetResolution() */
设置
camera
在预览模式下的高度、宽度等
4.4
:
HI253FeatureControl
UINT32
HI253FeatureControl
(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;
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++=HI253_FULL_WIDTH;
*pFeatureReturnPara16=HI253_FULL_HEIGHT;
*pFeatureParaLen=4;
break
;
…
…
…
..
}
这个是上层会提供
featureid
,底层通过这个
id
进行不同
case
的执行为
para
和
paralen
赋值。
4.5
:
HI253Control
UINT32
HI253Control
(MSDK_SCENARIO_ID_ENUMScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow,
MSDK_SENSOR_CONFIG_STRUCT*pSensorConfigData)
{
switch
(ScenarioId)
{
case
MSDK_SCENARIO_ID_CAMERA_PREVIEW:
case
MSDK_SCENARIO_ID_VIDEO_PREVIEW:
case
MSDK_SCENARIO_ID_VIDEO_CAPTURE_MPEG4:
HI253Preview(pImageWindow,pSensorConfigData);
break
;
case
MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG:
case
MSDK_SCENARIO_ID_CAMERA_CAPTURE_MEM:
HI253Capture(pImageWindow,pSensorConfigData);
break
;
default
:
break
;
}
return
TRUE
;
}
/* HI253Control() */
这个函数和上面一样,也是提供控制的一个
Interface
4.6
:
HI253Close
UINT32
HI253Close
(
void
)
{
return
ERROR_NONE
;
}
/* HI253Close() */
这里的
close
没有执行任何工作,当然你也可以自己实现
通过
mtk
代码的分析,
mtk
的代码只是提供一个
Interface,
只是提供一个机制,至于策略是上层在控制。