camera HAL与驱动交互初始化

1、概述

  前面提到注册一个字符设备时,attach上file_operation添加到system;然而file_operations 是为上层调用底层提供的接口;即HAL层就是通过调用file_operations中提供的接口,继而调用驱动进行对硬件的操作。

2、file_operations接口

2.1 open接口

static const struct file_operations g_stCAMERA_HW_fops = {
    .owner = THIS_MODULE,
    .open = CAMERA_HW_Open,
    .release = CAMERA_HW_Release,
    .unlocked_ioctl = CAMERA_HW_Ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl = CAMERA_HW_Ioctl_Compat,
#endif

};

  一般而言上层先先打开接口open,因此先看一下open函数的实现。整个函数就是对g_CamDrvOpenCnt变量进行了一个原子读的过程,没有进行别的操作,如下所示:

static int CAMERA_HW_Open(struct inode * a_pstInode, struct file * a_pstFile)
{
    //reset once in multi-open
    if ( atomic_read(&g_CamDrvOpenCnt) == 0) {
         //default OFF state
         //MUST have
         //kdCISModulePowerOn(DUAL_CAMERA_MAIN_SENSOR,"",true,CAMERA_HW_DRVNAME1);
         //kdCISModulePowerOn(DUAL_CAMERA_SUB_SENSOR,"",true,CAMERA_HW_DRVNAME1);
         //kdCISModulePowerOn(DUAL_CAMERA_MAIN_2_SENSOR,"",true,CAMERA_HW_DRVNAME1);

         //kdCISModulePowerOn(DUAL_CAMERA_MAIN_SENSOR,"",false,CAMERA_HW_DRVNAME1);
         //kdCISModulePowerOn(DUAL_CAMERA_SUB_SENSOR,"",false,CAMERA_HW_DRVNAME1);
         //kdCISModulePowerOn(DUAL_CAMERA_MAIN_2_SENSOR,"",false,CAMERA_HW_DRVNAME1);
    }

    //
    atomic_inc(&g_CamDrvOpenCnt);
    return 0;
}

2.2 release接口

static int CAMERA_HW_Release(struct inode *a_pstInode, struct file *a_pstFile)
{
    atomic_dec(&g_CamDrvOpenCnt);

    return 0;
}

此接口函数也是对g_CamDrvOpenCnt变量进行了一个原子读的过程,没有进行别的操作。

2.3 ioctl接口

   ioctl主要是接收上层传下来的一些命令,是android上层跟底层通讯的一种重要的方法。此处先说明一下:compat_ioctl被使用在用户空间为32位模式,而内核运行在64位模式时。这时候,需要将64位转成32位。关于unlocked_ioctl和compat_ioctl执行的顺序
对于ioctl操作,优先执行f_op->unlocked_ioctl,如果没有unlocked_ioctl,那么执行f_op->ioctl。为此再看看.unlocked_ioctl = CAMERA_HW_Ioctl操作。

