Example #1
0
/**
 * @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();
}
Example #2
0
/*
 * @brief Timer function after sync request to wake up radio at beacon time
 *
 * This function is a callback from the tracking beacon timer and implements
 * the RX timer service  function during sync and enables the receiver before
 * the next beacon reception is expected.
 *
 * @param callback_parameter Callback parameter of the expired beacon
 *                           tracking timer
 */
void mac_t_tracking_beacons_cb(void *callback_parameter)
{
    /* Wake up radio first */
    mac_trx_wakeup();

     /* Turn the radio on */
    tal_rx_enable(PHY_RX_ON);

    callback_parameter = callback_parameter;  /* Keep compiler happy. */
}
Example #3
0
/*
 * @brief Continues handling of MLME-RX-ENABLE.request by
 * waking radio up and setting it into rx on state.
 *
 * @param rxe_buff_ptr Pointer to the MLME-RX-ENABLE buffer allocated by the
 * NHLE.
 */
static uint8_t mac_rx_enable()
{
	uint8_t status;

	/* Wake up the radio first */
	mac_trx_wakeup();

	/* Turn the receiver on immediately. */
	status = tal_rx_enable(PHY_RX_ON);

	/* Rx is enabled */
	mac_rx_enabled = true;

	return (status);
} /* mac_rx_enable() */
Example #4
0
/**
 * @brief Wakes-up the radio and sets the corresponding TAL PIB attribute
 *
 * @param attribute PIB attribute to be set
 * @param attribute_value Attribute value to be set
 *
 * @return Status of the attempt to set the TAL PIB attribute
 */
retval_t set_tal_pib_internal(uint8_t attribute, pib_value_t *attribute_value)
{
	retval_t status;

	if (RADIO_SLEEPING == mac_radio_sleep_state) {
		/* Wake up the radio */
		mac_trx_wakeup();

		status = tal_pib_set(attribute, attribute_value);

		/* Set radio to sleep if allowed */
		mac_sleep_trans();
	} else {
		status = tal_pib_set(attribute, attribute_value);
	}

	return status;
}
Example #5
0
/**
 * @brief Resets the MAC layer
 *
 * The MLME-RESET.request primitive allows the next higher layer to request
 * that the MLME performs a reset operation.
 *
 * @param m Pointer to the MLME_RESET.request given by the NHLE
 */
void mlme_reset_request(uint8_t *m)
{
	mlme_reset_req_t *mrr
		= (mlme_reset_req_t *)BMM_BUFFER_POINTER((buffer_t *)m);

	/* Wakeup the radio */
	mac_trx_wakeup();

	/* Start MAC reset functionality */
	uint8_t status = mac_reset(mrr->SetDefaultPIB);

	/* Set radio to sleep if allowed */
	mac_sleep_trans();

	/*
	 * As this is a mlme_reset request, all the requests, data (whether
	 * direct
	 * or indirect), incoming frames are removed from the queues
	 */
	flush_queues();

	send_reset_conf((buffer_t *)m, status);
} /* mlme_reset_request() */
Example #6
0
/*
 * @brief The MLME-GTS.request primitive makes a request for device to
 * request for GTS or on PANC to allocate or deallocate a GTS for itself
 * or other devices
 *
 * 802.15.4. Section 7.1.7.1.
 *
 * @param m The MLME-GTS.request message.
 */
