/******************************************************************************* * File Name : MQTT.c * Description : * Created on : 2018Äê5ÔÂ17ÈÕ * Author : ¶Å¼ü *******************************************************************************/ /******************************************************************************* * Include Files * *******************************************************************************/ #include "string.h" #include "MQTT.h" #include "HIDO_Util.h" #include "HIDO_Debug.h" #include "HIDO_ArraryQueue.h" /******************************************************************************* * Macro * *******************************************************************************/ /* SOICKETÏà¹Ø */ #define MQTT_SEND_QUEUE_BUF_SIZE (1024 * 2) #define MQTT_RECV_QUEUE_BUF_SIZE (1024 * 4) #define MQTT_SEND_QUEUE_MEMBER_CNT (5 + 1) #define MQTT_RECV_QUEUE_MEMBER_CNT 32 /******************************************************************************* * Type Definition * *******************************************************************************/ typedef struct { E_MQTTState m_eState; HIDO_BOOL m_bHasRecvData; HIDO_INT32 m_i32ID; FN_MQTTEventProc m_fnEventProc; HIDO_VOID *m_pArg; HIDO_UINT16 m_u16MsgID; ST_MQTTConfig m_stConfig; HIDO_VLQStruct m_stMQTTSendQueue; HIDO_VLQStruct m_stMQTTRecvQueue; HIDO_ArraryQueueStruct m_stMQTTRecvInfoQueue; ST_SubscribeTopic *m_pstTopicList; HIDO_UINT8 l_au8MQTTSendQueueBuf[MQTT_SEND_QUEUE_BUF_SIZE]; HIDO_UINT8 l_au8MQTTRecvQueueBuf[MQTT_RECV_QUEUE_BUF_SIZE]; } ST_MQTTData; /******************************************************************************* * Local Variable * *******************************************************************************/ static ST_MQTTData l_astMQTTData[MQTT_NUM]; static ST_SubscribeTopic l_astSubscribeTopicBuf[16]; static ST_SubscribeTopic *l_pstSubscribeTopicFreeList = HIDO_NULL; /******************************************************************************* * Local Function Declaration * *******************************************************************************/ /******************************************************************************* * Local Function * *******************************************************************************/ /******************************************************************************* * Global Function * *******************************************************************************/ /******************************************************************************* * Function Name : MQTT_RecvAll * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_HaveRecvData(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { l_astMQTTData[_i32ClientID].m_bHasRecvData = HIDO_TRUE; return HIDO_OK; } return HIDO_ERR; } HIDO_INT32 MQTT_NoRecvData(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { l_astMQTTData[_i32ClientID].m_bHasRecvData = HIDO_FALSE; return HIDO_OK; } return HIDO_ERR; } /******************************************************************************* * Function Name : MQTT_HasRecvData * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_BOOL MQTT_HasRecvData(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_bHasRecvData; } return HIDO_FALSE; } /******************************************************************************* * Function Name : MQTT_GetRecvQueue * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_VLQStruct *MQTT_GetRecvQueue(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return &l_astMQTTData[_i32ClientID].m_stMQTTRecvQueue; } return HIDO_NULL; } /******************************************************************************* * Function Name : MQTT_GetSendQueue * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_VLQStruct *MQTT_GetSendQueue(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return &l_astMQTTData[_i32ClientID].m_stMQTTSendQueue; } return HIDO_NULL; } /******************************************************************************* * Function Name : MQTT_GetMQTTState * Description : * Input : * Output : * Return : *******************************************************************************/ E_MQTTState MQTT_GetMQTTState(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_eState; } return MQTT_STATE_IDLE; } /******************************************************************************* * Function Name : MQTT_SetMQTTState * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_SetMQTTState(HIDO_INT32 _i32ClientID, E_MQTTState _eState) { if (_i32ClientID < MQTT_NUM) { l_astMQTTData[_i32ClientID].m_eState = _eState; return HIDO_OK; } return HIDO_ERR; } /******************************************************************************* * Function Name : MQTT_GetRemoteAddr * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_CHAR *MQTT_GetRemoteAddr(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_acRemoteAddr; } return ""; } /******************************************************************************* * Function Name : MQTT_GetRemotePort * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT16 MQTT_GetRemotePort(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u16RemotePort; } return 0; } /******************************************************************************* * Function Name : MQTT_GetVersion * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT8 MQTT_GetVersion(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u8Version; } return 0; } /******************************************************************************* * Function Name : MQTT_GetPdpCid * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT8 MQTT_GetPdpCid(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u8PdpCid; } return 0; } /******************************************************************************* * Function Name : MQTT_GetPktTimeout * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT32 MQTT_GetPktTimeout(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u32PktTimeout; } return 0; } /******************************************************************************* * Function Name : MQTT_GetRetryTimes * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT32 MQTT_GetRetryTimes(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u32RetryTimes; } return 0; } /******************************************************************************* * Function Name : MQTT_GetCleanSession * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT32 MQTT_GetCleanSession(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u8CleanSession; } return 0; } /******************************************************************************* * Function Name : MQTT_GetKeepAlive * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT32 MQTT_GetKeepAlive(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_u32KeepAlive; } return 0; } /******************************************************************************* * Function Name : MQTT_GetClientID * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_CHAR *MQTT_GetClientID(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_acClientID; } return ""; } /******************************************************************************* * Function Name : MQTT_GetUsername * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_CHAR *MQTT_GetUsername(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_acUsername; } return ""; } /******************************************************************************* * Function Name : MQTT_GetPassword * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_CHAR *MQTT_GetmPassword(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_stConfig.m_acPassword; } return ""; } /******************************************************************************* * Function Name : MQTT_RecvAll * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_RecvAll(void) { HIDO_INT32 i32ClinetID = 0; ST_MQTTData *pstMQTTData = HIDO_NULL; for (i32ClinetID = 0; i32ClinetID < MQTT_NUM; i32ClinetID++) { pstMQTTData = &l_astMQTTData[i32ClinetID]; if (pstMQTTData != HIDO_NULL && MQTT_STATE_CONNECTED == pstMQTTData->m_eState) { pstMQTTData->m_bHasRecvData = HIDO_TRUE; } } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_ClosedAll * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_ClosedAll(void) { HIDO_INT32 i32ClinetID = 0; ST_MQTTData *pstMQTTData = HIDO_NULL; for (i32ClinetID = 0; i32ClinetID < MQTT_NUM; i32ClinetID++) { pstMQTTData = &l_astMQTTData[i32ClinetID]; switch (pstMQTTData->m_eState) { case MQTT_STATE_CONNECT: case MQTT_STATE_CLOSE_BEFORE_CONNECT: case MQTT_STATE_CONNECTED: { pstMQTTData->m_bHasRecvData = HIDO_FALSE; pstMQTTData->m_eState = MQTT_STATE_CLOSED; if (pstMQTTData->m_fnEventProc != HIDO_NULL) { pstMQTTData->m_fnEventProc(i32ClinetID, MQTT_EVENT_CLOSED, pstMQTTData->m_pArg); } break; } default: { break; } } } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_OnConnectFailed * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_OnConnectFailed(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } pstMQTTData->m_eState = MQTT_STATE_CONNECT_FAILED; if (pstMQTTData->m_fnEventProc != HIDO_NULL) { pstMQTTData->m_fnEventProc(_i32ClientID, MQTT_EVENT_CONNECT_FAILED, pstMQTTData->m_pArg); } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_OnConnected * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_OnConnected(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } pstMQTTData->m_eState = MQTT_STATE_CONNECTED; /* ÖØÖöÓÁÐ */ HIDO_VLQInit(&pstMQTTData->m_stMQTTSendQueue, pstMQTTData->l_au8MQTTSendQueueBuf, MQTT_SEND_QUEUE_BUF_SIZE, MQTT_SEND_QUEUE_MEMBER_CNT); HIDO_VLQInit(&pstMQTTData->m_stMQTTRecvQueue, pstMQTTData->l_au8MQTTRecvQueueBuf, MQTT_RECV_QUEUE_BUF_SIZE, MQTT_RECV_QUEUE_MEMBER_CNT); /* ֪ͨÉϲã */ if (pstMQTTData->m_fnEventProc != HIDO_NULL) { pstMQTTData->m_fnEventProc(_i32ClientID, MQTT_EVENT_CONNECTED, pstMQTTData->m_pArg); } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_OnClosed * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_OnClosed(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } if (MQTT_STATE_CLOSE_BEFORE_CONNECT == pstMQTTData->m_eState) { return HIDO_ERR; } pstMQTTData->m_eState = MQTT_STATE_CLOSED; if (pstMQTTData->m_fnEventProc != HIDO_NULL) { pstMQTTData->m_fnEventProc(_i32ClientID, MQTT_EVENT_CLOSED, pstMQTTData->m_pArg); } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_OnRecv * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_OnRecv(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } if (pstMQTTData->m_fnEventProc != HIDO_NULL) { pstMQTTData->m_fnEventProc(_i32ClientID, MQTT_EVENT_RECV_DATA, pstMQTTData->m_pArg); } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_OnSend * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_OnSend(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } if (pstMQTTData->m_fnEventProc != HIDO_NULL) { pstMQTTData->m_fnEventProc(_i32ClientID, MQTT_EVENT_DATA_PUBLISHED, pstMQTTData->m_pArg); } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_Create * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Create(HIDO_INT32 *_pi32ClinetID, FN_MQTTEventProc _fnEventProc, HIDO_VOID *_pArg) { HIDO_INT32 i32ClinetID = 0; ST_MQTTData *pstMQTTData = HIDO_NULL; for (i32ClinetID = 0; i32ClinetID < MQTT_NUM; i32ClinetID++) { pstMQTTData = &l_astMQTTData[i32ClinetID]; if (pstMQTTData != HIDO_NULL && MQTT_STATE_IDLE == pstMQTTData->m_eState) { HIDO_UtilBzero(pstMQTTData, sizeof(ST_MQTTData)); pstMQTTData->m_i32ID = i32ClinetID; pstMQTTData->m_eState = MQTT_STATE_CREATED; pstMQTTData->m_fnEventProc = _fnEventProc; pstMQTTData->m_pArg = _pArg; HIDO_VLQInit(&pstMQTTData->m_stMQTTSendQueue, pstMQTTData->l_au8MQTTSendQueueBuf, MQTT_SEND_QUEUE_BUF_SIZE, MQTT_SEND_QUEUE_MEMBER_CNT); HIDO_VLQInit(&pstMQTTData->m_stMQTTRecvQueue, pstMQTTData->l_au8MQTTRecvQueueBuf, MQTT_RECV_QUEUE_BUF_SIZE, MQTT_RECV_QUEUE_MEMBER_CNT); *_pi32ClinetID = i32ClinetID; return HIDO_OK; } } return HIDO_ERR; } /******************************************************************************* * Function Name : MQTT_Subscribe * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Subscribe(HIDO_INT32 _i32ClientID, HIDO_CHAR *_pcTopic, HIDO_UINT32 _u32QOS) { ST_MQTTData *pstMQTTData = HIDO_NULL; ST_SubscribeTopic *pstSubscribeTopic = HIDO_NULL; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || _pcTopic == HIDO_NULL) { return HIDO_ERR; } if (HIDO_NULL == l_pstSubscribeTopicFreeList) { return HIDO_ERR; } pstMQTTData = &l_astMQTTData[_i32ClientID]; pstSubscribeTopic = l_pstSubscribeTopicFreeList; if (pstSubscribeTopic != HIDO_NULL) { l_pstSubscribeTopicFreeList = l_pstSubscribeTopicFreeList->m_pstNext; HIDO_UtilSnprintf(pstSubscribeTopic->m_acTopic, sizeof(pstSubscribeTopic->m_acTopic), _pcTopic); pstSubscribeTopic->m_u32QOS = _u32QOS; pstSubscribeTopic->m_pstNext = pstMQTTData->m_pstTopicList; pstMQTTData->m_pstTopicList = pstSubscribeTopic; } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_GetSubscribeTopicList * Description : * Input : * Output : * Return : *******************************************************************************/ ST_SubscribeTopic *MQTT_GetSubscribeTopicList(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { return l_astMQTTData[_i32ClientID].m_pstTopicList; } return HIDO_NULL; } /******************************************************************************* * Function Name : MQTT_GetMsgID * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_UINT16 MQTT_GetMsgID(HIDO_INT32 _i32ClientID) { if (_i32ClientID < MQTT_NUM) { l_astMQTTData[_i32ClientID].m_u16MsgID++; if (l_astMQTTData[_i32ClientID].m_u16MsgID == 0) { l_astMQTTData[_i32ClientID].m_u16MsgID = 1; } return l_astMQTTData[_i32ClientID].m_u16MsgID; } return 1; } /******************************************************************************* * Function Name : MQTT_SetMsgID * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_SetMsgID(HIDO_INT32 _i32ClientID, HIDO_UINT16 _u16MsgID) { if (_i32ClientID < MQTT_NUM) { l_astMQTTData[_i32ClientID].m_u16MsgID = _u16MsgID; } return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_Connect * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Config(HIDO_INT32 _i32ClientID, ST_MQTTConfig *_pstConfig) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || _pstConfig == HIDO_NULL) { return HIDO_ERR; } memcpy(&(pstMQTTData->m_stConfig), _pstConfig, sizeof(ST_MQTTConfig)); return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_Connect * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Connect(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } pstMQTTData->m_eState = MQTT_STATE_CONNECT; return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_Close * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Close(HIDO_INT32 _i32ClientID) { ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL) { return HIDO_ERR; } pstMQTTData->m_eState = MQTT_STATE_CLOSE; return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_Publish * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Publish(HIDO_INT32 _i32ClientID, HIDO_CHAR *_pcTopic, HIDO_UINT8 *_pu8Data, HIDO_UINT32 _u32DataLen, HIDO_UINT32 _u32QOS) { HIDO_VLQMemberStruct *pstMember = HIDO_NULL; ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; ST_MQTTMessage *pstMessage = HIDO_NULL; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL || _pcTopic == HIDO_NULL) { return HIDO_ERR; } pstMember = HIDO_VLQGetEnqueueMember(&pstMQTTData->m_stMQTTSendQueue, sizeof(ST_MQTTMessage) + _u32DataLen); /* »ñÈ¡Èë¶Ó¿Õ¼ä */ if (HIDO_NULL == pstMember) { // HIDO_Debug("MQTT[%d] send buf full\r\n", _i32ClientID); return HIDO_ERR; } pstMessage = pstMember->m_pDataAddr; HIDO_UtilSnprintf(pstMessage->m_acTopic, sizeof(pstMessage->m_acTopic), _pcTopic); pstMessage->m_u32DataLen = _u32DataLen; pstMessage->m_u32QOS = _u32QOS; pstMessage->m_u32Retain = 0; memcpy(pstMessage->m_au8Data, _pu8Data, _u32DataLen); HIDO_VLQEnqueue(&pstMQTTData->m_stMQTTSendQueue, pstMember); /* Èë¶Ó */ return HIDO_OK; } /******************************************************************************* * Function Name : MQTT_ReadData * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Recv(HIDO_INT32 _i32ClientID, HIDO_CHAR *_pcTopic, HIDO_UINT8 *_pu8RecvBuff, HIDO_UINT32 _u32RecvBuffSize, HIDO_UINT32 *_u32RecvLen) { HIDO_INT32 i32Result = HIDO_ERR; HIDO_VLQMemberStruct *pstMember = HIDO_NULL; ST_MQTTData *pstMQTTData = &l_astMQTTData[_i32ClientID]; ST_MQTTMessage *pcMessage = HIDO_NULL; if (_i32ClientID < 0 || _i32ClientID >= MQTT_NUM || pstMQTTData == HIDO_NULL || _pcTopic == HIDO_NULL) { return HIDO_ERR; } pstMember = HIDO_VLQGetDequeueMember(&pstMQTTData->m_stMQTTRecvQueue); if (pstMember != HIDO_NULL) { pcMessage = pstMember->m_pDataAddr; HIDO_UtilSnprintf(_pcTopic, sizeof(pcMessage->m_acTopic), pcMessage->m_acTopic); if (_u32RecvBuffSize > pcMessage->m_u32DataLen) { memcpy(_pu8RecvBuff, pcMessage->m_au8Data, pcMessage->m_u32DataLen); *_u32RecvLen = pcMessage->m_u32DataLen; i32Result = HIDO_OK; } HIDO_VLQDequeue(&pstMQTTData->m_stMQTTRecvQueue, pstMember); } return i32Result; } /******************************************************************************* * Function Name : MQTT_Init * Description : * Input : * Output : * Return : *******************************************************************************/ HIDO_INT32 MQTT_Init(HIDO_VOID) { HIDO_UINT32 i = 0; ST_SubscribeTopic *pstNext = HIDO_NULL; for (i = 0; i < HIDO_ARRARY_COUNT(l_astSubscribeTopicBuf) - 1; i++) { pstNext = &l_astSubscribeTopicBuf[i + 1]; l_astSubscribeTopicBuf[i].m_pstNext = pstNext; } l_astSubscribeTopicBuf[i].m_pstNext = HIDO_NULL; l_pstSubscribeTopicFreeList = &l_astSubscribeTopicBuf[0]; return HIDO_OK; }