/** * @brief Resets the MAC helper variables and transition to idle state * * This function sets the MAC to idle state and resets * MAC helper variables */ void mac_idle_trans(void) { /* Wake up radio first */ mac_trx_wakeup(); { uint16_t default_shortaddress = macShortAddress_def; uint16_t default_panid = macPANId_def; #if (_DEBUG_ > 0) retval_t set_status = #endif set_tal_pib_internal(macShortAddress, (void *)&default_shortaddress); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); set_status = #endif set_tal_pib_internal(macPANId, (void *)&default_panid); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); set_status = set_status; #endif } mac_soft_reset(true); /* Set radio to sleep if allowed */ mac_sleep_trans(); }
/* * @brief Clean-up for scanning * * This is a helper function for clean-up functionality during the end of * scanning. * * @param buffer Pointer to mlme_scan_conf_t structure */ static void scan_clean_up(buffer_t *buffer) { #if (_DEBUG_ > 0) retval_t set_status; #endif /* Append the scan confirm message into the internal event queue */ qmm_queue_append(&mac_nhle_q, buffer); /* Set original channel page and channel. */ scan_curr_page = mac_scan_orig_page; #if (_DEBUG_ > 0) set_status = #endif set_tal_pib_internal(phyCurrentPage, (void *)&scan_curr_page); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); set_status = set_status; #endif scan_curr_channel = mac_scan_orig_channel; #if (_DEBUG_ > 0) set_status = #endif set_tal_pib_internal(phyCurrentChannel, (void *)&scan_curr_channel); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif mac_scan_state = MAC_SCAN_IDLE; /* Set radio to sleep if allowed */ mac_sleep_trans(); }
/** * @brief Processes received beacon frame * * This function processes a received beacon frame. * When the system is scanning it records PAN descriptor information * contained in the beacon. These PAN descriptors will be reported to the * next higher layer via MLME_SCAN.confirm. * Also this routine constructs the MLME_BEACON_NOTIFY.indication. * Additionally when a device is synced with the coordinator, it tracks beacon * frames, checks whether the coordinator does have pending data and will * initiate the transmission of a data request frame. * The routine uses global "parse_data" structure. * The PAN descriptors are stored in the mlme_scan_conf_t structure. * * @param beacon Pointer to the buffer in which the beacon was received * */ void mac_process_beacon_frame(buffer_t *beacon) { bool matchflag; wpan_pandescriptor_t *pand_long_start_p = NULL; wpan_pandescriptor_t pand_long; mlme_scan_conf_t *msc = NULL; #if ((MAC_BEACON_NOTIFY_INDICATION == 1) || \ ((MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) \ ) uint8_t numaddrshort; uint8_t numaddrlong; #endif #ifdef BEACON_SUPPORT uint16_t beacon_length; /* * Extract the superframe parameters of the beacon frame only if * scanning is NOT ongoing. */ if (MAC_SCAN_IDLE == mac_scan_state) { #if (MAC_START_REQUEST_CONFIRM == 1) /* Beacon frames are not of interest for a PAN coordinator. */ if (MAC_PAN_COORD_STARTED != mac_state) #endif /* MAC_START_REQUEST_CONFIRM */ { uint8_t superframe_order; uint8_t beacon_order; /* * For a device, the parameters obtained from the beacons are used to * update the PIBs at TAL */ beacon_order = GET_BEACON_ORDER(mac_parse_data.mac_payload_data.beacon_data.superframe_spec); #if (_DEBUG_ > 0) retval_t set_status = #endif set_tal_pib_internal(macBeaconOrder, (void *)&beacon_order); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif superframe_order = GET_SUPERFRAME_ORDER(mac_parse_data.mac_payload_data.beacon_data.superframe_spec); #if (_DEBUG_ > 0) set_status = #endif set_tal_pib_internal(macSuperframeOrder, (void *)&superframe_order); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif mac_final_cap_slot = GET_FINAL_CAP(mac_parse_data.mac_payload_data.beacon_data.superframe_spec); /* * In a beacon-enabled network with the batterylife extension * enabled, the first backoff slot boundary is computed after the * end of the beacon's IFS */ if ((tal_pib.BeaconOrder < NON_BEACON_NWK) && tal_pib.BattLifeExt) { /* Length given in octets */ beacon_length = mac_parse_data.mpdu_length + PHY_OVERHEAD; /* Convert to symbols */ beacon_length *= SYMBOLS_PER_OCTET; /* Space needed for IFS is added to it */ if (mac_parse_data.mpdu_length <= aMaxSIFSFrameSize) { beacon_length += macMinSIFSPeriod_def; } else { beacon_length += macMinLIFSPeriod_def; } /* Round up to backoff slot boundary */ beacon_length = (beacon_length + aUnitBackoffPeriod - 1) / aUnitBackoffPeriod; beacon_length *= aUnitBackoffPeriod; /* * Slotted CSMA-CA with macBattLifeExt must start within * the first macBattLifeExtPeriods backoff slots of the CAP */ beacon_length += mac_pib.mac_BattLifeExtPeriods * aUnitBackoffPeriod; } } /* (MAC_PAN_COORD_STARTED != mac_state) */ } /* (MAC_SCAN_IDLE == mac_scan_state) */ #endif /* BEACON_SUPPORT */ /* * The following section needs to be done when we are * either scanning (and look for a new PAN descriptor to be returned * as part of the scan confirm message), * or we need to create a beacon notification (in which case we are * interested in any beacon, but omit the generation of scan confirm). */ { uint8_t index; /* * If we are scanning a scan confirm needs to be created. * * According to 802.15.4-2006 this is only done in case the PIB * attribute macAutoRequest is true. Otherwise the PAN descriptor will * NOT be put into the PAN descriptor list of the Scan confirm message. */ if ( ((MAC_SCAN_ACTIVE == mac_scan_state) || (MAC_SCAN_PASSIVE == mac_scan_state)) && mac_pib.mac_AutoRequest ) { /* * mac_conf_buf_ptr points to the buffer allocated for scan * confirmation. */ msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER( ((buffer_t *)mac_conf_buf_ptr)); /* * The PAN descriptor list is updated with the PANDescriptor of the * received beacon */ pand_long_start_p = (wpan_pandescriptor_t *)&msc->scan_result_list; } /* * The beacon data received from the parse variable is arranged * into a PAN descriptor structure style */ pand_long.CoordAddrSpec.AddrMode = mac_parse_data.src_addr_mode; pand_long.CoordAddrSpec.PANId = mac_parse_data.src_panid; if (FCF_SHORT_ADDR == pand_long.CoordAddrSpec.AddrMode) { /* Initially clear the complete address. */ pand_long.CoordAddrSpec.Addr.long_address = 0; ADDR_COPY_DST_SRC_16(pand_long.CoordAddrSpec.Addr.short_address, mac_parse_data.src_addr.short_address); } else { ADDR_COPY_DST_SRC_64(pand_long.CoordAddrSpec.Addr.long_address, mac_parse_data.src_addr.long_address); } pand_long.LogicalChannel = tal_pib.CurrentChannel; pand_long.ChannelPage = tal_pib.CurrentPage; pand_long.SuperframeSpec = mac_parse_data.mac_payload_data.beacon_data.superframe_spec; pand_long.GTSPermit = mac_parse_data.mac_payload_data.beacon_data.gts_spec >> 7; pand_long.LinkQuality = mac_parse_data.ppdu_link_quality; #ifdef ENABLE_TSTAMP pand_long.TimeStamp = mac_parse_data.time_stamp; #endif /* ENABLE_TSTAMP */ /* * If we are scanning we need to check whether this is a new * PAN descriptor. * * According to 802.15.4-2006 this is only done in case the PIB * attribute macAutoRequest is true. Otherwise the PAN descriptor will * NOT be put into the PAN descriptor list of the Scan confirm message. */ if ( ((MAC_SCAN_ACTIVE == mac_scan_state) || (MAC_SCAN_PASSIVE == mac_scan_state)) && mac_pib.mac_AutoRequest ) { /* * This flag is used to indicate a match of the current (received) PAN * descriptor with one of those present already in the list. */ matchflag = false; /* * The beacon frame PAN descriptor is compared with the PAN descriptors * present in the list and determine if the current PAN * descriptor is to be taken as a valid one. A PAN is considered to be * the same as an existing one, if all, the PAN Id, the coordinator address * mode, the coordinator address, and the Logical Channel are same. */ for (index = 0; index < msc->ResultListSize; index++, pand_long_start_p++) { if ((pand_long.CoordAddrSpec.PANId == pand_long_start_p->CoordAddrSpec.PANId) && (pand_long.CoordAddrSpec.AddrMode == pand_long_start_p->CoordAddrSpec.AddrMode) && (pand_long.LogicalChannel == pand_long_start_p->LogicalChannel) && (pand_long.ChannelPage == pand_long_start_p->ChannelPage) ) { if (pand_long.CoordAddrSpec.AddrMode == WPAN_ADDRMODE_SHORT) { if (pand_long.CoordAddrSpec.Addr.short_address == pand_long_start_p->CoordAddrSpec.Addr.short_address) { /* Beacon with same parameters already received */ matchflag = true; break; } } else { if (pand_long.CoordAddrSpec.Addr.long_address == pand_long_start_p->CoordAddrSpec.Addr.long_address) { /* Beacon with same parameters already received */ matchflag = true; break; } } } } /* * If the PAN descriptor is not in the current list, and there is space * left, it is put into the list */ if ((!matchflag) && (msc->ResultListSize < MAX_PANDESCRIPTORS)) { memcpy(pand_long_start_p, &pand_long, sizeof(pand_long)); msc->ResultListSize++; } } } #if ((MAC_BEACON_NOTIFY_INDICATION == 1) || \ ((MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) \ ) /* The short and extended pending addresses are extracted from the beacon */ numaddrshort = NUM_SHORT_PEND_ADDR(mac_parse_data.mac_payload_data.beacon_data.pending_addr_spec); numaddrlong = NUM_LONG_PEND_ADDR(mac_parse_data.mac_payload_data.beacon_data.pending_addr_spec); #endif #if (MAC_BEACON_NOTIFY_INDICATION == 1) /* * In all cases (PAN or device) if the payload is not equal to zero * or macAutoRequest is false, MLME_BEACON_NOTIFY.indication is * generated */ if ((mac_parse_data.mac_payload_data.beacon_data.beacon_payload_len > 0) || (!mac_pib.mac_AutoRequest) ) { mlme_beacon_notify_ind_t *mbni = (mlme_beacon_notify_ind_t *)BMM_BUFFER_POINTER(((buffer_t *)beacon)); /* The beacon notify indication structure is built */ mbni->cmdcode = MLME_BEACON_NOTIFY_INDICATION; mbni->BSN = mac_parse_data.sequence_number; mbni->PANDescriptor = pand_long; mbni->PendAddrSpec = mac_parse_data.mac_payload_data.beacon_data.pending_addr_spec; if ((numaddrshort > 0) || (numaddrlong > 0)) { mbni->AddrList = mac_parse_data.mac_payload_data.beacon_data.pending_addr_list; } mbni->sduLength = mac_parse_data.mac_payload_data.beacon_data.beacon_payload_len; mbni->sdu = mac_parse_data.mac_payload_data.beacon_data.beacon_payload; /* * The beacon notify indication is given to the NHLE and then the buffer * is freed up. */ qmm_queue_append(&mac_nhle_q, (buffer_t *)beacon); } else #endif /* (MAC_BEACON_NOTIFY_INDICATION == 1) */ { /* Payload is not present, hence the buffer is freed here */ bmm_buffer_free(beacon); } /* Handling of ancounced broadcast traffic by the parent. */ #ifdef BEACON_SUPPORT if (MAC_SCAN_IDLE == mac_scan_state) { /* * In case this is a beaconing network, and this node is not scanning, * and the FCF indicates pending data thus indicating broadcast data at * parent, the node needs to be awake until the received broadcast * data has been received. */ if (mac_parse_data.fcf & FCF_FRAME_PENDING) { mac_bc_data_indicated = true; /* * Start timer since the broadcast frame is expected within * macMaxFrameTotalWaitTime symbols. */ if (MAC_POLL_IDLE == mac_poll_state) { /* * If the poll state is not idle, there is already an * indirect transaction ongoing. * Since the T_Poll_Wait_Time is going to be re-used, * this timer can only be started, if we are not in * a polling state other than idle. */ uint32_t response_timer = mac_pib.mac_MaxFrameTotalWaitTime; response_timer = TAL_CONVERT_SYMBOLS_TO_US(response_timer); if (MAC_SUCCESS != pal_timer_start(T_Poll_Wait_Time, response_timer, TIMEOUT_RELATIVE, (FUNC_PTR)mac_t_wait_for_bc_time_cb, NULL)) { mac_t_wait_for_bc_time_cb(NULL); } } else { /* * Any indirect poll operation is ongoing, so the timer will * not be started, i.e. nothing to be done here. * Once this ongoing indirect transaction has finished, this * node will go back to sleep anyway. */ } } else { mac_bc_data_indicated = false; } } /* (MAC_SCAN_IDLE == mac_scan_state) */ #endif /* BEACON_SUPPORT */ /* Handling of presented indirect traffic by the parent for this node. */ #if ((MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) if (MAC_SCAN_IDLE == mac_scan_state) { /* * If this node is NOT scanning, and is doing a mlme_sync_request, * then the pending address list of the beacon is examined to see * if the node's parent has data for this node. */ if (mac_pib.mac_AutoRequest) { if (MAC_SYNC_NEVER != mac_sync_state) { uint8_t index; #if (_DEBUG_ > 0) bool status; #endif /* * Short address of the device is compared with the * pending short address in the beacon frame */ /* * PAN-ID and CoordAddress does not have to be checked here, * since the device is already synced with the coordinator, and * only beacon frames passed from data_ind.c (where the first level * filtering is already done) are received. The pending addresses * in the beacon frame are compared with the device address. If a * match is found, it indicates that a data belonging to this * deivce is present with the coordinator and hence a data request * is sent to the coordinator. */ uint16_t cur_short_addr; for (index = 0; index < numaddrshort; index++) { cur_short_addr = convert_byte_array_to_16_bit((mac_parse_data.mac_payload_data.beacon_data.pending_addr_list + index * sizeof(uint16_t))); if (cur_short_addr == tal_pib.ShortAddress) { /* * Device short address matches with one of the address * in the beacon address list. Implicit poll (using the * device short address) is done to get the pending data */ #if (_DEBUG_ > 0) status = #endif mac_build_and_tx_data_req(false, false, 0, NULL, 0); #if (_DEBUG_ > 0) Assert(status == true); #endif return; } } /* * Extended address of the device is compared with * the pending extended address in the beacon frame */ uint64_t cur_long_addr; for (index = 0; index < numaddrlong; index++) { cur_long_addr = convert_byte_array_to_64_bit((mac_parse_data.mac_payload_data.beacon_data.pending_addr_list + numaddrshort * sizeof(uint16_t) + index * sizeof(uint64_t))); if (cur_long_addr == tal_pib.IeeeAddress) { /* * Device extended address matches with one of the * address in the beacon address list. Implicit poll * (using the device extended address) is done to get * the pending data */ #if (_DEBUG_ > 0) status = #endif mac_build_and_tx_data_req(false, true, 0, NULL, 0); #if (_DEBUG_ > 0) Assert(status == true); #endif return; } } } } /* (mac_pib.mac_AutoRequest) */ } /* (MAC_SCAN_IDLE == mac_scan_state) */ #endif /* (MAC_INDIRECT_DATA_BASIC == 1) && (MAC_SYNC_REQUEST == 1)) */ } /* mac_process_beacon_frame() */
/** * @brief Continues handling of MLME_START.request (Coordinator realignment) * command * * This function is called once the coordinator realignment command is * sent out to continue the handling of the MLME_START.request command. * * @param tx_status Status of the coordinator realignment command * transmission * @param buf_ptr Buffer for start confirmation */ void mac_coord_realignment_command_tx_success(uint8_t tx_status, buffer_t *buf_ptr) { uint8_t conf_status = MAC_INVALID_PARAMETER; retval_t channel_set_status, channel_page_set_status; if (MAC_SUCCESS == tx_status) { /* The parameters of the existing PAN are updated. */ channel_page_set_status = set_tal_pib_internal(phyCurrentPage, (void *)&(msr_params.ChannelPage)); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == channel_page_set_status); #endif channel_set_status = set_tal_pib_internal(phyCurrentChannel, (void *)&msr_params.LogicalChannel); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == channel_set_status); #endif if ((MAC_SUCCESS == channel_set_status) && (MAC_SUCCESS == channel_page_set_status)) { conf_status = MAC_SUCCESS; set_tal_pib_internal(macPANId, (void *)&(msr_params.PANId)); #ifdef BEACON_SUPPORT /* * Store current beacon order in order to be able to detect * switching from nonbeacon to beacon network. */ uint8_t cur_beacon_order = tal_pib.BeaconOrder; set_tal_pib_internal(macBeaconOrder, (void *)&(msr_params.BeaconOrder)); set_tal_pib_internal(macSuperframeOrder, (void *)&(msr_params.SuperframeOrder)); /* * New symbol times for beacon time (in sysbols) and inactive time are * calculated according to the new superframe configuration. */ if (msr_params.BeaconOrder < NON_BEACON_NWK) { set_tal_pib_internal(macBattLifeExt, (void *)&(msr_params.BatteryLifeExtension)); } if ((NON_BEACON_NWK < cur_beacon_order) && (msr_params.BeaconOrder == NON_BEACON_NWK)) { /* * This is a transition from a beacon enabled network to * a nonbeacon enabled network. * In this case the broadcast data queue will never be served. * * Therefore the broadcast queue needs to be emptied. * The standard does not define what to do now. * The current implementation will try to send all pending broadcast * data frames immediately, thus giving the receiving nodes a chance * receive them. */ while (broadcast_q.size > 0) { mac_tx_pending_bc_data(); } } if ((NON_BEACON_NWK == cur_beacon_order) && (msr_params.BeaconOrder < NON_BEACON_NWK)) { /* * This is a transition from a nonbeacon enabled network to * a beacon enabled network, hence the beacon timer will be * started. */ mac_start_beacon_timer(); } #endif /* BEACON_SUPPORT */ } } gen_mlme_start_conf(buf_ptr, conf_status); /* Set radio to sleep if allowed */ mac_sleep_trans(); } /* mac_coord_realignment_command_tx_success() */
/** * @brief The MLME-START.request primitive makes a request for the device to * start using a new superframe configuration * * @param m Pointer to MLME_START.request message issued by the NHLE */ void mlme_start_request(uint8_t *m) { mlme_start_req_t *msg = (mlme_start_req_t *)BMM_BUFFER_POINTER((buffer_t *)m); /* * The MLME_START.request parameters are copied into a global variable * structure, which is used by check_start_parameter() function. */ memcpy(&msr_params, msg, sizeof(msr_params)); if (BROADCAST == tal_pib.ShortAddress) { /* * The device is void of short address. This device cannot start a * network, hence a confirmation is given back. */ gen_mlme_start_conf((buffer_t *)m, MAC_NO_SHORT_ADDRESS); return; } #ifndef REDUCED_PARAM_CHECK if (!check_start_parameter(msg)) { /* * The MLME_START.request parameters are invalid, hence confirmation * is given to NHLE. */ gen_mlme_start_conf((buffer_t *)m, MAC_INVALID_PARAMETER); } else #endif /* REDUCED_PARAM_CHECK */ { /* * All the start parameters are valid, hence MLME_START.request can * proceed. */ set_tal_pib_internal(mac_i_pan_coordinator, (void *)&(msg->PANCoordinator)); if (msr_params.CoordRealignment) { /* First inform our devices of the configuration change */ if (!mac_tx_coord_realignment_command(COORDINATORREALIGNMENT, (buffer_t *)m, msr_params.PANId, msr_params.LogicalChannel, msr_params.ChannelPage)) { /* * The coordinator realignment command was unsuccessful, * hence the confiramtion is given to NHLE. */ gen_mlme_start_conf((buffer_t *)m, MAC_INVALID_PARAMETER); } } else { /* This is a normal MLME_START.request. */ retval_t channel_set_status, channel_page_set_status; /* The new PIBs are set at the TAL. */ set_tal_pib_internal(macBeaconOrder, (void *)&(msg->BeaconOrder)); /* If macBeaconOrder is equal to 15, set also macSuperframeOrder to 15. */ if (msg->BeaconOrder == NON_BEACON_NWK) { msg->SuperframeOrder = NON_BEACON_NWK; } set_tal_pib_internal(macSuperframeOrder, (void *)&(msg->SuperframeOrder)); #ifdef BEACON_SUPPORT /* * Symbol times are calculated according to the new BO and SO * values. */ if (tal_pib.BeaconOrder < NON_BEACON_NWK) { set_tal_pib_internal(macBattLifeExt, (void *)&(msr_params.BatteryLifeExtension)); } #endif /* BEACON_SUPPORT */ /* Wake up radio first */ mac_trx_wakeup(); /* MLME_START.request parameters other than BO and SO are set at TAL */ set_tal_pib_internal(macPANId, (void *)&(msr_params.PANId)); channel_page_set_status = set_tal_pib_internal(phyCurrentPage, (void *)&(msr_params.ChannelPage)); channel_set_status = set_tal_pib_internal(phyCurrentChannel, (void *)&(msr_params.LogicalChannel)); set_tal_pib_internal(mac_i_pan_coordinator, (void *)&(msr_params.PANCoordinator)); if ((MAC_SUCCESS == channel_page_set_status) && (MAC_SUCCESS == channel_set_status) && (PHY_RX_ON == tal_rx_enable(PHY_RX_ON)) ) { if (msr_params.PANCoordinator) { mac_state = MAC_PAN_COORD_STARTED; } else { mac_state = MAC_COORDINATOR; } gen_mlme_start_conf((buffer_t *)m, MAC_SUCCESS); #ifdef BEACON_SUPPORT /* * In case we have a beaconing network, the beacon timer needs * to be started now. */ if (tal_pib.BeaconOrder != NON_BEACON_NWK) { mac_start_beacon_timer(); } #endif /* BEACON_SUPPORT */ } else { /* Start of network failed. */ gen_mlme_start_conf((buffer_t *)m, MAC_INVALID_PARAMETER); } /* Set radio to sleep if allowed */ mac_sleep_trans(); } } }
/** * @brief Implements the MLME-SYNC request. * * The MLME-SYNC.request primitive requests to synchronize with the * coordinator by acquiring and, if specified, tracking its beacons. * The MLME-SYNC.request primitive is generated by the next higher layer of a * device on a beacon-enabled PAN and issued to its MLME to synchronize with * the coordinator. * * Enable receiver and search for beacons for at most an interval of * [aBaseSuperframeDuration * ((2 ^ (n))+ 1)] symbols where n is the value of * macBeaconOrder. If a beacon frame containing the current PAN identifier of * the device is not received, the MLME shall repeat this search. Once the * number of missed beacons reaches aMaxLostBeacons, the MLME shall notify * the next higher layer by issuing the MLME-SYNC-LOSS.indication primitive * with a loss reason of BEACON_LOSS. * * @param m Pointer to the MLME sync request parameters. */ void mlme_sync_request(uint8_t *m) { #if (DEBUG > 0) retval_t set_status, set_status_2; #endif mlme_sync_req_t *msr = (mlme_sync_req_t *)BMM_BUFFER_POINTER((buffer_t *)m); /* * Sync is only allowed for nodes that are: * 1) Devices (also before association.) or coordinators * (no PAN coordinators), * 2) Currently NOT polling, and * 3) Currently NOT scanning. */ if ( #if (MAC_START_REQUEST_CONFIRM == 1) (MAC_PAN_COORD_STARTED == mac_state) || #endif /* (MAC_START_REQUEST_CONFIRM == 1) */ (MAC_POLL_IDLE != mac_poll_state) || (MAC_SCAN_IDLE != mac_scan_state) ) { /* Free the buffer allocated for MLME-SYNC-Request */ bmm_buffer_free((buffer_t *)m); mac_sync_loss(MAC_BEACON_LOSS); return; } /* Stop the beacon tracking period timer. */ pal_timer_stop(T_Beacon_Tracking_Period); #if (DEBUG > 0) if (pal_is_timer_running(T_Beacon_Tracking_Period)) { ASSERT("BCN tmr running" == 0); } #endif /* Set MAC Sync state properly. */ if (MAC_IDLE == mac_state) { /* * We try to sync before association. * This is a special sync state that checks beacon frames similar to * MAC_SYNC_TRACKING_BEACON while being associated. * * Before this state can be entered successfully a number of PIB * attributes have to be set properly: * 1) PAN-Id (macPANId) * 2) Coordinator Short or Long address (depending upon which type * of addressing the coordinator is using) * (macCoordShortAddress or mac macCoordExtendedAddress) * * Furthermore it is strongly recommended to set the Beacon order and * Superframe order (macBeaconOrder, macSuperframeOrder). * If these parameters are not set and the node tries to sync with a * network, where it never receives a beacon from, the missed beacon * timer (required for reporting a sync loss condition) will start * with a huge time value (based on a beacon order = 15). * If finally a beacon is received from the desired network, the timer * will be updated. * Nevertheless setting the PIB attributes before sync is safer. */ mac_sync_state = MAC_SYNC_BEFORE_ASSOC; } else { if (msr->TrackBeacon) { mac_sync_state = MAC_SYNC_TRACKING_BEACON; } else { mac_sync_state = MAC_SYNC_ONCE; } } /* Wake up radio first */ mac_trx_wakeup(); #if (DEBUG > 0) set_status = #endif set_tal_pib_internal(phyCurrentPage, (void *)&(msr->ChannelPage)); #if (DEBUG > 0) ASSERT(MAC_SUCCESS == set_status); #endif #if (DEBUG > 0) set_status_2 = #endif set_tal_pib_internal(phyCurrentChannel, (void *)&(msr->LogicalChannel)); #if (DEBUG > 0) ASSERT(MAC_SUCCESS == set_status_2); #endif mac_start_missed_beacon_timer(); /* Start synching by switching ON the receiver. */ tal_rx_enable(PHY_RX_ON); /* Free the buffer allocated by the higher layer */ bmm_buffer_free((buffer_t *)m); }
/** * @brief Processing a coordinator realignment command frame * * This function processes a coordinator realignment command frame received * from the coordinator (while NOT being in the middle of an Orphan scan, but * rather after initiation of a start request primitive from the coordinator * indicating realingment. * The PAN ID, coord. short address, logical channel, and the device's new * short address will be written to the PIB. * * @param ind Frame reception buffer */ void mac_process_coord_realign(buffer_t *ind) { /* * The coordinator realignment command is received without the orphan * notification. Hence a sync loss indication is given to NHLE. */ mac_sync_loss(MAC_REALIGNMENT); /* * The buffer in which the coordinator realignment is received is * freed up */ bmm_buffer_free((buffer_t *)ind); /* Set the appropriate PIB entries */ #if (DEBUG > 0) retval_t set_status = #endif set_tal_pib_internal(macPANId, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.pan_id); #if (DEBUG > 0) ASSERT(MAC_SUCCESS == set_status); #endif if (BROADCAST != mac_parse_data.mac_payload_data.coord_realign_data.short_addr) { /* Short address only to be set if not broadcast address */ #if (DEBUG > 0) set_status = #endif set_tal_pib_internal(macShortAddress, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.short_addr); #if (DEBUG > 0) ASSERT(MAC_SUCCESS == set_status); #endif } mac_pib.mac_CoordShortAddress = mac_parse_data.mac_payload_data.coord_realign_data.coord_short_addr; /* * If frame version subfield indicates a 802.15.4-2006 compatible frame, * the channel page is appended as additional information element. */ if (mac_parse_data.fcf & FCF_FRAME_VERSION_2006) { #if (DEBUG > 0) set_status = #endif set_tal_pib_internal(phyCurrentPage, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.channel_page); #if (DEBUG > 0) ASSERT(MAC_SUCCESS == set_status); #endif } #if (DEBUG > 0) set_status = #endif set_tal_pib_internal(phyCurrentChannel, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.logical_channel); #if (DEBUG > 0) ASSERT(MAC_SUCCESS == set_status); #endif } /* mac_process_coord_realign() */
/** * @brief Continues processing a data indication from the TAL for * non-polling and non-scanning states of the MAC * (mac_poll_state == MAC_POLL_IDLE, mac_scan_state == MAC_SCAN_IDLE). * * @param b_ptr Pointer to the buffer header. * @param f_ptr Pointer to the frame_info_t structure. * * @return bool True if frame has been processed, or false otherwise. */ static bool process_data_ind_not_transient(buffer_t *b_ptr, frame_info_t *f_ptr) { bool processed_in_not_transient = false; /* * We are in MAC_POLL_IDLE and MAC_SCAN_IDLE now, * so continue with the real MAC states. */ switch (mac_state) { #if (MAC_START_REQUEST_CONFIRM == 1) case MAC_PAN_COORD_STARTED: { switch (mac_parse_data.frame_type) { case FCF_FRAMETYPE_MAC_CMD: { switch (mac_parse_data.mac_command) { #if (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) case ASSOCIATIONREQUEST: mac_process_associate_request(b_ptr); processed_in_not_transient = true; break; #endif /* (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) */ #if (MAC_DISASSOCIATION_BASIC_SUPPORT == 1) case DISASSOCIATIONNOTIFICATION: mac_process_disassociate_notification(b_ptr); processed_in_not_transient = true; break; #endif /* (MAC_DISASSOCIATION_BASIC_SUPPORT == 1) */ #if (MAC_INDIRECT_DATA_FFD == 1) case DATAREQUEST: if (indirect_data_q.size > 0) { mac_process_data_request(b_ptr); processed_in_not_transient = true; } else { mac_handle_tx_null_data_frame(); } break; #endif /* (MAC_INDIRECT_DATA_FFD == 1) */ #if (MAC_ORPHAN_INDICATION_RESPONSE == 1) case ORPHANNOTIFICATION: mac_process_orphan_notification(b_ptr); processed_in_not_transient = true; break; #endif /* (MAC_ORPHAN_INDICATION_RESPONSE == 1) */ case BEACONREQUEST: mac_process_beacon_request(b_ptr); processed_in_not_transient = true; break; #if (MAC_PAN_ID_CONFLICT_AS_PC == 1) case PANIDCONFLICTNOTIFICAION: mac_sync_loss(MAC_PAN_ID_CONFLICT); break; #endif /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */ #ifdef GTS_SUPPORT case GTSREQUEST: mac_process_gts_request(b_ptr); processed_in_not_transient = true; #endif /* GTS_SUPPORT */ default: break; } } break; case FCF_FRAMETYPE_DATA: mac_process_data_frame(b_ptr); processed_in_not_transient = true; break; #if (MAC_PAN_ID_CONFLICT_AS_PC == 1) case FCF_FRAMETYPE_BEACON: /* PAN-Id conflict detection as PAN-Coordinator. */ /* Node is not scanning. */ check_for_pan_id_conflict_as_pc(false); break; #endif /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */ default: break; } } break; /* MAC_PAN_COORD_STARTED */ #endif /* (MAC_START_REQUEST_CONFIRM == 1) */ case MAC_IDLE: #if (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) case MAC_ASSOCIATED: #endif /* (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) */ #if (MAC_START_REQUEST_CONFIRM == 1) case MAC_COORDINATOR: #endif /* (MAC_START_REQUEST_CONFIRM == 1) */ { /* Is it a Beacon from our parent? */ switch (mac_parse_data.frame_type) { #if (MAC_SYNC_REQUEST == 1) case FCF_FRAMETYPE_BEACON: { uint32_t beacon_tx_time_symb; /* Check for PAN-Id conflict being NOT a PAN * Corodinator. */ #if (MAC_PAN_ID_CONFLICT_NON_PC == 1) if (mac_pib.mac_AssociatedPANCoord && (MAC_IDLE != mac_state)) { check_for_pan_id_conflict_non_pc(false); } #endif /* (MAC_PAN_ID_CONFLICT_NON_PC == 1) */ /* Check if the beacon is received from my * parent. */ if ((mac_parse_data.src_panid == tal_pib.PANId) && (((mac_parse_data.src_addr_mode == FCF_SHORT_ADDR) && (mac_parse_data.src_addr. short_address == mac_pib.mac_CoordShortAddress)) || ((mac_parse_data.src_addr_mode == FCF_LONG_ADDR) && (mac_parse_data.src_addr. long_address == mac_pib.mac_CoordExtendedAddress)))) { beacon_tx_time_symb = TAL_CONVERT_US_TO_SYMBOLS( f_ptr->time_stamp); #if (_DEBUG_ > 0) retval_t set_status = #endif set_tal_pib_internal(macBeaconTxTime, (void *)&beacon_tx_time_symb); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif if ((MAC_SYNC_TRACKING_BEACON == mac_sync_state) || (MAC_SYNC_BEFORE_ASSOC == mac_sync_state) ) { uint32_t nxt_bcn_tm; uint32_t beacon_int_symb; /* Process a received beacon. */ mac_process_beacon_frame(b_ptr); /* Initialize beacon tracking * timer. */ { retval_t tmr_start_res = FAILURE; #ifdef BEACON_SUPPORT if (tal_pib.BeaconOrder < NON_BEACON_NWK) { beacon_int_symb = TAL_GET_BEACON_INTERVAL_TIME( tal_pib.BeaconOrder); } else #endif /* BEACON_SUPPORT */ { beacon_int_symb = TAL_GET_BEACON_INTERVAL_TIME( BO_USED_FOR_MAC_PERS_TIME); } pal_timer_stop( T_Beacon_Tracking_Period); #if (_DEBUG_ > 0) if (pal_is_timer_running( T_Beacon_Tracking_Period)) { Assert( "Bcn tmr running" == 0); } #endif do { /* * Calculate the * time for next * beacon * transmission */ beacon_tx_time_symb = tal_add_time_symbols( beacon_tx_time_symb, beacon_int_symb); /* * Take into * account the * time taken by * the radio to * wakeup from * sleep state */ nxt_bcn_tm = tal_sub_time_symbols( beacon_tx_time_symb, TAL_RADIO_WAKEUP_TIME_SYM << ( tal_pib . BeaconOrder + 2)); tmr_start_res = pal_timer_start( T_Beacon_Tracking_Period, TAL_CONVERT_SYMBOLS_TO_US( nxt_bcn_tm), TIMEOUT_ABSOLUTE, ( FUNC_PTR)mac_t_tracking_beacons_cb, NULL); } while (MAC_SUCCESS != tmr_start_res); #ifdef GTS_DEBUG port_pin_toggle_output_level( DEBUG_PIN1); port_pin_set_output_level( DEBUG_PIN2, 0); #endif } /* * Initialize superframe timer * if required only * for devices because * Superframe timer is already * running for * coordinator. */ /* TODO */ if (MAC_ASSOCIATED == mac_state) { mac_superframe_state = MAC_ACTIVE_CAP; /* Check whether the * radio needs to be * woken up. */ mac_trx_wakeup(); /* Set transceiver in rx * mode, otherwise it * may stay in * TRX_OFF). */ tal_rx_enable(PHY_RX_ON); if (tal_pib. SuperFrameOrder < tal_pib . BeaconOrder) { pal_timer_start( T_Superframe, TAL_CONVERT_SYMBOLS_TO_US( TAL_GET_SUPERFRAME_DURATION_TIME( tal_pib . SuperFrameOrder)), TIMEOUT_RELATIVE, ( FUNC_PTR)mac_t_start_inactive_device_cb, NULL); #ifdef GTS_DEBUG port_pin_set_output_level( DEBUG_PIN2, 1); #endif } #ifdef GTS_SUPPORT if (mac_final_cap_slot < FINAL_CAP_SLOT_DEFAULT) { uint32_t gts_tx_time = ( TAL_CONVERT_SYMBOLS_TO_US( TAL_GET_SUPERFRAME_DURATION_TIME( tal_pib . SuperFrameOrder)) >> 4) * ( mac_final_cap_slot + 1); pal_timer_start( T_CAP, gts_tx_time, TIMEOUT_RELATIVE, ( FUNC_PTR)mac_t_gts_cb, NULL); #ifdef GTS_DEBUG port_pin_set_output_level( DEBUG_PIN3, 1); #endif } #endif /* GTS_SUPPORT */ } /* Initialize missed beacon * timer. */ mac_start_missed_beacon_timer(); /* A device that is neither * scanning nor polling shall go * to sleep now. */ if ( (MAC_COORDINATOR != mac_state) && (MAC_SCAN_IDLE == mac_scan_state) && (MAC_POLL_IDLE == mac_poll_state) ) { /* * If the last received * beacon frame from our * parent * has indicated pending * broadbast data, we * need to * stay awake, until the * broadcast data has * been received. */ if (! mac_bc_data_indicated) { /* Set radio to * sleep if * allowed */ mac_sleep_trans(); } } } else if (MAC_SYNC_ONCE == mac_sync_state) { mac_process_beacon_frame(b_ptr); /* Do this after processing the * beacon. */ mac_sync_state = MAC_SYNC_NEVER; /* A device that is neither * scanning nor polling shall go * to sleep now. */ if ( (MAC_COORDINATOR != mac_state) && (MAC_SCAN_IDLE == mac_scan_state) && (MAC_POLL_IDLE == mac_poll_state) ) { /* * If the last received * beacon frame from our * parent * has indicated pending * broadbast data, we * need to * stay awake, until the * broadcast data has * been received. */ if (! mac_bc_data_indicated) { /* Set radio to * sleep if * allowed */ mac_sleep_trans(); } } } else { /* Process the beacon frame */ bmm_buffer_free(b_ptr); } processed_in_not_transient = true; } else {
/* * @brief Continues handling of MLME_SCAN.request once the radio is awake * * @param scan_buf Pointer to Scan request buffer. */ static void mac_awake_scan(buffer_t *scan_buf) { mlme_scan_conf_t *msc; msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER(scan_buf); /* Set the first channel at which the scan is started */ scan_curr_channel = MIN_CHANNEL; switch (scan_type) { #if (MAC_SCAN_ED_REQUEST_CONFIRM == 1) case MLME_SCAN_TYPE_ED: msc->scan_result_list[0].ed_value[1] = 0; /* First channel's * accumulated energy * level */ mac_scan_state = MAC_SCAN_ED; scan_proceed(MLME_SCAN_TYPE_ED, (buffer_t *)scan_buf); break; #endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */ #if ((MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) || \ (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1)) case MLME_SCAN_TYPE_ACTIVE: case MLME_SCAN_TYPE_PASSIVE: { /* * Before commencing an active or passive scan, the MAC sublayer * shall store the value of macPANId and then set it to 0cFFFF * for * the duration of the scan. This enables the receive filter to * accept all beacons rather than just the beacons from its * current PAN (see 7.5.6.2). On completion of the scan, the * MAC sublayer shall restore the value of macPANId to the * value stored before the scan began. */ uint16_t broadcast_panid = BROADCAST; mac_scan_orig_panid = tal_pib.PANId; #if (_DEBUG_ > 0) retval_t set_status = #endif set_tal_pib_internal(macPANId, (void *)&broadcast_panid); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); set_status = set_status; #endif if (MLME_SCAN_TYPE_ACTIVE == scan_type) { /* * In active scan reuse the scan request buffer for * sending beacon request. */ mac_scan_cmd_buf_ptr = (uint8_t *)scan_buf; } /* Allocate a large size buffer for scan confirm. */ mac_conf_buf_ptr = (uint8_t *)bmm_buffer_alloc(LARGE_BUFFER_SIZE); if (NULL == mac_conf_buf_ptr) { /* * Large buffer is not available for sending scan * confirmation, * hence the scan request buffer (small buffer) is used * to send * the scan confirmation. */ msc->status = MAC_INVALID_PARAMETER; /* Append scan confirm message to the MAC-NHLE queue */ qmm_queue_append(&mac_nhle_q, scan_buf); /* Set radio to sleep if allowed */ mac_sleep_trans(); return; } if (MLME_SCAN_TYPE_PASSIVE == scan_type) { /* Free the scan request buffer when in passive scan. */ bmm_buffer_free(scan_buf); } msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER( (buffer_t *)mac_conf_buf_ptr); msc->cmdcode = MLME_SCAN_CONFIRM; msc->ScanType = scan_type; msc->ChannelPage = scan_curr_page; msc->UnscannedChannels = scan_channels; msc->ResultListSize = 0; msc->scan_result_list[0].ed_value[0] = 0; scan_proceed(scan_type, (buffer_t *)mac_conf_buf_ptr); break; } #endif /* ((MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) || *(MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1)) */ #if (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) case MLME_SCAN_TYPE_ORPHAN: /* Buffer allocated for orphan notification command */ mac_scan_cmd_buf_ptr = (uint8_t *)bmm_buffer_alloc(LARGE_BUFFER_SIZE); if (NULL == mac_scan_cmd_buf_ptr) { msc->status = MAC_INVALID_PARAMETER; /* Append scan confirm message to the MAC-NHLE queue */ qmm_queue_append(&mac_nhle_q, scan_buf); /* Set radio to sleep if allowed */ mac_sleep_trans(); return; } scan_proceed(MLME_SCAN_TYPE_ORPHAN, (buffer_t *)mac_conf_buf_ptr); break; #endif /* (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) */ default: msc->status = MAC_INVALID_PARAMETER; /* Append scan confirm message to the MAC-NHLE queue */ qmm_queue_append(&mac_nhle_q, scan_buf); /* Set radio to sleep if allowed */ mac_sleep_trans(); break; } } /* mac_awake_scan() */
/* * @brief Proceed with a scan request * * This function proceeds with the scanning. * The current channel is incremented. It is checked if it belongs to the * list of channels to scan. If so, start scanning. If all channels done, * send out the MLME_SCAN.confirm message. * * @param scanning_type The type of the scan operation to proceed with. * @param buf Buffer to send mlme scan confirm to NHLE. */ static void scan_proceed(uint8_t scanning_type, buffer_t *buf) { retval_t set_status; mlme_scan_conf_t *msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER(buf); /* Set the channel page to perform scan */ set_status = set_tal_pib_internal(phyCurrentPage, (void *)&scan_curr_page); /* Loop over all channels the MAC has been requested to scan */ for (; scan_curr_channel <= MAX_CHANNEL; scan_curr_channel++) { #if ((MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) || \ (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1)) if ( ((MAC_SCAN_ACTIVE == mac_scan_state) || (MAC_SCAN_PASSIVE == mac_scan_state)) && mac_pib.mac_AutoRequest ) { /* * For active or passive scans, bail out if we * reached our maximum number of PANDescriptors that * could * be stored. That way, the upper layer will get the * correct set of unscanned channels returned, so it can * continue scanning if desired. * * According to 802.15.4-2006 PAN descriptor are only * present * in the scan confirm message in case the PIB attribute * macAutoRequest is true. */ if (msc->ResultListSize >= MAX_PANDESCRIPTORS) { break; } } #endif /* ((MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) || *(MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1)) */ #if (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) if (MLME_SCAN_TYPE_ORPHAN == scanning_type) { /* * In an orphan scan, terminate if any coordinator * realignment packet has been received. */ if (msc->ResultListSize) { break; } } #endif /* (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) */ if ((msc->UnscannedChannels & (1UL << scan_curr_channel)) != 0) { #if (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) if (MLME_SCAN_TYPE_ACTIVE == scanning_type) { mac_scan_state = MAC_SCAN_ACTIVE; } #endif /* (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) if (MLME_SCAN_TYPE_PASSIVE == scanning_type) { mac_scan_state = MAC_SCAN_PASSIVE; } #endif /* (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) */ if (MLME_SCAN_TYPE_ORPHAN == scanning_type) { mac_scan_state = MAC_SCAN_ORPHAN; } /* Set the channel to perform scan */ set_status = set_tal_pib_internal(phyCurrentChannel, (void *)&scan_curr_channel); if (MAC_SUCCESS != set_status) { /* * Free the buffer used for sending orphan * notification command */ bmm_buffer_free((buffer_t *)mac_scan_cmd_buf_ptr); mac_scan_cmd_buf_ptr = NULL; /* Set radio to sleep if allowed */ mac_sleep_trans(); msc->status = MAC_NO_BEACON; /* Orphan scan does not return any list. */ msc->ResultListSize = 0; /* Append the scan confirm message to the * MAC-NHLE queue */ qmm_queue_append(&mac_nhle_q, buf); mac_scan_state = MAC_SCAN_IDLE; } #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif /* Continue scanning, after setting channel */ scan_set_complete(set_status); return; } } /* All channels were scanned. The confirm needs to be prepared */ switch (scanning_type) { #if (MAC_SCAN_ED_REQUEST_CONFIRM == 1) case MLME_SCAN_TYPE_ED: msc->status = MAC_SUCCESS; scan_clean_up(buf); break; #endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) case MLME_SCAN_TYPE_ACTIVE: { /* * Free the buffer which was received from scan request and * reused * for beacon request frame transmission. */ bmm_buffer_free((buffer_t *)mac_scan_cmd_buf_ptr); mac_scan_cmd_buf_ptr = NULL; if (!mac_pib.mac_AutoRequest) { msc->status = MAC_SUCCESS; } else if (msc->ResultListSize >= MAX_PANDESCRIPTORS) { msc->status = MAC_LIMIT_REACHED; } else if (msc->ResultListSize) { msc->status = MAC_SUCCESS; } else { msc->status = MAC_NO_BEACON; } /* Restore macPANId after active scan completed. */ #if (_DEBUG_ > 0) set_status = #endif set_tal_pib_internal(macPANId, (void *)&mac_scan_orig_panid); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif /* Done with scanning */ scan_clean_up((buffer_t *)mac_conf_buf_ptr); } break; #endif /* (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) case MLME_SCAN_TYPE_PASSIVE: if (!mac_pib.mac_AutoRequest) { msc->status = MAC_SUCCESS; } else if (msc->ResultListSize >= MAX_PANDESCRIPTORS) { msc->status = MAC_LIMIT_REACHED; } else if (msc->ResultListSize) { msc->status = MAC_SUCCESS; } else { msc->status = MAC_NO_BEACON; } /* Restore macPANId after passive scan completed. */ #if (_DEBUG_ > 0) set_status = #endif set_tal_pib_internal(macPANId, (void *)&mac_scan_orig_panid); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif scan_clean_up(buf); break; #endif /* (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) case MLME_SCAN_TYPE_ORPHAN: /* Free the buffer used for sending orphan notification command **/ bmm_buffer_free((buffer_t *)mac_scan_cmd_buf_ptr); mac_scan_cmd_buf_ptr = NULL; if (msc->ResultListSize > 0) { msc->status = MAC_SUCCESS; } else { msc->status = MAC_NO_BEACON; } /* Orphan scan does not return any list. */ msc->ResultListSize = 0; scan_clean_up(buf); break; #endif /* (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) */ default: break; } } /* scan_proceed() */
/** * @brief Processing a coordinator realignment command frame during Orphan scan * * This function processes a coordinator realignment command frame received * as a response to the reception of an orphan notification * command frame (i.e. while being in the middle of an orphan scan procedure). * The PAN ID, coord. short address, logical channel, and the device's new * short address will be written to the PIB. * * @param ind Frame reception buffer */ void mac_process_orphan_realign(buffer_t *buf_ptr) { retval_t set_status; /* Device received a coordinator realignment during an orphan scan */ /* Free the buffer used for sending orphan notification command */ bmm_buffer_free((buffer_t *)mac_scan_cmd_buf_ptr); mac_scan_cmd_buf_ptr = NULL; /* * Scan confirm with scan type orphan is given to the NHLE using the * scan request buffer, which was stored in mac_conf_buf_ptr. */ mlme_scan_conf_t *msc = (mlme_scan_conf_t *)BMM_BUFFER_POINTER( (buffer_t *)mac_conf_buf_ptr); msc->cmdcode = MLME_SCAN_CONFIRM; msc->status = MAC_SUCCESS; msc->ScanType = MLME_SCAN_TYPE_ORPHAN; msc->UnscannedChannels = 0; msc->ResultListSize = 0; /* Append the scan confirmation message to the MAC-NHLE queue */ qmm_queue_append(&mac_nhle_q, (buffer_t *)mac_conf_buf_ptr); mac_scan_state = MAC_SCAN_IDLE; /* Set radio to sleep if allowed */ mac_sleep_trans(); /* * The buffer in which the coordinator realignment is received is * freed up */ bmm_buffer_free(buf_ptr); /* Set the appropriate PIB entries */ set_status = set_tal_pib_internal(macPANId, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.pan_id); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif if (BROADCAST != mac_parse_data.mac_payload_data.coord_realign_data. short_addr) { /* Short address only to be set if not broadcast address */ set_status = set_tal_pib_internal(macShortAddress, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.short_addr); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif } mac_pib.mac_CoordShortAddress = mac_parse_data.mac_payload_data.coord_realign_data. coord_short_addr; /* * If frame version subfield indicates a 802.15.4-2006 compatible frame, * the channel page is appended as additional information element. */ if (mac_parse_data.fcf & FCF_FRAME_VERSION_2006) { set_status = set_tal_pib_internal(phyCurrentPage, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.channel_page); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif } set_status = set_tal_pib_internal(phyCurrentChannel, (void *)&mac_parse_data.mac_payload_data.coord_realign_data.logical_channel); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif scan_set_complete(set_status); } /* mac_process_orphan_realign() */