// 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(×tamp, 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;
}