当前位置: 首页 > news >正文

一、MTK6580 平台 Camera 驱动整体框架

原文:http://www.codexiu.cn/android/blog/33878/

mtk平台三大件调试中,camera的调试难度最大,问题也就最多,为此特地分析了一下整个camera驱动

部分实现过程,以下为camera驱动框架序列图:

      

从图中可以看出,整个框架分为三个部分hal部分逻辑调用,kernel层的通用驱动sensorlist.c 和具体IC的

驱动xxxx_mipi_raw.c,kernel起来后不会直接去访问硬件sensor,而是会注册相关的驱动,之后Android

统起来后会启动相关的服务如:camera_service,在camera服务中会直接去访问hal,kernel驱动,进而操

作camera为此本文也穿插了部分hal层的调用,至于camera_service后面章节会继续补充。

二、 Camera 驱动的具体实现

========================HAL 层部分初始调用========================
文件:vendor/mediatek/proprietary/hardware/mtkcam/common/module_hal/devicemgr/CamDeviceManagerBase.cpp

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">int32_t
CamDeviceManagerBase::
getNumberOfDevices()
{...mi4DeviceNum = enumDeviceLocked();...
}</code>
文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/devicemgr/CamDeviceManagerImp.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">int32_t
CamDeviceManagerImp::
enumDeviceLocked()
{...
<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//------------------------------------------------------------------------------</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#if '1'==MTKCAM_HAVE_SENSOR_HAL</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//</span>IHalSensorList*<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> pHalSensorList = IHalSensorList::get();size_t <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> sensorNum = pHalSensorList->searchSensors();
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>...<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span>  i4DeviceNum;
}</code>
文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MUINT
HalSensorList::
searchSensors()
{Mutex::Autolock _l(mEnumSensorMutex);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//</span>MY_LOGD(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"searchSensors"</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span>  enumerateSensor_Locked();
}</code>
文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.enumList.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MUINT
HalSensorList::
enumerateSensor_Locked()
{....MUINT halSensorDev = SENSOR_DEV_NONE;NSFeature::SensorInfoBase* pSensorInfo ;SensorDrv *<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> pSensorDrv = SensorDrv::get();SeninfDrv *<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> pSeninfDrv = SeninfDrv::createInstance();<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> iSensorsList = pSensorDrv->impSearchSensor(NULL);....
}</code>
文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/imgsensor_drv.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MINT32
ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)
{....GetSensorInitFuncList(&m_pstSensorInitFunc);LOG_MSG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"SENSOR search start \n"</span>);<span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">sprintf</span>(cBuf,<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"/dev/%s"</span>,CAMERA_HW_DEVNAME);m_fdSensor = ::open(cBuf, O_RDWR);......<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {....err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );...err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);......
}</code>
GetSensorInitFuncList的实现
文件:vendor/mediatek/proprietary/custom/mt6580/hal/imgsensor_src/sensorlist.cpp

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (NULL == ppSensorList) {ALOGE(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"ERROR: NULL pSensorList\n"</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> MHAL_UNKNOWN_ERROR;}*ppSensorList = &SensorList[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>];<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> MHAL_NO_ERROR;
} </code>
Sensor 列表的定义如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
{
<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//xc add camera start</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#if defined(GC2365MIPI_RAW)</span>RAW_INFO(GC2365MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2365MIPI_RAW, NULL),
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-preprocessor" style="border-radius: 0px !important;">#if defined(GC2355_MIPI_RAW_BAIKANG_M8112)</span>RAW_INFO(GC2355_SENSOR_ID, SENSOR_DRVNAME_GC2355_MIPI_RAW,NULL),
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>
....
}</code>
获取sensor列表后,紧接着通过:
err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);

访问kernel层的数据

