/*************************************************************************** deal with the HA discover request *****************************************************************************/ void AT_AF_Cmd_HA_DISC_req(afIncomingMSGPacket_t *pkt ){ AT_AF_Cmd_HA_DISC_req_t *req = (AT_AF_Cmd_HA_DISC_req_t *)pkt->cmd.Data; AT_AF_Cmd_HA_DISC_rsp_t *rsp; uint8 zcl_epCount =0; uint8 AT_CMD_EP_ARRAY[]=AT_CMD_EPs; uint8 i; uint8 buf_temp[sizeof(AT_AF_Cmd_HA_DISC_rsp_t)+sizeof(AT_CMD_EP_ARRAY)*sizeof(AT_AF_Cmd_HA_DISC_item_t)]; rsp = (AT_AF_Cmd_HA_DISC_rsp_t *) buf_temp; for(i=0;i<sizeof(AT_CMD_EP_ARRAY);i++){ epList_t* epList = AT_af_get_ep(AT_CMD_EP_ARRAY[i]); SimpleDescriptionFormat_t* simDesc=epList->epDesc->simpleDesc; //find the CID bool found=false; uint8 j; for(j=0;j<simDesc->AppNumOutClusters;j++){ if(simDesc->pAppOutClusterList[j]==req->CID) { if(req->option==0){ if(afFindEndPointDesc(AT_CMD_EP_ARRAY[i])) found=true; }else{ found=true; } break; } } if(!found){ for(j=0;j<simDesc->AppNumInClusters;j++){ if(simDesc->pAppInClusterList[j]==req->CID) { if(req->option==0){ if(afFindEndPointDesc(AT_CMD_EP_ARRAY[i])) found=true; }else{ found=true; } break; } } } //if found the CID if(found){ rsp->item[zcl_epCount].ep = AT_CMD_EP_ARRAY[i]; rsp->item[zcl_epCount].status = afFindEndPointDesc(AT_CMD_EP_ARRAY[i]) ? AT_AF_enable : AT_AF_disable; zcl_epCount++; } } if(zcl_epCount!=0){ rsp->hdr.numItem=zcl_epCount; rsp->hdr.cmd=AT_AF_Cmd_rsp; AF_DataRequest( & (pkt->srcAddr), & AT_AF_epDesc, AT_AF_Cmd_HA_DISC_CLUSTERID, sizeof(AT_AF_Cmd_HA_DISC_rsp_t)+zcl_epCount*sizeof(AT_AF_Cmd_HA_DISC_item_t), (uint8*)rsp, &AT_AF_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } }
/*************************************************************************************************** * @fn MT_AppPB_ZCLCfg * * @brief Process MT_APP_PB_ZCL_CFG command * * @param pBuf - pointer to the received buffer * * @return void ***************************************************************************************************/ static void MT_AppPB_ZCLCfg( uint8 *pBuf ) { uint8 retValue = ZFailure; uint8 appEP; endPointDesc_t *epDesc; mtAppPB_ZCLCfg_t *cmd; uint8 cmdId; /* Parse the RPC header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; /* Application End Point */ appEP = *pBuf++; /* Look up the endpoint */ epDesc = afFindEndPointDesc( appEP ); if ( epDesc ) { /* Build and send the message to the APP */ cmd = (mtAppPB_ZCLCfg_t *)osal_msg_allocate( sizeof( mtAppPB_ZCLCfg_t ) ); if ( cmd ) { /* Build and send message to the app */ cmd->hdr.event = MT_SYS_APP_PB_ZCL_CMD; /* PB ZCL command type*/ cmd->type = MT_APP_PB_ZCL_CMD_CFG; /* PB ZCL Config Mode */ cmd->mode = *pBuf++; /* Send the message */ osal_msg_send( *(epDesc->task_id), (uint8 *)cmd ); /* Info for response */ retValue = ZSuccess; } } /* Build and send back the response */ MT_BuildAndSendZToolResponse( ( (uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_APP ), cmdId, 1, &retValue ); }
/*************************************************************************************************** * @fn MT_AfInterPanCtl * * @brief Process the AF Inter Pan control command. * * @param pBuf - pointer to the received buffer * * @return none ***************************************************************************************************/ static void MT_AfInterPanCtl(uint8 *pBuf) { uint8 cmd, rtrn; uint16 panId; endPointDesc_t *pEP; cmd = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; switch (*pBuf++) // Inter-pan request parameter. { case InterPanClr: rtrn = StubAPS_SetIntraPanChannel(); // Switch channel back to the NIB channel. break; case InterPanSet: rtrn = StubAPS_SetInterPanChannel(*pBuf); // Set channel for inter-pan communication. break; case InterPanReg: if ((pEP = afFindEndPointDesc(*pBuf))) { StubAPS_RegisterApp(pEP); rtrn = SUCCESS; } else { rtrn = FAILURE; } break; case InterPanChk: panId = BUILD_UINT16(pBuf[0], pBuf[1]); rtrn = (StubAPS_InterPan(panId, pBuf[2])) ? ZSuccess : ZFailure; break; default: rtrn = afStatus_INVALID_PARAMETER; break; } MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_AF), cmd, 1, &rtrn); }
/*************************************************************************************************** * @fn MT_AppMsg * * @brief Process APP_MSG command * * @param pBuf - pointer to the received buffer * * @return void ***************************************************************************************************/ static void MT_AppMsg(uint8 *pBuf) { uint8 retValue = ZFailure; uint8 endpoint; endPointDesc_t *epDesc; mtSysAppMsg_t *msg; uint8 cmdId, dataLen; /* parse header */ dataLen = pBuf[MT_RPC_POS_LEN]; cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; /* Get the endpoint and skip past it.*/ endpoint = *pBuf++; dataLen--; /* Look up the endpoint */ epDesc = afFindEndPointDesc( endpoint ); if (epDesc) { /* Build and send the message to the APP */ msg = (mtSysAppMsg_t *)osal_msg_allocate(sizeof(mtSysAppMsg_t) + (dataLen)); if ( msg ) { /* Build and send message up the app */ msg->hdr.event = MT_SYS_APP_MSG; msg->endpoint = endpoint; msg->appDataLen = dataLen; msg->appData = (uint8*)(msg+1); osal_memcpy( msg->appData, pBuf, dataLen); osal_msg_send( *(epDesc->task_id), (uint8 *)msg ); /* Info for response */ retValue = ZSuccess; } } /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_APP), cmdId, 1, &retValue); }
/********************************************************************* * @fn afReflectError * * @brief This function will generate the Reflect Error message to * the application. * * @param srcEP - Source Endpoint * @param dstAddrMode - mode of dstAdd - 0 - normal short addr, 1 - group Address * @param dstAddr - intended destination * @param dstEP - Destination Endpoint * @param transID - transaction ID from APSDE_DATA_REQUEST * @param status - status of APSDE_DATA_REQUEST * * @return none */ void afReflectError( uint8 srcEP, uint8 dstAddrMode, uint16 dstAddr, uint8 dstEP, uint8 transID, ZStatus_t status ) { endPointDesc_t *epDesc; afReflectError_t *msgPtr; // Find the endpoint description epDesc = afFindEndPointDesc( srcEP ); if ( epDesc == NULL ) return; // Determine the incoming command type msgPtr = (afReflectError_t *)osal_msg_allocate( sizeof(afReflectError_t) ); if ( msgPtr ) { // Build the Data Confirm message msgPtr->hdr.event = AF_REFLECT_ERROR_CMD; msgPtr->hdr.status = status; msgPtr->endpoint = dstEP; msgPtr->transID = transID; msgPtr->dstAddrMode = dstAddrMode; msgPtr->dstAddr = dstAddr; #if defined ( MT_AF_CB_FUNC ) /* If MT has subscribed for this callback, don't send as a message. */ if ( AFCB_CHECK( CB_ID_AF_REFLECT_ERROR, *(epDesc->task_id) ) ) { /* Send callback if it's subscribed */ MT_AfReflectError( (void *)msgPtr ); /* Release the memory. */ osal_msg_deallocate( (void *)msgPtr ); } else #endif { /* send message through task message */ osal_msg_send( *(epDesc->task_id), (uint8 *)msgPtr ); } } }
/********************************************************************* * @fn afDataConfirm * * @brief This function will generate the Data Confirm back to * the application. * * @param endPoint - confirm end point * @param transID - transaction ID from APSDE_DATA_REQUEST * @param status - status of APSDE_DATA_REQUEST * * @return none */ void afDataConfirm( uint8 endPoint, uint8 transID, ZStatus_t status ) { endPointDesc_t *epDesc; afDataConfirm_t *msgPtr; // Find the endpoint description epDesc = afFindEndPointDesc( endPoint ); if ( epDesc == NULL ) return; // Determine the incoming command type msgPtr = (afDataConfirm_t *)osal_msg_allocate( sizeof(afDataConfirm_t) ); if ( msgPtr ) { // Build the Data Confirm message msgPtr->hdr.event = AF_DATA_CONFIRM_CMD; msgPtr->hdr.status = status; msgPtr->endpoint = endPoint; msgPtr->transID = transID; #if defined ( MT_AF_CB_FUNC ) /* If MT has subscribed for this callback, don't send as a message. */ if ( AFCB_CHECK(CB_ID_AF_DATA_CNF,*(epDesc->task_id)) ) { /* Send callback if it's subscribed */ MT_AfDataConfirm ((void *)msgPtr); /* Release the memory. */ osal_msg_deallocate( (void *)msgPtr ); } else #endif { /* send message through task message */ osal_msg_send( *(epDesc->task_id), (byte *)msgPtr ); } } }
/********************************************************************* * @fn afIncomingData * * @brief Transfer a data PDU (ASDU) from the APS sub-layer to the AF. * * @param aff - pointer to APS frame format * @param SrcAddress - Source address * @param sig - incoming message's link quality * @param SecurityUse - Security enable/disable * * @return none */ void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16 SrcPanId, NLDE_Signal_t *sig, byte SecurityUse, uint32 timestamp ) { endPointDesc_t *epDesc = NULL; uint16 epProfileID = 0xFFFF; // Invalid Profile ID epList_t *pList = epList; #if !defined ( APS_NO_GROUPS ) uint8 grpEp = APS_GROUPS_EP_NOT_FOUND; #endif if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) ) { #if !defined ( APS_NO_GROUPS ) // Find the first endpoint for this group grpEp = aps_FindGroupForEndpoint( aff->GroupID, APS_GROUPS_FIND_FIRST ); if ( grpEp == APS_GROUPS_EP_NOT_FOUND ) return; // No endpoint found epDesc = afFindEndPointDesc( grpEp ); if ( epDesc == NULL ) return; // Endpoint descriptor not found pList = afFindEndPointDescList( epDesc->endPoint ); #else return; // Not supported #endif } else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT ) { // Set the list if ( pList != NULL ) { epDesc = pList->epDesc; } } else if ( (epDesc = afFindEndPointDesc( aff->DstEndPoint )) ) { pList = afFindEndPointDescList( epDesc->endPoint ); } while ( epDesc ) { if ( pList->pfnDescCB ) { uint16 *pID = (uint16 *)(pList->pfnDescCB( AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint )); if ( pID ) { epProfileID = *pID; osal_mem_free( pID ); } } else if ( epDesc->simpleDesc ) { epProfileID = epDesc->simpleDesc->AppProfId; } if ( (aff->ProfileID == epProfileID) || ((epDesc->endPoint == ZDO_EP) && (aff->ProfileID == ZDO_PROFILE_ID)) ) { { afBuildMSGIncoming( aff, epDesc, SrcAddress, SrcPanId, sig, SecurityUse, timestamp ); } } if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) ) { #if !defined ( APS_NO_GROUPS ) // Find the next endpoint for this group grpEp = aps_FindGroupForEndpoint( aff->GroupID, grpEp ); if ( grpEp == APS_GROUPS_EP_NOT_FOUND ) return; // No endpoint found epDesc = afFindEndPointDesc( grpEp ); if ( epDesc == NULL ) return; // Endpoint descriptor not found pList = afFindEndPointDescList( epDesc->endPoint ); #else return; #endif } else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT ) { pList = pList->nextDesc; if ( pList ) epDesc = pList->epDesc; else epDesc = NULL; } else epDesc = NULL; } }
/*************************************************************************************************** * @fn MT_AfDataRequestSrcRtg * * @brief Process AF Register command * * @param pBuf - pointer to the received buffer * * @return none ***************************************************************************************************/ void MT_AfDataRequestSrcRtg(uint8 *pBuf) { uint8 cmdId, dataLen = 0; uint8 retValue = ZFailure; endPointDesc_t *epDesc; byte transId; afAddrType_t dstAddr; cId_t cId; byte txOpts, radius, srcEP, relayCnt; uint16 *pRelayList; uint8 i; /* parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; /* Destination address */ /* Initialize the panID field to zero to avoid inter-pan */ osal_memset( &dstAddr, 0, sizeof(afAddrType_t) ); dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; /* Destination endpoint */ dstAddr.endPoint = *pBuf++; /* Source endpoint */ srcEP = *pBuf++; epDesc = afFindEndPointDesc( srcEP ); /* ClusterId */ cId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf +=2; /* TransId */ transId = *pBuf++; /* TxOption */ txOpts = *pBuf++; /* Radius */ radius = *pBuf++; /* Source route relay count */ relayCnt = *pBuf++; /* Convert the source route relay list */ if( (pRelayList = osal_mem_alloc( relayCnt * sizeof( uint16 ))) != NULL ) { for( i = 0; i < relayCnt; i++ ) { pRelayList[i] = BUILD_UINT16( pBuf[0], pBuf[1] ); pBuf += 2; } /* Data payload Length */ dataLen = *pBuf++; if ( epDesc == NULL ) { retValue = afStatus_INVALID_PARAMETER; } else { retValue = AF_DataRequestSrcRtg( &dstAddr, epDesc, cId, dataLen, pBuf, &transId, txOpts, radius, relayCnt, pRelayList ); } /* Free the memory allocated */ osal_mem_free( pRelayList ); } else { retValue = afStatus_MEM_FAIL; } /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_AF), cmdId, 1, &retValue); }
/*************************************************************************************************** * @fn MT_AfDataRequest * * @brief Process AF Register command * * @param pBuf - pointer to the received buffer * * @return none ***************************************************************************************************/ void MT_AfDataRequest(uint8 *pBuf) { #define MT_AF_REQ_MSG_LEN 10 #define MT_AF_REQ_MSG_EXT 10 endPointDesc_t *epDesc; afAddrType_t dstAddr; cId_t cId; uint8 transId, txOpts, radius; uint8 cmd0, cmd1; uint8 retValue = ZFailure; uint16 dataLen, tempLen; /* Parse header */ cmd0 = pBuf[MT_RPC_POS_CMD0]; cmd1 = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; if (cmd1 == MT_AF_DATA_REQUEST_EXT) { dstAddr.addrMode = (afAddrMode_t)*pBuf++; if (dstAddr.addrMode == afAddr64Bit) { (void)osal_memcpy(dstAddr.addr.extAddr, pBuf, Z_EXTADDR_LEN); } else { dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); } pBuf += Z_EXTADDR_LEN; dstAddr.endPoint = *pBuf++; dstAddr.panId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; } else { /* Destination address */ dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; /* Destination endpoint */ dstAddr.endPoint = *pBuf++; dstAddr.panId = 0; } /* Source endpoint */ epDesc = afFindEndPointDesc(*pBuf++); /* ClusterId */ cId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf +=2; /* TransId */ transId = *pBuf++; /* TxOption */ txOpts = *pBuf++; /* Radius */ radius = *pBuf++; /* Length */ if (cmd1 == MT_AF_DATA_REQUEST_EXT) { dataLen = BUILD_UINT16(pBuf[0], pBuf[1]); tempLen = dataLen + MT_AF_REQ_MSG_LEN + MT_AF_REQ_MSG_EXT; pBuf += 2; } else { dataLen = *pBuf++; tempLen = dataLen + MT_AF_REQ_MSG_LEN; } if ( epDesc == NULL ) { retValue = afStatus_INVALID_PARAMETER; } else if (tempLen > (uint16)MT_RPC_DATA_MAX) { if (pMtAfDataReq != NULL) { retValue = afStatus_INVALID_PARAMETER; } else if ((pMtAfDataReq = osal_mem_alloc(sizeof(mtAfDataReq_t) + dataLen)) == NULL) { retValue = afStatus_MEM_FAIL; } else { retValue = afStatus_SUCCESS; pMtAfDataReq->data = (uint8 *)(pMtAfDataReq+1); (void)osal_memcpy(&(pMtAfDataReq->dstAddr), &dstAddr, sizeof(afAddrType_t)); pMtAfDataReq->epDesc = epDesc; pMtAfDataReq->cId = cId; pMtAfDataReq->dataLen = dataLen; pMtAfDataReq->transId = transId; pMtAfDataReq->txOpts = txOpts; pMtAfDataReq->radius = radius; // Setup to time-out the huge outgoing item if host does not MT_AF_DATA_STORE it. pMtAfDataReq->tick = MT_AF_EXEC_CNT; if (ZSuccess != osal_start_timerEx(MT_TaskID, MT_AF_EXEC_EVT, MT_AF_EXEC_DLY)) { (void)osal_set_event(MT_TaskID, MT_AF_EXEC_EVT); } } } else { retValue = AF_DataRequest(&dstAddr, epDesc, cId, dataLen, pBuf, &transId, txOpts, radius); } if (MT_RPC_CMD_SREQ == (cmd0 & MT_RPC_CMD_TYPE_MASK)) { MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP|(uint8)MT_RPC_SYS_AF), cmd1, 1, &retValue); } }
/********************************************************************* * @fn MT_afCommandProcessing * * @brief * * Process all the AF commands that are issued by test tool * * @param cmd_id - Command ID * @param len - Length of received SPI data message * @param data - pointer to received SPI data message * * @return none */ void MT_afCommandProcessing( uint16 cmd_id , byte len , byte *pData ) { byte i; endPointDesc_t *epDesc; uint8 af_stat = afStatus_FAILED; switch (cmd_id) { case SPI_CMD_AF_INIT: afInit(); //No response for this command break; case SPI_CMD_AF_REGISTER: // First allocate memory for the AF structure epIntDesc epDesc = ( endPointDesc_t * ) osal_mem_alloc( sizeof( endPointDesc_t ) ); if ( epDesc ) { //Assemble the AF structures with the data received //First the Endpoint epDesc->simpleDesc = ( SimpleDescriptionFormat_t * ) osal_mem_alloc( sizeof( SimpleDescriptionFormat_t ) ); if ( epDesc->simpleDesc ) { epDesc->endPoint = *pData++; epDesc->simpleDesc->EndPoint = epDesc->endPoint; epDesc->task_id = &MT_TaskID; //Now for the simple description part epDesc->simpleDesc->AppProfId = BUILD_UINT16( pData[1],pData[0]); pData += sizeof( uint16 ); epDesc->simpleDesc->AppDeviceId = BUILD_UINT16( pData[1],pData[0]); pData += sizeof( uint16 ); epDesc->simpleDesc->AppDevVer = (*pData++) & AF_APP_DEV_VER_MASK ; epDesc->simpleDesc->Reserved = (*pData++) & AF_APP_FLAGS_MASK ; epDesc->simpleDesc->AppNumInClusters = *pData++; if (epDesc->simpleDesc->AppNumInClusters) { epDesc->simpleDesc->pAppInClusterList = (uint16 *) osal_mem_alloc(ZTEST_DEFAULT_PARAM_LEN*sizeof(uint16)); for (i=0; i<ZTEST_DEFAULT_PARAM_LEN; i++) { epDesc->simpleDesc->pAppInClusterList[i] = BUILD_UINT16(*pData, 0); pData++; } } else { pData += ZTEST_DEFAULT_PARAM_LEN; } epDesc->simpleDesc->AppNumOutClusters = *pData++; if (epDesc->simpleDesc->AppNumOutClusters) { epDesc->simpleDesc->pAppOutClusterList = (uint16 *) osal_mem_alloc(ZTEST_DEFAULT_PARAM_LEN*sizeof(uint16)); for (i=0; i<ZTEST_DEFAULT_PARAM_LEN; i++) { epDesc->simpleDesc->pAppOutClusterList[i] = BUILD_UINT16(*pData, 0); pData++; } } else { pData += ZTEST_DEFAULT_PARAM_LEN; } epDesc->latencyReq = (afNetworkLatencyReq_t)*pData; if ( afFindEndPointDesc( epDesc->endPoint ) == NULL ) { af_stat = afRegister( epDesc ); } } else { osal_mem_free( epDesc ); af_stat = afStatus_MEM_FAIL; } } len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_AF_DEFAULT; MT_SendSPIRespMsg( af_stat, SPI_CMD_AF_REGISTER, len, SPI_RESP_LEN_AF_DEFAULT ); break; case SPI_CMD_AF_SENDMSG: { #if ( AF_KVP_SUPPORT ) afKVPCommandFormat_t kvp; afAddOrSend_t addOrSend; byte frameType; #else endPointDesc_t *epDesc; byte transId; #endif afAddrType_t dstAddr; cId_t cId; byte txOpts, radius, srcEP; #if ( AF_KVP_SUPPORT ) frameType = *pData; #endif pData++; txOpts = *pData++; radius = *pData++; // Fill the AF structures with the data received. dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = BUILD_UINT16( pData[1], pData[0] ); pData += 2; dstAddr.endPoint = *pData++; srcEP = *pData++; cId = BUILD_UINT16( pData[1], pData[0] ); pData += 2; #if ( AF_KVP_SUPPORT ) addOrSend = (afAddOrSend_t)(*pData++); kvp.TransSeqNumber = *pData++; kvp.CommandType = *pData++; kvp.AttribDataType = *pData++; kvp.AttribId = BUILD_UINT16( pData[1], pData[0] ); pData += 2; kvp.ErrorCode = *pData++; kvp.DataLength = *pData++; kvp.Data = pData; af_stat = afAddOrSendMessage( &dstAddr, srcEP, cId, addOrSend, frameType, &kvp.TransSeqNumber, kvp.CommandType, kvp.AttribDataType, kvp.AttribId, kvp.ErrorCode, kvp.DataLength, kvp.Data, (txOpts & ~AF_DISCV_ROUTE), (txOpts & AF_DISCV_ROUTE), radius ); #else pData++; transId = *pData++; pData += 5; len = *pData++; epDesc = afFindEndPointDesc( srcEP ); if ( epDesc == NULL ) { af_stat = afStatus_INVALID_PARAMETER; } else { af_stat = AF_DataRequest( &dstAddr, epDesc, cId, len, pData, &transId, txOpts, radius ); } #endif len = SPI_0DATA_MSG_LEN + SPI_RESP_LEN_AF_DEFAULT; MT_SendSPIRespMsg( af_stat, SPI_CMD_AF_SENDMSG, len, SPI_RESP_LEN_AF_DEFAULT ); } break; } }
/*************************************************************************************************** * @fn MT_BuildEndpointDesc * * @brief Build endpoint descriptor and simple descriptor structure from incoming buffer * * @param pBuf - byte array * * @return epDesc - pointer to the endpoint descriptor ***************************************************************************************************/ uint8 MT_BuildEndpointDesc( uint8 *pBuf, void *param ) { uint8 i; uint8 ret = ZSuccess; endPointDesc_t *epDesc; epDesc = (endPointDesc_t *)param; /* check if this endpoint is already registered */ if ( afFindEndPointDesc( *pBuf ) != NULL ) { ret = ZApsDuplicateEntry; } else if ( epDesc ) { epDesc->endPoint = *pBuf; /* Ignore the latency reqs */ epDesc->latencyReq = noLatencyReqs; /* allocate memory for the simple descriptor */ epDesc->simpleDesc = (SimpleDescriptionFormat_t *) osal_mem_alloc(sizeof(SimpleDescriptionFormat_t)); if (epDesc->simpleDesc) { /* Endpoint */ epDesc->simpleDesc->EndPoint = *pBuf++; /* AppProfId */ epDesc->simpleDesc->AppProfId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += sizeof(uint16); /* AppDeviceId */ epDesc->simpleDesc->AppDeviceId = BUILD_UINT16(pBuf[0],pBuf[1]); pBuf += sizeof(uint16); /* AppDevVer */ epDesc->simpleDesc->AppDevVer = (*pBuf++) & AF_APP_DEV_VER_MASK ; /* LatencyReq */ pBuf++; /* AppNumInClusters */ epDesc->simpleDesc->AppNumInClusters = *pBuf++; if (epDesc->simpleDesc->AppNumInClusters) { epDesc->simpleDesc->pAppInClusterList = (uint16 *) osal_mem_alloc((epDesc->simpleDesc->AppNumInClusters)*sizeof(uint16)); if ( epDesc->simpleDesc->pAppInClusterList ) { for (i=0; i<(epDesc->simpleDesc->AppNumInClusters); i++) { epDesc->simpleDesc->pAppInClusterList[i] = BUILD_UINT16(*pBuf, *(pBuf+1)); pBuf += 2; } } else { ret = ZMemError; } } /* AppNumOutClusters */ epDesc->simpleDesc->AppNumOutClusters = *pBuf++; if (epDesc->simpleDesc->AppNumOutClusters) { epDesc->simpleDesc->pAppOutClusterList = (uint16 *) osal_mem_alloc((epDesc->simpleDesc->AppNumOutClusters)*sizeof(uint16)); if (epDesc->simpleDesc->pAppOutClusterList) { for (i=0; i<(epDesc->simpleDesc->AppNumOutClusters); i++) { epDesc->simpleDesc->pAppOutClusterList[i] = BUILD_UINT16(*pBuf, *(pBuf+1)); pBuf += 2; } } else { ret = ZMemError; } } /* if any list cannot be allocated...free all */ if ( ret == ZMemError ) { if (epDesc->simpleDesc->pAppInClusterList) { osal_mem_free(epDesc->simpleDesc->pAppInClusterList); } if (epDesc->simpleDesc->AppNumOutClusters) { osal_mem_free(epDesc->simpleDesc->pAppOutClusterList); } osal_mem_free(epDesc->simpleDesc); } } else { ret = ZMemError; } } return ret; }
/*************************************************************************************************** * @fn MT_AppPB_ZCLMsg * * @brief Process MT_APP_PB_ZCL_MSG command * * @param pBuf - pointer to the received buffer * * @return void ***************************************************************************************************/ static void MT_AppPB_ZCLMsg( uint8 *pBuf ) { uint8 retValue = ZFailure; uint8 appEP; endPointDesc_t *epDesc; mtAppPB_ZCLMsg_t *cmd; uint8 cmdId; uint8 dataLen; /* Parse the RPC header */ dataLen = pBuf[MT_RPC_POS_LEN] - MT_APP_PB_ZCL_MSG_HDR_LEN; cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; /* Application End Point */ appEP = *pBuf++; /* Look up the endpoint */ epDesc = afFindEndPointDesc( appEP ); if ( epDesc ) { /* Build and send the message to the APP */ cmd = (mtAppPB_ZCLMsg_t *)osal_msg_allocate( sizeof( mtAppPB_ZCLMsg_t ) + dataLen ); if ( cmd ) { /* Build and send message to the app */ cmd->hdr.event = MT_SYS_APP_PB_ZCL_CMD; /* PB ZCL command type */ cmd->type = MT_APP_PB_ZCL_CMD_MSG; /* Application End Point */ cmd->appEP = appEP; /* Destination Address */ cmd->dstAddr.addr.shortAddr = osal_build_uint16( pBuf ); pBuf += sizeof(uint16); /* Destination Address Mode */ cmd->dstAddr.addrMode = afAddr16Bit; /* Destination End Point */ cmd->dstAddr.endPoint = *pBuf++;; /* Use Default PAN ID */ cmd->dstAddr.panId = 0xFFFF; /* Cluster ID */ cmd->clusterID = osal_build_uint16( pBuf ); pBuf += sizeof( uint16 ); /* Command ID */ cmd->commandID = *pBuf++; /* Cluster Specific Command */ cmd->specific = *pBuf++; /* Command Direction */ cmd->direction = *pBuf++; /* Disable Default Response */ cmd->disableDefRsp = *pBuf++; /* Manufacturer Code */ cmd->manuCode = osal_build_uint16( pBuf ); pBuf += sizeof( uint16 ); /* ZCL Transaction Sequence Number */ cmd->transSeqNum = *pBuf++; /* Application Data Length */ cmd->appPBDataLen = dataLen; /* Application Data */ cmd->appPBData = (uint8 *)( cmd + 1 ); osal_memcpy( cmd->appPBData, pBuf, dataLen ); /* Send the message */ osal_msg_send( *(epDesc->task_id), (uint8 *)cmd ); /* Info for response */ retValue = ZSuccess; } } /* Build and send back the response */ MT_BuildAndSendZToolResponse( ( (uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_APP ), cmdId, 1, &retValue); }
/*************************************************************************************************** * @fn MT_AfDataRequest * * @brief Process AF Register command * * @param pBuf - pointer to the received buffer * * @return none ***************************************************************************************************/ void MT_AfDataRequest(uint8 *pBuf) { uint8 cmd0, cmd1, tempLen = 0; uint8 retValue = ZFailure; endPointDesc_t *epDesc; byte transId; afAddrType_t dstAddr; cId_t cId; byte txOpts, radius, srcEP; /* Parse header */ cmd0 = pBuf[MT_RPC_POS_CMD0]; cmd1 = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; if (cmd1 == MT_AF_DATA_REQUEST_EXT) { dstAddr.addrMode = (afAddrMode_t)*pBuf++; if (dstAddr.addrMode == afAddr64Bit) { (void)osal_memcpy(dstAddr.addr.extAddr, pBuf, Z_EXTADDR_LEN); } else { dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); } pBuf += Z_EXTADDR_LEN; dstAddr.endPoint = *pBuf++; dstAddr.panId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; } else { /* Destination address */ dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf += 2; /* Destination endpoint */ dstAddr.endPoint = *pBuf++; dstAddr.panId = 0; } /* Source endpoint */ srcEP = *pBuf++; epDesc = afFindEndPointDesc( srcEP ); /* ClusterId */ cId = BUILD_UINT16(pBuf[0], pBuf[1]); pBuf +=2; /* TransId */ transId = *pBuf++; /* TxOption */ txOpts = *pBuf++; /* Radius */ radius = *pBuf++; /* Length */ tempLen = *pBuf++; if ( epDesc == NULL ) { retValue = afStatus_INVALID_PARAMETER; } else { retValue = AF_DataRequest( &dstAddr, epDesc, cId, tempLen, pBuf, &transId, txOpts, radius ); } if (MT_RPC_CMD_SREQ == (cmd0 & MT_RPC_CMD_TYPE_MASK)) { MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP|(uint8)MT_RPC_SYS_AF), cmd1, 1, &retValue); } }
/********************************************************************* * @fn afIncomingData * * @brief Transfer a data PDU (ASDU) from the APS sub-layer to the AF. * * @param aff - pointer to APS frame format * @param SrcAddress - Source address * @param SrcPanId - Source PAN ID * @param sig - incoming message's link quality * @param nwkSeqNum - incoming network sequence number (from nwk header frame) * @param SecurityUse - Security enable/disable * @param timestamp - the MAC Timer2 timestamp at Rx. * @param radius - incoming messages received radius * * @return none */ void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16 SrcPanId, NLDE_Signal_t *sig, uint8 nwkSeqNum, uint8 SecurityUse, uint32 timestamp, uint8 radius ) { endPointDesc_t *epDesc = NULL; epList_t *pList = epList; #if !defined ( APS_NO_GROUPS ) uint8 grpEp = APS_GROUPS_EP_NOT_FOUND; #endif if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) ) { #if !defined ( APS_NO_GROUPS ) // Find the first endpoint for this group grpEp = aps_FindGroupForEndpoint( aff->GroupID, APS_GROUPS_FIND_FIRST ); if ( grpEp == APS_GROUPS_EP_NOT_FOUND ) return; // No endpoint found epDesc = afFindEndPointDesc( grpEp ); if ( epDesc == NULL ) return; // Endpoint descriptor not found pList = afFindEndPointDescList( epDesc->endPoint ); #else return; // Not supported #endif } else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT ) { // Set the list if ( pList != NULL ) { epDesc = pList->epDesc; } } else if ( (epDesc = afFindEndPointDesc( aff->DstEndPoint )) ) { pList = afFindEndPointDescList( epDesc->endPoint ); } while ( epDesc ) { uint16 epProfileID = 0xFFFE; // Invalid Profile ID if ( pList->pfnDescCB ) { uint16 *pID = (uint16 *)(pList->pfnDescCB( AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint )); if ( pID ) { epProfileID = *pID; osal_mem_free( pID ); } } else if ( epDesc->simpleDesc ) { epProfileID = epDesc->simpleDesc->AppProfId; } // First part of verification is to make sure that: // the local Endpoint ProfileID matches the received ProfileID OR // the message is specifically send to ZDO (this excludes the broadcast endpoint) OR // if the Wildcard ProfileID is received the message should not be sent to ZDO endpoint if ( (aff->ProfileID == epProfileID) || ((epDesc->endPoint == ZDO_EP) && (aff->ProfileID == ZDO_PROFILE_ID)) || ((epDesc->endPoint != ZDO_EP) && ( aff->ProfileID == ZDO_WILDCARD_PROFILE_ID )) ) { // Save original endpoint uint8 endpoint = aff->DstEndPoint; // overwrite with descriptor's endpoint aff->DstEndPoint = epDesc->endPoint; afBuildMSGIncoming( aff, epDesc, SrcAddress, SrcPanId, sig, nwkSeqNum, SecurityUse, timestamp, radius ); // Restore with original endpoint aff->DstEndPoint = endpoint; } if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) ) { #if !defined ( APS_NO_GROUPS ) // Find the next endpoint for this group grpEp = aps_FindGroupForEndpoint( aff->GroupID, grpEp ); if ( grpEp == APS_GROUPS_EP_NOT_FOUND ) return; // No endpoint found epDesc = afFindEndPointDesc( grpEp ); if ( epDesc == NULL ) return; // Endpoint descriptor not found pList = afFindEndPointDescList( epDesc->endPoint ); #else return; #endif } else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT ) { pList = pList->nextDesc; if ( pList ) epDesc = pList->epDesc; else epDesc = NULL; } else epDesc = NULL; } }