/* * 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); }
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; } }