static long CAMERA_HW_Ioctl(struct file *a_pstFile,unsigned int a_u4Command,unsigned long a_u4Param)
{
    int i4RetValue = 0;
    void *pBuff = NULL;
    u32 *pIdx = NULL;

    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("[CAMERA SENSOR] ioctl allocate mem failed\n");
            i4RetValue = -ENOMEM;
            goto CAMERA_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("[CAMERA SENSOR] ioctl copy from user failed\n");
                i4RetValue =  -EFAULT;
                goto CAMERA_HW_Ioctl_EXIT;
            }
        }
    }

    pIdx = (u32 *)pBuff;
    switch (a_u4Command) {

    case KDIMGSENSORIOC_X_SET_DRIVER:
        i4RetValue = kdSetDriver((unsigned int *)pBuff);
        break;
    case KDIMGSENSORIOC_T_OPEN:
        i4RetValue = adopt_CAMERA_HW_Open();
        break;
    case KDIMGSENSORIOC_X_GETINFO:
        i4RetValue = adopt_CAMERA_HW_GetInfo(pBuff);
        break;
    case KDIMGSENSORIOC_X_GETRESOLUTION2:
        i4RetValue = adopt_CAMERA_HW_GetResolution(pBuff);
        break;
    case KDIMGSENSORIOC_X_GETINFO2:
        i4RetValue = adopt_CAMERA_HW_GetInfo2(pBuff);
        break;
    case KDIMGSENSORIOC_X_FEATURECONCTROL:
        i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
        break;
    case KDIMGSENSORIOC_X_CONTROL:
        i4RetValue = adopt_CAMERA_HW_Control(pBuff);
        break;
    case KDIMGSENSORIOC_T_CLOSE:
        i4RetValue = adopt_CAMERA_HW_Close();
        break;
    case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
        i4RetValue = adopt_CAMERA_HW_CheckIsAlive();
        break;
    case KDIMGSENSORIOC_X_GET_SOCKET_POS:
        i4RetValue = kdGetSocketPostion((unsigned int *)pBuff);
        break;
    case KDIMGSENSORIOC_X_SET_I2CBUS:
        /* i4RetValue = kdSetI2CBusNum(*pIdx); */
        break;
    case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK:
        /* i4RetValue = kdReleaseI2CTriggerLock(); */
        break;

    case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE:
        i4RetValue = kdSensorSetExpGainWaitDone((int *)pBuff);
        break;

    case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:
        i4RetValue = kdSetCurrentSensorIdx(*pIdx);
        break;

    case KDIMGSENSORIOC_X_SET_MCLK_PLL:
        i4RetValue = kdSetSensorMclk(pBuff);
        break;

    case KDIMGSENSORIOC_X_SET_GPIO:
        i4RetValue = kdSetSensorGpio(pBuff);
        break;

    case KDIMGSENSORIOC_X_GET_ISP_CLK:
        /* PK_DBG("get_isp_clk=%d\n",get_isp_clk()); */
        /* *(unsigned int*)pBuff = get_isp_clk(); */
        break;

    default:
        PK_DBG("No such command\n");
        i4RetValue = -EPERM;
        break;

    }

    if (_IOC_READ & _IOC_DIR(a_u4Command)) {
        //将获得的数据传递给user空间
        if (copy_to_user((void __user *) a_u4Param , pBuff , _IOC_SIZE(a_u4Command))) {
            kfree(pBuff);
            PK_DBG("[CAMERA SENSOR] ioctl copy to user failed\n");
            i4RetValue =  -EFAULT;
            goto CAMERA_HW_Ioctl_EXIT;
        }
    }

    kfree(pBuff);
CAMERA_HW_Ioctl_EXIT:
    mutex_unlock(&kdCam_Mutex);
    return i4RetValue;
}

  camera模块主要就是通过ioctl接口,通过发送不同的cmd命令来与底层进行通信。

3、HAL层通过ioctl设置sensor驱动

  ->imgsensor_drv.cpp

MINT32
ImgSensorDrv::init(MINT32 sensorIdx)
{
    UCHAR cBuf[64];
    MINT32 ret = SENSOR_NO_ERROR;
    MUINT16 pFeaturePara16[2];
    MUINT32 FeaturePara32;
    MUINT32 FeatureParaLen;
    //MUINT32 sensorDrvInfo[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0,0};
    IMAGE_SENSOR_TYPE sensorType_prioriy = IMAGE_SENSOR_TYPE_UNKNOWN;
    ACDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResInfo[2];
    SENSOR_DEV_ENUM sensorDevId;

    if (  0 == sensorIdx ) {
        LOG_ERR("invalid sensorIdx[0x%08x] \n",sensorIdx);
        return SENSOR_INVALID_PARA;
    }
    //select driver
    if ( ( DUAL_CAMERA_MAIN_SENSOR|DUAL_CAMERA_MAIN_2_SENSOR ) == sensorIdx ) {
        //N3D mode
        SELECT_PRIORITY_DRIVER(main,N3D_PRIORITY_DRIVER);
    }
    else {
        //2D mode
        SELECT_PRIORITY_DRIVER(main,N2D_PRIORITY_DRIVER);
        //SELECT_PRIORITY_DRIVER(main2,N2D_PRIORITY_DRIVER);
        SELECT_PRIORITY_DRIVER(sub,N2D_PRIORITY_DRIVER);
    }
    //配置为前摄 或者后摄
    IMGSNESOR_FILL_SET_DRIVER_INFO(sensorIdx);
    //
    LOG_MSG("[init] mUsers = %d\n", mUsers);
    Mutex::Autolock lock(mLock);

    if (mUsers == 0) {
        if (m_fdSensor == -1) {
            sprintf(cBuf,"/dev/%s",CAMERA_HW_DEVNAME);
            m_fdSensor = ::open(cBuf, O_RDWR);
            if (m_fdSensor < 0) {
                LOG_ERR("[init]: error opening %s: %s \n", cBuf, strerror(errno));
                return SENSOR_INVALID_DRIVER;
            }
        }
    }


    //设置sensor驱动
    **ret = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,sensorDrvInit);**
    if (ret < 0) {
       LOG_ERR("[init]: ERROR:KDCAMERAHWIOC_X_SET_DRIVER\n");
    }

    android_atomic_inc(&mUsers);

    //init. resolution
    pSensorResInfo[0] = &m_SenosrResInfo[0];
    pSensorResInfo[1] = &m_SenosrResInfo[1];

    ret = getResolution(pSensorResInfo);
    if (ret < 0) {
        LOG_ERR("[init]: Get Resolution error\n");
        return SENSOR_UNKNOWN_ERROR;
    }


    if(SENSOR_MAIN & sensorIdx ) {
        sensorDevId = SENSOR_MAIN;

        //calculater g_LineTimeInus for exposure time convert.
        FeatureParaLen = sizeof(MUINTPTR);
        LOG_MSG("[featureControl]: SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ\n");
        ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ,  (MUINT8*)&FeaturePara32,(MUINT32*)&FeatureParaLen);
        if (ret < 0) {
           LOG_ERR("[init]:  SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ error\n");
           return SENSOR_UNKNOWN_ERROR;
        }

        FeatureParaLen = sizeof(pFeaturePara16);
        ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PERIOD,  (MUINT8*)pFeaturePara16,(MUINT32*)&FeatureParaLen);
        if (ret < 0) {
            LOG_ERR("[init]: SENSOR_FEATURE_GET_PERIOD error\n");
            return SENSOR_UNKNOWN_ERROR;
        }

        if (FeaturePara32 && FeaturePara32>1000) {
            //in setting domain, use preview line time only
            //sensor drv will convert to capture line time when setting to capture mode.
            m_LineTimeInus[0] = (MUINT32)(((MUINT64)pFeaturePara16[0]*1000000 + ((FeaturePara32/1000)-1))/(FeaturePara32/1000));   // 1000 base , 33657 mean 33.657 us
        } else {
            LOG_ERR("[init]:  SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ error = %d\n",FeaturePara32);
        }
        LOG_MSG("[init]: m_LineTimeInus[0] = %d\n", m_LineTimeInus[0] );
    }

    if((SENSOR_MAIN_2 & sensorIdx)|| (SENSOR_SUB & sensorIdx)) {
        if(SENSOR_MAIN_2 & sensorIdx) {
            sensorDevId = SENSOR_MAIN_2;
        }
        else {
            sensorDevId = SENSOR_SUB;
        }

        //calculater g_LineTimeInus for exposure time convert.
        FeatureParaLen = sizeof(MUINTPTR);
        ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ,  (MUINT8*)&FeaturePara32,(MUINT32*)&FeatureParaLen);
        if (ret < 0) {
           LOG_ERR("[init]:  SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ error\n");
           return SENSOR_UNKNOWN_ERROR;
        }

        FeatureParaLen = sizeof(pFeaturePara16);
        ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PERIOD,  (MUINT8*)pFeaturePara16,(MUINT32*)&FeatureParaLen);
        if (ret < 0) {
            LOG_ERR("[init]: SENSOR_FEATURE_GET_PERIOD error\n");
            return SENSOR_UNKNOWN_ERROR;
        }

        if (FeaturePara32 && FeaturePara32>1000) {
            //in setting domain, use preview line time only
            //sensor drv will convert to capture line time when setting to capture mode.
            m_LineTimeInus[1] = (MUINT32)(((MUINT64)pFeaturePara16[0]*1000000 + ((FeaturePara32/1000)-1))/(FeaturePara32/1000));   // 1000 base , 33657 mean 33.657 us
        } else {
            LOG_ERR("[init]:  SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ error = %d\n",FeaturePara32);
        }
        LOG_MSG("[init]: m_LineTimeInus[1] = %d\n", m_LineTimeInus[1] );
    }


    return SENSOR_NO_ERROR;
}

大致调用过程为:
ioctl(m_fdSensor,KDIMGSENSORIOC_X_SET_DRIVER,sensorDrvInit);->KDIMGSENSORIOC_X_SET_DRIVER->CAMERA_HW_Ioctl->copy_from_user->a_u4Command= KDIMGSENSORIOC_X_SET_DRIVER->kdSetDriver((unsigned int *)pBuff);
接下来分析一下kdSetDriver实现:

/*******************************************************************************
* kdSetDriver
********************************************************************************/
int kdSetDriver(unsigned int *pDrvIndex)
{
    .........
    if (0 != kdGetSensorInitFuncList(&pSensorList)) {
        PK_ERR("ERROR:kdGetSensorInitFuncList()\n");
        return -EIO;
    }

    for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
        /*  */
        spin_lock(&kdsensor_drv_lock);
        g_bEnableDriver[i] = FALSE;
         // 保存camera的sensorId
        g_invokeSocketIdx[i] = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_MSB) >> KDIMGSENSOR_DUAL_SHIFT);
        spin_unlock(&kdsensor_drv_lock);
        drvIdx[i] = (pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_LSB);
        /*  */
        if (DUAL_CAMERA_NONE_SENSOR == g_invokeSocketIdx[i]) {
                continue;
        }
        if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) {
            spin_lock(&kdsensor_drv_lock);
            gI2CBusNum = SUPPORT_I2C_BUS_NUM2;
            spin_unlock(&kdsensor_drv_lock);
            /* PK_XLOG_INFO("kdSetDriver: switch I2C BUS2\n"); */
        } else {
            spin_lock(&kdsensor_drv_lock);
            gI2CBusNum = SUPPORT_I2C_BUS_NUM1;
            spin_unlock(&kdsensor_drv_lock);
            /* PK_XLOG_INFO("kdSetDriver: switch I2C BUS1\n"); */
        }
        PK_INF("g_invokeSocketIdx[%d]=%d,drvIdx[%d]=%d\n", i, g_invokeSocketIdx[i], i, drvIdx[i]);
        /* PK_INF("[kdSetDriver]drvIdx[%d] = %d\n", i, drvIdx[i]); */
        /*  */
        if (MAX_NUM_OF_SUPPORT_SENSOR > drvIdx[i]) {
            if (NULL == pSensorList[drvIdx[i]].SensorInit) {
                PK_ERR("ERROR:kdSetDriver()\n");
                return -EIO;
            }

// 调用sensor模块驱动中的init函数,例如HI843B_MIPI_RAW_SensorInit;
pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);
            if (NULL == g_pInvokeSensorFunc[i]) {
                PK_ERR("ERROR:NULL g_pSensorFunc[%d]\n", i);
                return -EIO;
            }
            /*  */
            spin_lock(&kdsensor_drv_lock);
            g_bEnableDriver[i] = TRUE;
            spin_unlock(&kdsensor_drv_lock);
            /* get sensor name */
            memcpy((char *)g_invokeSensorNameStr[i], (char *)pSensorList[drvIdx[i]].drvname, sizeof(pSensorList[drvIdx[i]].drvname));
            /* return sensor ID */
            /* pDrvIndex[0] = (unsigned int)pSensorList[drvIdx].SensorId; */
            PK_INF("[%d][%d][%d][%s]\n", i, g_bEnableDriver[i], g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);
        }
    }
    return 0;
}

通过kdGetSensorInitFuncList获取sensor初始化列表,并把地址赋给pSensorList:

UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{
    if (NULL == ppSensorList) {
        PK_ERR("[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n");
        return 1;
    }
    *ppSensorList = &kdSensorList[0];
    return 0;
} /* kdGetSensorInitFuncList() */

ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
{
    ..............
#if defined(HI843B_MIPI_RAW)
    {HI843B_SENSOR_ID, SENSOR_DRVNAME_HI843B_MIPI_RAW,HI843B_MIPI_RAW_SensorInit},
#endif
/*  ADD sensor driver before this line */
    {0,{0},NULL}, //end of list
};

  获取到sensorlist后,回到kdSetDriver函数中继续往下分析pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);根据ID获取到对应的摄像头厂家,并调用其sensor驱动初始化函数,此处以HI843B_MIPI_RAW_SensorInit为例:

UINT32 HI843B_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
{
    /* To Do : Check Sensor status here */
    if (pfFunc!=NULL)
        *pfFunc=&sensor_func;
    return ERROR_NONE;
}   /*  HI843B_MIPI_RAW_SensorInit  */

该函数主要的作用是将sensor_func地址赋给结构体PSENSOR_FUNCTION_STRUCT 的变量pfFunc。而sensor_func其实是sensor驱动提供的接口,如下所示:

static SENSOR_FUNCTION_STRUCT sensor_func = {
    open,//.SensorOpen= open
    get_info,//.SensorGetInfo = get_info
    get_resolution,//.SensorGetResolution = get_resolution
    feature_control,//.SensorFeatureControl =  feature_control
    control,//.SensorControl = control
    close//.SensorClose = close
};

相信大家看到这个结构体一定不陌生了,因为它类似前面提到的file_operations。后面就可以通过此结构体提供的接口操作sensor驱动了。

4、总结

  本文分析HAL层怎么通过接口函数ioctl,一步步地进行sensor驱动设置过程。
如果你觉得好,随手点赞,也是对笔者的肯定,谢谢!

你可能感兴趣的:(kernel,Android,Camera系统框架分析)