====================== Kernel 层驱动的实现 ========================
1. 针对前后摄注册platform 设备和驱动
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> __init CAMERA_HW_i2C_init(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)
{....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (platform_driver_register(&g_stCAMERA_HW_Driver)) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册主摄platform 驱动</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (platform_driver_register(&g_stCAMERA_HW_Driver2)) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册副摄platform 驱动</span>....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}</code>
主摄平台驱动的定义:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>
<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW_of_ids[] = {{.compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw"</span>,},  <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//主摄匹配规则</span>{}
};
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_driver g_stCAMERA_HW_Driver = {.probe = CAMERA_HW_probe,.remove = CAMERA_HW_remove,.suspend = CAMERA_HW_suspend,.resume = CAMERA_HW_resume,.driver = {.name = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"image_sensor"</span>,.owner = THIS_MODULE,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>.of_match_table = CAMERA_HW_of_ids,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>}
};</code>
副摄平台驱动的定义:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>
<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW2_of_ids[] = {{.compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw2"</span>,},<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//副摄匹配规则</span>{}
};
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_driver g_stCAMERA_HW_Driver2 = {.probe = CAMERA_HW_probe2,.remove = CAMERA_HW_remove2,.suspend = CAMERA_HW_suspend2,.resume = CAMERA_HW_resume2,.driver = {.name = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"image_sensor_bus2"</span>,.owner = THIS_MODULE,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>.of_match_table = CAMERA_HW2_of_ids,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>}
};</code>
主副摄cam在dts中定义设备信息:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">kd_camera_hw1:kd_camera_hw1@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">15008000</span> {compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//这里必须和主摄一致</span>reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x15008000</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x1000</span>>;  <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* SENINF_ADDR */</span>vcama-supply = <&mt_pmic_vcama_ldo_reg>;vcamd-supply = <&mt_pmic_vcamd_ldo_reg>;vcamaf-supply = <&mt_pmic_vcamaf_ldo_reg>;vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;};
kd_camera_hw2:kd_camera_hw2@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">15008000</span> {compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw2"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//这里必须和副摄一致</span>reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x15008000</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x1000</span>>;  <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* SENINF_ADDR */</span>
};</code>
       当内核启动后,会解析dts编译生成的dtb文件,注册里面定义的device,如果和驱动中定义id一致,

则挂载启动。上面注册了两个platform 驱动g_stCAMERA_HW_Driver,g_stCAMERA_HW_Driver2,

如果匹配成功会调用各自的probe函数CAMERA_HW_probe,CAMERA_HW_probe2

2. 平台probe 函数的实现
主摄probe,CAMERA_HW_probe的实现如下:

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_probe(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_device *pdev)
{
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#if !defined(CONFIG_MTK_LEGACY)</span>mtkcam_gpio_init(pdev);mtkcam_pin_mux_init(pdev);
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> i2c_add_driver(&CAMERA_HW_i2c_driver);
}</code>
副摄probe,CAMERA_HW_probe的实现如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_probe2(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_device *pdev)
{<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> i2c_add_driver(&CAMERA_HW_i2c_driver2);
}</code>
从上可以看出在main/sub 的平台probe中分别注册了各自的i2c驱动CAMERA_HW_i2c_driver,
CAMERA_HW_i2c_driver2,
main sensor 的CAMERA_HW_i2c_driver定义如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>
<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW_i2c_of_ids[] = {{ .compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_main"</span>, },{}
};
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_driver CAMERA_HW_i2c_driver = {.probe = CAMERA_HW_i2c_probe,.remove = CAMERA_HW_i2c_remove,.driver = {.name = CAMERA_HW_DRVNAME1,.owner = THIS_MODULE,<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>.of_match_table = CAMERA_HW_i2c_of_ids,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>},.id_table = CAMERA_HW_i2c_id,
};
sub sensor 的CAMERA_HW_i2c_driver定义如下:
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW2_i2c_driver_of_ids[] = {{ .compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_sub"</span>, },{}};
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_driver CAMERA_HW_i2c_driver2 = {.probe = CAMERA_HW_i2c_probe2,.remove = CAMERA_HW_i2c_remove2,.driver = {.name = CAMERA_HW_DRVNAME2,.owner = THIS_MODULE,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span>.of_match_table = CAMERA_HW2_i2c_driver_of_ids,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>},.id_table = CAMERA_HW_i2c_id2,
};</code>
对应main/sub camera i2c 设备dts定义如下
文件:kernel-3.18/arch/arm/boot/dts/cust_i2c.dtsi

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">&i2c0 {camera_main@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span> {compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_main"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//和 CAMERA_HW_i2c_driver定义的一致</span>reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x10</span>>;};camera_main_af@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>c {compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_main_af"</span>;reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x0c</span>>;};camera_sub@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">3</span>c {compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_sub"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//和CAMERA_HW_i2c_driver2定义的一致</span>reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x3c</span>>;};};</code>
3. I2c probe的实现
从上可以看出main/sub sensor在各自的平台probe中,注册了i2c_driver,当各自的i2c_driver 和设备
匹配(如何匹配本章不作分析)成功后,会调用各自的i2c_probe函数。
main sensor  的probe函数
CAMERA_HW_i2c_probe:

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_i2c_probe(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_client *client, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_device_id *id)
{.....<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Register char driver */</span>i4RetValue = RegisterCAMERA_HWCharDrv();.....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}</code>
sub sensor 的probe函数CAMERA_HW_i2c_probe2:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_i2c_probe2(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_client *client, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_device_id *id)
{.....<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Register char driver */</span>i4RetValue = RegisterCAMERA_HWCharDrv2();.....
}</code>
从上可以看出main/sub 在各自的i2cprobe中,通过该调用RegisterCAMERA_HWCharDrv,RegisterCAMERA_HWCharDrv2 注册了字符设备。 各自注册cdev函数实现如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">inline</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> RegisterCAMERA_HWCharDrv(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//main sensor 注册cdev</span>
{.....<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Attatch file operation. */</span>cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//初始化字符设备</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Add to system */</span>cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册到内核</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录 /sys/class/sensordrv/</span>sensor_class = class_create(THIS_MODULE, <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"sensordrv"</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录/sys/class/sensordrv/kd_camera_hw </span>sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1); ....	<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}
<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">inline</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> RegisterCAMERA_HWCharDrv2(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//sub sensor 注册cdev</span>
{....<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Attatch file operation. */</span>cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//初始化字符设备 </span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Add to system */</span>cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>));<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册到内核</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录 /sys/class/sensordrv2/</span>sensor2_class = class_create(THIS_MODULE, <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"sensordrv2"</span>);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录/sys/class/sensordrv2/kd_camera_hw_bus2</span>sensor_device2 = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2);....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}
main/sub 创建各自的字符设备过程中绑定各自的fops,g_stCAMERA_HW_fops和g_stCAMERA_HW_fops0
他们各自定义如下
<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> file_operations g_stCAMERA_HW_fops = { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//main sensor fops</span>.owner = THIS_MODULE,.open = CAMERA_HW_Open,.release = CAMERA_HW_Release,.unlocked_ioctl = CAMERA_HW_Ioctl,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_COMPAT</span>.compat_ioctl = CAMERA_HW_Ioctl_Compat,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>};<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> file_operations g_stCAMERA_HW_fops0 = { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//sub sensor fops</span>.owner = THIS_MODULE,.open = CAMERA_HW_Open2,.release = CAMERA_HW_Release2,.unlocked_ioctl = CAMERA_HW_Ioctl,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_COMPAT</span>.compat_ioctl = CAMERA_HW_Ioctl_Compat,
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>};</code>
从上可以看出各自的fops指定了相同的Iioctl函数,意味着上层操作main/sub sensor  只需要对应一个
底层的ioctl即可,至于sensor的区分可以借助idx,后面会讲到

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/*******************************************************************************
* CAMERA_HW_Ioctl
********************************************************************************/</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">long</span> CAMERA_HW_Ioctl(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> file *a_pstFile,<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> a_u4Command, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">long</span> a_u4Param)
{...pIdx = (u32 *) pBuff;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">switch</span> (a_u4Command) {...<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> KDIMGSENSORIOC_X_SET_DRIVER:i4RetValue = kdSetDriver((<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> *)pBuff);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> KDIMGSENSORIOC_X_FEATURECONCTROL:i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> KDIMGSENSORIOC_T_CHECK_IS_ALIVE:i4RetValue = adopt_CAMERA_HW_CheckIsAlive();<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>;....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">default</span>:PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"No such command\n"</span>);i4RetValue = -EPERM;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>;}.....
}</code>
这里ioctl和上层一一对应,上层要控制caemra 只需要传入相应的cmd和data而已

=================== HAL 调用Kernel 层驱动的逻辑 ======================
       前面介绍了HAL层调用ioctl 和 kernel层注册驱动,接下来继续分析,HAL层调用 后驱动
具体的实现流程。
4. ioctl 底层的实现
4.1先来看ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
当KDIMGSENSORIOC_X_SET_DRIVER被传下时,会调用kernel层的kdSetDriver接口

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> kdSetDriver(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> *pDrvIndex)
{...kdGetSensorInitFuncList(&pSensorList))   <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//获得sensor初始化列表</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {....pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//获取各个cam驱动中Init函数入口</span>....}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}</code>
kdGetSensorInitFuncList的实现:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (NULL == ppSensorList) {PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n"</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;}*ppSensorList = &kdSensorList[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>];  <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//获取sensorlist数组首地址</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}				<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* kdGetSensorInitFuncList() */</span></code>
kdSensorList定义如下:
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.h
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>] =
{....<span class="hljs-preprocessor" style="border-radius: 0px !important;">#if defined(SUB_GC2355_MIPI_RAW)</span>{GC2355S_SENSOR_ID, SENSOR_DRVNAME_GC2355S_MIPI_RAW,Sub_GC2355_MIPI_RAW_SensorInit},
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>....
}</code>
获取列表之后紧接着调用各自的Init函数,这里以GC2355为例
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">UINT32 GC2235MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
{<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* To Do : Check Sensor status here */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (pfFunc!=NULL)*pfFunc=&sensor_func;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE;
}	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/*	GC2235MIPI_RAW_SensorInit	*/</span></code>
丛中可以看出,gc2355的Init函数地址传给了pfFunc,也就是时候,后面在通用驱动可以直接 凭借pfun
指针调用sensorlist中的驱动

4.2 再来看ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);

当KDIMGSENSORIOC_T_CHECK_IS_ALIVE被传下时,会调用kernel层的adopt_CAMERA_HW_Feature

Control接口

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">inline</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> adopt_CAMERA_HW_CheckIsAlive(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)
{....<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* power on sensor */</span>kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *) g_invokeSocketIdx, g_invokeSensorNameStr,<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">true</span>, CAMERA_HW_DRVNAME1);....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_pSensorFunc) {<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) {err =g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],SENSOR_FEATURE_CHECK_SENSOR_ID,(MUINT8 *) &sensorID,&retLen);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (sensorID == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>) {	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* not implement this feature ID */</span>PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">" Not implement!!, use old open function to check\n"</span>);err = ERROR_SENSOR_CONNECT_FAIL;} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (sensorID == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xFFFFFFFF</span>) {	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* fail to open the sensor */</span>PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">" No Sensor Found"</span>);err = ERROR_SENSOR_CONNECT_FAIL;} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> {PK_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">" Sensor found ID = 0x%x\n"</span>, sensorID);<span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">snprintf</span>(mtk_ccm_name, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">sizeof</span>(mtk_ccm_name),<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"%s CAM[%d]:%s;"</span>, mtk_ccm_name,g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);psensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>] = &sensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>];psensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>] = &sensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>];<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">// don't care of the result</span>g_pSensorFunc->SensorGetResolution(psensorResolution);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span>(g_invokeSocketIdx[i] == DUAL_CAMERA_MAIN_SENSOR)curr_sensor_id = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span>(g_invokeSocketIdx[i] == DUAL_CAMERA_SUB_SENSOR)curr_sensor_id = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* fill the cam infos with name/width/height */</span><span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">snprintf</span>(g_cam_infos, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">sizeof</span>(g_cam_infos),<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"%s CAM[%d]:%s,Width:%d, Height:%d;"</span>,g_cam_infos, g_invokeSocketIdx[i], g_invokeSensorNameStr[i],sensorResolution[curr_sensor_id].SensorFullWidth, sensorResolution[curr_sensor_id].SensorFullHeight);err = ERROR_NONE;}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (ERROR_NONE != err) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n"</span>);}}}} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"ERROR:NULL g_pSensorFunc\n"</span>);}
}				<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* adopt_CAMERA_HW_Open() */</span></code>
这个函数非常重要,它主要进行了以下几个动作,
1)通过kdModulePowerOn给Sensor上电
2)通过SensorFeatureControl读取SensorID 
先看kdModulePowerOn的实现

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span>
kdModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM socketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS],<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> sensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">32</span>], BOOL On, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *mode_name)
{MINT32 ret = ERROR_NONE;u32 i = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_bEnableDriver[i]) {<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* PK_XLOG_INFO("[%s][%d][%d][%s][%s]\r\n",__FUNCTION__,g_bEnableDriver[i],socketIdx[i],sensorNameStr[i],mode_name); */</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifndef CONFIG_FPGA_EARLY_PORTING</span>ret = _kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name);
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (ERROR_NONE != ret) {PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[%s]"</span>, __func__);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ret;}}}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE;
}</code>
在kdModulePowerOn中又调用_kdCISModulePowerOn
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> _kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *currSensorName, BOOL On,<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *mode_name)
{....ret = kdCISModulePowerOn(SensorIdx, currSensorName, On, mode_name);....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ret;
}</code>
在_kdCISModulePowerOn又调用kdCISModulePowerOn函数
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/camera_hw/kd_camera_hw.c
//改函数为上下电函数,通过传入BOOL值来判断上/下电

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *currSensorName, BOOL On,<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *mode_name)
{u32 pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* default main sensor */</span><span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_CMRST 0</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_CMPDN 4</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_MODE 1</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_ON   2</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_OFF  3</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_2800 2800000</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1800 1800000</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1500 1500000</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1200 1200000</span>
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1000 1000000</span>u32 pinSet[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">3</span>][<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">8</span>] = {<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* for main sensor */</span>{		<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* The reset pin of main sensor uses GPIO10 of mt6306, please call mt6306 API to set */</span>CAMERA_CMRST_PIN,CAMERA_CMRST_PIN_M_GPIO,	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* mode */</span>GPIO_OUT_ONE,	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* ON state */</span>GPIO_OUT_ZERO,	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* OFF state */</span>CAMERA_CMPDN_PIN,CAMERA_CMPDN_PIN_M_GPIO,GPIO_OUT_ONE,GPIO_OUT_ZERO,},<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* for sub sensor */</span>{CAMERA_CMRST1_PIN,CAMERA_CMRST1_PIN_M_GPIO,GPIO_OUT_ONE,GPIO_OUT_ZERO,CAMERA_CMPDN1_PIN,CAMERA_CMPDN1_PIN_M_GPIO,GPIO_OUT_ONE,GPIO_OUT_ZERO,},<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* for main_2 sensor */</span>{GPIO_CAMERA_INVALID,GPIO_CAMERA_INVALID,	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* mode */</span>GPIO_OUT_ONE,	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* ON state */</span>GPIO_OUT_ZERO,	<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* OFF state */</span>GPIO_CAMERA_INVALID,GPIO_CAMERA_INVALID,GPIO_OUT_ONE,GPIO_OUT_ZERO,}};<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_MAIN_SENSOR == SensorIdx)pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_SUB_SENSOR == SensorIdx)pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx)pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">2</span>;<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* power ON */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (On) {<span class="hljs-preprocessor" style="border-radius: 0px !important;">#if 0</span>ISP_MCLK1_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);ISP_MCLK2_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);ISP_MCLK3_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#else</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (pinSetIdx == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>)ISP_MCLK1_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (pinSetIdx == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>)ISP_MCLK2_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span>printk(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"fangkuiccm %d ,currSensorName = %s pinSetIdx = %d "</span>,__LINE__,currSensorName,pinSetIdx );<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//通过DriverName来区分SensorIC</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (currSensorName && (<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span> == <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">strcmp</span>(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* First Power Pin low and Reset Pin Low */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])mtkcam_gpio_set(pinSetIdx, CAMPDN,pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST])mtkcam_gpio_set(pinSetIdx, CAMRST,pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">50</span>);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* VCAM_A */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMA, VOL_2800)) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable analog power (VCAM_A),power id = %d\n"</span>,VCAMA);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_;}mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span>);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* VCAM_IO */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMIO, VOL_1800)) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable IO power (VCAM_IO),power id = %d\n"</span>,VCAMIO);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_;}mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMD, VOL_1500)) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable digital power (VCAM_D),power id = %d\n"</span>,VCAMD);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_;}mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span>);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* AF_VCC */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMAF, VOL_2800)) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable analog power (VCAM_AF),power id = %d\n"</span>,VCAMAF);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_;}mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">50</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) {mtkcam_gpio_set(pinSetIdx, CAMRST,pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>);mtkcam_gpio_set(pinSetIdx, CAMRST,pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON]);}mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* enable active sensor */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {mtkcam_gpio_set(pinSetIdx, CAMPDN,pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]);mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>);mtkcam_gpio_set(pinSetIdx, CAMPDN,pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);}mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>);} }<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span>{ <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//poweroff</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (currSensorName   <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//上完电就要下电不然会造成漏电,最终会影响手机功耗</span>&& (<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span> == <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">strcmp</span>(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#if 0</span>mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_MODE_00);mt_set_gpio_dir(GPIO_SPI_MOSI_PIN, GPIO_DIR_OUT);mt_set_gpio_out(GPIO_SPI_MOSI_PIN, GPIO_OUT_ONE);
<span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* First Power Pin low and Reset Pin Low */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (mt_set_gpio_mode(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"</span>);}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"</span>);}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) {PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA LENS] set gpio failed!! (CMPDN)\n"</span>);}}}
}</code>
上电操作完成后,紧接着读取SensorID,通用驱动使用SensorFeatureControl来读取ID如:
 g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],
