mtk camera加載流程

平臺:mt6735

從imgsensor_drv.cpp中的impSearchSensor()函數說起。
MINT32
ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)
{
    MUINT32 SensorEnum = (MUINT32) DUAL_CAMERA_MAIN_SENSOR;
    MUINT32 i,id[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0,0};
    MBOOL SensorConnect=TRUE;
    UCHAR cBuf[64];
    MINT32 err = SENSOR_NO_ERROR;
    MINT32 err2 = SENSOR_NO_ERROR;
    ACDK_SENSOR_INFO_STRUCT SensorInfo;
    ACDK_SENSOR_CONFIG_STRUCT SensorConfigData;
    ACDK_SENSOR_RESOLUTION_INFO_STRUCT SensorResolution;
    MINT32 sensorDevs = SENSOR_NONE;
    IMAGE_SENSOR_TYPE sensorType = IMAGE_SENSOR_TYPE_UNKNOWN;
    IMGSENSOR_SOCKET_POSITION_ENUM socketPos = IMGSENSOR_SOCKET_POS_NONE;


    //! If imp sensor search process already done before,
    //! only need to return the sensorDevs, not need to
    //! search again.
    if (SENSOR_DOES_NOT_EXIST != m_mainSensorId) {
        //been processed.
        LOG_MSG("[impSearchSensor] Already processed \n");
        if (BAD_SENSOR_INDEX != m_mainSensorIdx) {
            sensorDevs |= SENSOR_MAIN;
        }
        if (BAD_SENSOR_INDEX != m_main2SensorIdx) {
            sensorDevs |= SENSOR_MAIN_2;
        }
        if (BAD_SENSOR_INDEX != m_subSensorIdx) {
            sensorDevs |= SENSOR_SUB;
        }

        #ifdef  ATVCHIP_MTK_ENABLE

            sensorDevs |= SENSOR_ATV;

        #endif


        return sensorDevs;
    }

    GetSensorInitFuncList(&m_pstSensorInitFunc);

    LOG_MSG("SENSOR search start \n");

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

    // search main/main_2/sub 3 sockets
#ifdef MTK_MAIN2_IMGSENSOR
    for (SensorEnum = DUAL_CAMERA_MAIN_SENSOR; SensorEnum <= DUAL_CAMERA_MAIN_2_SENSOR; SensorEnum <<= 1)  {
        LOG_MSG("impSearchSensor search to main_2\n");
#else
   #ifdef MTK_SUB_IMGSENSOR
    for (SensorEnum = DUAL_CAMERA_MAIN_SENSOR; SensorEnum <= DUAL_CAMERA_SUB_SENSOR; SensorEnum <<= 1)  {
        LOG_MSG("impSearchSensor search to sub\n");
   #else
    for (SensorEnum = DUAL_CAMERA_MAIN_SENSOR; SensorEnum < DUAL_CAMERA_SUB_SENSOR; SensorEnum <<= 1)  {
        LOG_MSG("impSearchSensor search to main\n");
   #endif
#endif


        //
        for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {
            //end of driver list
            if (m_pstSensorInitFunc[i].getCameraDefault == NULL) {
                LOG_MSG("m_pstSensorInitFunc[i].getCameraDefault is NULL: %d \n", i);
                break;
            }
                //set sensor driver
            id[KDIMGSENSOR_INVOKE_DRIVER_0] = (SensorEnum << KDIMGSENSOR_DUAL_SHIFT) | i;
            LOG_MSG("set sensor driver id =%x\n", id[KDIMGSENSOR_INVOKE_DRIVER_0]);
            err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
                if (err < 0) {
                    LOG_ERR("ERROR:KDCAMERAHWIOC_X_SET_DRIVER\n");
                }


                //err = open();
                err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);


                if (err < 0) {
                    LOG_MSG("[impSearchSensor] Err-ctrlCode (%s) \n", strerror(errno));
                }
            //
            sensorType = this->getCurrentSensorType((SENSOR_DEV_ENUM)SensorEnum);
            //
            socketPos = this->getSocketPosition((CAMERA_DUAL_CAMERA_SENSOR_ENUM)SensorEnum);
                //check extra ID , from EEPROM maybe
                //may need to keep power here
                if (NULL != pExIdChkCbf) {
                    err2 = pExIdChkCbf();
                    if (err2 < 0) {
                        LOG_ERR("Error:pExIdChkCbf() \n");
                    }
                }

                //power off sensor
                //close(SensorEnum);//ToDo: Check if necessary

                if (err < 0 || err2 < 0) {
                    LOG_MSG("sensor ID mismatch\n");
                }
                else {
                    if (SensorEnum == DUAL_CAMERA_MAIN_SENSOR) {
                //m_mainSensorIdx = i;
                //m_mainSensorId = m_pstSensorInitFunc[m_mainSensorIdx].SensorId;
                m_mainSensorDrv.index[m_mainSensorDrv.number] = i;
                m_mainSensorDrv.type[m_mainSensorDrv.number] = sensorType;
                if ( IMAGE_SENSOR_TYPE_RAW == sensorType && BAD_SENSOR_INDEX == m_mainSensorDrv.firstRawIndex ) {
                    m_mainSensorDrv.firstRawIndex = i;
                }
                else if ( IMAGE_SENSOR_TYPE_YUV == sensorType && BAD_SENSOR_INDEX == m_mainSensorDrv.firstYuvIndex ) {
                    m_mainSensorDrv.firstYuvIndex = i;
                }
                m_mainSensorDrv.position = socketPos;
                m_mainSensorDrv.sensorID = m_pstSensorInitFunc[m_mainSensorDrv.index[m_mainSensorDrv.number]].SensorId;
                // LOG_MSG("MAIN sensor m_mainSensorDrv.number=%d, m_mainSensorDrv.index=%d\n",m_mainSensorDrv.number,m_mainSensorDrv.index[m_mainSensorDrv.number]);
                m_mainSensorDrv.number++;
                //
                m_pMainSensorInfo = m_pstSensorInitFunc[i].pSensorInfo;
                if  ( m_pMainSensorInfo )
                {
                    NSFeature::SensorInfoBase* pSensorInfo = m_pstSensorInitFunc[i].pSensorInfo;
                    LOG_MSG("found <%#x/%s/%s>", pSensorInfo->GetID(), pSensorInfo->getDrvName(), pSensorInfo->getDrvMacroName());
                }
                else
                {
                    LOG_WRN("m_pMainSensorInfo==NULL\n");
                }
                LOG_MSG("MAIN sensor found:[%d]/[0x%x]/[%d]/[%d] \n",i,id[KDIMGSENSOR_INVOKE_DRIVER_0],sensorType,socketPos);
                //break;
            }
            else if (SensorEnum == DUAL_CAMERA_MAIN_2_SENSOR) {
                //m_main2SensorIdx = i;
                //m_main2SensorId = m_pstSensorInitFunc[m_main2SensorIdx].SensorId;

                m_main2SensorDrv.index[m_main2SensorDrv.number] = i;
                m_main2SensorDrv.type[m_main2SensorDrv.number] = sensorType;
                if ( IMAGE_SENSOR_TYPE_RAW == sensorType && BAD_SENSOR_INDEX == m_main2SensorDrv.firstRawIndex ) {
                    m_main2SensorDrv.firstRawIndex = i;
                }
                else if ( IMAGE_SENSOR_TYPE_YUV == sensorType && BAD_SENSOR_INDEX == m_main2SensorDrv.firstYuvIndex ) {
                    m_main2SensorDrv.firstYuvIndex = i;
                }
                m_main2SensorDrv.position = socketPos;
                m_main2SensorDrv.sensorID = m_pstSensorInitFunc[m_main2SensorDrv.index[m_main2SensorDrv.number]].SensorId;
                //LOG_MSG("MAIN2 sensor m_main2SensorDrv.number=%d, m_main2SensorDrv.index=%d\n",m_main2SensorDrv.number,m_main2SensorDrv.index[m_main2SensorDrv.number]);
                m_main2SensorDrv.number++;
                //
                m_pMain2SensorInfo = m_pstSensorInitFunc[i].pSensorInfo;
                if  ( m_pMain2SensorInfo )
                {
                    NSFeature::SensorInfoBase* pSensorInfo = m_pstSensorInitFunc[i].pSensorInfo;
                    LOG_MSG("found <%#x/%s/%s>", pSensorInfo->GetID(), pSensorInfo->getDrvName(), pSensorInfo->getDrvMacroName());
                }
                else
                {
                    LOG_WRN("m_pMain2SensorInfo==NULL\n");
                }
                LOG_MSG("MAIN_2 sensor found:[%d]/[0x%x]/[%d]/[%d] \n",i,id[KDIMGSENSOR_INVOKE_DRIVER_0],sensorType,socketPos);
            }
            else if (SensorEnum == DUAL_CAMERA_SUB_SENSOR) {
                //m_subSensorIdx = i;
                //m_subSensorId = m_pstSensorInitFunc[m_subSensorIdx].SensorId;
                m_subSensorDrv.index[m_subSensorDrv.number] = i;
                m_subSensorDrv.type[m_subSensorDrv.number] = sensorType;
                if ( IMAGE_SENSOR_TYPE_RAW == sensorType && BAD_SENSOR_INDEX == m_subSensorDrv.firstRawIndex ) {
                    m_subSensorDrv.firstRawIndex = i;
                }
                else if ( IMAGE_SENSOR_TYPE_YUV == sensorType && BAD_SENSOR_INDEX == m_subSensorDrv.firstYuvIndex ) {
                    m_subSensorDrv.firstYuvIndex = i;
                }
                m_subSensorDrv.position = socketPos;
                m_subSensorDrv.sensorID = m_pstSensorInitFunc[m_subSensorDrv.index[m_subSensorDrv.number]].SensorId;
                //LOG_MSG("SUB sensor m_subSensorDrv.number=%d, m_subSensorDrv.index=%d\n",m_subSensorDrv.number,m_subSensorDrv.index[m_subSensorDrv.number]);
                m_subSensorDrv.number++;
                //
                m_pSubSensorInfo = m_pstSensorInitFunc[i].pSensorInfo;
                if  ( m_pSubSensorInfo )
                {
                    NSFeature::SensorInfoBase* pSensorInfo = m_pstSensorInitFunc[i].pSensorInfo;
                    LOG_MSG("found <%#x/%s/%s>", pSensorInfo->GetID(), pSensorInfo->getDrvName(), pSensorInfo->getDrvMacroName());
                }
                else
                {
                    LOG_WRN("m_pSubSensorInfo==NULL\n");
                }
                LOG_MSG("SUB sensor found:[%d]/[0x%x]/[%d]/[%d] \n",i,id[KDIMGSENSOR_INVOKE_DRIVER_0],sensorType,socketPos);
                //break;
            }
        }//

        }
    }
    //close system call may be off sensor power. check first!!!
    if(m_fdSensor >= 0)
    {
        ::close(m_fdSensor);
        m_fdSensor = -1;
    }

    //
    if (BAD_SENSOR_INDEX != m_mainSensorDrv.index[0]) {
        m_mainSensorId = m_mainSensorDrv.sensorID;
        //init to choose first
        m_mainSensorIdx = m_mainSensorDrv.index[0];
        sensorDevs |= SENSOR_MAIN;
    }
    if (BAD_SENSOR_INDEX != m_main2SensorDrv.index[0]) {
        m_main2SensorId = m_main2SensorDrv.sensorID;
        //init to choose first
        m_main2SensorIdx = m_main2SensorDrv.index[0];
        sensorDevs |= SENSOR_MAIN_2;
    }
    if (BAD_SENSOR_INDEX != m_subSensorDrv.index[0]) {
        m_subSensorId = m_subSensorDrv.sensorID;
        //init to choose first
        m_subSensorIdx = m_subSensorDrv.index[0];
        sensorDevs |= SENSOR_SUB;
    }

    #ifdef  ATVCHIP_MTK_ENABLE

        sensorDevs |= SENSOR_ATV;

    #endif


    if (sensorDevs == SENSOR_NONE) {
        LOG_ERR( "Error No sensor found!! \n");
    }
    //
    LOG_MSG("SENSOR search end: 0x%x /[0x%x][%d]/[0x%x][%d]/[0x%x][%d]\n", sensorDevs,
    m_mainSensorId,m_mainSensorIdx,m_main2SensorId,m_main2SensorIdx,m_subSensorId,m_subSensorIdx);

    return sensorDevs;
}//

1. 首先獲取hal層的sensor列表。
GetSensorInitFuncList(&m_pstSensorInitFunc);

GetSensorInitFuncList()函數代碼如下(sensorlist.cpp)

UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{
    if (NULL == ppSensorList) {
        ALOGE("ERROR: NULL pSensorList\n");
        return MHAL_UNKNOWN_ERROR;
    }
    *ppSensorList = &SensorList[0];
	return MHAL_NO_ERROR;
} // GetSensorInitFuncList()
也就是得到一個sensor列表。

如果你要新增一個camera,必須在這個數組中使用RAW_INFO或YUV_INFO宏新增一個成員。

然後使用open函數打開一個字符設備,hal層同驅動層的接口實際上實際上是通過一個字符設備,這個字符設備提供了相應的fops操作,使用最多的當然是ioctl函數。


2. set driver
默認android中只支持兩個camera,即前camera、後camera,所以在這裏首先是要找到這兩個camera(先後camera、再前camera)。

而在mtk平臺代碼中,最多支持16種攝像頭配置,然後是調用ioctl函數。

ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );

