Beispiel #1
0
/*
 * This function will start a network discovery operation. It will start an active scan
 * which records all the networks on the given channels. Once the scan is finished,
 * it will call mlme_scan_confirm which will then send the results up to the ZDO.
 */
void nwk_disc_req(U32 channel_mask, U8 duration)
{
	nwk_pcb_t *nwk_pcb = nwk_pcb_get();
	mac_pcb_t *mac_pcb = mac_pcb_get();

	/*
	 * set the state. we will need this later when we do
	 * the confirm to know what function we are confirming.
	 */
	nwk_pcb->nlme_state = NLME_NWK_DISC;

	/*
	 * need to fill out the mac pcb with the channel mask
	 * and duration because the function uses a callback
	 * timer so the argument needs to be void
	 */
	mac_pcb->channel_mask   = nwk_pcb->channel_mask = channel_mask;
	mac_pcb->duration       = nwk_pcb->duration     = duration;
	mac_pcb->scan_type      = MAC_ACTIVE_SCAN;

	/* clear the pan descriptor list and do the active scan. */
	mac_scan_descr_clear();
	mac_scan(NULL);
}
Beispiel #2
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;
    }
}