📄 aps.c
字号:
/*
* "Copyright (c) 2006 Robert B. Reese ("AUTHOR")"
* All rights reserved.
* (R. Reese, reese@ece.msstate.edu, Mississippi State University)
* IN NO EVENT SHALL THE "AUTHOR" BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHOR"
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE "AUTHOR" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE "AUTHOR" HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*
* This file makes use of Zigbee Alliance intellectual property in the
* form of frame formats as specified in the Zigbee 1.0 standard.
* The author consulted the
* Zigbee standard when writing this file, and agreed to the terms
* of conditions by the Zibee Alliance when downloading the standard.
* As such, use of this file is governed by the Zigbee Trademarks,
* Designations, and Logos policy. A paraphrase of this policy is
* that free usage is granted for research, educational or personal
* use. Commercial usage is restricted, see the policy for details.
*
* Please maintain this header in its entirety when copying/modifying
* these files.
*
* Files in this software distribution may have different usage
* permissions, see the header in each file. Some files have NO permission
* headers since parts of the original sources in these files
* came from vendor sources with no usage restrictions.
*
*/
/*
V0.2 added PC-based binding 21/July/2006 RBR
V0.1 Initial Release 10/July/2006 RBR
*/
/*
APS Layer
*/
#include "compiler.h"
#include "lrwpan_config.h" //user configurations
#include "lrwpan_common_types.h" //types common acrosss most files
#include "ieee_lrwpan_defs.h"
#include "console.h"
#include "debug.h"
#include "memalloc.h"
#include "neighbor.h"
#include "hal.h"
#include "halStack.h"
//#include "phy.h"
//#include "mac.h"
//#include "nwk.h"
//#include "zep.h"
#include "aps.h"
#include "evboard.h"
#include "aps_headers.h"
#define apsTXIdle() (!aps_pib.flags.bits.TxInProgress)
#define apsTXBusy() (aps_pib.flags.bits.TxInProgress)
#define apsSetTxBusy() aps_pib.flags.bits.TxInProgress = 1
#define apsSetTxIdle() aps_pib.flags.bits.TxInProgress = 0
APS_RX_DATA globalApsRxData;
typedef enum _APS_RXSTATE_ENUM {
APS_RXSTATE_IDLE,
APS_RXSTATE_START,
APS_RXSTATE_RESOLVE_INDIRECT,
APS_RXSTATE_ACK_SEND_WAIT
} APS_RXSTATE_ENUM;
//APS_PIB aps_pib;
//APS_SERVICE a_aps_service;
//APS_STATE_ENUM apsState;
//APS_EP_ELEM apsEndPoints[LRWPAN_MAX_ENDPOINTS];
//
////there can only be one TX in progress at a time, so
////a_aps_tx_data contains the arguments for that TX on the APS layer.
//APS_TX_DATA a_aps_tx_data;
//APS_RX_DATA a_aps_rx_data;
//APS_RX_DATA indirect_data; //used for holding an indirect packet while being reflected. --li
void apsFSM(void);
void apsTxData(BOOL copy_payload);
//locals
static APS_RXSTATE_ENUM apsRxState;
static LRWPAN_STATUS_ENUM apsTxFSM_status;
static void apsParseHdr(BYTE *ptr);
static void apsRxFSM(void);
static BOOL apsCheckAck(void);
static void apsFormatAck(void);
static void apsTxFSM(void);
static void apsInjectPacket(BOOL indirect_flag);
static void apsInjectTxPacket(void);
#ifdef LRWPAN_COORDINATOR
void apsRxBuffInit(void);
BOOL apsRxBuffFull(void);
BOOL apsRxBuffEmpty(void);
APS_RX_DATA *apsGetRxPacket(void);
void apsFreeRxPacket(BOOL freemem);
void apsRxBuffAdd (APS_RX_DATA *ptr);
#endif
//converts MAC TICKs to Microseconds
UINT32 aplMacTicksToUs(UINT32 ticks){
return(halMacTicksToUs(ticks));
}
//this sleeps, then restarts the stack and the radio
void aplShutdown(void){
//wait until stack is idle
while(apsBusy()) apsFSM();
DISABLE_GLOBAL_INTERRUPT(); //disable interrupts, if halSleep wants to reenable them, let it.
halShutdown();
//a_aps_service.status = LRWPAN_STATUS_SUCCESS; --li
}
void aplWarmstart(void){
/*a_aps_service.status = macWarmStartRadio();*/ //--li
}
//this is top level init, does inits for other layers
void apsInit(void){
// debug_level = 0;
// //apsState = APS_STATE_IDLE;
// //apsRxState = APS_RXSTATE_IDLE; --li
//#ifdef LRWPAN_COORDINATOR
// aps_pib.rxCnt = 0;
// aps_pib.rxTail = 0;
// aps_pib.rxHead = 0;
//#endif
//aps_pib.apsTSN = 0;
//aps_pib.flags.val = 0;
//aps_pib.apscAckWaitDuration = MSECS_TO_MACTICKS(LRWPAN_APS_ACK_WAIT_DURATION) ; //convert to MAC Ticks
//aps_pib.apsAckWaitMultiplier = 1; //default value
//aps_pib.apscMaxFrameRetries = LRWPAN_APS_MAX_FRAME_RETRIES ;
////initialize the endpoints
//aps_pib.activeEPs = 0; //only tracks user endpoints.
//phyInit();
//macInit();
//nwkInit();
//zepInit(); --li
}
//simply remembers these so that we can report them to the coordinator.
LRWPAN_STATUS_ENUM aplRegisterEndPoint(BYTE epNum)
{
/*if (aps_pib.activeEPs == LRWPAN_MAX_ENDPOINTS) return(LRWPAN_STATUS_APS_MAX_ENDPOINTS_EXCEEDED);
if (epNum == 0) return(LRWPAN_STATUS_APS_ILLEGAL_ENDPOINT);
apsEndPoints[aps_pib.activeEPs++].epNum = epNum;*/
return(LRWPAN_STATUS_SUCCESS);
}
//Formats a Send Message service
void aplFmtSendMSG (BYTE dstMode,
LADDR_UNION *dstADDR,
BYTE dstEP,
BYTE cluster,
BYTE srcEP,
BYTE* pload,
BYTE plen,
BYTE tsn,
BYTE reqack)
{
//BYTE buf[8];
//BYTE i;
//while(apsBusy()) apsFSM();
//a_aps_service.cmd = LRWPAN_SVC_APS_GENERIC_TX;
//a_aps_tx_data.flags.val = 0;
//a_aps_tx_data.srcEP = srcEP;
//a_aps_tx_data.usrPlen = plen;
//a_aps_tx_data.usrPload = pload;
//a_aps_tx_data.tsn = tsn;
//a_aps_tx_data.cluster = cluster;
//a_aps_tx_data.dstMode = dstMode;
//a_aps_tx_data.dstEP = dstEP;
//a_aps_tx_data.srcSADDR = macGetShortAddr();
//a_aps_tx_data.af_fcf = (1 | AF_FRM_TYPE_MSG);
//if (dstMode == APS_DSTMODE_NONE) {
// a_aps_tx_data.aps_fcf = APS_FRM_TYPE_DATA | APS_FRM_DLVRMODE_INDIRECT;
//}else {
// a_aps_tx_data.aps_fcf = APS_FRM_TYPE_DATA | APS_FRM_DLVRMODE_NORMAL;
// if (a_aps_tx_data.dstMode == APS_DSTMODE_SHORT ){
// a_aps_tx_data.dstSADDR = dstADDR->saddr;
// if (dstADDR->saddr == macGetShortAddr()) {
// //sending to ourselves
// a_aps_tx_data.flags.bits.loopback = 1;
// }
// }
// else {
// a_aps_tx_data.dstLADDR = &dstADDR->laddr.bytes[0];
// a_aps_tx_data.dstSADDR = LRWPAN_SADDR_USE_LADDR;
// /* APS acks to no make sense for LONG addressing, which is
// being used to bypass routing. The MAC acks serve for APS acks
// in this case. Also APS acks would be returned via routing,
// negating the bypass of the routing in the first place.
// */
// reqack = 0;
// //see if we are sending to ourself
// halGetProcessorIEEEAddress(buf);
// for(i=0;i<8;i++) {
// if (buf[i] != dstADDR->laddr.bytes[i]) break;
// }
// if (i==8) {
// //this is a loopback, so use our short address in this field
// a_aps_tx_data.dstSADDR = macGetShortAddr();
// a_aps_tx_data.flags.bits.loopback = 1;
// }
// }
//}
//if (reqack) a_aps_tx_data.aps_fcf |= (APS_FRM_ACKREQ_MASK); --li
}
//TODO - add a pib flag that indicates when the User's TX
//buffer has been copied so that user can begin building a
//new TX packet while the old one is being TX'ed.
void apsFSM(void) {
Sleep(500);
//#ifdef LRWPAN_COORDINATOR
// APS_RX_DATA *rxPtr;
//#endif
//
//
//
// nwkFSM();
// //if TxFSM is busy we need to call it
// if (apsTXBusy()) apsTxFSM();
// apsRxFSM(); //check RX
// zepFSM(); //do ZEP
//
//apsFSM_start:
//
//
// switch (apsState) {
// case APS_STATE_IDLE:
//
// //ackSendPending check must come before the indirect Pending check!
// if (aps_pib.flags.bits.ackSendPending) {
// apsState = APS_STATE_ACK_SEND_START;
// goto apsFSM_start;
// }
//
//#ifdef LRWPAN_COORDINATOR
// if (aps_pib.flags.bits.indirectPending) {
// //free up RX FSM so that we can receive possible APS acks for this packet.
// aps_pib.flags.bits.indirectPending = 0; //free up RX FSM
// // an indirect message needs resolving
// //initialize the binding table iterator
// //get pointer to current indirect packet
// rxPtr = &aps_pib.rxBuff[aps_pib.rxTail];
// if (!evbBindTableIterInit(rxPtr->srcEP, rxPtr->srcSADDR,rxPtr->cluster)){
// //a failure to initialize the iterator, give up.
// DEBUG_STRING(DBG_ERR,"APS: BindTable Iterator initialize failed. Discarding indirect msg.\n");
// apsState = APS_STATE_IDLE;
// }else
// {
// apsState = APS_STATE_INDIRECT_GETDST;
// goto apsFSM_start;
// }
// }
//#endif
//
//
// break;
// case APS_STATE_COMMAND_START:
// switch(a_aps_service.cmd) {
// case LRWPAN_SVC_APS_GENERIC_TX:
// aps_pib.flags.bits.IsUsrBufferFree = 0;
//#ifdef LRWPAN_COORDINATOR
// if (APS_GET_FRM_DLVRMODE(a_aps_tx_data.aps_fcf) == APS_FRM_DLVRMODE_INDIRECT){
// //this is a special case. A Coordinator endpoint is sending indirect.
// //we need to inject this into the stack as if it has been received
// apsState = APS_STATE_INJECT_INDIRECT;
// goto apsFSM_start;
// }
//#endif
//
//
// if (a_aps_tx_data.flags.bits.loopback) {
// apsState = APS_STATE_INJECT_LOOPBACK; //we are sending a direct packet to ourself!
// goto apsFSM_start;
// }
//
// //Indirect vs Direct is handled within the apsTxData() function
// //at this point ready to begin formating packet.
// //do not exit this state until we can grab the TX buffer.
// if (phyTxUnLocked()) {
// phyGrabTxLock(); //prevents lower stack layers from grabbing TX buffer.
// phy_pib.currentTxFlen = 0; //set frame length to zero, build from scratch
// apsTxData(TRUE);
// aps_pib.flags.bits.IsUsrBufferFree = 1;
// apsState = APS_STATE_GENERIC_TX_WAIT;
// }
// break;
//
// case LRWPAN_SVC_APS_DO_ZEP_TX:
// if (phyTxUnLocked()) {
// phyGrabTxLock(); //prevents lower stack layers from grabbing TX buffer.
// switch(a_aps_service.args.zep_tx.clusterID)
// {
// case ZEP_END_DEVICE_ANNOUNCE:
// zepFmtEndDeviceAnnounce(a_aps_service.args.zep_tx.dst);
// break;
// case ZEP_EXTENDED_CMD:
// switch(a_aps_service.args.zep_tx.extID)
// {
// case ZEP_EXT_NODE_INFO_RSP:
// zepFmtNodeInfoRsp(a_aps_service.args.zep_tx.dst);
// break;
// case ZEP_EXT_PING:
// zepFmtPing(a_aps_service.args.zep_tx.dst);
// break;
// case ZEP_EXT_SEND_ALARM:
// zepFmtAlarm(a_aps_service.args.zep_tx.dst,
// a_aps_service.args.zep_tx.ext.alarm.mode
// );
// break;
//
// }
// break;
// default: break;
// }
//
// phy_pib.currentTxFlen = 0; //set frame length to zero, build from scratch
// apsTxData(FALSE); //payload already in TX buffer
// apsState = APS_STATE_GENERIC_TX_WAIT;
// }
//
// break;
//
//
// case LRWPAN_SVC_APS_NWK_PASSTHRU:
// //for NWK calls that have to pass thru the APS layer
// //this just serves to lock the APS layer while the
// //the NWK layer is doing its thing
// if (nwkBusy()) break; //wait until nwk is idle
// nwkDoService();
// apsState = APS_STATE_NWK_PASSTHRU_WAIT;
// break;
//
// default: break;
// }//end switch(a_aps_service.cmd)
//
// break;
//
// case APS_STATE_ACK_SEND_START:
// if (phyTxLocked()) break;
// //send an ACK
// //lock the TX buffer
// phyGrabTxLock();
// //we are now ready
// apsFormatAck();
// phy_pib.currentTxFlen = 0; //set frame length to zero, build from scratch
// apsTxData(TRUE);
// //data sent, release the RX buffer, will let RX FSM resume
// aps_pib.flags.bits.ackSendPending = 0;
// apsState = APS_STATE_GENERIC_TX_WAIT;
//
// break;
//
// case APS_STATE_GENERIC_TX_WAIT:
// if (!apsTXIdle()) break;
// //TX is finished, copy status
// a_aps_service.status = apsTxFSM_status;
// //release the TX buffer lock before exiting.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -