/**************************************************************************************** * @fn nwk_processFreq * * @brief Process a Frequency application frame. * * input parameters * @param frame - pointer to frame * * @return Disposition for frame: either release (FHS_RELEASE) or replay (FHS_REPLAY). */ fhStatus_t nwk_processFreq(mrfiPacket_t *frame) { fhStatus_t rc = FHS_RELEASE; uint8_t replyType; /* Make sure this is a reply and see if we sent this. Validate the * packet for reception by client app. */ if (SMPL_MY_REPLY == (replyType=nwk_isValidReply(frame, sTid, FB_APP_INFO_OS, FB_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 if (SMPL_NOT_REPLY == replyType) { rc = handle_freq_cmd(frame); } return rc; }
fhStatus_t nwk_processPing(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. */ replyType = nwk_isValidReply(frame, sTid, PB_REQ_OS, PB_TID_OS); if (SMPL_MY_REPLY == replyType) { /* 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 assuming it's a Ping intended for us. */ handlePingRequest(frame); rc = FHS_RELEASE; } return rc; }
/****************************************************************************** * @fn nwk_isConnectionValid * * @brief Do a sanity/validity check on the frame target address by * validating frame against connection info * * input parameters * @param frame - pointer to frame in question * * output parameters * @param lid - link ID of found connection * * @return 0 if connection specified in frame is not valid, otherwise non-zero. */ uint8_t nwk_isConnectionValid(mrfiPacket_t *frame, linkID_t *lid) { uint8_t i; connInfo_t *ptr = sPersistInfo.connStruct; uint8_t port = GET_FROM_FRAME(MRFI_P_PAYLOAD(frame), F_PORT_OS); for (i=0; i<SYS_NUM_CONNECTIONS; ++i,++ptr) { if (CONNSTATE_CONNECTED == ptr->connState) { /* check port first since we're done if the port is the user bcast port. */ if (port == ptr->portRx) { /* yep...ports match. */ if ((SMPL_PORT_USER_BCAST == port) || !(memcmp(ptr->peerAddr, MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE))) { uint8_t rc = 1; /* we're done. */ *lid = ptr->thisLinkID; #ifdef APP_AUTO_ACK /* can't ack the broadcast port... */ if (!(SMPL_PORT_USER_BCAST == port)) { if (GET_FROM_FRAME(MRFI_P_PAYLOAD(frame), F_ACK_REQ)) { /* Ack requested. Send ack now */ nwk_sendAckReply(frame, ptr->portTx); } else if (GET_FROM_FRAME(MRFI_P_PAYLOAD(frame), F_ACK_RPLY)) { /* This is a reply. Signal that it was received by resetting the * saved transaction ID in the connection object if they match. The * main thread is polling this value. The setting here is in the * Rx ISR thread. */ if (ptr->ackTID == GET_FROM_FRAME(MRFI_P_PAYLOAD(frame), F_TRACTID_OS)) { ptr->ackTID = 0; } /* This causes the frame to be dropped. All ack frames are * dropped. */ rc = 0; } } #endif /* APP_AUTO_ACK */ /* Unconditionally kill the reply delay semaphore. This used to be done * unconditionally in the calling routine. */ MRFI_PostKillSem(); return rc; } } } } /* no matches */ return 0; }
/****************************************************************************** * @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; }
fhStatus_t nwk_processLink(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, LB_REQ_OS, LB_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. Process request assuming it's * intended for us. */ rc = handleLinkRequest(frame); } (void) replyType; /* keep compiler happy when ED built... */ return rc; }
/****************************************************************************** * @fn nwk_join * * @brief Join functioanlity for non-AP devices. Send the Join token * and wait for the reply. * * input parameters * * output parameters * * @return Status of operation. */ smplStatus_t nwk_join(void) { uint8_t msg[JOIN_FRAME_SIZE]; uint32_t linkToken; addr_t apAddr; uint8_t radioState = MRFI_GetRadioState(); smplStatus_t rc = SMPL_NO_JOIN; union { ioctlRawSend_t send; ioctlRawReceive_t recv; } ioctl_info; #if defined( FREQUENCY_AGILITY ) uint8_t i, numChan; freqEntry_t channels[NWK_FREQ_TBL_SIZE]; if (!(numChan=nwk_scanForChannels(channels))) { return SMPL_NO_CHANNEL; } for (i=0; i<numChan; ++i) { nwk_setChannel(&channels[i]); #else { #endif ioctl_info.send.addr = (addr_t *)nwk_getBCastAddress(); ioctl_info.send.msg = msg; ioctl_info.send.len = sizeof(msg); ioctl_info.send.port = SMPL_PORT_JOIN; /* Put join token in */ nwk_putNumObjectIntoMsg((void *)&sJoinToken, msg+J_JOIN_TOKEN_OS, sizeof(sJoinToken)); /* set app info byte */ msg[JB_REQ_OS] = JOIN_REQ_JOIN; msg[JB_TID_OS] = sTid; /* Set number of connections supported. Used only by AP if it is * a data hub. */ msg[J_NUMCONN_OS] = NUM_CONNECTIONS; /* protocol version number */ msg[J_PROTOCOL_VERSION_OS] = nwk_getProtocolVersion(); SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send); ioctl_info.recv.port = SMPL_PORT_JOIN; ioctl_info.recv.msg = msg; ioctl_info.recv.addr = &apAddr; /* save AP address from reply */ NWK_CHECK_FOR_SETRX(radioState); NWK_REPLY_DELAY(); NWK_CHECK_FOR_RESTORE_STATE(radioState); if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv)) { uint8_t firstByte = msg[JB_REQ_OS] & (~NWK_APP_REPLY_BIT); /* Sanity check for correct reply frame. Older version * has the length instead of the request as the first byte. */ if ((firstByte == JOIN_REQ_JOIN) || (firstByte == JOIN_REPLY_LEGACY_MSG_LENGTH) ) { /* join reply returns link token */ memcpy(&linkToken, msg+JR_LINK_TOKEN_OS, sizeof(linkToken)); nwk_setLinkToken(linkToken); /* save AP address */ nwk_setAPAddress(&apAddr); sTid++; /* guard against duplicates */ rc = SMPL_SUCCESS; #if defined( FREQUENCY_AGILITY ) break; #endif } } /* TODO: process encryption stuff */ } return rc; } #endif /* ACCESS_POINT */ /****************************************************************************** * @fn nwk_processJoin * * @brief Processes a Join frame. If this is a reply let it go to the * application. Otherwise generate and send the reply. * * input parameters * @param frame - Pointer to Join frame * * output parameters * * @return Keep frame for application, release frame, or replay frame. */ fhStatus_t nwk_processJoin(mrfiPacket_t *frame) { fhStatus_t rc = FHS_RELEASE; uint8_t replyType; /* Make sure this is a reply and see if we sent this. Validate the * packet for reception by client app. */ if (SMPL_MY_REPLY == (replyType=nwk_isValidReply(frame, sTid, JB_REQ_OS, JB_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(ACCESS_POINT) 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; } else { /* Send reply if we're an Access Point otherwise ignore the frame. */ if ((SMPL_NOT_REPLY == replyType) && sJoinOK) { handleJoinRequest(frame); } } #elif defined(RANGE_EXTENDER) else {