/********************************************************************* * @fn ZDOInitDevice * * @brief Start the device in the network. This function will read * ZCD_NV_STARTUP_OPTION (NV item) to determine whether or not to * restore the network state of the device. * * @param startDelay - timeDelay to start device (in milliseconds). * There is a jitter added to this delay: * ((NWK_START_DELAY + startDelay) * + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK)) * * NOTE: If the application would like to force a "new" join, the * application should set the ZCD_STARTOPT_DEFAULT_NETWORK_STATE * bit in the ZCD_NV_STARTUP_OPTION NV item before calling * this function. "new" join means to not restore the network * state of the device. Use zgWriteStartupOptions() to set these * options. * * @return * ZDO_INITDEV_RESTORED_NETWORK_STATE - The device's network state was * restored. * ZDO_INITDEV_NEW_NETWORK_STATE - The network state was initialized. * This could mean that ZCD_NV_STARTUP_OPTION said to not restore, or * it could mean that there was no network state to restore. * ZDO_INITDEV_LEAVE_NOT_STARTED - Before the reset, a network leave was issued * with the rejoin option set to TRUE. So, the device was not * started in the network (one time only). The next time this * function is called it will start. * 0xFF for failure. */ uint8 ZDOInitDevice(uint16 startDelay) { uint8 *pBuf; #if !ZAP_ZDO_STARTUP_AREQ uint8 rtrn; #endif (void)startDelay; // ZNP MT_ZDO_STARTUP_FROM_APP processing forces delay 0. zb_GetDeviceInfo(ZB_INFO_DEV_STATE, &devState); if ((DEV_HOLD != devState) && (DEV_INIT != devState) && (DEV_NWK_ORPHAN != devState)) { return FAILURE; } #if ZAP_ZDO_STARTUP_AREQ pBuf = zap_msg_allocate(0, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_AREQ, (uint8)MT_ZDO_STARTUP_FROM_APP); #else pBuf = zap_msg_allocate(0, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_ZDO_STARTUP_FROM_APP); #endif if (NULL == pBuf) { return 0xFF; } zapPhySend(zapAppPort, pBuf); #if !ZAP_ZDO_STARTUP_AREQ if (ZSuccess == (rtrn = ZAP_SRSP_STATUS(pBuf))) #endif // Need to locally enter the discovery state to holdoff calls to ZDOInitDevice() until the ZAP // monitoring task requests the actual ZNP state. devState = DEV_NWK_DISC; zap_msg_deallocate(&pBuf); // Joining can take some time - especially with > 1 scan channel. if (ZSuccess != osal_start_timerEx(zapTaskId, ZAP_APP_TMR_EVT, ZAP_APP_JOIN_DLY)) { (void)osal_set_event(zapTaskId, ZAP_APP_TMR_EVT); } #if ZAP_ZDO_STARTUP_AREQ // Made into an AREQ after empirical results showed > 400 msec delay on SRSP. #if ZAP_NV_RESTORE return ZDO_INITDEV_RESTORED_NETWORK_STATE; #else return ZDO_INITDEV_NEW_NETWORK_STATE; #endif #else return rtrn; #endif }
/************************************************************************************************** * @fn sapiReq * * @brief This function packs and sends an RPC SAPI request. * * input parameters * * @param cmd - A valid SAPI command. * @param arg - A valid argument corresponding to the SAPI command. * @param req - A buffer containing the contents of the request, or NULL. * @param len - The non-zero length of a non-NULL req buffer, or NULL. * * output parameters * * None. * * @return SUCCESS or FAILURE. ************************************************************************************************** */ static uint8 sapiReq(uint8 cmd, uint8 arg, uint8 *req, uint8 len) { uint8 cmd0 = (MT_SAPI_SYS_RESET == cmd) ? ((uint8)MT_RPC_SYS_SAPI | (uint8)MT_RPC_CMD_AREQ): ((uint8)MT_RPC_SYS_SAPI | (uint8)MT_RPC_CMD_SREQ); uint8 *pBuf = zap_msg_allocate((uint8)(len + 2), cmd0, cmd); uint8 rtrn = FAILURE; if (NULL != pBuf) { pBuf[0] = arg; pBuf[1] = len; if (NULL != req) { (void)osal_memcpy(pBuf+2, req, len); } if (((rtrn = zapPhySend(zapAppPort, pBuf)) == SUCCESS) && (NULL != req)) { (void)osal_memcpy(req, pBuf, ZAP_MSG_LEN(pBuf)); } zap_msg_deallocate(&pBuf); } return rtrn; }
/********************************************************************* * @fn ZDP_SimpleDescReq * * @brief This builds and send a NWK_Simple_Desc_req * message. This function sends unicast message to the * destination device. * * @param dstAddr - destination address * @param nwkAddr - 16 bit address * @param epIntf - endpoint/interface * @param SecurityEnable - Security Options * * @return afStatus_t */ afStatus_t ZDP_SimpleDescReq( zAddrType_t *dstAddr, uint16 nwkAddr, byte endPoint, byte SecurityEnable ) { uint8 *pBuf, rtrn; (void)SecurityEnable; pBuf = zap_msg_allocate(5, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_ZDO_SIMPLE_DESC_REQ); if (NULL == pBuf) { return afStatus_MEM_FAIL; } pBuf[0] = LO_UINT16(dstAddr->addr.shortAddr); pBuf[1] = HI_UINT16(dstAddr->addr.shortAddr); pBuf[2] = LO_UINT16(nwkAddr); pBuf[3] = HI_UINT16(nwkAddr); pBuf[4] = endPoint; zapPhySend(zapAppPort, pBuf); rtrn = ZAP_SRSP_STATUS(pBuf); zap_msg_deallocate(&pBuf); return (afStatus_t)rtrn; }
/************************************************************************************************** * @fn ZDP_EndDeviceBindReq * * @brief This builds and sends a End_Device_Bind_req message. * This function sends a unicast message. * * input parameters * * @param dstAddr - destination address * @param LocalCoordinator - short address of local coordinator * @param epIntf - Endpoint/Interface of Simple Desc * @param ProfileID - Profile ID * * The Input cluster list is the opposite of what you would think. * This is the output cluster list of this device * @param NumInClusters - number of input clusters * @param InClusterList - input cluster ID list * * The Output cluster list is the opposite of what you would think. * This is the input cluster list of this device * @param NumOutClusters - number of output clusters * @param OutClusterList - output cluster ID list * * @param SecurityEnable - Security Options * * output parameters * * None. * * @return afStatus_t ************************************************************************************************** */ afStatus_t ZDP_EndDeviceBindReq(zAddrType_t *dstAddr, uint16 LocalCoordinator, byte endPoint, uint16 ProfileID, byte NumInClusters, cId_t *InClusterList, byte NumOutClusters, cId_t *OutClusterList, byte SecurityEnable) { const uint8 len = 17 + ((NumInClusters + NumOutClusters) * 2); uint8 *pBuf, *pPtr, cnt; (void)SecurityEnable; if ((Addr16Bit != dstAddr->addrMode) && (AddrBroadcast != dstAddr->addrMode)) { return afStatus_INVALID_PARAMETER; } pBuf = zap_msg_allocate(len, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_ZDO_END_DEV_BIND_REQ); if (NULL == pBuf) { return afStatus_MEM_FAIL; } pPtr = pBuf; *pPtr++ = LO_UINT16(dstAddr->addr.shortAddr); *pPtr++ = HI_UINT16(dstAddr->addr.shortAddr); *pPtr++ = LO_UINT16(LocalCoordinator); *pPtr++ = HI_UINT16(LocalCoordinator); //(void)osal_memset(pPtr, 0, Z_EXTADDR_LEN); // MT_ZDO ignores extended address. pPtr += Z_EXTADDR_LEN; *pPtr++ = endPoint; *pPtr++ = LO_UINT16(ProfileID); *pPtr++ = HI_UINT16(ProfileID); *pPtr++ = NumInClusters; for (cnt = 0; cnt < NumInClusters; cnt++) { *pPtr++ = LO_UINT16(*InClusterList); *pPtr++ = HI_UINT16(*InClusterList); InClusterList++; } *pPtr++ = NumOutClusters; for (cnt = 0; cnt < NumOutClusters; cnt++) { *pPtr++ = LO_UINT16(*OutClusterList); *pPtr++ = HI_UINT16(*OutClusterList); OutClusterList++; } zapPhySend(zapAppPort, pBuf); cnt = ZAP_SRSP_STATUS(pBuf); zap_msg_deallocate(&pBuf); return (afStatus_t)cnt; }
/********************************************************************* * @fn ZDO_RemoveRegisteredCB * * @brief Call this function if you don't want to receive the * incoming message. * * @param taskID - Where the messages are being delivered. * @param clusterID - What message? * * @return ZSuccess - successful, ZFailure if not found */ ZStatus_t ZDO_RemoveRegisteredCB( uint8 taskID, uint16 clusterID ) { ZDO_MsgCB_t *pList; ZDO_MsgCB_t *pLast = NULL; pList = zdoMsgCBs; while ( pList ) { if ( pList->taskID == taskID && pList->clusterID == clusterID ) { uint8 *pBuf, rtrn; // Note that this could be sent AREQ to free up the host (but then no status.) if (NULL == (pBuf = zap_msg_allocate(2, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_ZDO_MSG_CB_REMOVE))) { return ZMemError; } pBuf[0] = LO_UINT16(clusterID); pBuf[1] = HI_UINT16(clusterID); zapPhySend(zapAppPort, pBuf); rtrn = ZAP_SRSP_STATUS(pBuf); zap_msg_deallocate(&pBuf); if (ZSuccess != rtrn) { return (ZStatus_t)rtrn; } if ( pLast ) { // remove this one from the linked list pLast->next = pList->next; } else if ( pList->next ) { // remove the first one from the linked list zdoMsgCBs = pList->next; } else { // remove the only item from the list zdoMsgCBs = (ZDO_MsgCB_t *)NULL; } osal_mem_free( pList ); return ( ZSuccess ); } pLast = pList; pList = pList->next; } return ( ZFailure ); }
/************************************************************************************************** * @fn afRetrieve * * @brief This function retrieves the data of a huge incoming message. On an failure during * the retrieval, the incoming message is freed. Otherwise, the incoming message is * forwarded to the corresponding task. * * input parameters * * @param pMsg - Pointer to the incoming AF message. * @param taskId - The task ID corresponding to the destination endpoint of the message. * * output parameters * * @param pMsg->cmd.Data - The incoming message data buffer member is filled. * * @return None. ************************************************************************************************** */ static void afRetrieve(uint8 taskId, afIncomingMSGPacket_t *pMsg) { #define ZAP_AF_RTV_MSG_HDR 7 // Retrieve message header length. #define ZAP_AF_RTV_RPY_HDR 2 // Retrieve-reply message header length. #define ZAP_AF_RTV_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_RTV_RPY_HDR) uint16 idx = 0, len = pMsg->cmd.DataLength; uint8 *pBuf, rtrn, tmpLen = 0; do { /* This trick to pre-decrement (with zero on the first pass) allows the while() test to * succeed and loop to send a zero data length message which will trigger the ZNP to * de-allocate the huge incoming message being held. */ len -= tmpLen; idx += tmpLen; if (len > ZAP_AF_RTV_DAT_MAX) { tmpLen = ZAP_AF_RTV_DAT_MAX; } else { tmpLen = len; } if ((pBuf = zap_msg_allocate(ZAP_AF_RTV_MSG_HDR, ((uint8)MT_RPC_SYS_AF | MT_RPC_CMD_SREQ), MT_AF_DATA_RETRIEVE)) == NULL) { rtrn = afStatus_MEM_FAIL; break; } pBuf[0] = BREAK_UINT32(pMsg->timestamp, 0); pBuf[1] = BREAK_UINT32(pMsg->timestamp, 1); pBuf[2] = BREAK_UINT32(pMsg->timestamp, 2); pBuf[3] = BREAK_UINT32(pMsg->timestamp, 3); pBuf[4] = LO_UINT16(idx); pBuf[5] = HI_UINT16(idx); pBuf[6] = tmpLen; zapPhySend(zapAppPort, pBuf); rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf); (void)osal_memcpy(pMsg->cmd.Data+idx, pBuf+ZAP_AF_RTV_RPY_HDR, tmpLen); zap_msg_deallocate(&pBuf); } while ((rtrn == afStatus_SUCCESS) && len); if (rtrn == afStatus_SUCCESS) { (void)osal_msg_send(taskId, (uint8 *)pMsg); } else { (void)osal_msg_deallocate((uint8 *)pMsg); } }
/************************************************************************************************** * @fn ZDP_MatchDescReq * * @brief This builds and send a Match_Desc_req message. This * function sends a broadcast or unicast message * requesting the list of endpoint/interfaces that * match profile ID and cluster IDs. * * input parameters * * @param dstAddr - destination address * @param ProfileID - Profile ID * @param NumInClusters - number of input clusters * @param InClusterList - input cluster ID list * @param NumOutClusters - number of output clusters * @param OutClusterList - output cluster ID list * @param SecurityEnable - Security Options * * output parameters * * None. * * @return afStatus_t ************************************************************************************************** */ afStatus_t ZDP_MatchDescReq(zAddrType_t *dstAddr, uint16 nwkAddr, uint16 ProfileID, byte NumInClusters, cId_t *InClusterList, byte NumOutClusters, cId_t *OutClusterList, byte SecurityEnable) { const uint8 len = 8 + ((NumInClusters + NumOutClusters) * 2); uint8 *pBuf, *pPtr, cnt; (void)SecurityEnable; if ((Addr16Bit != dstAddr->addrMode) && (AddrBroadcast != dstAddr->addrMode)) { return afStatus_INVALID_PARAMETER; } pBuf = zap_msg_allocate(len, (uint8)MT_RPC_SYS_ZDO | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_ZDO_MATCH_DESC_REQ); if (NULL == pBuf) { return afStatus_MEM_FAIL; } pPtr = pBuf; *pPtr++ = LO_UINT16(dstAddr->addr.shortAddr); *pPtr++ = HI_UINT16(dstAddr->addr.shortAddr); *pPtr++ = LO_UINT16(nwkAddr); *pPtr++ = HI_UINT16(nwkAddr); *pPtr++ = LO_UINT16(ProfileID); *pPtr++ = HI_UINT16(ProfileID); *pPtr++ = NumInClusters; for (cnt = 0; cnt < NumInClusters; cnt++) { *pPtr++ = LO_UINT16(*InClusterList); *pPtr++ = HI_UINT16(*InClusterList); InClusterList++; } *pPtr++ = NumOutClusters; for (cnt = 0; cnt < NumOutClusters; cnt++) { *pPtr++ = LO_UINT16(*OutClusterList); *pPtr++ = HI_UINT16(*OutClusterList); OutClusterList++; } zapPhySend(zapAppPort, pBuf); cnt = ZAP_SRSP_STATUS(pBuf); zap_msg_deallocate(&pBuf); return (afStatus_t)cnt; }
/************************************************************************************************** * @fn afStore * * @brief This function stores a huge outgoing message data buffer on the ZNP. * * input parameters * * @param buf - Pointer to the message data buffer. * @param len - The length of the message data buffer 'buf'. * * output parameters * * None. * * @return The AF-Status of storing the message data on the ZNP. ************************************************************************************************** */ static afStatus_t afStore(uint8 *buf, uint16 len) { #define ZAP_AF_STO_MSG_HDR 3 #define ZAP_AF_STO_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_STO_MSG_HDR) uint8 *pBuf; uint16 idx = 0; uint8 tmpLen = 0; afStatus_t rtrn; do { /* This trick to pre-decrement (with zero on the first pass) allows the while() test to * succeed and loop to send a zero data length message which will trigger the ZNP to send the * accumulated data OTA in an AF_DataRequest(). */ len -= tmpLen; idx += tmpLen; if (len > ZAP_AF_STO_DAT_MAX) { tmpLen = ZAP_AF_STO_DAT_MAX; } else { tmpLen = len; } if ((pBuf = zap_msg_allocate((uint8)(tmpLen + ZAP_AF_STO_MSG_HDR), (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_AF_DATA_STORE)) == NULL) { rtrn = afStatus_MEM_FAIL; break; } pBuf[0] = LO_UINT16(idx); pBuf[1] = HI_UINT16(idx); pBuf[2] = tmpLen; (void)osal_memcpy(pBuf+3, buf+idx, tmpLen); zapPhySend(zapAppPort, pBuf); rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf); zap_msg_deallocate(&pBuf); } while ((rtrn == afStatus_SUCCESS) && len); return rtrn; }
/****************************************************************************** * @fn zb_PermitJoiningRequest * * @brief The zb_PermitJoiningRequest function is used to control the * joining permissions and thus allow or disallow new devices from * joining the network. * * @param destination - The destination parameter indicates the address * of the device for which the joining permissions * should be set. This is usually the local device * address or the special broadcast address that denotes * all routers and coordinator ( 0xFFFC ). This way * the joining permissions of a single device or the * whole network can be controlled. * timeout - Indicates the amount of time in seconds for which * the joining permissions should be turned on. * If timeout is set to 0x00, the device will turn off the * joining permissions indefinitely. If it is set to 0xFF, * the joining permissions will be turned on indefinitely. * * * @return ZB_SUCCESS or a failure code * */ uint8 zb_PermitJoiningRequest(uint16 destination, uint8 timeout) { uint8 rtrn = ZB_FAILURE; uint8 *pBuf = zap_msg_allocate(3, ((uint8)MT_RPC_SYS_SAPI | (uint8)MT_RPC_CMD_SREQ), MT_SAPI_PMT_JOIN_REQ); if (pBuf != NULL) { pBuf[0] = LO_UINT16(destination); pBuf[1] = HI_UINT16(destination); pBuf[2] = timeout; if (zapPhySend(zapAppPort, pBuf) == SUCCESS) { rtrn = pBuf[0]; } zap_msg_deallocate(&pBuf); } return rtrn; }
/************************************************************************************************** * @fn zapSysReq * * @brief This function packs and sends an RPC SYS request. * * input parameters * * @param cmd - A valid SYS command. * @param req - A buffer containing the contents of the request/response, or NULL. * @param args - Valid argument(s) corresponding to the SYS command. * * output parameters * * @param req - The buffer filled with the contents or success of a response. * @param args - The buffer filled with the contents or success of a response. * * @return SUCCESS or FAILURE. ************************************************************************************************** */ uint8 zapSysReq(uint8 cmd, uint8 *req, uint8 *args) { uint8 len, cmd0 = (uint8)MT_RPC_CMD_SREQ; uint8 *pBuf; switch (cmd) { // SREQ's to ZNP. case MT_SYS_PING: case MT_SYS_RANDOM: case MT_SYS_ADC_READ: len = 2; break; case MT_SYS_VERSION: len = sizeof(MTVersionString); break; case MT_SYS_SET_EXTADDR: case MT_SYS_GET_EXTADDR: len = Z_EXTADDR_LEN; break; case MT_SYS_OSAL_NV_READ: len = 3; break; case MT_SYS_OSAL_NV_WRITE: len = args[3] + 4; break; case MT_SYS_OSAL_START_TIMER: len = 3; break; case MT_SYS_OSAL_STOP_TIMER: len = 1; break; case MT_SYS_GPIO: break; case MT_SYS_STACK_TUNE: len = args[1] + 1; break; // AREQ's to ZNP. case MT_SYS_RESET_REQ: cmd0 = (uint8)MT_RPC_CMD_AREQ; len = 1; break; default: len = 8; // Biggest return buffer size besides NV access. break; } cmd0 |= (uint8)MT_RPC_SYS_SYS; if (NULL == (pBuf = zap_msg_allocate(len, cmd0, cmd))) { return FAILURE; } switch (cmd) { case MT_SYS_SET_EXTADDR: (void)osal_memcpy(pBuf, req, Z_EXTADDR_LEN); break; case MT_SYS_OSAL_NV_WRITE: (void)osal_memcpy(pBuf+4, req, args[3]); pBuf[3] = args[3]; // NV Item len. case MT_SYS_OSAL_NV_READ: case MT_SYS_OSAL_START_TIMER: pBuf[2] = args[2]; // NV Item offset / Timer Period MSB. case MT_SYS_ADC_READ: pBuf[1] = args[1]; // NV Item Id MSB / Timer Period LSB / ADC Resolution. case MT_SYS_RESET_REQ: case MT_SYS_OSAL_STOP_TIMER: pBuf[0] = args[0]; // NV Item Id LSB / Timer Idx / ADC Chan. break; case MT_SYS_GPIO: break; case MT_SYS_STACK_TUNE: pBuf[0] = args[0]; // The MT_SYS_STACK_TUNE command from STK_Tune_t. (void)osal_memcpy(pBuf+1, req, args[1]); break; default: break; } if (zapPhySend(zapAppPort, pBuf) == FAILURE) { zap_msg_deallocate(&pBuf); return FAILURE; } switch (cmd) { // SREQ's to ZNP. case MT_SYS_PING: case MT_SYS_RANDOM: case MT_SYS_ADC_READ: (void)osal_memcpy(req, pBuf, 2); break; case MT_SYS_VERSION: (void)osal_memcpy(req, pBuf, sizeof(MTVersionString)); break; case MT_SYS_SET_EXTADDR: // It is not intuitive to have non-NULL args just for return value that should always be TRUE. break; case MT_SYS_OSAL_NV_WRITE: case MT_SYS_OSAL_START_TIMER: case MT_SYS_OSAL_STOP_TIMER: args[0] = pBuf[0]; break; case MT_SYS_GET_EXTADDR: (void)osal_memcpy(req, pBuf, Z_EXTADDR_LEN); break; case MT_SYS_OSAL_NV_READ: if ((SUCCESS == (args[0] = pBuf[0])) && (args[3] == (args[1] = pBuf[1]))) { (void)osal_memcpy(req, pBuf+2, args[1]); } else { args[0] = NV_OPER_FAILED; } break; case MT_SYS_GPIO: break; case MT_SYS_STACK_TUNE: *req = *pBuf; break; default: break; } zap_msg_deallocate(&pBuf); return SUCCESS; }
/************************************************************************************************** * @fn zapUtilReq * * @brief This function packs and sends an RPC NWK request. * * input parameters * * @param cmd - A valid NWK command. * @param req - A buffer containing the contents of the request/response, or NULL. * @param args - Valid argument(s) corresponding to the NWK command. * * output parameters * * @param req - The buffer filled with the contents or success of a response. * @param args - The buffer filled with the contents or success of a response. * * @return SUCCESS or FAILURE. ************************************************************************************************** */ uint8 zapUtilReq(uint8 cmd, uint8 *req, uint8 *args) { uint8 len, cmd0 = (uint8)MT_RPC_CMD_SREQ; uint8 rtrn = SUCCESS; uint8 *pBuf; if (DEV_STATE_INVALID <= devState) { return FAILURE; } switch (cmd) { // SREQ's to ZNP. case MT_UTIL_ASSOC_GET_WITH_ADDRESS: len = Z_EXTADDR_LEN + 2; break; case MT_UTIL_ADDRMGR_NWK_ADDR_LOOKUP: case MT_UTIL_ASSOC_COUNT: len = 2; break; #if SECURE case MT_UTIL_APSME_LINK_KEY_DATA_GET: len = Z_EXTADDR_LEN; break; case MT_UTIL_APSME_LINK_KEY_NV_ID_GET: len = Z_EXTADDR_LEN; break; #endif case MT_UTIL_ASSOC_FIND_DEVICE: len = 1; break; #if defined ZCL_KEY_ESTABLISH case MT_UTIL_ZCL_KEY_EST_INIT_EST: len = 12; break; case MT_UTIL_ZCL_KEY_EST_SIGN: len = *args +1; break; #endif // AREQ's to ZNP. case MT_UTIL_SYNC_REQ: cmd0 = (uint8)MT_RPC_CMD_AREQ; len = 0; break; default: return FAILURE; } cmd0 |= (uint8)MT_RPC_SYS_UTIL; if (NULL == (pBuf = zap_msg_allocate(len, cmd0, cmd))) { return FAILURE; } switch (cmd) { // SREQ's to ZNP. case MT_UTIL_ADDRMGR_NWK_ADDR_LOOKUP: pBuf[0] = *args++; pBuf[1] = *args; break; #if SECURE case MT_UTIL_APSME_LINK_KEY_DATA_GET: (void)osal_memcpy(pBuf, req, Z_EXTADDR_LEN); break; case MT_UTIL_APSME_LINK_KEY_NV_ID_GET: (void)osal_memcpy(pBuf, req, Z_EXTADDR_LEN); break; #endif case MT_UTIL_ASSOC_COUNT: (void)osal_memcpy(pBuf, req, 2); break; case MT_UTIL_ASSOC_FIND_DEVICE: pBuf[0] = *args; break; case MT_UTIL_ASSOC_GET_WITH_ADDRESS: if (NULL == args) { (void)osal_memset(pBuf, 0, Z_EXTADDR_LEN); } else { (void)osal_memcpy(pBuf, args, Z_EXTADDR_LEN); } pBuf[Z_EXTADDR_LEN] = LO_UINT16(assocDevT.shortAddr); pBuf[Z_EXTADDR_LEN+1] = HI_UINT16(assocDevT.shortAddr); break; #if defined ZCL_KEY_ESTABLISH case MT_UTIL_ZCL_KEY_EST_INIT_EST: (void)osal_memcpy(pBuf, req, 12); break; case MT_UTIL_ZCL_KEY_EST_SIGN: *pBuf = *args; (void)osal_memcpy(pBuf+1, req, *args); break; #endif // AREQ's to ZNP. default: break; } if (zapPhySend(zapAppPort, pBuf) == FAILURE) { zap_msg_deallocate(&pBuf); return FAILURE; } switch (cmd) { // SREQ's to ZNP. case MT_UTIL_ADDRMGR_NWK_ADDR_LOOKUP: (void)osal_memcpy(req, pBuf, Z_EXTADDR_LEN); break; #if SECURE case MT_UTIL_APSME_LINK_KEY_DATA_GET: if (SUCCESS == (rtrn = *pBuf)) { APSME_LinkKeyData_t *pData = (APSME_LinkKeyData_t *)args; uint8 *ptr = pBuf+1; // copy key data (void)osal_memcpy(pData->key, ptr, SEC_KEY_LEN); ptr += SEC_KEY_LEN; pData->txFrmCntr = BUILD_UINT32(ptr[0], ptr[1], ptr[2], ptr[3]); ptr += 4; pData->rxFrmCntr = BUILD_UINT32(ptr[0], ptr[1], ptr[2], ptr[3]); } break; case MT_UTIL_APSME_LINK_KEY_NV_ID_GET: if (SUCCESS == (rtrn = *pBuf)) { uint16 *pNvId = (uint16 *)args; uint8 *ptr = pBuf+1; *pNvId = BUILD_UINT16(ptr[0], ptr[1]); } break; #endif case MT_UTIL_ASSOC_COUNT: (void)osal_memcpy(req, pBuf, 2); break; case MT_UTIL_ASSOC_FIND_DEVICE: case MT_UTIL_ASSOC_GET_WITH_ADDRESS: (void)osal_memcpy(req, pBuf, sizeof(associated_devices_t)); break; #if defined ZCL_KEY_ESTABLISH case MT_UTIL_ZCL_KEY_EST_SIGN: #if defined SECURE (void)osal_memcpy(req, pBuf+1, SE_PROFILE_SIGNATURE_LENGTH); #endif case MT_UTIL_ZCL_KEY_EST_INIT_EST: rtrn = *pBuf; break; #endif // AREQ's to ZNP. default: break; } zap_msg_deallocate(&pBuf); return rtrn; }
/************************************************************************************************** * @fn AF_DataRequest * * @brief API definition to invoke AF_DataRequest on the ZNP. * * input parameters * * @param *dstAddr - Full ZB destination address: Nwk Addr + End Point. * @param *srcEP - Origination (i.e. respond to or ack to) End Point Descr. * @param cID - A valid cluster ID as specified by the Profile. * @param len - Number of bytes of data pointed to by next param. * @param *buf - A pointer to the data bytes to send. * @param *transID - A pointer to a byte which can be modified and which will * be used as the transaction sequence number of the msg. * @param options - Valid bit mask of Tx options. * @param radius - Normally set to AF_DEFAULT_RADIUS. * * output parameters * * @param *transID - Incremented by one if the return value is success. * * @return afStatus_t per declaration. ************************************************************************************************** */ afStatus_t AF_DataRequest(afAddrType_t *dstAddr, endPointDesc_t *srcEP, uint16 cID, uint16 len, uint8 *buf, uint8 *transID, uint8 options, uint8 radius) { #define ZAP_AF_REQ_MSG_HDR 20 #define ZAP_AF_REQ_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_REQ_MSG_HDR) uint8 *pBuf; #if !ZAP_AF_DATA_REQ_AREQ afStatus_t rtrn; #if ZAP_AF_DATA_REQ_FRAG if (len > ZAP_AF_REQ_DAT_MAX) { pBuf = zap_msg_allocate(ZAP_AF_REQ_MSG_HDR, (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_AF_DATA_REQUEST_EXT); } else #endif { pBuf = zap_msg_allocate((uint8)(len + ZAP_AF_REQ_MSG_HDR), (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_SREQ, (uint8)MT_AF_DATA_REQUEST_EXT); } #else pBuf = zap_msg_allocate((uint8)(len + ZAP_AF_REQ_MSG_HDR), (uint8)MT_RPC_SYS_AF | (uint8)MT_RPC_CMD_AREQ, (uint8)MT_AF_DATA_REQUEST_EXT); #endif if (NULL == pBuf) { return afStatus_MEM_FAIL; } *pBuf++ = dstAddr->addrMode; if (dstAddr->addrMode == afAddr64Bit) { (void)osal_memcpy(pBuf, dstAddr->addr.extAddr, Z_EXTADDR_LEN); } else { pBuf[0] = LO_UINT16(dstAddr->addr.shortAddr); pBuf[1] = HI_UINT16(dstAddr->addr.shortAddr); } pBuf += Z_EXTADDR_LEN; *pBuf++ = dstAddr->endPoint; #if defined INTER_PAN *pBuf++ = LO_UINT16(dstAddr->panId); *pBuf++ = HI_UINT16(dstAddr->panId); #else *pBuf++ = 0; *pBuf++ = 0; #endif *pBuf++ = srcEP->endPoint; *pBuf++ = LO_UINT16(cID); *pBuf++ = HI_UINT16(cID); *pBuf++ = *transID; (*transID)++; *pBuf++ = options; *pBuf++ = radius; *pBuf++ = LO_UINT16(len); *pBuf++ = HI_UINT16(len); #if ZAP_AF_DATA_REQ_FRAG if (len <= ZAP_AF_REQ_DAT_MAX) #endif { (void)osal_memcpy(pBuf, buf, len); } pBuf -= ZAP_AF_REQ_MSG_HDR; zapPhySend(zapAppPort, pBuf); #if !ZAP_AF_DATA_REQ_AREQ rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf); #endif zap_msg_deallocate(&pBuf); #if ZAP_AF_DATA_REQ_FRAG if ((len > ZAP_AF_REQ_DAT_MAX) && (rtrn == afStatus_SUCCESS)) { rtrn = afStore(buf, len); } #endif #if ZAP_AF_DATA_REQ_AREQ return SUCCESS; #else return rtrn; #endif }