SA8650 camera messagedispatcher

// waits for async calls to complete according to call mask and specified timeout
//static CamStatus_e qcxsi_WaitForInitComplete(const uint32_t callMask, uint64_t *pTimeoutMs);

/***================================================================================================
** Variables
================================================================================================**/

// none

/***================================================================================================
                        FUNCTION DEFINITIONS
================================================================================================**/


CamStatus_e SI_Init(boolean bEnableCCIDbgr)
{
    CamStatus_e         status          = CAMERA_EFAILED;
    CamStatus_e         status1         = status;

    //To do: need to remove this
    QCarCamInit_t init_params = {0};
    init_params.apiVersion = QCARCAM_VERSION_MINOR;
    // Camera KPI requires < 2 seconds from system boot to 1st frame on display.
    // Assuming,
    // - 1600ms is used in other boot time system initialization.
    // -  200ms is used by other parts of the camera driver initialization.  We left with
    // -  200ms max budget to wait for all async calls to complete.
    // -  Additional delay of 5 millisecond is required for single camera detection
    //    per port usecase, this is the requirement for ti960 only.
    // TODO: Temporarily increasing timeout to 1700ms assuming 16 TI971 cameras are connected,
    //       each of those can roughly take 100ms to initialize + 100 ms for init of other
    //       components of the camera driver.
    //uint64_t            timeoutMs       = 1700U;

    QCX_KPI_LOG_START();

    SI_ON_ENTER();

#ifdef FEAT_ENABLE_CCIDBGR
    if(bEnableCCIDbgr == TRUE)
    {
        PLM_enable_ccidbgr(bEnableCCIDbgr);
    }
#endif
    // Clocks should be enabled before DM_Init() registers with safety monitor
    if (CAMERA_SUCCESS != (status1 = PLM_Init()))
    {
        SI_LOGE1("PLM_Init failed: 0x%08x", status1);
    }
    else if (CAMERA_SUCCESS != (status1 = MD_Init()))
    {
        SI_LOGE1("MD_Init failed: 0x%08x", status1);
        (void) qcxsi_Deinit(DEINIT_FROM_PLM);
    }
    // To do: Need to do STRM_Initialize() via MD
    else if (CAMERA_SUCCESS != (status1 = STRM_Initialize(&init_params)))
    {
        SI_LOGE1("STRM_Initialize failed: 0x%08x", status1);
        (void) qcxsi_Deinit(DEINIT_FROM_MD);
    }
    else if (CAMERA_SUCCESS != (status1 = CM_ServerInit()))
    {
        SI_LOGE1("CM_ServerInit failed: 0x%08x", status1);
        (void) qcxsi_Deinit(DEINIT_FROM_STRM);
    }
    else
    {
        // success
    }

    // status1 from above should have captured a SUCCESS or a
    // non-CAMERA_EFAILED failure.  If it contained CAMERA_EFAILED,
    // it means one of the calls it made returns the value, which
    // is a bug that must be fixed.
    if (CAMERA_EFAILED == status1)
    {
        SI_LOGF0("Logic error: Fix me");
    }

    status = status1;

    SI_ON_EXIT(status);

    if(CAMERA_SUCCESS == status)
    {
        QCX_KPI_LOG_READY();
    }

    return status;
}

 初始化 massage dispatcher

/**
*@brief Initialize message dispatcher
*        Initialization comprises creation of queues, command and event threads
*
*@param void
*
*@return Status as defined in CamStatus_e
*/
CamStatus_e MD_Init (
    void)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;

    QCX_LOG(MSG_DPR, HIGH, "MD Init Enter");

    if (NULL != OSAL_Memset(&g_mdCtxt, 0x0, sizeof(MDCtxt_t)))
    {
        qcxStatus = CAMERA_SUCCESS;
    }
    else
    {
        QCX_LOG(MSG_DPR, ERROR,
                "OSAL Memset failed (result = 0x%X)", qcxStatus);

        qcxStatus = CAMERA_EFAILED;
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        qcxStatus = MD_CmdCtxtInit(&g_mdCtxt.cmdCtxt);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                    "MD cmd ctxt init failed (result = 0x%X)", qcxStatus);
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        qcxStatus = MD_EventCtxtInit(&g_mdCtxt.eventCtxt);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                    "MD event ctxt init failed (result = 0x%X)", qcxStatus);
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        qcxStatus = MD_ErrorEventCtxtInit(&g_mdCtxt.errorEventCtxt);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                    "MD error event ctxt init failed (result = 0x%X)", qcxStatus);
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        // Register callback with Platform
        qcxStatus = PLM_RegisterCallback(&MD_PLMCallback);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                      "PLM_RegisterCallback failed (result = 0x%X)", qcxStatus);
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        qcxStatus = CMCSync_Init();

        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                "CMCSync_Init failed (qcxStatus = 0x%X)", qcxStatus);
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        QCX_LOG(MSG_DPR, HIGH,
                "MD Init success (result = 0x%X)", qcxStatus);
    }
    else
    {
        QCX_LOG(MSG_DPR, ERROR,
                "MD Init failed (result = 0x%X)", qcxStatus);
    }

    return qcxStatus;
}

 创建cmd thread 线程池

/**
*@brief Perform initialization of command context
*
*@param pCmdCtxt[In] Pointer to command context
*
*@return Status as defined in CamStatus_e
*/
static CamStatus_e MD_CmdCtxtInit (
    CmdCtxt_t* pCmdCtxt)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;

    if (NULL == pCmdCtxt)
    {
        qcxStatus = CAMERA_EBADPARAM;
        QCX_LOG(MSG_DPR, ERROR, "Bad param. NULL cmd ctxt");
    }
    else
    {
        qcxStatus = OSAL_CriticalSectionCreate(&pCmdCtxt->cmdCtxtMutex);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                    "Cmd mutex init failed (result = 0x%X)",
                    qcxStatus);
        }

        if (CAMERA_SUCCESS == qcxStatus)
        {
            for (uint32_t idx = 0U; idx < MAX_NUM_COMMAND_THREADS; idx++)
            {
                // Create pool of cmd threads
                qcxStatus = MD_CmdThreadCtxtInit(&pCmdCtxt->cmdThreadList[idx], idx);
                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(MSG_DPR, ERROR,
                            "Cmd thread ctxt init failed (idx = %u, result = 0x%X)",
                            idx, qcxStatus);
                    break;
                }
            }
        }
    }

    return qcxStatus;
}

 初始化cmdthread

