/********************************************************************* * @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 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 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 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 }