Beispiel #1
0
/************************************************
 * Description: The mac layer service FSM.
 *
 * Arguments:
 * 	None.
 * Return:
 * 	None.
 *
 * Date: 2010-05-20
 ***********************************************/
void mac_FSM()
{
	phy_FSM();

	// Check new data from radio
	if ( mac_check_new_frame() )
		mac_analyse_new_frame();

	// If Tx FSM is busy we need to call it
	if (mac_tx_busy())
		mac_tx_handler();
	
	// If the mac layer idle
	if (mac_tx_idle() && new_mhr_filled == FALSE)
		load_queue_data();

	//check background tasks here
	switch (mac_state)
	{
		case MAC_STATE_IDLE:
			break;
		case MAC_STATE_COMMAND_START:
			switch(a_mac_service.cmd)
			{
				case LRWPAN_SVC_MAC_ERROR:
					//dummy service, just return the status that was passed in
					mac_state = MAC_STATE_IDLE;
					break;
				
				case LRWPAN_SVC_MAC_GENERIC_TX:
					//send a generic packet with arguments specified by upper level
					mac_tx_data();
					mac_state = MAC_STATE_GENERIC_TX_WAIT;
					break;

				case LRWPAN_SVC_MAC_RETRANSMIT:
					//retransmit the last packet used for frames that are
					//only transmitted once because of no ACK request
					//assumes the TX lock is grabbed, and the TX buffer formatted.
					break;

				default:
					break;
			} //end switch cmd
			break;

		case MAC_STATE_GENERIC_TX_WAIT:
			// Just return;
			break;
		//this is used by MAC CMDs in general which send a packet with no ACK.
		case MAC_STATE_GENERIC_TX_WAIT_AND_UNLOCK:
			if (!mac_tx_idle())
				break;
			mac_state = MAC_STATE_IDLE;
			break;

		default:
			break;
	}// end for switch(mac_state)
}
Beispiel #2
0
void mac_data_req(mac_data_req_t *req)
{
    mac_hdr_t hdr;
    bool indirect;

    memset(&hdr, 0, sizeof(mac_hdr_t));
    hdr.mac_frm_ctrl.frame_type     = MAC_DATA;
    hdr.mac_frm_ctrl.ack_req        = (bool)(req->tx_options & MAC_ACK_REQUEST);
    hdr.mac_frm_ctrl.frame_ver      = MAC_802_15_4_2006;
    hdr.dsn                         = pib.dsn++;

    hdr.dest_pan_id                 = req->dest_pan_id;
    hdr.src_pan_id                  = req->src_pan_id;
    memcpy(&hdr.src_addr, &req->src_addr, sizeof(address_t));
    memcpy(&hdr.dest_addr, &req->dest_addr, sizeof(address_t));

    // generate the header
    mac_gen_header(req->buf, &hdr);
    DBG_PRINT_RAW("\n<OUTGOING>\n");
    debug_dump_mac_hdr(&hdr);

    // send the frame to the tx handler for processing
    indirect = (req->tx_options & MAC_INDIRECT_TRANS);
    mac_tx_handler(req->buf, &hdr.dest_addr, indirect, hdr.mac_frm_ctrl.ack_req, hdr.dsn, req->msdu_handle);
}
Beispiel #3
0
void mac_cmd_handler(mac_cmd_t *cmd, mac_hdr_t *hdr)
{
    buffer_t *buf_out;
    mac_hdr_t hdr_out;
    nwk_nib_t *nib = nwk_nib_get();

    DBG_PRINT_SIMONLY("\n<INCOMING>");
    debug_dump_mac_cmd(cmd);
    switch (cmd->cmd_id)
    {
    case MAC_ASSOC_REQ:
        if (nib->joined)
        {
            DBG_PRINT_SIMONLY("MAC: MAC Association Request Command Received.\n");
            // check to make sure that association is permitted and the src address is the correct mode
            if ((pib.assoc_permit) && (hdr->src_addr.mode == LONG_ADDR))
            {
                mac_assoc_ind_t assoc_args;
                assoc_args.capability = cmd->assoc_req.cap_info;
                memcpy(&assoc_args.dev_addr, &hdr->src_addr, sizeof(address_t));
                mac_assoc_ind(&assoc_args);
            }
            else
            {
                mac_assoc_resp_t resp_args;
                memcpy(&resp_args.dev_addr, &hdr->src_addr, sizeof(address_t));
                resp_args.assoc_short_addr = 0xFFFF;
                resp_args.status = MAC_INVALID_PARAMETER;
                mac_assoc_resp(&resp_args);
            }
        }
        break;

    case MAC_ASSOC_RESP:
        if ((pcb.mac_state == MLME_DATA_REQ) || (pcb.mac_state == MLME_ASSOC_REQ))
        {
            pcb.mac_state = MLME_IDLE;
        }
        mac_assoc_conf(cmd->assoc_resp.short_addr, cmd->assoc_resp.assoc_status);
        break;

    case MAC_DATA_REQ:
        if (nib->joined)
        {
            DBG_PRINT("MAC: MAC Data Request Command Received.\n");
            mac_indir_data_req_handler(&hdr->src_addr);
        }
        break;

    case MAC_BEACON_REQ:
        if (nib->joined)
        {
            DBG_PRINT("MAC: MAC Beacon Request Command Received.\n");
            BUF_ALLOC(buf_out, TX);
            mac_gen_beacon_frm(buf_out, &hdr_out);
            mac_tx_handler(buf_out, &hdr_out.dest_addr, false, false, hdr_out.dsn, 0);
        }
        break;

    case MAC_ORPHAN_NOT:
        if (hdr->src_addr.mode == LONG_ADDR)
        {
            mac_orphan_ind(hdr->src_addr.long_addr);
        }
        break;

    case MAC_COORD_REALIGN:
        // check over the coord realign frame to make sure that the data is what we had previously
        if  ((cmd->coord_realign.pan_id == pib.pan_id) && (cmd->coord_realign.short_addr == pib.short_addr))
        {
            if ((pib.coord_addr.mode == SHORT_ADDR) && (cmd->coord_realign.coord_short_addr == pib.coord_addr.short_addr))
            {
                pcb.coor_realign_rcvd = true;
            }
            else if ((pib.coord_addr.mode == LONG_ADDR) && (hdr->src_addr.mode == LONG_ADDR) &&
                     (hdr->src_addr.long_addr == pib.coord_addr.long_addr))
            {
                pcb.coor_realign_rcvd = true;
            }
            else
            {
                return;
            }
        }
        else
        {
            return;
        }

        // stop the scan once we get a valid coord realignment command frame
        // the scan will end once the channel is beyond the channel range
        pcb.curr_scan_channel = MAC_PHY_CHANNEL_OFFSET + MAC_MAX_CHANNELS;
        ctimer_stop(&pcb.mlme_tmr);
        mac_scan(NULL);
        break;
    default:
        break;
    }
}
Beispiel #4
0
//lint -e{715} Info 715: Symbol 'ptr' not referenced
//lint -e{818} Info 818: Pointer parameter ptr' could be declared as pointing to const
void mac_scan(void *ptr)
{
    mac_cmd_t cmd;
    mac_hdr_t hdr;
    buffer_t *buf;
    address_t src_addr, dest_addr;
    mac_scan_conf_t scan_conf;
    U32 duration;
    mac_pcb_t *pcb = mac_pcb_get();
    mac_pib_t *pib = mac_pib_get();

    // increment the current scan channel on entry into this function.
    pcb->curr_scan_channel++;

    // check if we are initializing the scan. if so, then start the init procedure.
    if (pcb->mac_state != MLME_SCAN)
    {
        // on a new scan, first save the original pan id
        pcb->original_pan_id = pib->pan_id;

        // then set the pan id to the broadcast pan id.
        // NOTE: the broadcast addr is same as broadcast pan id
        pib->pan_id = MAC_BROADCAST_ADDR;

        // init the curr scan channel to the first one
        pcb->curr_scan_channel  = MAC_PHY_CHANNEL_OFFSET;
        pcb->mac_state          = MLME_SCAN;
        pcb->nwk_cnt            = 0;
    }

    // search the channel mask to find the next allowable channel.
    // if the curr scan channel is not in the mask, then increment the channel and check again. keep doing
    // it until we either find an allowable channel or we exceed the max channels that are supported.
    for (;pcb->curr_scan_channel < (MAC_PHY_CHANNEL_OFFSET + MAC_MAX_CHANNELS); pcb->curr_scan_channel++)
    {
        //lint -e{701} Info 701: Shift left of signed quantity (int)
        // shift the bitmask and compare to the channel mask
        if (pcb->channel_mask & (1 << pcb->curr_scan_channel))
        {
            break;
        }
    }

    // we may get here if the curr scan channel exceeds the max channels. if thats the case, then we will
    // automatically end the active scan.
    if (pcb->curr_scan_channel < (MAC_PHY_CHANNEL_OFFSET + MAC_MAX_CHANNELS))
    {
        // set the channel on the radio
        mac_set_channel(pcb->curr_scan_channel);

        // generate and send the beacon request
        // get a free buffer, build the beacon request command, and then
        // send it using the mac_data_req service.
        BUF_ALLOC(buf, TX);

        dest_addr.mode          = SHORT_ADDR;
        dest_addr.short_addr    = MAC_BROADCAST_ADDR;

        if (pcb->scan_type == MAC_ACTIVE_SCAN)
        {
            cmd.cmd_id          = MAC_BEACON_REQ;
            src_addr.mode       = NO_PAN_ID_ADDR;
        }
        else if (pcb->scan_type == MAC_ORPHAN_SCAN)
        {
            cmd.cmd_id          = MAC_ORPHAN_NOT;
            src_addr.mode       = LONG_ADDR;
            src_addr.long_addr  = pib->ext_addr;
        }

        mac_gen_cmd(buf, &cmd);
        mac_gen_cmd_header(buf, &hdr, false, &src_addr, &dest_addr);
        mac_tx_handler(buf, &hdr.dest_addr, false, false, hdr.dsn, ZIGBEE_INVALID_HANDLE);

        // set the callback timer
        duration = (pcb->scan_type == MAC_ACTIVE_SCAN) ? MAC_SCAN_TIME(pcb->duration) : aMacResponseWaitTime;
        ctimer_set(&pcb->mlme_tmr, duration, mac_scan, NULL);
    }
    else
    {
        pcb->mac_state = MLME_IDLE;

        // Send the nwk scan confirm
        scan_conf.scan_type     = pcb->scan_type;
        scan_conf.energy_list   = NULL;

        if (pcb->scan_type == MAC_ACTIVE_SCAN)
        {
            scan_conf.status = MAC_SUCCESS;
        }
        else if (pcb->scan_type == MAC_ORPHAN_SCAN)
        {
            scan_conf.status = (pcb->coor_realign_rcvd) ? MAC_SUCCESS : MAC_NO_BEACON;
            pcb->coor_realign_rcvd = false;
        }

        // restore the original pan ID.
        pib->pan_id = pcb->original_pan_id;
        mac_scan_conf(&scan_conf);
    }
}