📄 mac_rx_engine.c
字号:
//-------------------------------------------------------------------------------------------------------
ROOT MLME_BEACON_NOTIFY_INDICATION * mrxMakeBeaconNotifyIndication(MAC_RX_PACKET *pPacket) {
MLME_BEACON_NOTIFY_INDICATION *pMBNI = (MLME_BEACON_NOTIFY_INDICATION *) (((BYTE *) pPacket) + 1);
MCPS_DATA_INDICATION *pMDI = &pPacket->mdi;
PAN_DESCRIPTOR *pPanDescriptor = &pMBNI->panDescriptor;
UINT8 n;
UINT8 payloadOffset;
UINT8 pendAddrOffset;
UINT8 pendAddrSpec;
UINT8 pendingIndex;
// Do not change the order of these operations!!!
// Calculate the pSDU offset
n = pMDI->pMsdu[2] & 0x07;
if (n) {
n = 3 + 1 + 3 * n;
} else {
n = 3;
}
pendAddrSpec = pMDI->pMsdu[n];
payloadOffset = (n + 1 + (sizeof(WORD) * (pendAddrSpec & 0x07)) + (sizeof(ADDRESS) * ((pendAddrSpec & 0x70) >> 4)));
// Start by copying the payload in reverse order to avoid overwriting
msupReverseCopy(pMBNI->pSdu, pMDI->pMsdu + payloadOffset, aMaxBeaconPayloadLength);
// Copy lots of parameters (no fields are overwritten!)
pMBNI->sduLength = pMDI->msduLength - payloadOffset;
pPanDescriptor->logicalChannel = ppib.phyCurrentChannel;
pPanDescriptor->linkQuality = pMDI->mpduLinkQuality;
pPanDescriptor->superframeSpec = *((WORD *) pMDI->pMsdu);
pPanDescriptor->gtsPermit = !!(pMDI->pMsdu[2] & 0x80);
pPanDescriptor->securityUse = pMDI->securityUse;
pPanDescriptor->aclEntry = pMDI->aclEntry;
#if ((MAC_OPT_SECURITY) || (MAC_OPT_ACL_SIZE>0))
pPanDescriptor->securityFailure = (pPacket->securityStatus != SUCCESS);
#else
pPanDescriptor->securityFailure = pMDI->securityUse;
#endif
pMBNI->pendAddrSpec = pendAddrSpec;
// Copy the pending addresses in the reverse order
pendingIndex = (pendAddrSpec & 0x07) + ((pendAddrSpec & 0x70) >> 4) - 1;
// Extended addresses first
n = (pendAddrSpec & 0x70) >> 4;
while (n--) {
pendAddrOffset -= sizeof(ADDRESS);
msupReverseCopy((BYTE *) (&pMBNI->pAddrList[pendingIndex--]), (BYTE *) (&pMDI->pMsdu[pendAddrOffset]), sizeof(ADDRESS));
}
// Then short addresses
n = pendAddrSpec & 0x07;
while (n--) {
pendAddrOffset -= sizeof(WORD);
msupReverseCopy((BYTE *) (&pMBNI->pAddrList[pendingIndex--]), (BYTE *) (&pMDI->pMsdu[pendAddrOffset]), sizeof(WORD));
}
return pMBNI;
} // mrxMakeBeaconNotifyIndication
//-------------------------------------------------------------------------------------------------------
// void mrxProcessBeacon(MAC_TASK_INFO *pTask)
//
// DESCRIPTION:
// This task is responsible for processing beacon packets.
//
// TASK DATA
// A pointer to the MAC_RX_PACKET to be processed
//-------------------------------------------------------------------------------------------------------
void mrxProcessBeacon(MAC_TASK_INFO *pTask) NEAR {
MAC_RX_PACKET *pPacket = (MAC_RX_PACKET*) pTask->taskData;
MLME_BEACON_NOTIFY_INDICATION *pMBNI;
MCPS_DATA_INDICATION *pMDI = &pPacket->mdi;
BYTE pendAddrOffset;
BOOL pendDataAvailable;
WORD superframeSpec;
BOOL panIdConflict;
BYTE pendAddrSpec;
UINT8 oldBeaconOrder;
BOOL findBeacon;
BOOL securityEnable = FALSE;
switch (pTask->state) {
case MRX_STATE_BCN_ALIGN_OR_SPEC_MODES:
// When received by a scanning device/coordinator...
if (macInfo.state == MAC_STATE_ACTIVE_OR_PASSIVE_SCAN) {
// Turn off RX if "RX on when idle" was on
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
// Make the beacon notify indication (overwrites the pPacket structure)
pMBNI = mrxMakeBeaconNotifyIndication(pPacket);
// Store the PAN descriptor in the scan result table
if (mscInfo.pScanResult->resultListSize < MAC_OPT_MAX_PAN_DESCRIPTORS) {
memcpy(&mscInfo.pScanResult->list.pPANDescriptorList[mscInfo.pScanResult->resultListSize], &pMBNI->panDescriptor, sizeof(PAN_DESCRIPTOR));
if (!mscPanDescriptorExists(&pMBNI->panDescriptor)) mscInfo.pScanResult->resultListSize++;
}
// Abort the scan if the result buffer is full
if (mscInfo.pScanResult->resultListSize == MAC_OPT_MAX_PAN_DESCRIPTORS) {
macSetState(MAC_STATE_SCAN_RESULT_BUFFER_FULL);
mscInfo.channelComplete = TRUE;
}
// Remove the task
mschRemoveTask(pTask->priority, 0);
// Make the call to the higher layer when there's a beacon payload
if (pMBNI->sduLength) mlmeBeaconNotifyIndication(pMBNI);
// Release the task
mrxpReleasePacket(pPacket);
break;
// Ignore additional beacons until we've finished the scanning
} else if (macInfo.state == MAC_STATE_SCAN_RESULT_BUFFER_FULL) {
// Turn off RX if "RX on when idle" was on
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
// Clean up
mschRemoveTask(pTask->priority, 0);
mrxpReleasePacket(pPacket);
// When received by a PAN coordinator...
} else if (GET_MF(MF_PAN_COORDINATOR)) {
// Turn off RX if "RX on when idle" was on
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
// Detect PAN ID conflict: When another unit is transmitting beacons with the PAN coordinator bit set
// and using the same PAN ID as we are -> Report as a PAN_ID_CONFLICT.
panIdConflict = (pMDI->pMsdu[1] & (SS_PAN_COORDINATOR_BM >> 8)) && (pMDI->srcPanId == mpib.macPANId);
mschRemoveTask(pTask->priority, 0);
mrxpReleasePacket(pPacket);
if (panIdConflict) mlmeSyncLossIndication(PAN_ID_CONFLICT);
// When received by a device...
} else {
//Find out if we have PAN ID conflict, check pan id then address if one or both failes we have a porblem
if (pMDI->srcPanId == mpib.macPANId)
{
panIdConflict = FALSE;
if (pMDI->srcAddrMode == AM_SHORT_16)
{
if (pMDI->srcAddr.Short != mpib.macCoordShortAddress)
{
panIdConflict = TRUE;
}
}
if(pMDI->srcAddrMode == AM_EXTENDED_64)
{
if (msupCompareExtendedAddress(&pMDI->srcAddr, (ADDRESS *) mpib.pMacCoordExtendedAddress)) {
panIdConflict = TRUE;
}
}
if(!panIdConflict) //Correct PANID and no conflict
{
// Update the PIB and the superframe spec. structure
superframeSpec = *((WORD*) &pMDI->pMsdu[0]);
mpib.macSuperframeOrder = BF(superframeSpec, SS_SUPERFRAME_ORDER_BM, SS_SUPERFRAME_ORDER_IDX);
oldBeaconOrder = mpib.macBeaconOrder;
mpib.macBeaconOrder = BF(superframeSpec, SS_BEACON_ORDER_BM, SS_BEACON_ORDER_IDX);
mbcnInfo.lastSfSpec.finalCap = BF(superframeSpec, SS_FINAL_CAP_SLOT_BM, SS_FINAL_CAP_SLOT_IDX);
mbcnInfo.lastSfSpec.battLifeExt = BF(superframeSpec, SS_BATT_LIFE_EXT_BM, SS_BATT_LIFE_EXT_IDX);
// Align the local timer with the beacon (in beacon-enabled networks only)
if (mpib.macBeaconOrder != 15) {
mtimAlignWithBeacon(&pPacket->timestamp);
}
// Handle non-beacon <-> beacon network change
mbcnHandleBeaconModeChange(oldBeaconOrder == 15);
// Calculate the beacon duration (BOS) including IFS
mbcnInfo.beaconDuration = msupCalcPacketDuration(2 + 1 + 2 + ((pMDI->srcAddrMode == AM_EXTENDED_64) ? 8 : 2) + pMDI->msduLength, FALSE);
pTask->state = MRX_STATE_BCN_TX_AFTER_BEACON;
}else
{
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
mschRemoveTask(pTask->priority, 0);
mrxpReleasePacket(pPacket);
if (panIdConflict) mlmeSyncLossIndication(PAN_ID_CONFLICT);
// Try to transmit the PAN ID COnflict message
if(mpib.macAssociatedPanCordinator)
{
if (pMDI->srcAddrMode == AM_SHORT_16)
{
msupTransmitPanConflict(AM_SHORT_16, mpib.macPANId, (ADDRESS*) &mpib.macCoordShortAddress, securityEnable);
} else {
msupTransmitPanConflict(AM_EXTENDED_64, mpib.macPANId, (ADDRESS *) mpib.pMacCoordExtendedAddress, securityEnable);
}
}
}
} else
{ //Wrong PAN ID drop beacon, Clean up
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
mschRemoveTask(pTask->priority, 0);
mrxpReleasePacket(pPacket);
}
}
break;
case MRX_STATE_BCN_TX_AFTER_BEACON:
// Cancel the beacon reception timeout!
if (mtimCancelCallback(mbcnRxBeaconTimeout)) {
mrxDecrOnCounter();
}
mbcnInfo.noBcnCountdown = aMaxLostBeacons;
mtxResumeAfterBeacon();
pTask->state = MRX_STATE_BCN_EXAMINE_PENDING_FIELDS;
break;
case MRX_STATE_BCN_EXAMINE_PENDING_FIELDS:
// Adjust the timing of the beacon handler
if (mtimCancelCallback(mbcnRxPeriodicalBeacon)) {
// <-- Beacon interval ---> <--------- Used CAP ----------> <----- Margin ------> <- RX startup overhead ->
mtimSetCallback(mbcnRxPeriodicalBeacon, msupCalcBeaconInterval() - (T2_GET_OVERFLOW_COUNTER() - 1) - mbcnGetBeaconMargin() - MBCN_RX_STARTUP_OVERHEAD);
}
// Handle "RX on when idle"
if (mpib.macSuperframeOrder != 15) {
if (mpib.macRxOnWhenIdle) {
// On:
mrxAutoIncrOnCounter();
// Off: Force when the superframe is shorter than the beacon interval
mtimSetCallback((mpib.macBeaconOrder == mpib.macSuperframeOrder) ? mrxDecrOnCounter : mrxForceRxOff, msupCalcCapDuration() - T2_GET_OVERFLOW_COUNTER());
}
}
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
// Stop searching for the beacon
findBeacon = mbcnInfo.findBeacon;
if (findBeacon) {
mrxDecrOnCounter();
mbcnInfo.findBeacon = FALSE;
}
// Remove the task
mschRemoveTask(pTask->priority, 0);
// Auto-request pending data?
if ((mpib.macAutoRequest || (macInfo.state == MAC_STATE_ASSOC_REQUEST_SENT)) && (mbcnInfo.trackBeacon || findBeacon)) {
// Find offset to Pending Address Specification in the payload
// < SFS + GTS > <-------- GTS list ------->
pendAddrOffset = 2 + 1 + 3 * (pMDI->pMsdu[2] & 0x07);
// Get the Pending Address Specification
pendAddrSpec = pMDI->pMsdu[pendAddrOffset++];
// Short addresses are located first...
while (pendAddrSpec & 0x07) {
if (mpib.macShortAddress == *((WORD *) (pMDI->pMsdu + pendAddrOffset))) {
pendDataAvailable = TRUE;
goto stopPendSearch;
}
pendAddrOffset += 2;
pendAddrSpec -= 0x01;
}
// Then check extended addresses, see if anyone has pending data!
while (pendAddrSpec & 0x70) {
if (msupCompareExtendedAddress((ADDRESS *) &aExtendedAddress, (ADDRESS *) (pMDI->pMsdu + pendAddrOffset))) {
pendDataAvailable = TRUE;
goto stopPendSearch;
}
pendAddrOffset += 8;
pendAddrSpec -= 0x10;
}
// Nothing was found :(
pendDataAvailable = FALSE;
stopPendSearch:
// Transmit the data request?
if (pendDataAvailable) {
if (macInfo.state == MAC_STATE_ASSOC_REQUEST_SENT) {
mipTransmitAssocDataRequest();
} else {
mipTransmitAutoDataRequest();
}
}
}
// Make the beacon notify indication (overwrites the pPacket structure)
pMBNI = mrxMakeBeaconNotifyIndication(pPacket);
// Beacon notify indication
if (pMBNI->sduLength || !mpib.macAutoRequest) {
// Make the call to the higher layer
mlmeBeaconNotifyIndication(pMBNI);
}
// Release the packet
mrxpReleasePacket(pPacket);
break;
}
} // mrxProcessBeacon
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -