📄 mac_rx_engine.c
字号:
// MAC_RX_PACKET *pPacket
// The packet that contains the beacon. This structure will be modified to contain the
// notification.
//
// RETURN VALUE:
// MLME_BEACON_NOTIFY_INDICATION*
// A pointer to the notification to be passed to the higher layer
//-------------------------------------------------------------------------------------------------------
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(QWORD) * ((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;
pendAddrOffset = payloadOffset - 1;
// Extended addresses first
n = (pendAddrSpec & 0x70) >> 4;
while (n--) {
pendAddrOffset -= sizeof(QWORD);
msupReverseCopy((BYTE*) (&pMBNI->pAddrList[pendingIndex--]), (BYTE*) (&pMDI->pMsdu[pendAddrOffset]), sizeof(QWORD));
}
// Then short addresses
n = pendAddrSpec & 0x07;
while (n--) {
pendAddrOffset -= sizeof(WORD);
pMBNI->pAddrList[pendingIndex--].Short = *((WORD*) (pMDI->pMsdu + pendAddrOffset));
}
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) {
MAC_RX_PACKET *pPacket = (MAC_RX_PACKET*) pTask->taskData;
MLME_BEACON_NOTIFY_INDICATION *pMBNI;
MCPS_DATA_INDICATION *pMDI = &pPacket->mdi;
BYTE pendAddrOffset;
ZBOOL pendDataAvailable;
WORD superframeSpec;
ZBOOL panIdConflict;
BYTE pendAddrSpec;
UINT8 oldBeaconOrder;
ZBOOL findBeacon;
MAC_ENUM result;
ZBOOL 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) {
/// ENABLE_FIFOP_INT();
// 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->ENERGY_OR_ACTIVE.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)) {
/// ENABLE_FIFOP_INT();
// 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 (!msupCompareQword((QWORD*)&mpib.macCoordExtendedAddress, (QWORD*)&pMDI->srcAddr.Extended))
{
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();
}
// 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.macAssocatedPanCordinator)
{
if (pMDI->srcAddrMode == AM_SHORT_16)
{
result = msupTransmitPanConflict(AM_SHORT_16, mpib.macPANId, (ADDRESS*) &mpib.macCoordShortAddress, securityEnable);
} else {
result = msupTransmitPanConflict(AM_EXTENDED_64, mpib.macPANId, (ADDRESS*) &mpib.macCoordExtendedAddress, 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() - (mtimInfo.bosCounter - 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() - mtimInfo.bosCounter);
}
}
if (pPacket->flags & MRXP_FLAG_RX_NOT_TURNED_OFF_BM) mrxDecrOnCounter();
/// ENABLE_FIFOP_INT();
// 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 (msupCompareQword(&aExtendedAddress, (QWORD*) (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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -