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 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();
}
Example #3
0
/**
 * @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() */
Example #4
0
File: mac_start.c Project: bswe/6.1
/**
 * @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() */
Example #5
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 #6
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 #7
0
/**
 * @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() */
Example #8
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 #9
0
/*
 * @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() */
Example #10
0
/*
 * @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() */
Example #11
0
/**
 * @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() */