/**
*@brief Perform initialization of command thread context
*
*@param pCmdThreadCtxt [In] Pointer to command thread context
*@param threadIdx[In] Index of command thread context
*
*@return Status as defined in CamStatus_e
*/
static CamStatus_e MD_CmdThreadCtxtInit (
    CmdThrdCtxt_t* pCmdThreadCtxt,
    const uint32_t threadIdx)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;

    if (NULL == pCmdThreadCtxt)
    {
        qcxStatus = CAMERA_EBADPARAM;
        QCX_LOG(MSG_DPR, ERROR, "Bad param. NULL thread ctxt");
    }
    else
    {
        // Set thread Id
        pCmdThreadCtxt->cmdThrdId = threadIdx;

        // Create blocking queue for cmd thread
        qcxStatus = QCXQueueCreate (sizeof(MDCmdMsg_t),
                                     CMD_Q_SIZE,
                                     TRUE,
                                     &pCmdThreadCtxt->hCmdThrdQ);

        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(MSG_DPR, ERROR,
                    "Cmd ctxt queue creation failed (idx = %u, result = 0x%X)",
                    threadIdx, qcxStatus);
        }

        if (CAMERA_SUCCESS == qcxStatus)
        {
            // Create cmd thread
            char threadName[MD_MAX_NAME_SIZE] = {0};
            int32_t result = snprintf(threadName, sizeof(threadName),
                                  "cmd_thrd_%X", threadIdx);

            if (0 < result)
            {
                qcxStatus = OSAL_ThreadCreate(QCXThreadRealtimePriority,
                                              &MD_CommandThread,
                                              pCmdThreadCtxt,
                                              0,
                                              threadName,
                                              &pCmdThreadCtxt->hCmdThrd);

                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(MSG_DPR, ERROR,
                            "Cmd thread queue creation failed (idx = %u, result = 0x%X)",
                            threadIdx, qcxStatus);
                }
            }
            else
            {
                qcxStatus = CAMERA_EFAILED;
                QCX_LOG(MSG_DPR, ERROR,
                        "Failed to set thread name (idx = %u, result = 0x%X)",
                         threadIdx, qcxStatus);
            }
        }
    }

    return qcxStatus;
}

 

*
*@param pArg[In] Pointer to thread arguments
*        Points to command thread context
*
*@return 0 if successful
*/
static int32_t MD_CommandThread (
    void* pArg)
{
    CmdThrdCtxt_t* pCmdThrdCtxt = (CmdThrdCtxt_t*)pArg;
    CamStatus_e qcxStatus = CAMERA_EFAILED;
    volatile boolean bAbortThread = FALSE;
    uint32_t n_attempts = 0U;

    while (FALSE == bAbortThread)
    {
        boolean bRelCtxt = FALSE;
        MDCmdMsg_t cmdMsg = {0};

        // Wait until message is available to be dequeued
        qcxStatus = MD_CmdDequeue(pCmdThrdCtxt,
                                  &cmdMsg);

        if (CAMERA_EFAILED == qcxStatus)
        {
            // End while loop if exit notification is received
            bAbortThread = TRUE;

            QCX_LOG(MSG_DPR, HIGH,
                    "Cmd Q received exit notification (msgType = %d, ctxt = %u, result = 0x%X)",
                    cmdMsg.msgType, pCmdThrdCtxt->cmdThrdId, qcxStatus);
        }
        else if (CAMERA_SUCCESS != qcxStatus)
        {
            // Retry if dequeue fails
            // If dequeue fails more than MAX_NUM_DEQUEUE_ATTEMPTS,
            // set thread abort flag and exit
            if (MAX_NUM_DEQUEUE_ATTEMPTS < n_attempts)
            {
                bAbortThread = TRUE;
            }
            else
            {
                n_attempts++;
            }

            QCX_LOG(MSG_DPR, ERROR,
                    "Dequeue cmd failed (msgType = %d, ctxt = %u, result = 0x%X)",
                    cmdMsg.msgType, pCmdThrdCtxt->cmdThrdId, qcxStatus);
        }
        else
        {
            n_attempts = 0U;

            qcxStatus = MD_ProcessCmd(&cmdMsg, &bRelCtxt);

            if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(MSG_DPR, ERROR,
                        "Process cmd failed (msgType = %d, ctxt = %u, result = 0x%X)",
                        cmdMsg.msgType, pCmdThrdCtxt->cmdThrdId, qcxStatus);
            }
        }
    }

    if ((CAMERA_SUCCESS == qcxStatus) || (CAMERA_EFAILED == qcxStatus))
    {
        QCX_LOG(MSG_DPR, LOW, "Exit Cmd Thread (ctxt = %u, result = 0x%X)",
                pCmdThrdCtxt->cmdThrdId, qcxStatus);
    }
    else
    {
        QCX_LOG(MSG_DPR, FATAL, "Exit Cmd Thread (ctxt = %u, result = 0x%X)",
                pCmdThrdCtxt->cmdThrdId, qcxStatus);
    }

    return 0;
}

 下发command massage 进行处理

*@brief Process command message
*
*@param pCmdMsg [In] Pointer to command message to be processed
*
*@param pbRelCtxt [Out] Pointer to value which indicates if caller should release cmd ctxt after processing
*
*@return Status as defined in CamStatus_e
*/
static CamStatus_e MD_ProcessCmd (
    MDCmdMsg_t* pCmdMsg,
    boolean* pbRelCtxt)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;

    if ((NULL == pCmdMsg) || (NULL == pbRelCtxt))
    {
        qcxStatus = CAMERA_EBADPARAM;
        QCX_LOG(MSG_DPR, ERROR, "Bad param. NULL param");
    }
    else
    {
        QCX_LOG_MD_MSG(pCmdMsg);

        switch (pCmdMsg->msgType)
        {
            case MD_MSG_CMD_CLIENT:
            {
                qcxStatus                  = CAMERA_EFAILED;
                qcxStatus = CMCSync_ProcessCmd(&pCmdMsg->u.clientMsg);

                if (CAMERA_SUCCESS != qcxStatus)
                {
                    if (CAMERA_ENOCONNECTION == qcxStatus)
                    {
                        QCX_LOG(MSG_DPR, ERROR,
                                "Failed to establish communication to client (result = 0x%X)",
                                qcxStatus);

                        // Release cmd thread if connection to client is unsuccessful
                        *pbRelCtxt = TRUE;
                    }
                    else
                    {
                        QCX_LOG(MSG_DPR, ERROR,
                                "Command processing failed (msgId = 0x%X, result = 0x%X)",
                                pCmdMsg->u.clientMsg.msgHeader.msgId, qcxStatus);

                        if (CM_MSG_OPEN == pCmdMsg->u.clientMsg.msgHeader.msgId)
                        {
                            // Release cmd thread after a failed open
                            *pbRelCtxt = TRUE;
                        }
                    }
                }
                break;
            }
            case MD_MSG_CMD_SM_INIT:
            {
                const SMCmdData_t *pSMCmdData = &pCmdMsg->u.cmdMsgData.smData;
                QCarCamInit_t init_params = {};
                init_params.apiVersion = QCARCAM_VERSION;

                // Initialize stream controller
                qcxStatus = STRM_Initialize(&init_params);

                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(MSG_DPR, ERROR,
                            "SC Init failed (result = 0x%X)", qcxStatus);
                }

                if ((NULL != pSMCmdData->pUsrCtxt) && (NULL != pSMCmdData->cbFcn))
                {
                    // Call callback function upon completion of command
                    (void)pSMCmdData->cbFcn(pSMCmdData->pUsrCtxt, qcxStatus);
                }

                // Release context when processing is done
                *pbRelCtxt = TRUE;

                break;
            }
            case MD_MSG_CMD_SC_CLOSE:
            {
                qcxStatus = CAMERA_SUCCESS;
                QCX_LOG(MSG_DPR, HIGH,
                        "MD_MSG_CMD_SC_CLOSE event received.");
                *pbRelCtxt = TRUE;
                break;
            }
            default:
            {
                qcxStatus = CAMERA_EINVALIDOP;
                QCX_LOG(MSG_DPR, ERROR,
                        "Invalid cmd %x. Will not be processed (result = 0x%X)",
                        pCmdMsg->msgType,
                        qcxStatus);
                break;
            }
        }
    }

    return qcxStatus;
}
// Registers all Message Dispatcher callbacks used by Service Initializer
CamStatus_e qcxsi_RegisterMDCallBack(void)
{
    CamStatus_e         status = CAMERA_EFAILED;
    SI_Context_t* const pSICtx = qcxsi_GetCtx();

    SI_ON_ENTER();

    if (NULL == pSICtx)
    {
        status = CAMERA_EINVALIDSTATE;
        SI_LOGE1("qcxsi_GetCtx failed: 0x%08x", status);
    }

    // register for SM_Init
    else if (CAMERA_SUCCESS != (status = qcxsimd_SMInitRegister(&pSICtx->smCtx, MDCallBackFcn)))
    {
        SI_LOGE1("qcxsimd_SMInitRegister failed: 0x%08x", status);
    }

    else
    {
        // success
    }

    SI_ON_EXIT(status);

    return status;
}

 初始化cmd msg 结构体