ioctl接口函數爲kd_sensorlist.c的中的CAMERA_HW_Ioctl()函數。

而kdSetDriver代碼如下:
int kdSetDriver(unsigned int *pDrvIndex)
{
    ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
    u32 drvIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0, 0};
    u32 i;

    /* set driver for MAIN or SUB sensor */
    PK_INF("pDrvIndex:0x%08x/0x%08x\n", pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0], pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_1]);

    /* Camera information */
    gDrvIndex = pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0];

    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;
    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 0
            if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i] || DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) {
            spin_lock(&kdsensor_drv_lock);
            gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]];
            spin_unlock(&kdsensor_drv_lock);
            PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum);
            }
#else

    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"); */
    }
#endif
    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;
        }

        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;
}
kdSetDriver()函數有一個參數,這個參數是由impSearchSensor()傳下來的,如果主(後)camera,那麼這個值是10000、10001、10002等,如果是次(前)camera,那麼這個值是20000、20001、20002等。

在kdSetDriver函數中,首先調用kdGetSensorInitFuncList()函數去獲得kernel中定義的sensor列表。

來到for循環那裏,如果是後camera,那麼g_invokeSocketIdx[0]的值應爲1,如果是前camera,那麼應是2。而drvIdx[0]的值是sensor驅動列表的索引號,例如0、1、2等。

設置i2c的總線號,再來到最後面的if語句處,根據drvIdx[0]找到驅動中定義的sensor代碼,調用驅動中的SensorInit函數,這樣就得到了具體sensor驅動的接口。

最後把sensor驅動的name字段拷貝到g_invokeSensorNameStr[0]這裏。

注意傳給kdSetDriver()的id值只有一個,例如10000,所以第2遍for循環是不會走到最後的(continue掉)。

再回到impSearchSensor()。


3. check is alive
前面已經指定了一個sensor驅動,那麼這裏就會調用ioctl函數去檢查驅動和camera設備是否匹配。

調用的是kd_sensorlist.c中的adopt_CAMERA_HW_CheckIsAlive()函數。
inline static int adopt_CAMERA_HW_CheckIsAlive(void)
{
    UINT32 err = 0;
    UINT32 err1 = 0;
    UINT32 i = 0;
    MUINT32 sensorID = 0;
    MUINT32 retLen = 0;
#ifndef CONFIG_MTK_FPGA
    KD_IMGSENSOR_PROFILE_INIT();
    /* power on sensor */
    kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *)g_invokeSocketIdx, g_invokeSensorNameStr, true, CAMERA_HW_DRVNAME1);
    /* wait for power stable */
    mDELAY(10);
    KD_IMGSENSOR_PROFILE("kdModulePowerOn");

    /* initial for search sensor function */
    g_CurrentSensorIdx = 0;
    /* Search sensor keep i2c debug log */
    g_IsSearchSensor = 1;
    /* Camera information */
    if(gDrvIndex == 0x10000)
    {
        memset(mtk_ccm_name,0,camera_info_size);
    }

    if (g_pSensorFunc) {
    for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
        if (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) {
        err = g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i], SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *)&sensorID, &retLen);
        if (sensorID == 0) {    /* not implement this feature ID */
            PK_DBG(" Not implement!!, use old open function to check\n");
            err = ERROR_SENSOR_CONNECT_FAIL;
        }
        else if (sensorID == 0xFFFFFFFF) {    /* fail to open the sensor */
            PK_DBG(" No Sensor Found");
            err = ERROR_SENSOR_CONNECT_FAIL;
        }
        else {

            PK_INF(" Sensor found ID = 0x%x\n", sensorID);
            snprintf(mtk_ccm_name,sizeof(mtk_ccm_name),"%s CAM[%d]:%s;",mtk_ccm_name,g_invokeSocketIdx[i],g_invokeSensorNameStr[i]);
            err = ERROR_NONE;
        }
        if (ERROR_NONE != err)
        {
            PK_DBG("ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n");
        }
        }
    }
    }
    else {
    PK_DBG("ERROR:NULL g_pSensorFunc\n");
    }

    /* reset sensor state after power off */
    err1 = g_pSensorFunc->SensorClose();
    if (ERROR_NONE != err1) {
    PK_DBG("SensorClose\n");
    }
    /*  */
    kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *)g_invokeSocketIdx, g_invokeSensorNameStr, false, CAMERA_HW_DRVNAME1);
    /*  */
    KD_IMGSENSOR_PROFILE("CheckIsAlive");