void mlme_gts_request(uint8_t *m)
{
    mlme_gts_req_t mgr;
    memcpy(&mgr, BMM_BUFFER_POINTER((buffer_t *)m),
           sizeof(mlme_gts_req_t));

    if (MAC_NO_SHORT_ADDR_VALUE <= tal_pib.ShortAddress ||
            (MAC_NO_SHORT_ADDR_VALUE <=
             mac_pib.mac_CoordShortAddress &&
             MAC_PAN_COORD_STARTED != mac_state)) {
        mac_gen_mlme_gts_conf((buffer_t *)m, MAC_NO_SHORT_ADDRESS,
                              mgr.GtsChar);
        return;
    } else if (true != mac_pib.mac_GTSPermit    ||
               (0 == mgr.GtsChar.GtsLength) ||
               (MAC_ASSOCIATED == mac_state &&
                (mgr.DeviceShortAddr != tal_pib.ShortAddress ||
                 MAC_SYNC_TRACKING_BEACON != mac_sync_state ||
                 (mgr.GtsChar.GtsCharType == GTS_DEALLOCATE &&
                  (!mac_dev_gts_table[mgr.GtsChar.GtsDirection].
                   GtsStartingSlot ||
                   mgr.GtsChar.GtsLength !=
                   mac_dev_gts_table[mgr.GtsChar.GtsDirection].GtsLength))
                )
               )
              ) {
        mac_gen_mlme_gts_conf((buffer_t *)m, MAC_INVALID_PARAMETER,
                              mgr.GtsChar);
        return;
    }

#ifdef FFD
    else if (MAC_PAN_COORD_STARTED == mac_state) {
        if (GTS_ALLOCATE & mgr.GtsChar.GtsCharType) {
            if (mac_gts_allocate(mgr.GtsChar,
                                 mgr.DeviceShortAddr)) {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_SUCCESS,
                                      mgr.GtsChar);
                return;
            } else {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_NO_DATA,
                                      mgr.GtsChar);
                return;
            }
        } else {
            if (mac_gts_deallocate(mgr.GtsChar, mgr.DeviceShortAddr,
                                   true)) {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_SUCCESS,
                                      mgr.GtsChar);
                return;
            } else {
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_NO_DATA,
                                      mgr.GtsChar);
                return;
            }
        }
    }
#endif /* FFD */
    else if (MAC_ASSOCIATED == mac_state) {
        frame_info_t *transmit_frame
            = (frame_info_t *)BMM_BUFFER_POINTER((buffer_t *)m);

        mac_trx_wakeup();

        /* Build the GTS Request command frame. */
        uint8_t tal_tx_status;
        uint8_t frame_len;
        uint8_t *frame_ptr;
        uint8_t *temp_frame_ptr;
        uint16_t fcf;

        /*
         * Use the mlme gts request buffer for transmitting
         * gts request frame.
         */
        frame_info_t *gts_req_frame
            = (frame_info_t *)(BMM_BUFFER_POINTER((buffer_t *)m));

        gts_req_frame->msg_type = GTSREQUEST;
        gts_req_frame->buffer_header = (buffer_t *)m;

        /* Get the payload pointer. */
        frame_ptr = temp_frame_ptr
                    = (uint8_t *)gts_req_frame +
                      LARGE_BUFFER_SIZE -
                      GTS_REQ_PAYLOAD_LEN - 2; /* Add
		                                                          *2
		                                                          *octets
		                                                          *for
		                                                          *FCS.
		                                                          **/

        /* Update the payload field. */
        *frame_ptr++ = GTSREQUEST;
        /* Build the GTS characteristics info. */
        *frame_ptr = *((uint8_t *)&mgr.GtsChar);

        /* Get the payload pointer again to add the MHR. */
        frame_ptr = temp_frame_ptr;

        /* Update the length. */
        frame_len = GTS_REQ_PAYLOAD_LEN +
                    2 + /* Add 2 octets for FCS */
                    2 + /* 2 octets for Destination PAN-Id */
                    2 + /* 2 octets for short Destination Address */
                    2 + /* 2 octets for short Source Address */
                    3; /* 3 octets DSN and FCF */

        /* Source address */
        frame_ptr -= 2;

        convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr);

        frame_ptr -= 2;
        convert_16_bit_to_byte_array(mac_pib.mac_CoordShortAddress,
                                     frame_ptr);

        fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) |
              FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) |
              FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) |
              FCF_ACK_REQUEST | FCF_PAN_ID_COMPRESSION;

        /* Destination PAN-Id */
        frame_ptr -= 2;
        convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr);

        /* Set DSN. */
        frame_ptr--;
        *frame_ptr = mac_pib.mac_DSN++;

        /* Set the FCF. */
        frame_ptr -= 2;
        convert_spec_16_bit_to_byte_array(fcf, frame_ptr);

        /* First element shall be length of PHY frame. */
        frame_ptr--;
        *frame_ptr = frame_len;

        /* Finished building of frame. */
        gts_req_frame->mpdu = frame_ptr;

        tal_tx_status
            = tal_tx_frame(transmit_frame, CSMA_SLOTTED, true);

        if (MAC_SUCCESS == tal_tx_status) {
            uint8_t update_index = mgr.GtsChar.GtsDirection;

            if (mgr.DeviceShortAddr ==
                    mac_pib.mac_CoordShortAddress) {
                update_index |= 0x02;
            }

            if (GTS_DEALLOCATE == mgr.GtsChar.GtsCharType) {
                mac_dev_gts_table[update_index].GtsLength
                    = 0;
                mac_dev_gts_table[update_index].GtsStartingSlot
                    = 0;
                mac_dev_gts_table[update_index].GtsState
                    = GTS_STATE_IDLE;
                mac_gen_mlme_gts_conf((buffer_t *)m,
                                      MAC_SUCCESS, mgr.GtsChar);
                return;
            } else {
                mac_dev_gts_table[update_index].GtsReq_ptr = m;
                mac_dev_gts_table[update_index].GtsState
                    = GTS_STATE_REQ_SENT;
                mac_dev_gts_table[update_index].GtsPersistCount
                    = aGTSDescPersistenceTime;
                mac_dev_gts_table[update_index].GtsLength
                    = mgr.GtsChar.GtsLength;
                MAKE_MAC_BUSY();
            }
        } else {
            mac_gen_mlme_gts_conf((buffer_t *)m, tal_tx_status,
                                  mgr.GtsChar);
        }
    } else {
        mac_gen_mlme_gts_conf((buffer_t *)m, MAC_INVALID_PARAMETER,
                              mgr.GtsChar);
    }
    return;
}
Example #7
0
File: mac_start.c Project: bswe/6.1
/**
 * @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();
        }
    }
}
Example #8
0
/**
 * @brief Implements MLME-POLL.request
 *
 * This function handles an MLME-POLL.request primitive.
 * The MLME-POLL.request primitive is generated by the next
 * higher layer and issued to its MLME when data are to be
 * requested from a coordinator.
 *
 * @param m Pointer to the message
 */
void mlme_poll_request(uint8_t *m)
{
	/*
	 * Polling for data is only allowed, if the node
	 * 1) is not a PAN coordinator,
	 * 2) is not polling already, and
	 * 3) is not scanning.
	 */
	if (
		(MAC_POLL_IDLE == mac_poll_state) &&
#if (MAC_START_REQUEST_CONFIRM == 1)
		(MAC_PAN_COORD_STARTED != mac_state) &&
#endif  /* MAC_START_REQUEST_CONFIRM == 1) */
		(MAC_SCAN_IDLE == mac_scan_state)
		) {
		bool status;
		address_field_t coord_addr;

		/* Wake up radio first */
		mac_trx_wakeup();

		/*
		 * Extract the Coordinator address information from the Poll
		 * request.
		 * This is required later for building the proper destination
		 * address
		 * information in the data request frame.
		 */
		mlme_poll_req_t *msg
			= (mlme_poll_req_t *)BMM_BUFFER_POINTER((buffer_t
				*)m);

		{
			uint8_t data_req_addr_mode;

			if (msg->CoordAddrMode == FCF_SHORT_ADDR) {
				data_req_addr_mode = FCF_SHORT_ADDR;
				ADDR_COPY_DST_SRC_16(coord_addr.short_address,
						msg->CoordAddress);
			} else {
				data_req_addr_mode = FCF_LONG_ADDR;
				ADDR_COPY_DST_SRC_64(coord_addr.long_address,
						msg->CoordAddress);
			}

			/* Build and transmit data request frame due to explicit
			 * poll request */
			status = mac_build_and_tx_data_req(true,
					false,
					data_req_addr_mode,
					&coord_addr,
					msg->CoordPANId);
		}

		if (status) {
			/* Store the poll request buffer to give poll confirm */
			mac_conf_buf_ptr = m;
		} else {
			gen_mlme_poll_conf((buffer_t *)m,
					MAC_CHANNEL_ACCESS_FAILURE);
		}
	} else {
		gen_mlme_poll_conf((buffer_t *)m, MAC_CHANNEL_ACCESS_FAILURE);
	}
}
Example #9
0
/**
 * @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);
}
Example #10
0
retval_t mlme_set(uint8_t attribute, pib_value_t *attribute_value,
		bool set_trx_to_sleep)
#endif
{
	/*
	 * Variables indicates whether the transceiver has been woken up for
	 * setting a TAL PIB attribute.
	 */
	static bool trx_pib_wakeup;

	retval_t status = MAC_SUCCESS;

	switch (attribute) {
#if (MAC_ASSOCIATION_REQUEST_CONFIRM == 1)
	case macAssociatedPANCoord:
		mac_pib.mac_AssociatedPANCoord
			= attribute_value->pib_value_8bit;
		break;
#endif /* (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) */

#if ((MAC_INDIRECT_DATA_BASIC == 1) || defined(BEACON_SUPPORT))
	case macMaxFrameTotalWaitTime:
		mac_pib.mac_MaxFrameTotalWaitTime
			= attribute_value->pib_value_16bit;
		break;
#endif  /* ((MAC_INDIRECT_DATA_BASIC == 1) || defined(BEACON_SUPPORT)) */

	case macResponseWaitTime:
		mac_pib.mac_ResponseWaitTime = attribute_value->pib_value_16bit;
		break;

	case macAutoRequest:
#if (MAC_BEACON_NOTIFY_INDICATION == 1)

		/*
		 * If the beacon notification indications are not included
		 * in the build, macAutoRequest can be changed as desired, since
		 * beacon frames will be indicated to the higher
		 * layer if required as defined by IEEE 802.15.4.
		 */
		mac_pib.mac_AutoRequest = attribute_value->pib_value_8bit;
		break;
#else

		/*
		 * If the beacon notification indications are not included
		 * in the build, macAutoRequest must not be changed, since
		 * beacon frames will never be indicated to the higher
		 * layer, i.e. the higher would not be able to act on
		 * received beacon frame information itself.
		 */
		status = MAC_INVALID_PARAMETER;
		break;
#endif  /* (MAC_BEACON_NOTIFY_INDICATION == 1) */

#ifdef GTS_SUPPORT
	case macGTSPermit:
		mac_pib.mac_GTSPermit
			= attribute_value->pib_value_8bit;
		break;
#endif /* GTS_SUPPORT */

	case macBattLifeExtPeriods:
		mac_pib.mac_BattLifeExtPeriods
			= attribute_value->pib_value_8bit;
		break;

#if (MAC_ASSOCIATION_INDICATION_RESPONSE == 1)
	case macAssociationPermit:
		mac_pib.mac_AssociationPermit = attribute_value->pib_value_8bit;
		break;
#endif /* (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) */

#if (MAC_START_REQUEST_CONFIRM == 1)
	case macBeaconPayload:
		memcpy(mac_beacon_payload, attribute_value,
				mac_pib.mac_BeaconPayloadLength);
		break;

	case macBeaconPayloadLength:
#ifndef REDUCED_PARAM_CHECK

		/*
		 * If the application sits directly  on top of the MAC,
		 * this is also checked in mac_api.c.
		 */
		if (attribute_value->pib_value_8bit > aMaxBeaconPayloadLength) {
			status = MAC_INVALID_PARAMETER;
			break;
		}
#endif  /* REDUCED_PARAM_CHECK */
		mac_pib.mac_BeaconPayloadLength
			= attribute_value->pib_value_8bit;
		break;

	case macBSN:
		mac_pib.mac_BSN = attribute_value->pib_value_8bit;
		break;
#endif  /* (MAC_START_REQUEST_CONFIRM == 1) */

#if (MAC_INDIRECT_DATA_FFD == 1)
	case macTransactionPersistenceTime:
		mac_pib.mac_TransactionPersistenceTime
			= attribute_value->pib_value_16bit;
		break;
#endif /* (MAC_INDIRECT_DATA_FFD == 1) */
	case macCoordExtendedAddress:
		mac_pib.mac_CoordExtendedAddress
			= attribute_value->pib_value_64bit;
		break;

	case macCoordShortAddress:
		mac_pib.mac_CoordShortAddress
			= attribute_value->pib_value_16bit;
		break;

	case macDSN:
		mac_pib.mac_DSN = attribute_value->pib_value_8bit;
		break;

	case macRxOnWhenIdle:
		mac_pib.mac_RxOnWhenIdle = attribute_value->pib_value_8bit;
		/* Check whether radio state needs to change now, */
		if (mac_pib.mac_RxOnWhenIdle) {
			/* 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);
		} else {
			/* Check whether the radio needs to be put to sleep. */
			mac_sleep_trans();
		}

		break;

	case macBattLifeExt:
	case macBeaconOrder:
	case macMaxCSMABackoffs:
	case macMaxBE:
	case macMaxFrameRetries:
	case macMinBE:
	case macPANId:
#ifdef PROMISCUOUS_MODE
	case macPromiscuousMode:
#endif /* PROMISCUOUS_MODE */
	case macShortAddress:
	case macSuperframeOrder:
	case macIeeeAddress:
	case phyCurrentChannel:
	case phyCurrentPage:
	case phyTransmitPower:
	case phyCCAMode:
#ifdef TEST_HARNESS
	case macPrivateCCAFailure:
	case macPrivateDisableACK:
#endif /* TEST_HARNESS */
		{
			/* Now only TAL PIB attributes are handled anymore. */
			status = tal_pib_set(attribute, attribute_value);

			if (status == TAL_TRX_ASLEEP) {
				/*
				 * Wake up the transceiver and repeat the
				 * attempt
				 * to set the TAL PIB attribute.
				 */
				tal_trx_wakeup();
				status
					= tal_pib_set(attribute,
						attribute_value);
				if (status == MAC_SUCCESS) {
					/*
					 * Set flag indicating that the trx has
					 * been woken up
					 * during PIB setting.
					 */
					trx_pib_wakeup = true;
				}
			}

#if ((MAC_INDIRECT_DATA_BASIC == 1) || defined(BEACON_SUPPORT))

			/*
			 * In any case that the PIB setting was successful (no
			 * matter
			 * whether the trx had to be woken up or not), the PIB
			 * attribute
			 * recalculation needs to be done.
			 */
			if (status == MAC_SUCCESS) {
				/*
				 * The value of the PIB attribute
				 * macMaxFrameTotalWaitTime depends on the
				 * values of the
				 * following PIB attributes:
				 * macMinBE
				 * macMaxBE
				 * macMaxCSMABackoffs
				 * phyMaxFrameDuration
				 * In order to save code space and since
				 * changing of PIB
				 * attributes is going to happen not too often,
				 * this is done
				 * always whenever a PIB attribute residing in
				 * TAL is changed
				 * (since all above mentioned PIB attributes are
				 * in TAL).
				 */
				recalc_macMaxFrameTotalWaitTime();
			}
#endif  /* ((MAC_INDIRECT_DATA_BASIC == 1) || defined(BEACON_SUPPORT)) */
		}
		break;

	case macAckWaitDuration:
	default:
		status = MAC_UNSUPPORTED_ATTRIBUTE;
		break;

#if ((defined MAC_SECURITY_ZIP)  || (defined MAC_SECURITY_2006))
	case macSecurityEnabled:
		mac_pib.mac_SecurityEnabled = attribute_value->pib_value_8bit;
		break;

	case macKeyTable:
		if (attribute_index >= mac_sec_pib.KeyTableEntries) {
			status = MAC_INVALID_INDEX;
		} else {
			memcpy(&mac_sec_pib.KeyTable[attribute_index],
					attribute_value,
					sizeof(mac_key_table_t));
		}

		break;

	case macKeyTableEntries:
		if (attribute_value->pib_value_8bit >
				MAC_ZIP_MAX_KEY_TABLE_ENTRIES) {
			status = MAC_INVALID_PARAMETER;
		} else {
			mac_sec_pib.KeyTableEntries
				= attribute_value->pib_value_8bit;
		}

		break;

	case macDeviceTable:
		if (attribute_index >= mac_sec_pib.DeviceTableEntries) {
			status = MAC_INVALID_INDEX;
		} else {
			uint8_t *attribute_temp_ptr
				= (uint8_t *)attribute_value;

			/*
			 * Since the members of the mac_dev_table_t structure do
			 * contain padding bytes,
			 * each member needs to be filled in separately.
			 */
			/* PAN-Id */
			memcpy((uint8_t *)&mac_sec_pib.DeviceTable[
						attribute_index].DeviceDescriptor[
						0].PANId,
					attribute_temp_ptr,
					sizeof(uint16_t));

			/*
			 *
			 *ADDR_COPY_DST_SRC_16(mac_sec_pib.DeviceTable[attribute_index].DeviceDescriptor[0].PANId,
			 *(uint16_t *)attribute_temp_ptr); */
			attribute_temp_ptr += sizeof(uint16_t);

			/* Short Address */
			memcpy((uint8_t *)&mac_sec_pib.DeviceTable[
						attribute_index].DeviceDescriptor[
						0].ShortAddress,
					attribute_temp_ptr,
					sizeof(uint16_t));

			/*ADDR_COPY_DST_SRC_16(mac_sec_pib.DeviceTable[attribute_index].DeviceDescriptor[0].ShortAddress,
			 *(uint16_t *)attribute_temp_ptr);*/
			attribute_temp_ptr += sizeof(uint16_t);

			/* Extended Address */
			memcpy((uint8_t *)&mac_sec_pib.DeviceTable[
						attribute_index].DeviceDescriptor[
						0].ExtAddress,
					attribute_temp_ptr,
					sizeof(uint64_t));

			/*ADDR_COPY_DST_SRC_64(mac_sec_pib.DeviceTable[attribute_index].DeviceDescriptor[0].ExtAddress,
			 *(uint64_t *)attribute_temp_ptr);*/
			attribute_temp_ptr += sizeof(uint64_t);

			/* Extended Address */
			memcpy(
					&mac_sec_pib.DeviceTable[attribute_index].DeviceDescriptor[
						0].FrameCounter,
					attribute_temp_ptr,
					sizeof(uint32_t));
			attribute_temp_ptr += sizeof(uint32_t);

			/* Exempt */
			mac_sec_pib.DeviceTable[attribute_index].
			DeviceDescriptor[0].Exempt
				= *attribute_temp_ptr;
		}

		break;

	case macDeviceTableEntries:
		if (attribute_value->pib_value_16bit >
				MAC_ZIP_MAX_DEV_TABLE_ENTRIES) {
			status = MAC_INVALID_PARAMETER;
		} else {
			mac_sec_pib.DeviceTableEntries
				= attribute_value->pib_value_16bit;
		}

		break;

	case macSecurityLevelTable:
		if (attribute_index >= mac_sec_pib.SecurityLevelTableEntries) {
			status = MAC_INVALID_INDEX;
		} else {
			memcpy(&mac_sec_pib.SecurityLevelTable[attribute_index],
					attribute_value,
					sizeof(mac_sec_lvl_table_t));
		}

		break;

	case macSecurityLevelTableEntries:
		if (attribute_value->pib_value_8bit >
				MAC_ZIP_MAX_SEC_LVL_TABLE_ENTRIES) {
			status = MAC_INVALID_PARAMETER;
		} else {
			mac_sec_pib.SecurityLevelTableEntries
				= attribute_value->pib_value_8bit;
		}

		break;

	case macFrameCounter:
		mac_sec_pib.FrameCounter = attribute_value->pib_value_32bit;
		break;

	case macDefaultKeySource:
		/* Key Source length is 8 octets. */
		memcpy(mac_sec_pib.DefaultKeySource, attribute_value, 8);
		break;

	case macPANCoordExtendedAddress:
		memcpy(mac_sec_pib.PANCoordExtendedAddress, attribute_value, 8);
		break;

	case macPANCoordShortAddress:
		mac_sec_pib.PANCoordShortAddress
			= attribute_value->pib_value_16bit;
		break;
#endif  /* (MAC_SECURITY_ZIP || MAC_SECURITY_2006) */

#ifdef TEST_HARNESS
	case macPrivateIllegalFrameType:
		mac_pib.privateIllegalFrameType
			= attribute_value->pib_value_8bit;
		break;

	case macPrivateNoDataAfterAssocReq:
		mac_pib.privateNoDataAfterAssocReq
			= attribute_value->pib_value_8bit;
		break;

	case macPrivateVirtualPANs:
		mac_pib.privateVirtualPANs = attribute_value->pib_value_8bit;
		break;
#endif /* TEST_HARNESS */
	}

	/*
	 * In case the transceiver shall be forced back to sleep and
	 * has been woken up, it is put back to sleep again.
	 */
	if (set_trx_to_sleep && trx_pib_wakeup && !mac_pib.mac_RxOnWhenIdle) {
#ifdef ENABLE_DEEP_SLEEP
		tal_trx_sleep(DEEP_SLEEP_MODE);
#else
		tal_trx_sleep(SLEEP_MODE_1);
#endif
		trx_pib_wakeup = false;
	}

	return status;
}
Example #11
0
/**
 * @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 {
Example #12
0
/**
 * @brief The MLME-SCAN.request primitive makes a request for a node to
 * start a scan procedure.
 *
 * 802.15.4. Section 7.1.11.1.
 *
 * The MLME-SCAN.request primitive is used to initiate a channel scan over a
 * given list of channels. A device can use a channel scan to measure the
 * energy on the channel, search for the coordinator with which it associated,
 * or search for all coordinators transmitting beacon frames within the
 * POS of the scanning device.
 *
 * The MLME-SCAN.request primitive is generated by the next higher layer and
 * issued to its MLME to initiate a channel scan to search for activity within
 * the POS of the device. This primitive can be used to perform an ED scan to
 * determine channel usage, an active or passive scan to locate beacon frames
 * containing any PAN identifier, or an orphan scan to locate a PAN to which
 * the device is currently associated.
 *
 * ED or active scans can be performed before an FFD starts operation as a
 * PAN coordinator. Active or passive scans can be performed prior to selecting
 * a PAN for association. Orphan scans can be performed to attempt to locate a
 * specific coordinator with which communication has been lost.
 *
 * All devices shall be capable of performing passive scans and orphan scans;
 * ED scans and active scans are optional for an RFD.
 *
 * When the MLME receives the MLME-SCAN.request primitive, it initiates a scan
 * in all channels specified in the ScanChannels parameter. The MLME suspends
 * all beacon transmissions for the duration of the scan. During a scan, the
 * MAC sublayer only accepts frames received over the PHY data service that are
 * relevant to the scan being performed (see 7.5.2.1).
 *
 * An ED scan allows a device to obtain a measure of the peak energy in each
 * requested channel. The ED scan is performed on each channel by the MLMEs
 * repeatedly issuing the PLME-ED.request primitive to the PHY until
 * [aBaseSuperframeDuration * (2n + 1)] symbols, where n is the value of the
 * ScanDuration parameter, have elapsed. The MLME notes the maximum energy
 * measurement and moves on to the next channel in the channel list. A device
 * will be able to store between one and an implementation-specified maximum
 * number of channel ED measurements. The ED scan terminates when the number
 * of channel ED measurements stored equals this implementation-specified
 * maximum or when every channel specified in the channel list has been scanned.
 *
 * An active scan is used by an FFD to locate all coordinators transmitting
 * beacon frames within its POS. The active scan is performed on each channel
 * by the MLMEs first sending a beacon request command (see 7.3.2.4). The MLME
 * then enables the receiver and records the information contained in each
 * received beacon in a PAN descriptor structure (see Table 41 in 7.1.5.1.1).
 * A device will be able to store between one and an implementation-specified
 * maximum number of PAN descriptors. The active scan on a particular channel
 * terminates when the number of PAN descriptors stored equals this
 * implementation-specified maximum or when [aBaseSuperframeDuration*(2n + 1)]
 * symbols, where n is the value of the ScanDuration parameter, have elapsed.
 * If the latter condition has been satisfied, the channel is considered to
 * have been scanned. Where possible, the scan is repeated on each channel and
 * terminates when the number of PAN descriptors stored equals the
 * implementation-specified maximum or when every channel in the set of
 *  available channels has been scanned.
 *
 * A passive scan, like an active scan, is used to locate all coordinators
 * transmitting beacon frames within the POS of the scanning device; the
 * difference is that the passive scan is a receive-only operation and does not
 * transmit the beacon request command. The passive scan is performed on each
 * channel by the MLMEs enabling its receiver and recording the information
 * contained in each received beacon in a PAN descriptor structure
 * (see Table 41 in 7.1.5.1.1). A device will be able to store between one and
 * an implementation-specified maximum number of PAN descriptors. The passive
 * scan on a particular channel terminates when the number of PAN descriptors
 * stored equals this implementation-specified maximum or when
 * [aBaseSuperframeDuration * (2n + 1)] symbols, where n is the value of the
 * ScanDuration parameter, have elapsed. If the latter condition has been
 * satisfied, the channel is considered to have been scanned. Where possible,
 * the scan is repeated on each channel and terminates when the number of PAN
 * descriptors stored equals the implementation-specified maximum or when
 * every channel in the set of available channels has been scanned.
 *
 * An orphan scan is used to locate the coordinator with which the scanning
 * device had previously associated. The orphan scan is performed on each
 * channel by the MLME first sending an orphan notification command
 * (see 7.3.2.3). The MLME then enables its receiver for at most
 * aResponseWaitTime symbols. If the device receives a coordinator realignment
 * command within this time, the MLME will disable its receiver. Otherwise, the
 * scan is repeated on the next channel in the channel list. The scan
 * terminates when the device receives a coordinator realignment command
 * (see 7.3.2.5) or when every channel in the set of available channels has
 * been scanned.
 *
 * The results of an ED scan are recorded in a list of ED values and reported
 * to the next higher layer through the MLME-SCAN.confirm primitive with a
 * status of MAC_SUCCESS. The results of an active or passive scan are recorded
 * in a set of PAN descriptor values and reported to the next higher layer
 * through the MLME-SCAN.confirm primitive. If no beacons were found, the
 * MLME-SCAN.confirm primitive will contain a null set of PAN descriptor
 * values and a status of NO_BEACON. Otherwise, the MLME-SCAN.confirm primitive
 * will contain the set of PANDescriptor values found, a list of unscanned
 * channels, and a status of MAC_SUCCESS.
 *
 * The results of an orphan scan are reported to the next higher layer through
 * the MLME-SCAN.confirm primitive. If successful, the MLME-SCAN.confirm
 * primitive will contain a status of MAC_SUCCESS. If the device did not receive
 * a
 * coordinator realignment command, MLME-SCAN.confirm primitive will contain
 * a status of NO_BEACON. In either case, the PANDescriptorList and
 * EnergyDetectList parameters of the MLMESCAN.confirm primitive are null.
 *
 * If any parameter in the MLME-SCAN.request primitive is not supported or is
 * out of range, the MAC sublayer will issue the MLME-SCAN.confirm primitive
 * with a status of MAC_INVALID_PARAMETER.
 *
 * @param m The MLME_SCAN.request message
 */
void mlme_scan_request(uint8_t *m)
{
	mlme_scan_req_t *msr = (mlme_scan_req_t *)BMM_BUFFER_POINTER(
			(buffer_t *)m);
	mlme_scan_conf_t *msc;
	/* Save the original channel. */
	mac_scan_orig_channel = tal_pib.CurrentChannel;

	/* Save the original channel page. */
	mac_scan_orig_page = tal_pib.CurrentPage;

	/* Save the scan request parameters */
	scan_duration = msr->ScanDuration;
	scan_type = msr->ScanType;
	scan_channels = msr->ScanChannels;
	scan_curr_page = msr->ChannelPage;

	msc = (mlme_scan_conf_t *)msr;

	/*
	 * Store the scan request buffer reused to create the corresponding
	 * scan confirmation
	 */
	mac_conf_buf_ptr = m;

	msc->cmdcode = MLME_SCAN_CONFIRM;
	msc->ScanType = scan_type;
	msc->UnscannedChannels = scan_channels;
	msc->ChannelPage = scan_curr_page;
	msc->ResultListSize = 0;
	msc->scan_result_list[0].ed_value[0] = 0;

	if ((MAC_POLL_IDLE != mac_poll_state) ||
			(MAC_SCAN_IDLE != mac_scan_state)
			) {
		/* Ignore scan request while being in a polling state or
		 * scanning. */
		msc->status = MAC_INVALID_PARAMETER;

		/* Append the scan confirmation message to the MAC-NHLE queue */
		qmm_queue_append(&mac_nhle_q, (buffer_t *)m);

		return;
		/* no break here due to return */
	}

#ifndef REDUCED_PARAM_CHECK

	/*
	 * Check for invalid channels to scan.
	 * This can be either an emtpy scan mask, or a scan mask that contains
	 * invalid channels for this band.
	 */

	/*
	 * Checck also for a scan duration that is lower than
	 * the max. beacon order.
	 */
	if ((0 == scan_channels) ||
			((scan_channels & INVERSE_CHANNEL_MASK) != 0) ||
			(scan_duration > BEACON_NETWORK_MAX_BO)
			) {
		msc->status = MAC_INVALID_PARAMETER;

		/* Append the scan confirm message to the MAC-NHLE queue */
		qmm_queue_append(&mac_nhle_q, (buffer_t *)m);

		return;
	}
#endif  /* REDUCED_PARAM_CHECK */

#if (MAC_SCAN_ED_REQUEST_CONFIRM == 0)

	/*
	 * If ED scan is not supported, the ED scan request
	 * will be rejected before node will be woken up.
	 */
	if (MLME_SCAN_TYPE_ED == scan_type) {
		msc->status = MAC_INVALID_PARAMETER;

		/* Append the scan confirm message to the MAC-NHLE queue */
		qmm_queue_append(&mac_nhle_q, (buffer_t *)m);

		return;
	}
#endif /*  (MAC_SCAN_ED_REQUEST_CONFIRM == 0) */

	/* wake up radio first */
	mac_trx_wakeup();

	mac_awake_scan((buffer_t *)m);
} /* mlme_scan_request() */