interface Init;
interface MLME_SCAN;
interface MLME_BEACON_NOTIFY;
+ interface GetNow<token_requested_t> as IsRadioTokenRequested;
}
uses
{
interface Timer<TSymbolIEEE802154> as ScanTimer;
interface Pool<ieee154_txframe_t> as TxFramePool;
interface Pool<ieee154_txcontrol_t> as TxControlPool;
- interface Resource as Token;
+ interface TransferableResource as RadioToken;
interface FrameUtility;
interface Leds;
}
{
enum {
MAX_PAYLOAD_SIZE = 1,
+ LAST_CHANNEL = 26,
};
+#define INVALID_CHANNEL_BITMASK 0xFC000000L
ieee154_txframe_t *m_txFrame = NULL;
uint8_t m_payload[MAX_PAYLOAD_SIZE];
uint8_t m_scanType;
uint32_t m_scanChannels;
- uint32_t m_unscannedChannels;
- ieee154_macAutoRequest_t m_macAutoRequest;
- norace uint32_t m_currentChannelBit;
norace uint8_t m_currentChannelNum;
+ bool m_terminateScan;
void* m_resultList;
uint8_t m_resultListNumEntries;
uint8_t m_resultIndex;
ieee154_macPANId_t m_PANID;
norace uint32_t m_scanDuration;
- bool m_busy = FALSE;
+ norace bool m_busy = FALSE;
void nextIteration();
void continueScanRequest();
command error_t Init.init()
{
- // triggered by MLME_RESET; remember: Init will not be called
- // while this component owns the Token, so the worst case is
+ // triggered by MLME_RESET; Note: Init will not be called
+ // while this component owns the RadioToken, so the worst case is
// that a MLME_SCAN was accepted (returned IEEE154_SUCCESS)
- // but the Token.granted() has not been signalled
+ // but the RadioToken.granted() has not been signalled
if (m_busy) {
- m_currentChannelNum = 27;
+ m_terminateScan = TRUE;
nextIteration(); // signals confirm and resets state
}
return SUCCESS;
} else if (security && security->SecurityLevel) {
status = IEEE154_UNSUPPORTED_SECURITY;
} if ((ScanType > 3) || (ScanType < 3 && ScanDuration > 14) ||
- (ChannelPage != IEEE154_SUPPORTED_CHANNELPAGE) ||
- !(supportedChannels & ScanChannels) ||
- (EnergyDetectListNumEntries && PANDescriptorListNumEntries) ||
+ (ChannelPage != IEEE154_SUPPORTED_CHANNELPAGE) ||
+ !(supportedChannels & ScanChannels) ||
+ ((ScanType != ORPHAN_SCAN) &&
+ ((EnergyDetectListNumEntries && PANDescriptorListNumEntries) ||
(EnergyDetectList != NULL && PANDescriptorList != NULL) ||
(EnergyDetectListNumEntries && EnergyDetectList == NULL) ||
- (PANDescriptorListNumEntries && PANDescriptorList == NULL)) {
+ (PANDescriptorListNumEntries && PANDescriptorList == NULL)))) {
status = IEEE154_INVALID_PARAMETER;
- } else if (ScanType != ENERGY_DETECTION_SCAN &&
- !(m_txFrame = call TxFramePool.get())) {
+ } else if ((ScanType == ACTIVE_SCAN || ScanType == ORPHAN_SCAN) &&
+ ((m_txFrame = call TxFramePool.get()) == NULL)) {
status = IEEE154_TRANSACTION_OVERFLOW;
- } else if (ScanType != ENERGY_DETECTION_SCAN &&
- !(txControl = call TxControlPool.get())) {
+ } else if ((ScanType == ACTIVE_SCAN || ScanType == ORPHAN_SCAN) &&
+ ((txControl = call TxControlPool.get()) == NULL)) {
call TxFramePool.put(m_txFrame);
m_txFrame = NULL;
status = IEEE154_TRANSACTION_OVERFLOW;
} else {
- m_txFrame->header = &txControl->header;
- m_txFrame->payload = m_payload;
- m_txFrame->metadata = &txControl->metadata;
+ if (m_txFrame != NULL){
+ m_txFrame->header = &txControl->header;
+ m_txFrame->payload = m_payload;
+ m_txFrame->metadata = &txControl->metadata;
+ }
m_busy = TRUE;
m_scanType = ScanType;
m_scanChannels = ScanChannels;
m_scanDuration = (((uint32_t) 1 << ScanDuration) + 1) * IEEE154_aBaseSuperframeDuration;
- m_macAutoRequest = call MLME_GET.macAutoRequest();
m_PANID = call MLME_GET.macPANId();
- m_unscannedChannels = 0;
- m_currentChannelBit = 1;
m_currentChannelNum = 0;
+ m_terminateScan = FALSE;
m_resultIndex = 0;
if (ScanType == ENERGY_DETECTION_SCAN) {
m_resultList = EnergyDetectList;
}
if (m_resultList == NULL)
m_resultListNumEntries = 0;
- call Token.request();
+ call RadioToken.request();
}
dbg_serial("ScanP", "MLME_SCAN.request -> result: %lu\n", (uint32_t) status);
return status;
}
- event void Token.granted()
+ event void RadioToken.granted()
{
if (call RadioOff.isOff())
continueScanRequest();
ieee154_macDSN_t dsn = call MLME_GET.macDSN();
if (!m_busy) {
- call Token.release();
+ call RadioToken.release();
return;
}
switch (m_scanType) {
void nextIteration()
{
+ ieee154_phyChannelsSupported_t supportedChannels = call MLME_GET.phyChannelsSupported();
+ uint32_t currentChannelBit = (uint32_t) 1 << m_currentChannelNum;
error_t radioStatus = SUCCESS;
- uint32_t supportedChannels = IEEE154_SUPPORTED_CHANNELS;
- atomic {
- while (!(m_scanChannels & m_currentChannelBit & supportedChannels) && m_currentChannelNum < 27) {
- m_unscannedChannels |= m_currentChannelBit;
- m_currentChannelBit <<= 1;
+
+ if (!m_terminateScan){
+ while (m_currentChannelNum <= LAST_CHANNEL &&
+ !(m_scanChannels & currentChannelBit & supportedChannels)){
m_currentChannelNum++;
+ currentChannelBit <<= 1;
}
}
- if (m_currentChannelNum < 27) {
+
+ if (m_currentChannelNum <= LAST_CHANNEL && !m_terminateScan) {
+ // scan the next channel
call MLME_SET.phyCurrentChannel(m_currentChannelNum);
dbg_serial("ScanP", "Scanning channel %lu...\n", (uint32_t) m_currentChannelNum);
switch (m_scanType) {
} else {
// we're done
ieee154_status_t result = IEEE154_SUCCESS;
- m_currentChannelBit <<= 1;
- while (m_currentChannelBit) {
- m_unscannedChannels |= m_currentChannelBit;
- m_currentChannelBit <<= 1;
- }
- m_unscannedChannels &= m_scanChannels; // only channels that were requested
- if (m_scanType != ENERGY_DETECTION_SCAN && !m_resultIndex)
+ uint32_t unscannedChannels = 0;
+
+ if (m_terminateScan){
+ // Scan operation terminated because the max.
+ // number of PAN descriptors/ED samples was reached.
+ // Check if there are channels that were unscanned.
+ // In active/passive scan we consider a channel
+ // unscanned if it was not completely scanned.
+ if (m_scanType == PASSIVE_SCAN || m_scanType == ACTIVE_SCAN)
+ currentChannelBit >>= 1; // last (partially) scanned channel
+ while (!(currentChannelBit & INVALID_CHANNEL_BITMASK) &&
+ (m_scanChannels & currentChannelBit)){
+ unscannedChannels |= currentChannelBit;
+ currentChannelBit <<= 1;
+ }
+ if (unscannedChannels) // some channels were not (completely) scanned
+ result = IEEE154_LIMIT_REACHED;
+ } else if (m_scanType != ENERGY_DETECTION_SCAN && !m_resultIndex)
result = IEEE154_NO_BEACON;
+
if (m_scanType == PASSIVE_SCAN || m_scanType == ACTIVE_SCAN)
call MLME_SET.macPANId(m_PANID);
if (m_txFrame != NULL) {
call TxFramePool.put(m_txFrame);
}
m_txFrame = NULL;
- if (call Token.isOwner())
- call Token.release();
+ if (call RadioToken.isOwner())
+ call RadioToken.release();
m_busy = FALSE;
dbg_serial("ScanP", "MLME_SCAN.confirm()\n");
signal MLME_SCAN.confirm (
result,
m_scanType,
IEEE154_SUPPORTED_CHANNELPAGE,
- m_unscannedChannels,
+ unscannedChannels,
(m_scanType == ENERGY_DETECTION_SCAN) ? m_resultIndex : 0,
- (m_scanType == ENERGY_DETECTION_SCAN) ? (uint8_t*) m_resultList : NULL,
+ (m_scanType == ENERGY_DETECTION_SCAN) ? (int8_t*) m_resultList : NULL,
((m_scanType == ACTIVE_SCAN ||
- m_scanType == PASSIVE_SCAN) && m_macAutoRequest) ? m_resultIndex : 0,
+ m_scanType == PASSIVE_SCAN) && call MLME_GET.macAutoRequest()) ? m_resultIndex : 0,
((m_scanType == ACTIVE_SCAN ||
- m_scanType == PASSIVE_SCAN) && m_macAutoRequest) ? (ieee154_PANDescriptor_t*) m_resultList : NULL);
+ m_scanType == PASSIVE_SCAN) && call MLME_GET.macAutoRequest()) ? (ieee154_PANDescriptor_t*) m_resultList : NULL);
}
+ dbg_serial_flush();
}
async event void RadioRx.enableRxDone()
{
if (status == SUCCESS && m_resultListNumEntries)
((uint8_t*) m_resultList)[m_resultIndex++] = EnergyLevel;
- else
- m_unscannedChannels |= m_currentChannelBit;
if (m_resultIndex == m_resultListNumEntries)
- m_currentChannelNum = 27; // done
- else
- m_currentChannelNum++;
- call RadioOff.off();
+ m_terminateScan = TRUE; // done
+ if (call RadioOff.off() == EALREADY)
+ signal RadioOff.offDone();
}
/* ----------------------- Active/Orphan scan ----------------------- */
event message_t* RadioRx.received(message_t *frame, const ieee154_timestamp_t *timestamp)
{
- atomic {
- if (!m_busy)
- return frame;
- if (m_scanType == ORPHAN_SCAN) {
- if (!m_resultIndex)
- if ((MHR(frame)[0] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD &&
- ((uint8_t*)call Frame.getPayload(frame))[0] == CMD_FRAME_COORDINATOR_REALIGNMENT) {
- m_resultIndex++;
- dbg_serial("ScanP", "Received coordinator realignment frame.\n");
- m_currentChannelNum = 27; // terminate scan
- call RadioOff.off();
- }
- } else if ((((ieee154_header_t*) frame->header)->mhr[0] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_BEACON) {
- // PASSIVE_SCAN / ACTIVE_SCAN
- if (!m_macAutoRequest)
- return signal MLME_BEACON_NOTIFY.indication (frame);
- else if (m_resultListNumEntries && m_resultIndex < m_resultListNumEntries &&
- call BeaconFrame.parsePANDescriptor(
- frame,
- m_currentChannelNum,
- IEEE154_SUPPORTED_CHANNELPAGE,
- &((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex]) == SUCCESS) {
-
- // check uniqueness: both PAN ID and source address must not be in a previously received beacon
- uint8_t i;
- ieee154_PANDescriptor_t* descriptor = (ieee154_PANDescriptor_t*) m_resultList;
- if (m_resultIndex)
- for (i=0; i<m_resultIndex; i++)
- if (descriptor[i].CoordPANId == descriptor[m_resultIndex].CoordPANId &&
- descriptor[i].CoordAddrMode == descriptor[m_resultIndex].CoordAddrMode)
- if ((descriptor[i].CoordAddrMode == ADDR_MODE_SHORT_ADDRESS &&
- descriptor[i].CoordAddress.shortAddress ==
- descriptor[m_resultIndex].CoordAddress.shortAddress) ||
- (descriptor[i].CoordAddrMode == ADDR_MODE_EXTENDED_ADDRESS &&
- descriptor[i].CoordAddress.extendedAddress ==
- descriptor[m_resultIndex].CoordAddress.extendedAddress))
- return frame; // not unique
- dbg_serial("ScanP", "Received beacon, source: 0x%lx, channel: %lu.\n",
- (uint32_t) descriptor[m_resultIndex].CoordAddress.shortAddress, (uint32_t) m_currentChannelNum);
- m_resultIndex++;
- if (m_resultIndex == m_resultListNumEntries) {
- m_currentChannelNum = 27; // terminate scan
- call RadioOff.off();
- }
+ if (!m_busy)
+ return frame;
+
+ if (m_scanType == ORPHAN_SCAN) {
+ if (!m_resultIndex)
+ if ((MHR(frame)[0] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD &&
+ ((uint8_t*)call Frame.getPayload(frame))[0] == CMD_FRAME_COORDINATOR_REALIGNMENT) {
+ m_resultIndex++;
+ dbg_serial("ScanP", "Received coordinator realignment frame.\n");
+ m_terminateScan = TRUE;
+ call RadioOff.off();
}
- } // PASSIVE_SCAN / ACTIVE_SCAN
- }
+ } else if ((((ieee154_header_t*) frame->header)->mhr[0] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_BEACON) {
+
+ // PASSIVE_SCAN / ACTIVE_SCAN:
+ // A beacon frame containing a non-empty payload is always signalled
+ // to the next higher layer (regardless of the value of macAutoRequest);
+ // when macAutoRequest is set to TRUE, then the beacon is always
+ // stored in the PAN Descriptor list (see 7.1.11.2.1 - Table 68)
+
+ if (!call MLME_GET.macAutoRequest())
+ return signal MLME_BEACON_NOTIFY.indication (frame);
+ else if (m_resultIndex >= m_resultListNumEntries) {
+ m_terminateScan = TRUE;
+ call RadioOff.off();
+ } else if (call BeaconFrame.parsePANDescriptor(
+ frame,
+ m_currentChannelNum,
+ IEEE154_SUPPORTED_CHANNELPAGE,
+ &((ieee154_PANDescriptor_t*) m_resultList)[m_resultIndex]) == SUCCESS) {
+
+ // check uniqueness: PAN ID and source address must
+ // not be found in a previously received beacon
+ uint8_t i;
+ ieee154_PANDescriptor_t* descriptor = (ieee154_PANDescriptor_t*) m_resultList;
+
+ dbg_serial("ScanP", "Received beacon, source: 0x%lx, channel: %lu.\n",
+ (uint32_t) descriptor[m_resultIndex].CoordAddress.shortAddress, (uint32_t) m_currentChannelNum);
+ for (i=0; i<m_resultIndex; i++)
+ if (descriptor[i].CoordPANId == descriptor[m_resultIndex].CoordPANId &&
+ descriptor[i].CoordAddrMode == descriptor[m_resultIndex].CoordAddrMode)
+ if ((descriptor[i].CoordAddrMode == ADDR_MODE_SHORT_ADDRESS &&
+ descriptor[i].CoordAddress.shortAddress ==
+ descriptor[m_resultIndex].CoordAddress.shortAddress) ||
+ (descriptor[i].CoordAddrMode == ADDR_MODE_EXTENDED_ADDRESS &&
+ descriptor[i].CoordAddress.extendedAddress ==
+ descriptor[m_resultIndex].CoordAddress.extendedAddress))
+ break; // not unique
+ if (i == m_resultIndex)
+ m_resultIndex++; // was unique
+ }
+ if (call BeaconFrame.getBeaconPayloadLength(frame) > 0)
+ return signal MLME_BEACON_NOTIFY.indication (frame);
+ } // PASSIVE_SCAN / ACTIVE_SCAN
return frame;
}
if (m_currentChannelNum == 0)
post continueScanRequestTask();
else {
- m_currentChannelBit <<= 1;
m_currentChannelNum++;
post nextIterationTask();
}
nextIteration();
}
+ async command token_requested_t IsRadioTokenRequested.getNow(){ return m_busy;}
+ async event void RadioToken.transferredFrom(uint8_t id){ ASSERT(0);}
default event message_t* MLME_BEACON_NOTIFY.indication (message_t *beaconFrame) {return beaconFrame;}
default event void MLME_SCAN.confirm (
ieee154_status_t status,