static CamStatus_e qcxsimd_SMInitRegister(void* pUsrCtx, CmdCbFcn cbFcn)
{
    CamStatus_e status = CAMERA_EFAILED;
    MDCmdMsg_t cmdMsg  = { 0 };

    SI_ON_ENTER();

    cmdMsg.msgType                      = MD_MSG_CMD_SM_INIT;
    cmdMsg.u.cmdMsgData.smData.pUsrCtxt = pUsrCtx;
    cmdMsg.u.cmdMsgData.smData.cbFcn    = cbFcn;

    status = MD_CmdPush(&cmdMsg);

    SI_ON_EXIT(status);

    return status;
}

 qcxStatus = CMCCon_SenderCtxtCreate()

 qcxStatus = CMCCon_ReceiverCtxtCreate()

创建sender receiver 的处理线程

*
*@param isSyncMode Indicates if client is being initialized in synchronous mode
*
*@return Status as defined in CamStatus_e
*/
CamStatus_e CMCStream_InitGlobalCtxt (
    const boolean isSyncMode)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;
    if (NULL == OSAL_Memset(&g_clientCtxt, 0x0, sizeof(ClientCtxt_t)))
    {
        qcxStatus = CAMERA_EFAILED;
        QCX_LOG(CLIENT_MGR, ERROR,
                "OSAL_Memset failed (result = 0x%X)", qcxStatus);
    }
    else
    {
        // Set client mode to sync mode
        g_clientCtxt.isClientSync = isSyncMode;

        if (CAMERA_SUCCESS != (qcxStatus = CMCStream_ClientInfoInit()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCStream_ClientHandleInit failed (result = 0x%X)", qcxStatus);
        }
        else if (CAMERA_SUCCESS != (qcxStatus = CMCCon_SenderIPCConnect()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCCon_SenderIPCConnect failed (result = 0x%X)", qcxStatus);

            // Deinit client handle since connection to server failed
            // Ignore return code since function is always successful
            (void)CMCStream_ClientInfoDeinit();
        }
        else if (CAMERA_SUCCESS != (qcxStatus = CMCStream_GlobalCtxtInitInternal()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCStream_GlobalCtxtInitInternal failed (result = 0x%X)", qcxStatus);
        }
        else if (CAMERA_SUCCESS != (qcxStatus = CMCCon_SenderCtxtCreate()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCCon_SenderCtxtCreate failed (result = 0x%X)", qcxStatus);
        }
        else if (CAMERA_SUCCESS != (qcxStatus = CMCCon_ReceiverIPCCreate()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCCon_ReceiverIPCCreate failed (result = 0x%X)", qcxStatus);
        }
        else if (CAMERA_SUCCESS != (qcxStatus = CMCCon_ReceiverCtxtCreate()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCCon_ReceiverCtxtCreate failed (result = 0x%X)", qcxStatus);
        }
        else if (CAMERA_SUCCESS != (qcxStatus = CMCCon_GlobalEventCtxtCreate()))
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "CMCCon_GlobalEventCtxtCreate failed (result = 0x%X)", qcxStatus);
        }
        else
        {
            // Perform initialization only required for synchronous mode
            if (TRUE == isSyncMode)
            {
                // Initialize client utils for allocating persistent memory
                #ifdef __QNXNTO__
                qcxStatus = CM_ClientUtilsInit();
                #endif

                if (CAMERA_SUCCESS == qcxStatus)
                {
                    // Allocate persistent memory buffer
                    // Memory buffer is used in query inputs call
                    qcxStatus = CM_ClientAllocSharedBuffer(&g_clientCtxt.clientSharedBuf,
                                                           (uint32_t)sizeof(ClientSharedBufData_t));
                }
            }
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        QCX_LOG(CLIENT_MGR, LOW,
                "Client create (result = 0x%X)", qcxStatus);
    }
    else
    {
        QCX_LOG(CLIENT_MGR, ERROR,
                "Client create failed (result = 0x%X)", qcxStatus);
    }

    return qcxStatus;
}

Client 与 sever 进行交互 send msg

 // Enqueue msg data to sender thread qcxStatus = CMCMsg_EnqueueToSender(pHndl, (uint32_t)msgId, pMsgData, pMsgInfo);

/**
*@brief This function validates if necessary arguments to send message are valid and
*       calls CMC_MsgEnqueueToSender() which enqueues message to sender thread.
*
*@param hndl Qcarcam handle associated to message being sent
*@param msgId Message ID of message being sent
*@param pMsgData Pointer to message data structure
*@param pMsgInfo Pointer to message info structure
*
*@return Status as defined in CamStatus_e
*/
CamStatus_e CMCMsg_Enqueue (
    const QCarCamHndl_t* pHndl,
    const CMMsgId_e msgId,
    const CMMsgData_t* pMsgData,
    CMMsgInfo_t* pMsgInfo)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;

    switch (msgId)
    {
        case CM_MSG_OPEN:
        {
            ClientMsgRefKey_t valKey = {0};

            // Handle shall be NULL since handle is not assigned to stream yet
            valKey.isHndlReq = FALSE;
            valKey.isDataReq = TRUE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_CLOSE:
        {
            ClientMsgRefKey_t valKey = {0};

            // Data shall be NULL since only the handle is needed for closing the stream
            valKey.isHndlReq = TRUE;
            valKey.isDataReq = FALSE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_RESERVE:
        case CM_MSG_RELEASE:
        {
            ClientMsgRefKey_t valKey = { 0 };

            // Data shall be NULL since only the handle is needed for closing the stream
            valKey.isHndlReq = TRUE;
            valKey.isDataReq = FALSE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_QUERY_INPUTS:
        case CM_MSG_QUERY_INPUT_MODES:
        case CM_MSG_QUERY_SYSTEM_STATUS:
        case CM_MSG_GET_METADATA_TABLE:
        {
            ClientMsgRefKey_t valKey = {0};

            // Handle shall be NULL since query inputs/status does not belong to specific stream
            valKey.isHndlReq = FALSE;
            valKey.isDataReq = TRUE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_GET_FRAME:
        case CM_MSG_RELEASE_FRAME:
        case CM_MSG_GET_PARAM:
        case CM_MSG_SET_PARAM:
        case CM_MSG_SET_BUFFERS:
        case CM_MSG_SUBMIT_REQUEST:
        {
            ClientMsgRefKey_t valKey = {0};
            valKey.isHndlReq = TRUE;
            valKey.isDataReq = TRUE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_ATTACH:
        {
            ClientMsgRefKey_t valKey = {0};

            // Handle shall be NULL since attach does not belong to specific stream
            valKey.isHndlReq = FALSE;
            valKey.isDataReq = TRUE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            if (CAMERA_SUCCESS == qcxStatus)
            {
                qcxStatus = CMCMsg_VersionCheck(pMsgData->u.attachMsg.params.apiVersion);
            }
            break;
        }
        case CM_MSG_REGEVENT_CB:
        {
            ClientMsgRefKey_t valKey = { 0 };

            // Handle shall be NULL since deattach does not belong to specific stream
            // Data shall be NULL
            valKey.isHndlReq = FALSE;
            valKey.isDataReq = FALSE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_DETACH:
        {
            ClientMsgRefKey_t valKey = {0};

            // Handle shall be NULL since deattach does not belong to specific stream
            // Data shall be NULL
            valKey.isHndlReq = FALSE;
            valKey.isDataReq = FALSE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_START:
        case CM_MSG_STOP:
        case CM_MSG_PAUSE:
        case CM_MSG_RESUME:
        {
            ClientMsgRefKey_t valKey = {0};

            // Data shall be NULL since only the handle is required
            valKey.isHndlReq = TRUE;
            valKey.isDataReq = FALSE;

            // Check if required arguments are not NULL
            qcxStatus = CMCMsg_ArgValidate(msgId, pHndl, pMsgData, &valKey);
            break;
        }
        case CM_MSG_HEALTH:
        case CM_MSG_DIAGNOSTIC_DUMP:
        {
            qcxStatus = CAMERA_SUCCESS;
            break;
        }
        default:
        {
            qcxStatus = CAMERA_EINVALIDOP;
            QCX_LOG(CLIENT_MGR, ERROR,
                    "Invalid msgId (msgId = 0x%X)", msgId);
            break;
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        // Enqueue msg data to sender thread
        qcxStatus = CMCMsg_EnqueueToSender(pHndl, (uint32_t)msgId, pMsgData, pMsgInfo);
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        QCX_LOG(CLIENT_MGR, LOW,
                "Msg send (msgId = 0x%X, result = 0x%X)", msgId, qcxStatus);
    }
    else
    {
        QCX_LOG(CLIENT_MGR, ERROR,
                "Msg send failed (msgId = 0x%X, result = 0x%X)", msgId, qcxStatus);
    }

    return qcxStatus;
}

/创建pClientCtxt->senderQ消息队列

// Create blocking queue for sender

qcxStatus = CMCStream_ClientQueueCreate(sizeof(CMMsg_t), MSG_QUEUE_SIZE, QUEUE_BLOCKING, &pClientCtxt->senderQ);

创建CMCCon_SenderThread 发送index queue msg

qcxStatus = OSAL_ThreadCreate(QCXThreadRealtimePriority, &CMCCon_SenderThread,

/**
*@brief Enqueue message to sender thread
*
*@param hndl Qcarcam handle associated to message being sent
*@param msgId Message ID of message being sent
*@param pMsgData Pointer to message data structure
*@param pMsgInfo Pointer to message info structure
*
*@return Status as defined in CamStatus_e
*/
static CamStatus_e CMCMsg_EnqueueToSender (
    const QCarCamHndl_t* pHndl,
    const uint32_t msgId,
    const CMMsgData_t* pMsgData,
    CMMsgInfo_t* pMsgInfo)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;
    QCarCamHndl_t hndl = HANDLE_INVALID;
    uint64_t timestamp = 0U;
    uint32_t token = 0U;
    CMMsg_t msg = {0};
    static uint8_t threadIdx = 0;

    ClientCtxt_t* const pClientCtxt = CMCStream_GetGlobalCtxt();

    if (NULL == pClientCtxt)
    {
        qcxStatus = CAMERA_EINVALIDSTATE;
        QCX_LOG(CLIENT_MGR, ERROR,
                "Enqueue msg failed. Client context not initialized (result = 0x%X)", qcxStatus);
    }
    else
    {
        if (NULL == pHndl)
        {
            hndl = pClientCtxt->hClientCtxt;
            qcxStatus = CAMERA_SUCCESS;
        }
        else
        {
            // Check if handle is valid
            hndl = *pHndl;
            qcxStatus = CMCStream_HandleFind(hndl, NULL);
        }

        if (CAMERA_SUCCESS == qcxStatus)
        {
            qcxStatus = CMCMsg_GetNextToken(&token);
        }

        if (CAMERA_SUCCESS == qcxStatus)
        {
            qcxStatus = OSAL_TimeGetTimeMicroSecond(&timestamp, QCX_CLOCK_MONOTONIC);
        }

        if (CAMERA_SUCCESS == qcxStatus)
        {
            msg.msgHeader.msgQcarcamHndl = hndl;
            msg.msgHeader.msgId = (CMMsgId_e)msgId;
            msg.msgHeader.msgInfo.token = token;
            msg.msgHeader.msgTimestamp = timestamp;

            if (NULL != pMsgData)
            {
                msg.msgData = *pMsgData;
            }
            // 将msg enqueue 到 senderQ.hQueue
            qcxStatus = QCXQueuePush(pClientCtxt->senderQ.hQueue,
                                       &msg,
                                       sizeof(CMMsg_t));
            if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, ERROR,
                        "Failed to queue msg (hndl = %lX, msgId = 0x%X, result = 0x%X)",
                        hndl, msgId, qcxStatus);
            }
            else
            {
                if (NULL != pMsgInfo)
                {
                    pMsgInfo->token = token;
                }
                qcxStatus = OSAL_CriticalSectionEnter(pClientCtxt->hClientIpcLock);
                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(CLIENT_MGR, ERROR, "CS Enter failed (%u)",
                        qcxStatus);
                }
                else
                {
                    threadIdx = threadIdx % NUM_SERVER_IPC_CHANNELS;

                    OSAL_EventSet(pClientCtxt->senderCtxt[threadIdx].hThreadEvent);

                    threadIdx++;

                    qcxStatus = OSAL_CriticalSectionLeave(pClientCtxt->hClientIpcLock);
                     if (CAMERA_SUCCESS != qcxStatus)
                    {
                        QCX_LOG(CLIENT_MGR, ERROR, "CS Leave failed (result = 0x%X)",
                            qcxStatus);
                    }
                }
            }
        }
        else
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "Enqueue msg failed. (result = 0x%X)", qcxStatus);
        }
    }
    return qcxStatus;
}

 

/**
*@brief Create sender thread context
*       Initializes sender queue, IPC channel, and creates sender thread
*
*@param void
*
*@return Status as defined in CamStatus_e
*/
CamStatus_e CMCCon_SenderCtxtCreate (
    void)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;
    char threadName[CLIENT_MAX_NAME_SIZE] = {0};
    int32_t result = -1;
    ClientCtxt_t* const pClientCtxt = CMCStream_GetGlobalCtxt();

    if (NULL == pClientCtxt)
    {
        qcxStatus = CAMERA_EINVALIDSTATE;
    }
    else
    {
        //创建pClientCtxt->senderQ消息队列
        // Create blocking queue for sender
        qcxStatus = CMCStream_ClientQueueCreate(sizeof(CMMsg_t),
                                                MSG_QUEUE_SIZE,
                                                QUEUE_BLOCKING,
                                                &pClientCtxt->senderQ);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                    "Sender Q creation failed (result = 0x%X)", qcxStatus);
        }
        else
        {
            uint8_t idx = 0;
            static uint8_t p[NUM_SERVER_IPC_CHANNELS];
            for (idx = 0; idx < NUM_SERVER_IPC_CHANNELS; idx++)
            {
                p[idx] = idx;
                qcxStatus =  OSAL_EventCreate(&pClientCtxt->senderCtxt[idx].hThreadEvent, TRUE);
                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(CLIENT_MGR, ERROR,
                        "OSAL_EventCreate failed (result = 0x%X)",
                        qcxStatus);
                }
                else
                {
                    // Create sender thread
                    result = snprintf(threadName, sizeof(threadName), "c_send_%X", (pClientCtxt->clientId + idx));
                    pClientCtxt->senderThreadIdx = idx;
                    if (0 < result)
                    {  
                    //创建CMCCon_SenderThread 发送index queue msg
                        qcxStatus = OSAL_ThreadCreate(QCXThreadRealtimePriority,
                            &CMCCon_SenderThread,
                            &p[idx],
                            0,
                            threadName,
                            &pClientCtxt->senderCtxt[idx].hThread);

                        if (CAMERA_SUCCESS != qcxStatus)
                        {
                            QCX_LOG(CLIENT_MGR, ERROR,
                                "Sender thread creation failed (result = 0x%X)", qcxStatus);
                        }
                    }
                    else
                    {
                        qcxStatus = CAMERA_EFAILED;
                        QCX_LOG(CLIENT_MGR, ERROR,
                            "Failed to set thread name (result = 0x%X)",
                            qcxStatus);
                    }
                }
            }
        }
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        QCX_LOG(CLIENT_MGR, LOW,
                "Sender ctxt create (result = 0x%X)", qcxStatus);
    }
    else
    {
        QCX_LOG(CLIENT_MGR, ERROR,
                "Sender ctxt create failed (result = 0x%X)", qcxStatus);
    }

    return qcxStatus;
}

通过pClientCtxt->senderQ.hQueue获取msg信息

qcxStatus = QCXQueuePop(senderQHndl, &msg, &dataSize);

通过senderIpcHndl发送pClientCtxt->senderQ.hQueue 的msg 信息

qcxStatus = OSAL_IPCSendAsync(senderIpcHndl, &msg, sizeof(CMMsg_t), SENDER_IPC_TIMEOUT_MS);

* Variables
================================================================================================**/

/***================================================================================================
** Function definitions
================================================================================================**/

/**
*@brief Defines operations performed by sender thread
*       Waits for items to be queued in the sender queue.
*       Once an item is in the queue, it dequeues it and sends it to server.
*
*@param pArg Pointer to arguments of thread
*
*@return Return 0 if successful
*/
static int32_t CMCCon_SenderThread (
    void* pArg)
{
    ClientCtxt_t const* pClientCtxt = CMCStream_GetGlobalCtxt();
    QCXQueue_t senderQHndl = pClientCtxt->senderQ.hQueue;
    QCXEvent_t senderQEHndl = pClientCtxt->senderQ.hQueueEvent;
    uint8_t threadIdx = *((uint8_t *)pArg);
    QCXIPCHdl_t senderIpcHndl = pClientCtxt->senderCtxt[threadIdx].hIPCChannel;
    CamStatus_e qcxStatus = CAMERA_ENOMORE;

    while (CAMERA_EFAILED != qcxStatus)
    {
        CMMsg_t msg = {0};
        uint64_t dataSize = 0U;

        qcxStatus = CAMERA_SUCCESS;
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                "Event wait failed. (result = 0x%X)", qcxStatus);
        }
        else
        {   //通过pClientCtxt->senderQ.hQueue获取msg信息
            qcxStatus = QCXQueuePop(senderQHndl, &msg, &dataSize);

            if (CAMERA_EFAILED == qcxStatus)
            {
                qcxStatus = OSAL_EventSet(senderQEHndl);
                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(CLIENT_MGR, ERROR,
                            "Sender queue event set failed. (result = 0x%X)", qcxStatus);
                }

                QCX_LOG(CLIENT_MGR, HIGH,
                        "Sender queue wait was cancelled. Exiting thread (result = 0x%X)", qcxStatus);
                break;
            }
            if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, FATAL,
                        "Sender queue dequeue failed. Client library abort (result = 0x%X)", qcxStatus);

                qcxStatus = CMC_SetGlobalAbortState();
                if (CAMERA_SUCCESS != qcxStatus)
                {
                    QCX_LOG(CLIENT_MGR, FATAL,
                            "Failed setting client state (result = 0x%X)", qcxStatus);
                }
            }
            else
            {

                uint32_t nAttempts = 0U;
                while (TRUE != pClientCtxt->clientAbortFlag)
                { 
                  //通过senderIpcHndl发送pClientCtxt->senderQ.hQueue 的msg 信息
                    qcxStatus = OSAL_IPCSendAsync(senderIpcHndl,
                                                  &msg,
                                                  sizeof(CMMsg_t),
                                                  SENDER_IPC_TIMEOUT_MS);
                    if (CAMERA_ETIMEOUT == qcxStatus)
                    {
                        nAttempts++;
                        QCX_LOG(CLIENT_MGR, HIGH,
                                "Sender async send timed out. Retrying (result = 0x%X, attempt = %u)",
                                qcxStatus, nAttempts);

                        if (MAX_SENDER_IPC_ATTEMPTS < nAttempts)
                        {
                            QCX_LOG(CLIENT_MGR, ERROR,
                                    "Sender reached maximum IPC send attempts. Aborting");

                            qcxStatus = CMC_SetGlobalAbortState();
                            if (CAMERA_SUCCESS != qcxStatus)
                            {
                                QCX_LOG(CLIENT_MGR, FATAL,
                                        "Failed setting client state (result = 0x%X)", qcxStatus);
                            }

                            break;
                        }
                        else
                        {
                            // Try sending message again
                            continue;
                        }
                    }
                    else if (CAMERA_ENOCONNECTION == qcxStatus)
                    {
                        QCX_LOG(CLIENT_MGR, FATAL,
                                "Sender thread lost connection to server (result = 0x%X)",
                                qcxStatus);

                        qcxStatus = CMC_SetGlobalAbortState();
                        if (CAMERA_SUCCESS != qcxStatus)
                        {
                            QCX_LOG(CLIENT_MGR, FATAL,
                                    "Failed setting client state (result = 0x%X)", qcxStatus);
                        }
                    }
                    else if (CAMERA_SUCCESS != qcxStatus)
                    {
                        QCX_LOG(CLIENT_MGR, FATAL,
                                "Sender async send failed. Exiting thread (result = 0x%X)",
                                qcxStatus);

                        qcxStatus = CMC_SetGlobalAbortState();
                        if (CAMERA_SUCCESS != qcxStatus)
                        {
                            QCX_LOG(CLIENT_MGR, FATAL,
                                    "Failed setting client state (result = 0x%X)", qcxStatus);
                        }
                    }
                    else
                    {
                        QCX_LOG(CLIENT_MGR, LOW,
                                "Sender async send successful (msgId = 0x%X)", msg.msgHeader.msgId);
                        /** In case of detach set the event notification. */
                        if (CM_MSG_DETACH == msg.msgHeader.msgId)
                        {
                            /** Wait for the detach message to be sent before
                             * proceeding to client destroy. */
                            qcxStatus = OSAL_EventSet(pClientCtxt->hDetachEvent);
                            if (CAMERA_SUCCESS != qcxStatus)
                            {
                                QCX_LOG(CLIENT_MGR, ERROR,
                                        "Sender event set failed (result = 0x%X)", qcxStatus);
                            }
                        }

                        break;
                    }
                }
            }
        }
    }

    QCX_LOG(CLIENT_MGR, HIGH, "Sender thread exiting (result = 0x%X)", qcxStatus);
    return 0;
}

 pStreamCtxt->streamReplyQ.hQueue

 pStreamCtxt->streamEventQ.hQueue

获取两个事件的queue中的信息进行判断是否需要处理

*       Waits for messages sent by server.
*       Once a message is received, it places it in a response or event
*       queue of corresponding stream context.
*
*@param pArg Pointer to arguments of thread
*
*@return Return 0 if successful
*/
static int32_t CMCCon_ReceiverThread (
    void* pArg)
{
    ClientCtxt_t* pClientCtxt = CMCStream_GetGlobalCtxt();
    uint8_t threadIdx = *((uint8_t *)pArg);;
    QCXIPCHdl_t receiverIpcHndl = pClientCtxt->receiverCtxt[threadIdx].hIPCChannel;
    QCarCamHndl_t clientHndl = pClientCtxt->hClientCtxt;
    CamStatus_e qcxStatus = CAMERA_EFAILED;

#ifndef __QNXNTO__
    QCXIPCHdl_t pNewHdl;
    qcxStatus = OSAL_IPCAccept( receiverIpcHndl, &pNewHdl );
#else
    QCXIPCHdl_t pNewHdl = receiverIpcHndl;
#endif

#ifndef __QNXNTO__
   if(CAMERA_SUCCESS == qcxStatus)
   {
#endif
        while (TRUE != pClientCtxt->clientAbortFlag)
        {
            uint32_t streamIdx = 0U;
            size_t msgSize = sizeof(CMMsg_t);
            CMMsg_t msg = {0};

            //获取pClientCtxt->senderQ.hQueue
            // Listen for incoming msg from server
            qcxStatus = OSAL_IPCRecvAsync(pNewHdl, &msg, &msgSize, 0);

            if (CAMERA_ERETRY == qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, LOW,
                        "Server disconnected from channel");
            }
            else if (CAMERA_NEWCONNECTION == qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, LOW,
                        "Server has connected to channel");
            }
            else if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, FATAL,
                        "IPC receive failed (result = 0x%X)",
                        qcxStatus);
            }
            else
            {
                if (clientHndl == msg.msgHeader.msgQcarcamHndl || (CM_MSG_OPEN == msg.msgHeader.msgId))
                {
                    if (CM_MSG_OPEN == msg.msgHeader.msgId)
                    {
                        msg.msgData.u.openMsgBuf.streamHandle = msg.msgHeader.msgQcarcamHndl;
                    }
                    uint32_t msgType = (uint32_t)msg.msgHeader.msgId;

                    if (((uint32_t)CM_MSG_BASE_CM_EVENTS < msgType) &&
                        ((uint32_t)CM_MSG_BASE_RESERVED > msgType))
                    {
                        // Place message in client context event queue
                        qcxStatus = QCXQueuePush(pClientCtxt->clientEventQ.hQueue,
                                                   &msg,
                                                   (uint32_t)sizeof(CMMsg_t));
                    }
                    else
                    {
                        // Place message in client context reply queue
                        qcxStatus = QCXQueuePush(pClientCtxt->clientReplyQ.hQueue,
                                                   &msg,
                                                   (uint32_t)sizeof(CMMsg_t));
                    }

                    if (CAMERA_SUCCESS != qcxStatus)
                    {
                        QCX_LOG(CLIENT_MGR, ERROR,
                                "Receiver failed to queue msg \
                                (result = 0x%X, hndl = %lX, msgId = 0x%X)",
                                qcxStatus, msg.msgHeader.msgQcarcamHndl, msg.msgHeader.msgId);
                    }
                }
                else
                {
                    // Check if handle of received msg matches an active stream
                    qcxStatus = CMCStream_HandleFind(msg.msgHeader.msgQcarcamHndl, &streamIdx);
                    if (CAMERA_SUCCESS != qcxStatus)
                    {
                        QCX_LOG(CLIENT_MGR, ERROR,
                                "Received msg for invalid stream (result = 0x%X, hndl = %lX)",
                                 qcxStatus, msg.msgHeader.msgQcarcamHndl);
                    }
                    else
                    {
                        ClientStreamCtxt_t* pStreamCtxt = NULL;
                        QCXQueue_t streamQ = NULL;
                        uint32_t msgType = 0U;

                        pStreamCtxt = &pClientCtxt->streamCtxtList[streamIdx];
                        msgType = (uint32_t)msg.msgHeader.msgId;

                        if (((uint32_t)CM_MSG_BASE_CM_REQUESTS < msgType) &&
                            ((uint32_t)CM_MSG_BASE_CM_EVENTS > msgType))
                        {
                            streamQ = pStreamCtxt->streamReplyQ.hQueue;
                            QCX_LOG(CLIENT_MGR, LOW,
                                    "Received reply msg (msgType = %u, hndl = %lX)",
                                    msg.msgHeader.msgId, msg.msgHeader.msgQcarcamHndl);
                        }
                        else if (((uint32_t)CM_MSG_BASE_CM_EVENTS < msgType) &&
                                 ((uint32_t)CM_MSG_BASE_RESERVED > msgType))
                        {
                            streamQ = pStreamCtxt->streamEventQ.hQueue;
                            QCX_LOG(CLIENT_MGR, LOW,
                                    "Received event msg (msgType = %u, hndl = %lX)",
                                    msg.msgHeader.msgId, msg.msgHeader.msgQcarcamHndl);
                        }
                        else
                        {
                            qcxStatus = CAMERA_EINVALIDOP;
                            QCX_LOG(CLIENT_MGR, ERROR,
                                    "Received invalid msg type (msgType = %u, hndl = %lX)",
                                    msg.msgHeader.msgId, msg.msgHeader.msgQcarcamHndl);
                        }

                        if (CAMERA_SUCCESS == qcxStatus)
                        {
                            if ((CMMsgId_e)CM_MSG_CLOSE == msg.msgHeader.msgId)
                            {
                                // Place message in cached structure
                                pStreamCtxt->closeReplyCache.ret = msg.msgData.ret;
                                pStreamCtxt->closeReplyCache.msgInfo = msg.msgHeader.msgInfo;
                                qcxStatus = OSAL_EventSet(pStreamCtxt->hStreamCloseEvent);
                                if (CAMERA_SUCCESS != qcxStatus)
                                {
                                    QCX_LOG(CLIENT_MGR, ERROR,
                                            "Receiver failed to set event, "
                                            "(result = 0x%X, hndl = %lX, msgId = 0x%X)",
                                            qcxStatus,
                                            msg.msgHeader.msgQcarcamHndl,
                                            msg.msgHeader.msgId);
                                }
                            }
                            else
                            {
                                // Place message in queue of corresponding stream
                                qcxStatus = QCXQueuePush(streamQ, &msg, sizeof(CMMsg_t));
                                if (CAMERA_SUCCESS != qcxStatus)
                                {
                                    QCX_LOG(CLIENT_MGR, ERROR,
                                            "Receiver failed to queue msg, "
                                            "(result = 0x%X, hndl = %lX, msgId = 0x%X)",
                                            qcxStatus,
                                            msg.msgHeader.msgQcarcamHndl,
                                            msg.msgHeader.msgId);
                                }
                                else
                                {
                                    QCX_LOG(CLIENT_MGR, LOW,
                                            "Receiver enqueued msg successfully, "
                                            "(result = 0x%X, hndl = %lX, msgId = 0x%X)",
                                            qcxStatus,
                                            msg.msgHeader.msgQcarcamHndl,
                                            msg.msgHeader.msgId);
                                }
                            }
                        }
                    }
                }
            }
        }
#ifndef __QNXNTO__
    }
    else
    {
        QCX_LOG(CLIENT_MGR, HIGH, "Error on doing accept (result = 0x%X)", qcxStatus);
    }
    free(pNewHdl);
#endif
    QCX_LOG(CLIENT_MGR, HIGH, "Receiver thread exiting (result = 0x%X)", qcxStatus);
    return 0;
}

PLM_Init

MD_Init

STRM_Initialize 初始化streammanager 进行初始化 sensorlib

CM_ServerInit  初始化client 与server 进行通讯的msg 处理线程

cmdEnqueue将cmd 加入到server 处理的msg队列中

CamStatus_e SI_Init(boolean bEnableCCIDbgr)
{
    CamStatus_e         status          = CAMERA_EFAILED;
    CamStatus_e         status1         = status;

    //To do: need to remove this
    QCarCamInit_t init_params = {0};
    init_params.apiVersion = QCARCAM_VERSION_MINOR;
    // Camera KPI requires < 2 seconds from system boot to 1st frame on display.
    // Assuming,
    // - 1600ms is used in other boot time system initialization.
    // -  200ms is used by other parts of the camera driver initialization.  We left with
    // -  200ms max budget to wait for all async calls to complete.
    // -  Additional delay of 5 millisecond is required for single camera detection
    //    per port usecase, this is the requirement for ti960 only.
    // TODO: Temporarily increasing timeout to 1700ms assuming 16 TI971 cameras are connected,
    //       each of those can roughly take 100ms to initialize + 100 ms for init of other
    //       components of the camera driver.
    //uint64_t            timeoutMs       = 1700U;

    QCX_KPI_LOG_START();

    SI_ON_ENTER();

#ifdef FEAT_ENABLE_CCIDBGR
    if(bEnableCCIDbgr == TRUE)
    {
        PLM_enable_ccidbgr(bEnableCCIDbgr);
    }
#endif
    // Clocks should be enabled before DM_Init() registers with safety monitor
    if (CAMERA_SUCCESS != (status1 = PLM_Init()))
    {
        SI_LOGE1("PLM_Init failed: 0x%08x", status1);
    }
    else if (CAMERA_SUCCESS != (status1 = MD_Init()))
    {
        SI_LOGE1("MD_Init failed: 0x%08x", status1);
        (void) qcxsi_Deinit(DEINIT_FROM_PLM);
    }
    // To do: Need to do STRM_Initialize() via MD
    else if (CAMERA_SUCCESS != (status1 = STRM_Initialize(&init_params)))
    {
        SI_LOGE1("STRM_Initialize failed: 0x%08x", status1);
        (void) qcxsi_Deinit(DEINIT_FROM_MD);
    }
    else if (CAMERA_SUCCESS != (status1 = CM_ServerInit()))
    {
        SI_LOGE1("CM_ServerInit failed: 0x%08x", status1);
        (void) qcxsi_Deinit(DEINIT_FROM_STRM);
    }
    else
    {
        // success
    }

    // status1 from above should have captured a SUCCESS or a
    // non-CAMERA_EFAILED failure.  If it contained CAMERA_EFAILED,
    // it means one of the calls it made returns the value, which
    // is a bug that must be fixed.
    if (CAMERA_EFAILED == status1)
    {
        SI_LOGF0("Logic error: Fix me");
    }

    status = status1;

    SI_ON_EXIT(status);

    if(CAMERA_SUCCESS == status)
    {
        QCX_KPI_LOG_READY();
    }

    return status;
}

 

/**
*@brief Create instance of server
*        Initializes data structures, creates IPC channel and server thread
*
*@param void
*
*@return Status as defined in CamStatus_e
*/
CamStatus_e CM_ServerInit (void)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;
    static uint8_t p[NUM_SERVER_IPC_CHANNELS];
#ifdef HEALTH_ENABLE
    static uint8_t health_thrd = 0;
#endif
    uint8_t idx = 0;
    (void)memset(&g_serverCtxt, 0x0, sizeof(ServerCtxt_t));

    for (idx = 0; idx < NUM_SERVER_IPC_CHANNELS; idx++)
    {
        p[idx] = idx;
        g_serverCtxt.threadIdx = idx;
        // Create IPC channel with server ID
        qcxStatus = OSAL_IPCCreate((CM_SERVER_IPC_CHANNEL_ID + idx), &g_serverCtxt.serverHndl[idx].serverIpcHndl);
        QCX_LOG(CLIENT_MGR, HIGH,
                    "Server thread creation success (result = 0x%X)", qcxStatus);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                "Server IPC channel creation failed (result = 0x%X)", qcxStatus);
            break;
        }

        if (CAMERA_SUCCESS == qcxStatus)
        {
            // Create server thread
            qcxStatus = OSAL_ThreadCreate(QCXThreadRealtimePriority,
                &CM_ServerThread,
                &p[idx],
                0,
                "server_thrd",
                &g_serverCtxt.serverHndl[idx].serverThreadHndl);
            if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, ERROR,
                    "Server thread creation failed (result = 0x%X)", qcxStatus);
            }
        }
    }
#ifdef HEALTH_ENABLE
    if (CAMERA_SUCCESS == qcxStatus)
    {
        qcxStatus = OSAL_ThreadCreate(QCXThreadRealtimePriority,
            &CM_IPCHealthThread,
            &health_thrd,
            0,
            "health_thrd",
            &g_serverCtxt.healthThreadHndl);
        if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, ERROR,
                "Server thread creation failed (result = 0x%X)", qcxStatus);
        }
        else
        {
            QCX_LOG(CLIENT_MGR, HIGH, "Health thread created successfully");
        }
    }
#endif

    return qcxStatus;
}

 //创建线程server_thrdRecv对mdMsg 进行接收处理

CM_ServerRecv(ipcHndl) 

static int32_t CM_ServerThread(
    void* pArg)
{
    ServerCtxt_t* pServerCtxt = &g_serverCtxt;
    uint8_t index = *((uint8_t*)pArg);
    CamStatus_e result = CAMERA_EFAILED;

    if (NUM_SERVER_IPC_CHANNELS <= index)
    {
        result = CAMERA_EBADPARAM;
        QCX_LOG(CLIENT_MGR, ERROR,
            "thread index passed is not supported)");

    }
    else
    {
        QCXIPCHdl_t ipcHndl = pServerCtxt->serverHndl[index].serverIpcHndl;

#ifndef __QNXNTO__
        while (TRUE != pServerCtxt->serverAbort)
        {
            QCXIPCHdl_t pNewHdl;

            /*Blocking call. Waits for connect */
            result = OSAL_IPCAccept(ipcHndl, &pNewHdl);

           //创建线程server_thrdRecv对mdMsg 进行接收处理
            /* The implementation needs to be modified to store thread handle in an array and to
               destroy the thread when the client terminates */
            QCXThread_t threadHandle;
            CamStatus_e qcxStatus = OSAL_ThreadCreate(QCXThreadRealtimePriority,
                &CM_ServerRecv,
                pNewHdl,
                0,
                "server_thrdRecv",
                &threadHandle);
#else
            CamStatus_e qcxStatus = CM_ServerRecv(ipcHndl);
#endif

            if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, FATAL,
                    "Server failed to push message to, result = 0x%X)",
                    qcxStatus);
            }
#ifndef __QNXNTO__
        }