#else
    err = ERROR_SENSOR_CONNECT_FAIL;
#endif
    g_IsSearchSensor = 0;

    return err ?  -EIO:err;
}   /* adopt_CAMERA_HW_Open() */
首先是調用kdModulePowerOn()給模塊上電,等待10毫秒,來到for循環這裏。

調用sensor驅動的SensorFeatureControl接口去讀取sensor的id。sensor id只要大於0、小於0xffffffff都是合法的。

sensor id讀取完成之後再關閉掉模塊電源。

再回到impSearchSensor()。

只要這個id值找到,那麼表示驅動已經匹配上了,但是在impSearchSensor()函數中,找到並不意味着結束,for循環還是會繼續進行下去的,就是所有定義的sensor驅動都還是會去遍歷一遍。那麼這就是找到一個sensor的流程,先主(後)camera,後次(前)camera。

找後camera,會遍歷一遍sensor列表,找前camera,再遍歷一遍sensor列表,注意模塊的上電,id值的讀取。


// 2016-10-21 add
根據impSearchSensor()函數,如果有定義輔攝像頭,那麼需要定義宏MTK_SUB_IMGSENSOR,否則的話是不會去搜索輔攝像頭的。

MTK_SUB_IMGSENSOR宏是在hal層的Android.mk中被定義的,定義的前提是在ProjectConfig.mk中CUSTOM_KERNEL_SUB_IMGSENSOR要配置一下,否則不會去搜尋輔攝像頭的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章