/****************************************************************************** * @fn change_channel_cmd_is_valid * * @brief Check validity of a change channel command frame. * * input parameters * @param frame - pointer to frame with command context * * @return Returns non-zero if command is valid, otherwise returns 0. * Command is valid if either: * - frame is directed * - frame is from an AP and we know about that AP * * It is possible that either we don't know about an AP or that * we do but this frame comes from another AP in range. */ static uint8_t change_channel_cmd_is_valid(mrfiPacket_t *frame) { uint8_t rc = 0; addr_t const *apAddr; /* If this was a directed frame obey the command. */ if (!memcmp(MRFI_P_DST_ADDR(frame), nwk_getMyAddress(), NET_ADDR_SIZE)) { rc = 1; } else { /* Do we know about an AP? If not assume frame bogus. */ apAddr = nwk_getAPAddress(); if (apAddr) { /* Yes, we know about an AP. Is that who sent it? */ if (!memcmp(apAddr, MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE)) { /* OK. We obey. */ rc = 1; } } } return rc; }
/*********************************************************************************** * @fn SMPL_Init * * @brief Initialize the SimpliciTI stack. * * input parameters * @param f - Pointer to call back function. Function called by NWK when * user application frame received. The callback is done in the * ISR thread. Argument is Link ID associated with frame. Function * returns 0 if frame is to be kept by NWK, otherwise 1. Frame * should be kept if application will do a SMPL_Receive() in the * user thread (recommended). Pointer may be NULL. * * output parameters * * @return Status of operation: * SMPL_SUCCESS * SMPL_NO_JOIN No Join reply. AP possibly not yet up. * SMPL_NO_CHANNEL Only if Frequency Agility enabled. Channel scan * failed. AP possibly not yet up. */ smplStatus_t SMPL_Init(uint8_t (*f)(linkID_t)) { smplStatus_t rc; if (!sInit_done) { /* set up radio. */ MRFI_Init(); /* initialize network */ if ((rc=nwk_nwkInit(f)) != SMPL_SUCCESS) { return rc; } MRFI_WakeUp(); #if defined( FREQUENCY_AGILITY ) { freqEntry_t chan; chan.logicalChan = 0; /* ok to set default channel explicitly now that MRFI initialized. */ nwk_setChannel(&chan); } #endif /* don't turn Rx on if we're an end device that isn't always on. */ /* but do turn the radio on for PLL operations */ #if !defined( END_DEVICE ) || defined( NWK_PLL ) MRFI_RxOn(); #endif #if defined( END_DEVICE ) /* All except End Devices are in promiscuous mode */ MRFI_SetRxAddrFilter((uint8_t *)nwk_getMyAddress()); MRFI_EnableRxAddrFilter(); #endif } sInit_done = 1; #ifdef NWK_PLL /* If the PLL is enabled then it must get running before the join * request or the system may lock up in the join request becuase * PLL is not locked in. */ // turn on the PLL SMPL_Ioctl(IOCTL_OBJ_PLL, IOCTL_ACT_ON, NULL); // reference clocks are by definition always locked. #ifndef NWK_PLL_REFERENCE_CLOCK // wait for a 5ms failure rate to be achieved while( nwk_pllIsLocked( 0 ) == false ) nwk_pllBackgrounder( false ); #endif #endif /* Join. if no AP or Join fails that status is returned. */ rc = nwk_join(); return rc; }
/****************************************************************************** * @fn nwk_processMgmt * * @brief Process Management frame. Just save the frame for the Management * app it it is a reply. If it isn't a reply, send the reply in this * thread. * * input parameters * @param frame - pointer to frame to be processed * * output parameters * * @return Keep frame for application, release frame, or replay frame. */ fhStatus_t nwk_processMgmt(mrfiPacket_t *frame) { fhStatus_t rc; uint8_t replyType; /* If we sent this then this is the reply. Validate the * packet for reception by client app. If we didn't send * it then we are the target. send the reply. */ if (SMPL_MY_REPLY == (replyType=nwk_isValidReply(frame, sTid, MB_APP_INFO_OS, MB_TID_OS))) { /* It's a match and it's a reply. Validate the received packet by * returning a 1 so it can be received by the client app. */ MRFI_PostKillSem(); rc = FHS_KEEP; } #if !defined( END_DEVICE ) else if (SMPL_A_REPLY == replyType) { /* no match. if i'm not an ED this is a reply that should be passed on. */ rc = FHS_REPLAY; } #endif /* !END_DEVICE */ else { /* no, we didn't send it. send reply if it's intended for us */ if (!memcmp(MRFI_P_DST_ADDR(frame), nwk_getMyAddress(), NET_ADDR_SIZE)) { smpl_send_mgmt_reply(frame); /* we're done with the frame. */ rc = FHS_RELEASE; } else { rc = FHS_REPLAY; } } (void) replyType; /* keep compiler happy */ return rc; }
/*********************************************************************************** * @fn SMPL_Init * * @brief Initialize the SimpliciTI stack. * * input parameters * @param f - Pointer to call back function. Function called by NWK when * user application frame received. The callback is done in the * ISR thread. Argument is Link ID associated with frame. Function * returns 0 if frame is to be kept by NWK, otherwise 1. Frame * should be kept if application will do a SMPL_Receive() in the * user thread (recommended). Pointer may be NULL. * * output parameters * * @return Status of operation: * SMPL_SUCCESS * SMPL_NO_JOIN No Join reply. AP possibly not yet up. * SMPL_NO_CHANNEL Only if Frequency Agility enabled. Channel scan * failed. AP possibly not yet up. */ smplStatus_t SMPL_Init(uint8_t (*f)(linkID_t)) { smplStatus_t rc; if (!sInit_done) { /* set up radio. */ MRFI_Init(); /* initialize network */ if ((rc=nwk_nwkInit(f)) != SMPL_SUCCESS) { return rc; } MRFI_WakeUp(); #if defined( FREQUENCY_AGILITY ) { freqEntry_t chan; chan.logicalChan = 0; /* ok to set default channel explicitly now that MRFI initialized. */ nwk_setChannel(&chan); } #endif /* don't turn Rx on if we're an end device that isn't always on. */ #if !defined( END_DEVICE ) MRFI_RxOn(); #endif #if defined( END_DEVICE ) /* All except End Devices are in promiscuous mode */ MRFI_SetRxAddrFilter((uint8_t *)nwk_getMyAddress()); MRFI_EnableRxAddrFilter(); #endif } sInit_done = 1; /* Join. if no AP or Join fails that status is returned. */ rc = nwk_join(); return rc; }
smplStatus_t nwk_deviceAddress(ioctlAction_t action, addr_t *addr) { smplStatus_t rc = SMPL_BAD_PARAM; if (IOCTL_ACT_GET == action) { memcpy(addr, nwk_getMyAddress(), sizeof(addr_t)); rc = SMPL_SUCCESS; } else if (IOCTL_ACT_SET == action) { if (nwk_setMyAddress(addr)) { rc = SMPL_SUCCESS; } } return rc; }
/******************************************************************************* * @fn nwk_isValidReply * * @brief Examine a frame to see if it is a valid reply when compared with * expected parameters. * * input parameters * @param frame - pointer to frmae being examined * @param tid - expected transaction ID in application payload * @param infoOffset - offset to payload information containing reply hint * @param tidOffset - offset to transaction ID in payload * * output parameters * * @return reply category: * SMPL_NOT_REPLY: not a reply * SMPL_MY_REPLY : a reply that matches input parameters * SMPL_A_REPLY : a reply but does not match input parameters */ uint8_t nwk_isValidReply(mrfiPacket_t *frame, uint8_t tid, uint8_t infoOffset, uint8_t tidOffset) { uint8_t rc = SMPL_NOT_REPLY; if ((*(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+infoOffset) & NWK_APP_REPLY_BIT)) { if ((*(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+tidOffset) == tid) && !memcmp(MRFI_P_DST_ADDR(frame), nwk_getMyAddress(), NET_ADDR_SIZE)) { rc = SMPL_MY_REPLY; } else { rc = SMPL_A_REPLY; } } return rc; }
void nwk_frameInit(uint8_t (*pF)(linkID_t)) { /****** Fill static values for the DEVICEINFO byte that will go in each frame ******/ /* Rx type when frame originates from this device. Set in nwk_buildFrame() */ /* Tx type when frame sent from this device. Set in nwk_sendframe() */ #if !defined(END_DEVICE) sMyRxType = F_RX_TYPE_USER_CTL; #if defined(ACCESS_POINT) sMyTxType = F_TX_DEVICE_AP; #else sMyTxType = F_TX_DEVICE_RE; #endif #else sMyTxType = F_TX_DEVICE_ED; #if defined(RX_POLLS) sMyRxType = F_RX_TYPE_POLLS; #endif #if defined(RX_USER) sMyRxType = F_RX_TYPE_USER_CTL; #endif #endif /****** DONE fill static values for the DEVICEINFO byte that will go in each frame ******/ #if !defined(RX_POLLS) spCallback = pF; #else (void) pF; #endif sMyAddr = nwk_getMyAddress(); while (!(sTRACTID=MRFI_RandomByte())) ; return; }