#endif
    }
    if (CAMERA_EFAILED == result)
    {
        result = CAMERA_SUCCESS;
    }
    return CAMERA_SUCCESS;
}

 OSAL_IPCRecvAsync(ipcHndl, &mdMsg.u.clientMsg, &msgSize, 0); 

进行数据的接受

/**
*@brief Implementation of server thread
*        Waits for incoming messages from clients
*        Passes received messages to Message Dispatcher
*
*@param void
*
*@return Status as defined in CamStatus_e
*/


static int32_t CM_ServerRecv(
    void* pArg)
{
    QCXIPCHdl_t ipcHndl = (QCXIPCHdl_t)pArg;
    ServerCtxt_t* pServerCtxt = &g_serverCtxt;
    CamStatus_e result = CAMERA_EFAILED;

    uint8_t localAbort = FALSE;
    while ((TRUE != pServerCtxt->serverAbort) && (TRUE != localAbort))
    {
        CamStatus_e qcxStatus = CAMERA_EFAILED;
        size_t msgSize = sizeof(CMMsg_t);
        MDCmdMsg_t mdMsg = { 0 };

        // Listen for incoming messages from client. Blocking call
        qcxStatus = OSAL_IPCRecvAsync(ipcHndl, &mdMsg.u.clientMsg, &msgSize, 0);


        if (CAMERA_ERETRY == qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, LOW,
                "Client disconnected from Server channel");
        }
        else if (CAMERA_NEWCONNECTION == qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, HIGH,
                "New client connected to Server channel");
        }
        else if (CAMERA_SUCCESS != qcxStatus)
        {
            QCX_LOG(CLIENT_MGR, FATAL,
                    "Server IPC receive failed (result = 0x%X)",
                    qcxStatus);
            localAbort = TRUE;
        }
        else
        {
            mdMsg.msgType = MD_MSG_CMD_CLIENT;

            // Pass received message to message dispatcher
            qcxStatus = MD_CmdPush(&mdMsg);
            if (CAMERA_SUCCESS != qcxStatus)
            {
                QCX_LOG(CLIENT_MGR, FATAL,
                    "Server failed to push message to MD "
                    "(hndl = %lX, msgType = 0x%X, result = 0x%X)",
                    mdMsg.u.clientMsg.msgHeader.msgQcarcamHndl,
                    mdMsg.u.clientMsg.msgHeader.msgId,
                    qcxStatus);
            }
        }
    }

    if (CAMERA_EFAILED == result)
    {
        result = CAMERA_SUCCESS;
    }
    return CAMERA_SUCCESS;
}

 


/**
*@brief Place message in command queue
*        Message is placed in appropriate command queue based on type of message
*        and available command contexts
*
*@param pCmdMsg[In] Message to be placed in queue
*
*@return Status as defined in CamStatus_e
*/
CamStatus_e MD_CmdPush (
    const MDCmdMsg_t* pCmdMsg)
{
    CamStatus_e qcxStatus = CAMERA_EFAILED;

    if (NULL == pCmdMsg)
    {
        qcxStatus = CAMERA_EBADPARAM;
        QCX_LOG(MSG_DPR, ERROR, "Bad param. NULL msg");
    }
    else
    {
        qcxStatus = MD_CmdEnqueue(pCmdMsg);
    }

    if (CAMERA_SUCCESS == qcxStatus)
    {
        QCX_LOG(MSG_DPR, DEBUG,
                "MD Cmd Push success (result = 0x%X)", qcxStatus);
    }
    else
    {
        QCX_LOG(MSG_DPR, ERROR,
                "MD Cmd Push failed (result = 0x%X)", qcxStatus);
    }

    return qcxStatus;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值