SENSOR_FEATURE_CHECK_SENSOR_ID,
(MUINT8 *) &sensorID,
&retLen);
这步操作会调用GC2355中的feature_control函数如下:
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/gc2355_mipi_raw/gc2355mipi_Sensor.c

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id,UINT8 *feature_para,UINT32 *feature_para_len)
{....LOG_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"feature_id = %d\n"</span>, feature_id);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">switch</span> (feature_id) {....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> SENSOR_FEATURE_CHECK_SENSOR_ID:get_imgsensor_id(feature_return_para_32);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>;....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">default</span>:<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>;}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE;
}    </code>

优化传入的cmd为SENSOR_FEATURE_CHECK_SENSOR_ID,则会调用feature_control中的

get_imgsensor_id再看get_imgsensor_id的实现

<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint32 get_imgsensor_id(UINT32 *sensor_id)
{kal_uint8 i = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;kal_uint8 retry = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">2</span>;<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">while</span> (imgsensor_info.i2c_addr_table[i] != <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xff</span>) {spin_lock(&imgsensor_drv_lock);imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i];spin_unlock(&imgsensor_drv_lock);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">do</span> {*sensor_id = return_sensor_id(); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//return_sensor_id读取IC的ID</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (*sensor_id == imgsensor_info.sensor_id) {LOG_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"i2c write id: 0x%x, sensor id: 0x%x\n"</span>, imgsensor.i2c_write_id,*sensor_id);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE;}LOG_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"Read sensor id fail, write id: 0x%x, id: 0x%x\n"</span>, imgsensor.i2c_write_id,*sensor_id);retry--;} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">while</span>(retry > <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>);i++;retry = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">2</span>;}....<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE;
}</code>
再看return_sensor_id的实现
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint32 return_sensor_id(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)
{<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ((read_cmos_sensor(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xf0</span>) << <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">8</span>) | read_cmos_sensor(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xf1</span>));
}
<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint16 read_cmos_sensor(kal_uint32 addr)
{kal_uint16 get_byte=<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> pu_send_cmd[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>] = {(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span>)(addr & <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xFF</span>) };iReadRegI2C(pu_send_cmd, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>, (u8*)&get_byte, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>, imgsensor.i2c_write_id);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> get_byte;}</code>
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> iReadRegI2C(u8 *a_pSendData, u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData,u16 i2cId)
{<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> i4RetValue = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) {spin_lock(&kdsensor_drv_lock);g_pstI2Cclient->addr = (i2cId >> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Remove i2c ack error log during search sensor */</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* PK_ERR("g_pstI2Cclient->ext_flag: %d", g_IsSearchSensor); */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_IsSearchSensor == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) {g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG;} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> {g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_A_FILTER_MSG);}spin_unlock(&kdsensor_drv_lock);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/*  */</span>i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeSendData) {PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n"</span>, a_pSendData[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;}i4RetValue = i2c_master_recv(g_pstI2Cclient, (<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *)a_pRecvData, a_sizeRecvData);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeRecvData) {PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C read failed!!\n"</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;}} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> {spin_lock(&kdsensor_drv_lock);g_pstI2Cclient2->addr = (i2cId >> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Remove i2c ack error log during search sensor */</span><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* PK_ERR("g_pstI2Cclient2->ext_flag: %d", g_IsSearchSensor); */</span><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_IsSearchSensor == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) {g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG;} <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> {g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) & (~I2C_A_FILTER_MSG);}spin_unlock(&kdsensor_drv_lock);i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeSendData) {PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n"</span>, a_pSendData[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;}i4RetValue = i2c_master_recv(g_pstI2Cclient2, (<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *)a_pRecvData, a_sizeRecvData);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeRecvData) {PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C read failed!!\n"</span>);<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>;}}<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>;
}</code>

   这一步完成I2c的读取,也就是说如果I2c配置正确,并且上电正确,到这一步就可以正确的读取ID,

个camera也就基本就调通了。

三、总结

     通过上述分析,我们可以看出,camera驱动先是注册平台驱动,再注册I2c驱动,然后又为前后摄注册

字符设备,封装底层方法,上层访问底层驱动时候显示使用setdriver将具体IC的驱动入口获取,然后使用

checkisalive对sensorlist中的IC进行上电,上电完成就读取设备ID,到此为止,上层应用与底层驱动挂接

完成,紧接着就是预览和拍照,不过这都是具体IC驱动的实现了。


相关文章:

  • Android5.0 MTk Camera HAL层代码分析
  • Android 按键流程分析笔记
  • SurfaceView及Surface分析
  • MediaRecord 分析
  • Android5.0 Camera HAL3 源代码分析
  • Ubuntu下Docker安装
  • TensorFlow中的一个重要op---MatMul的实现(一)
  • TensorFlow中的一个重要ops---MatMul的实现(二)
  • Android 窗口的计算过程
  • 基于docker安装spark
  • Android 渲染过程分析
  • 神经网络中 BP 算法的原理与 PYTHON 实现源码解析
  • TensorFlow word2vec_basic 代码分析
  • ibatis执行过程
  • freeswitch 在redhat 7.0/centos 7.0上的编译安装
  • freeswitch 使用的问题
  • coredump分析
  • freeswitch.Session的实现过程
  • freeswitch lua/luarun的执行过程
  • freeswitch Session dtmf callback的触发过程
  • NAT穿越原理——STUN
  • MRCP UA的创建及SIP信令处理
  • (转)WebRTC手记之初探
  • libnice simple-example 分析
  • libsrtp rtpw 例子代码分析
  • WebRTC直播技术(二)-ICE/STUN/TURN
  • Android binder 设计思想
  • 在Java中使用堆排序求解TopK问题
  • SIP穿越NAT的rport机制
  • SIP的路由机制
  • FreeSWITCH代码分析(一)
  • FreeSWITCH代码分析(二)
  • FreeSwitch全局配置文件处理流程
  • 媒体与媒体处理
  • APR内存池的学习与实现
  • B2B在FreeSwitch中的呼叫流程
  • Freeswitch常见问题解决办法
  • switch_core_session_run函数处理流程分析
  • Socket:读写处理及连接断开的检测
  • 解决xlite和freeswitch通话没有语音的问题
  • 路由有关的SIP消息头的简单小结
  • open source project 之 callback 函数
  • Asterisk 拨号计划之匹配规则和优先级详解
  • Asterisk鉴权算法
  • freeswitch 内核研究笔记1
  • freeswitch 媒体早期协商模式分析
  • CentOS 6.5 64位系统OpenSips 1.11部属配置
  • P2P NAT穿越
  • Chapter 3. Locking system
  • opensips架构图
  • freeswitch配置文件目录结构
  • 路由数据结构图
  • struct sock、struct inet_sock、strct inet_connection_sock和struct tcp_sock数据结构
  • 抖动和延迟之间的区别
  • 分布式知识学习计划
  • 高性能高并发服务的瓶颈及突破思路
  • 白话TCP运输控制(一) -- TCP的拥塞控制
  • 白话TCP运输控制(二) -- TCP的流量控制
  • 白话讲解Nagle算法和延迟确认
  • Linux I/O多路复用——select函数中的算法
  • 使用ffmpeg将实时流保存为AVI
  • Hash表为什么要扩容?
  • 记一次阿里云服务器中毒事件
  • 1.Class文件
  • ASN.1学习
  • 领域驱动设计(一)
  • 系统分析教辅资料
  • (一)问题领域
  • (二)涉众分析
  • 使用双栈(参数栈、状态栈)实现树的前、中、后序遍历
  • Array题型:双指针Two Pointers套路
  • FPGA:硬件描述语言简介
  • 喜格临床实验室设计方案
  • 生物安全实验室建设布局SICOLAB
  • 医院实验室建设基础配置情况SICOLAB
  • 江门医院实验室施工材料选择
  • 医学实验室建设基本布局科普
  • 佛山水质监测实验室布局
  • 广州水质检测实验室装修要求
  • 肇庆水质检测实验室实施方案分享
  • 水质检测实验室仪器大全
  • 河源云浮环境监测实验室工作区设计
  • 环境监测实验室监测知识科普
  • 江门环境监测实验室通风工程设计
  • 广州环境监测站配电工程施工方案
  • 江门环境监测站建设施工注意事项
  • 关于广州环境监测站平面设计原则
  • 环境监测实验室建设准备前构想
  • 韶关企业化验室建设布置方案
  • 梅州企业化验室建设规划细节
  • 揭阳企业化验室建设通风要求
  • 广东企业化验室建设布局事项
  • 潮州企业化验室建设可实行方案
  • 湛江化工厂实验室电气系统设计
  • 清远化工厂实验室初步设计流程
  • 探讨化工厂实验室组规划设计项目
  • 东莞化工厂实验室设计基本程序
  • 深圳新材料实验室建设干货
  • 清远新材料实验室建设布局分析
  • 潮州新材料实验室建设细节
  • 广州电子厂实验室建设施工装修
  • 广州药企检测中心实验室建设指南
  • 汕头食品检测中心实验室施工计划分析
  • 潮州质量检测中心实验室建设|装修方案
  • 食品检测中心实验室洁净计划
  • 怀化检测中心实验室施工结构规划
  • 广州研发实验室建设研究项目
  • 湛江研发实验室装修设计图|布局
  • 南宁药品研发实验室设计要点
  • 钦州研发中心实验室建设准备构想
  • 广州临床实验室设计人员通道布局
  • 揭阳临床实验室建设规范
  • 崇左临床实验室设计布置
  • 上饶临床实验室改造规划要点
  • 吉安临床实验室建设之构成区域
  • 韶关生物实验室建设平面布局
  • 清远生物实验室建设设计七大要点
  • 二级生物实验室防护设计基本要求
  • 九江生物安全实验室建设施工要求
  • 佛山医学实验室建设要求:空间布局
  • 漳州医学实验室建设储存设施
  • 泉州医学实验室设计通风系统建设
  • 医学实验室装修材料要求那些点
  • 医学实验室筹建前的构思
  • 佛山第三方检测机构实验室设计
  • 汕头第三方检测实验室建设之解决方案
  • 湛江第三方检测实验室建设4大事项
  • 参考第三方检测实验室装修布局大全
  • 福州第三方检测实验室设计需求
  • 佛山法医鉴定中心实验室施工方案
  • 法医检验鉴定中心实验室建设思路
  • 三明法医鉴定中心实验室筹建与装修
  • 广州DNA实验室功能区大改造
  • 江门DNA实验室规化方案介绍报告
  • 出入境检验实验室功能区设计大纲
  • 汕头出入境检验实验室建设案例
  • 泉州出入境检验实验室改造设计
  • 新余动物实验室建设注意事项
  • 上饶动物实验室建设大全
  • 佛山植物组织培养实验室必备设备
  • 梅州组织培养实验室之室内布局建设
  • 揭阳植物组培实验室组成设计汇总
  • 柳州植物组织培养实验室建设施工意义
  • 植物组织培养实验室之洗涤室建设
  • 佛山细胞实验室建设标准要求
  • 汕尾细胞实验室建设攻略
  • 潮州细胞实验室改造规划
  • 永州细胞实验室装修计划
  • 柳州细胞实验室局部建设规划
  • 惠州细胞房建设分析
  • 三明细胞房建设可行性分析
  • 崇左细胞房装修建设方案
  • 湘潭细胞房建设工程计划
  • 惠州无菌洁净室建设设计指南
  • 南平无菌洁净室建设方案总结
  • 惠州无菌实验室装修要点
  • 河源无菌实验室建设室内设计
  • 厦门无菌实验室建设施工技术
  • 上饶无菌实验室设计与施工事项
  • 深圳污水处理厂实验室建设手册
  • 广州核酸检测实验室建设关键点
  • 污水处理厂实验室之化验室通风设计
  • 南平污水处理厂实验室建设之设备科普
  • 龙岩核酸检测实验室之PCR建设
  • 佛山疾控中心实验室建设计划
  • 韶关疾病预防控制中心建设要点
  • 揭阳疾控中心实验室装修事项
  • 北海疾控中心实验室建设浅析
  • 梅州医院检验科建设标准:设计规范
  • 深圳实验室装修设计攻略
  • 深圳实验室装修材料注意事项
  • 深圳实验室装修排风合理设计
  • 深圳实验室装修材料考虑大全
  • 深圳实验室装修可施行方案
  • 深圳实验室装修步骤分析
  • 深圳实验室装修改造工程参考
  • 深圳实验室装修室内总结方案
  • 深圳,200平实验室装修布置
  • 实验室装修工程设计内容有哪些
  • 深圳实验室设计装修布置图
  • 深圳实验室设计参考事宜
  • 深圳实验室装修必看4大设想
  • 深圳实验室装修准备工作
  • 深圳实验室装修建设分析
  • 深圳实验室装修:建设借鉴
  • 深圳实验室设计合理化事项
  • 深圳实验室设计理念风格浅析
  • 深圳实验室设计,现场勘查事项
  • 深圳实验室设计新建思路
  • 广州医院病理科设计误区
  • 揭阳医院输血科建设考虑
  • 潮州PCR实验室建设运用范围
  • 肇庆PCR实验室建设消毒事项汇总
  • 河源医院检验科设计:空调设计方案
  • 解锁医院输血科建设之服务范围
  • 深圳第三方检测实验室建设发展分析
  • 广州干细胞实验室改造:洁净空调选择
  • 韶关干细胞实验室设计:要求汇总
  • 中山医院检验科室改造须知要求
  • 肇庆医院病理科室建设心得
  • 深圳实验室装修报价
  • 深圳SPF级动物实验室建设建议
  • 汕头ABSL-2实验室建设:内部规划
  • 汕头肥料检测实验室建设内容分析
  • 汕头GLP实验室建设知识概述
  • 汕头恒温恒湿实验室建设注意事项
  • 汕头实验台材质知识归纳
  • 惠州实验室装修:地面材料选用
  • 惠州实验室设计要考虑因素
  • 惠州实验室装修:地板工艺知识整理
  • 惠州实验室建设选址、勘察事项
  • 惠州中学生物学实验室建设指南
  • 惠州生物实验室建设宝典
  • 惠州药检实验室建设分区说明
  • 惠州生物实验室设计细节,建设大纲
  • 惠州口罩厂无尘车间建设选址概述
  • 惠州环境监测实验室建设面积要求
  • 惠州教学实验室建设与管理
  • 惠州放射性实验室建设:人员管理
  • 惠州GLP实验室建设:工作人员要求
  • 珠海塑料检测实验室建设:仪器配置说明
  • 珠海电池负极材料实验室建设之知识总结
  • 珠海化学分析实验室建设思路
  • 珠海动物实验室建设资料概述
  • 珠海污水处理厂实验室建设总结
  • 珠海植物组培实验室建设布局概述
  • 珠海分子病理实验室建设方案解析
  • 珠海食品理化检测实验室建设方案
  • 珠海废气处理方案大曝光
  • 珠海实验室通风系统建设安装说明
  • 珠海净化实验室建设细节概述
  • 涂料检测实验室建设背后事项
  • 梅州护理实验室建设:设备配置
  • 梅州细胞室建设思路
  • 梅州兽医实验室建设细节概述
  • 梅州临床实验室设计心得整理
  • 梅州发热门诊科室实验室建设内部规划分享
  • 梅州化验室建设细节整理分享
  • 梅州放射性实验室建设布局要求分析
  • 梅州通风柜设计安装那些事
  • 梅州锂电池生产车间建设一囊概括
  • 阳江锂电池实验室建设:除湿方式分享
  • 汽车零部件检测实验室建设考虑概述
  • 潮州疾控中心实验室设计要点整理
  • 潮州GMP车间建设选址科普
  • 潮州化验室建设布置要点总结SICOLAB
  • 潮州二恶英实验室建设布局概述
  • 潮州化妆品检测实验室建设指南
  • 潮州兽医实验室建设构想分析
  • 潮州土壤检测实验室建设内容曝光
  • 潮州恒温恒湿实验室建设要点说明
  • 湛江肥料检测实验室建设浅度解析
  • 湛江实验室建设布局科普
  • 湛江植物细胞实验室建设布局大盘点
  • 湛江SPF级动物实验室建设知识大全
  • 湛江化妆品实验室装修用材归纳
  • 湛江疾控中心实验室设计:物流走向
  • 湛江植物组培实验室建设考虑分析
  • 湛江油品检测实验室建设要点分析
  • 阳江实验室装修工艺大盘点
  • 阳江石油化工实验室建设说明归纳
  • 阳江口罩洁净厂房设计布置总结
  • 阳江医院实验室建设场地要求分析
  • 阳江兽医实验室建设考虑事项说明
  • 江门药检实验室建设知识整理
  • 江门生物安全实验室建设方案总结
  • 江门疾控中心实验室建设划分用房浅析
  • 江门化妆品实验室建设知识归纳
  • 江门GLP实验室建设事项分析
  • 韶关实验室设计要点汇总
  • 韶关实验室设计事项分享
  • 韶关干细胞制备实验室建设基本要求解析
  • 肇庆植物组培实验室建设灭菌说明
  • 肇庆实验室通风系统知识大盘点
  • 肇庆实验室家具安装步骤说明
  • 肇庆GLP实验室建设方案归纳
  • 茂名实验室设计大纲分析
  • 茂名实验室建设内容分析
  • 茂名兽医实验室建设细节化事项说明
  • 茂名植物组培实验室建设方向总结
  • 元宇宙3D设计系统【构思与展望】
  • 茂名HIV实验室建设:环境要求分享
  • 茂名水质检测实验室建设知识科普
  • 河源实验室建设合理化细节探讨
  • 河源实验室建设:选址事项分享
  • 河源微生物实验室建设合理化布置整理
  • 河源医院病理科实验室设计细节分析
  • 河源水质检测实验室建设方案曝光
  • 河源食品安全检测实验室建设细节剖析
  • 揭阳生物制药实验室建设方案归纳
  • 揭阳水质检测实验室建设选址须知事项
  • 河源环境监测站实验室建设布局考虑归纳
  • 清远高校实验室建设要点解析
  • 海南煤炭检测实验室设计要点大曝光
  • 海南疾控中心实验室建设工艺说明
  • 海南化学分析实验室设计工艺归纳
  • 海南饲料肥料检测实验室建设规划方案
  • 海南纺织品检测实验室设计工艺概述
  • 海南PCR实验室建设须知识整理
  • 海南涂料检测实验室建设细节分享
  • 海南油品检测实验室建设要点考虑
  • 海南环境监测站实验室建设:排水系统说明
  • 儋州门诊临床实验室建设原则归纳
  • 福州口罩洁净厂房建设知识概述
  • 福州核酸检测实验室建设须知事项探讨
  • 福州汽车零部件实验建设工作内容整理SICOLAB
  • 梅州二恶英实验室建设注意事项分享
  • 梅州植物组培实验室建设资料整理
  • 福州化工实验室建设注意隐患分析
  • 梅州P2实验室建设方案阐述
  • 三沙日用品检测实验室建设构想分析
  • 三沙纺织品检测实验室建设大纲
  • 三沙GMP车间设计要点探讨
  • 三沙煤炭检测实验室建设内容浅析
  • 三沙第三方检测实验室建设要点科普
  • 儋州清洁级动物实验室建设细节说明
  • 常德植物组培实验室建设一囊概括
  • 郴州干细胞实验室建设:强电系统解析
  • 永州二恶英实验室建设细节查看
  • 永州分析实验室建设选址概述
  • 永州植物细胞实验室建设布局方案
  • 永州水质检测实验室建设:家具说明
  • 永州清洁级动物实验室建设选址注意事项
  • 永州出入境检验实验室建设那些事
  • 永州动力电池实验室建设合理布局方案
  • 娄底妆品实验室建设规划构思
  • 娄底农产品检验实验室建设指南盘点
  • 娄底污水处理厂实验室建设管理
  • 娄底干细胞制备实验室建设须知要求
  • 娄底石油化工实验设计、建设规划概述
  • 娄底植物细胞实验室建设基本组成要点
  • 娄底疾控中心实验室设计理念说明
  • 娄底高校实验室建设材料考虑
  • 娄底无菌室建设须知事项汇总
  • 娄底医药工业洁净厂建设基本要点概述
  • 娄底锂电池隔膜研发实验室建设资料科普
  • 娄底可靠性检测实验室建设知识概述
  • 鹰潭实验室建设细节说明
  • 鹰潭实验室设计要素盘点
  • 鹰潭恒温恒湿实验室设计方案总结
  • 鹰潭病理实验室建设、筹建考虑因素
  • 兽医实验室人员建设:储备解析
  • 岑溪SPF级动物实验室设计平面布局规划查看
  • 岑溪洁净实验室设计布局规划总结
  • 岑溪化验室设计布置原则探讨
  • 岑溪农产品检验实验室建设细节概述
  • 锂电池实验室设计SICOLAB
  • 低露点实验室设计SICOLAB
  • 锂电动力实验室设计方案|SICOLAB
  • 锂电池净化厂房低湿车间装修SICOLAB
  • 锂动力研究院揭牌仪式 | SICOLAB喜格
  • 医院洁净手术室设计装修要点SICOLAB
  • 实验室电气设计有哪些要注意的SICOLAB
  • 恒温恒湿实验室(房)建设、设计SICOLAB
  • 化工厂理化实验室设计、化工厂实验室装修SICOLAB
  • 高校实验室设计SICOLAB高校实验室装修
  • 化学实验室装修验收标准SICOLAB
  • 计算机组成原理 | 第一章:概论
  • 【流媒体】Linux系统搭建Red5服务器
  • 【流媒体】Red5流媒体服务器开发总结
  • 【流媒体】Red5文件结构简介
  • 《剑指offer》源码笔记
  • 【LeetCode】max-points-on-a-line一条线上最多点
  • 【深度学习】---行人检测应用
  • 【LeetCode】binary-tree-postorder-traversal
  • 【LeetCode】recorder-list
  • 【LeetCode】linked-list-cycle-ii
  • 图片测距实验
  • 【LeetCode】palindrome-partitioning iii
  • 【深度学习】---行人检测应用二
  • 【LeetCode】triangle pascals-triangle iii
  • 【LeetCode】populating-next-roght-pointers-in-each-node iii
  • 【LeetCode】path-sum iii
  • 【LeetCode】convert-sorted-link-to-binary-search-tree convert-sorted-array-to-binary-search-tree
  • 【LeetCode】binary-tree-level-order-traversal iiizigzag
  • 【嵌入式开发】DM6467T环境搭建
  • 【LeetCode】partition-list
  • 【转】校园招聘面试-操作系统知识总结
  • verilog实现计算器设计
  • 【转】操作系统常见面试题总结
  • 【转】string和stringstream用法总结
  • 【转】 字符串的全排列和组合算法
  • faster-rcnn在win10+cuda8.0+1080ti+vs2013+matlab2015b下的配置 疑难问题解答
  • KCF环境搭建相关问题
  • LeetCode[200]岛屿数量
  • PAT——1039 到底买不买
  • javacv实现rtsp转rtmp(支持拉一路推多路)
  • javacv拉流保存为视频
  • gb28181简单实现sip信令服务器(java版基于springboot):一、netty创建udp服务器
  • gb28181简单实现sip信令服务器(java版基于springboot):四、sip摄像头心跳保活、推流(tcp/udp)和结束推流
  • gb28181简单解包rtp ps流,推出rtmp(java版基于springboot):五、基于netty创建接收流的udp和tcp服务器
  • gb28181简单解包rtp ps流,推出rtmp(java版基于springboot):六、解包rtp ps流,推出rtmp
  • 反向放大电路并联电容与积分电路并联电阻的区别?
  • 如何安装最新的Debugging Tools for Windows
  • 解决:QT VS tools The following error occured
  • QT安装完毕之后,设置系统环境变量!
  • dockwidget 设置里面的控件填满整个dockwidget的方法
  • 2020-04-19
  • java范型
  • JAVA泛型2
  • JAVA泛型3
  • JAVA泛型%d %f %s
  • idea 默认maven设置
  • idea exclude Dependencies以后如何恢复
  • SpringBoot 2.2.6 不能访问静态资源,以及不能访问默认主页index.html的解决
  • Eclipe source not found的解决办法
  • eclipse中使用“Copy Qualified Name”复制全类名
  • import javax.validation.constraints.Past 包找不到的解决办法
  • wx:key 加不加大括号的问题
  • throwable和Exception的区别
  • 为什么不能直接new Map
  • jeecgboot 同步数据库报错 NoClassDefFoundError: javax/xml/bind/JAXBException
  • jeecgboot上传时的token验证:记录一个蠢坑
  • Cannot resolve plugin org.apache.maven.plugins:maven-site-plugin:3.3
  • window.location对象详解
  • JSP(<%...%>)
  • springboot swagger 不显示接口的问题
  • 解决办法:The POM for org.eclipse.m2e:lifecycle-mapping:jar:1.0.0 is missing
  • 解决eclipse代码的自动提示问题
  • 字符串转化为 List 集合
  • 记录uniapp中view按下后改变背景样色样式的一个坑
  • uniapp 使用app.vue中globalData全局变量的方法 绑定到页面 实时刷新
  • uniapp swiper-item 禁止滑动的方法
  • css一个小问题:为什么写样式的时候有时要用点连着,有时要空格分开?
  • jeecgboot 2.3新建module无效的坑
  • 记录一个iview i-swtich开关组件属性true-value=“0“ false-value=“-1“的问题
  • vue iview中向后端请求springboot后端数据searchForm表单中字段显示undefined的问题。
  • iview 表单验证
  • mybatis ew.sqlSegment @Param(“ew“)
  • mybatis plus 自定义sql查询遇到的坑<where> ${ew.sqlSegment} </where>
  • mybatis plus 添加字段后 字段读取值为null的一个坑
  • 2020-11-7 iview input number 数字验证最新坑
  • DatePicker 编辑时如果无修改动作 时间格式为中国标准时间
  • uniapp中uni.login提示the code is a mock one
  • @Transactional找不到以及Consider defining a bean of type ‘XXX.Dao‘ in your configuration的问题
  • StringUtils.contains()所在的包 pom依赖
  • C++ 多线程编程实战11:std::async
  • eclipse常见错误总结(实习期总结)
  • 快速获得一个文件夹的所有文件的名称技巧
  • 2018.10.18-----2018-11-2小结
  • Timer--预约单
  • Spring boot学习日记 -HelloWorld
  • 预约单
  • @Transactional注解导致service注入失败及解决办法
  • mysql有则更新 没有则插入
  • 有赞预售订单初版
  • @Transactional注解乱用引发的异常
  • springcloud 小结
  • 字符串直接转list集合方法
  • 转载:springboot自定义注解
  • 自定义注解经验
  • socket转http 简单的认证功能
  • Mysql分区表 sql优化
  • 分布式任务调度平台xxl-job demo
  • 重构决定!
  • xxl-job demo
  • redis 缓存击穿事件记录
  • 启动监听ApplicationListener与CommandLineRunner
  • es demo
  • mysql数据同步到es
  • ELK日志监控平台搭建记录
  • macOS Ventura 13.2 (22D49) Boot ISO 原版可引导镜像
  • Excel导出用IE浏览器文件名乱码解决
  • 将逗号分隔的字符串转换为List
  • dozer
  • java导出excel模板,java设置excel模板只能输入时间,数字,excel输入限制
  • java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName
  • Jackson使用手册 https://www.cnblogs.com/miaosj/p/10936451.html
  • 修改菜单排序
  • 根据儿子找爹
  • 字符串转list
  • java导出word 拿来直接用
  • mybatis设置添加新对象数据的时候id使用uuid类型自动写入数据库
  • java 操作ftp服务器
  • 一个list 分批次
  • Gson转换实体
  • 获取指定月份的数据 当月初不是星期天 月末不是星期六的时候,增加前后一周的数据
  • sharding-jdbc Data sources cannot be empty.
  • window下启动多个jar
  • 自定义orm,快速完成增删改查
  • object 反射实体类set属性的值
  • 在项目中用到的转换
  • 写了一个上传excel到解析到数据库的通用类,只能作为参考
  • 反射获取service
  • Java导出浏览器下载
  • 时间公共类
  • sun.security.validator.ValidatorException
  • nacos多个环境下配置文件
  • resttemplate 跳过安全验证
  • WebSocket java客户端请求WSS
  • 用redis作为消息推送
  • com.alibaba.fastjson.JSONException: illegal identifier : \pos 1, json : {
  • socket客户端的测试代码
  • object转list
  • 构建模拟数据的时候需要模拟时间
  • json根据key进行排序
  • 按照人名排序
  • 结构结构结构结构结构结构结构结构结构
  • java中排序
  • 2.4.1 整数型