/* * Select the network to join. This function is called after a network discovery * and will select the network from the list of scan descriptors. If the * use_ext_pan_id flag is set in the APS Info Base, then it will search for that * pan ID and join that network. * * Otherwise, it looks for the following criteria in evaluating a network to join: * - The scan descriptor sender is a potential parent * - It has capacity * - It is permitting joining * - The protocol version matches this device's version * - The Zigbee stack profile matches this device's profile (ie: Zigbee vs Zigbee Pro) */ static bool zdo_nwk_select() { aps_aib_t *aib = aps_aib_get(); nwk_nib_t *nib = nwk_nib_get(); zdo_pcb_t *pcb = zdo_pcb_get(); nwk_join_req_t args; mem_ptr_t *mem_ptr; bool capacity = false; bool permit_join = false; bool prot_ver_match = false; bool stack_prof_match = false; /* * currently, we will join the first network we find that * fits our join criteria */ for (mem_ptr = pcb->descr_list; mem_ptr != NULL; mem_ptr = mem_ptr->next) { /* * if we specify that we need to join a particular pan, * then we need to find a node descr that matches the * ext pan id. otherwise, if there's no such limitation, * then just go on ahead. */ if ((!aib->use_ext_pan_id) || (aib->use_ext_pan_id == SCAN_ENTRY(mem_ptr)->ext_pan_id)) { if ((aib->use_desig_parent && (aib->desig_parent == SCAN_ENTRY(mem_ptr)->coord_addr.short_addr)) || !aib->use_desig_parent) { capacity = (nib->dev_type == NWK_ROUTER) ? (SCAN_ENTRY(mem_ptr)->rtr_cap >0) : (SCAN_ENTRY(mem_ptr)->end_dev_cap > 0); permit_join = (SCAN_ENTRY(mem_ptr)->superfrm_spec & MAC_ASSOC_PERMIT_MASK) >> MAC_ASSOC_PERMIT_OFF; prot_ver_match = (SCAN_ENTRY(mem_ptr)->prot_ver == ZIGBEE_PROTOCOL_VERSION); stack_prof_match = (SCAN_ENTRY(mem_ptr)->stack_profile == ZIGBEE_STACK_PROFILE); if (SCAN_ENTRY(mem_ptr)->pot_parent && capacity && permit_join && prot_ver_match && stack_prof_match) { args.desc = pcb->curr_descr = mem_ptr; args.ext_pan_id = SCAN_ENTRY(mem_ptr)->ext_pan_id; args.join_as_rtr = (nib->dev_type == NWK_ROUTER); args.rejoin_nwk = (aib->use_ext_pan_id == 0) ? NWK_JOIN_NORMAL : NWK_JOIN_REJOIN; nwk_join_req(&args); return true; } } } }
void mac_scan_descr_add(address_t *src_addr, U16 src_pan_id, U8 channel, U16 superframe_spec) { mem_ptr_t *mem_ptr; if ((mem_ptr = mac_scan_alloc()) != NULL) { memcpy(&SCAN_ENTRY(mem_ptr)->coord_addr, src_addr, sizeof(address_t)); SCAN_ENTRY(mem_ptr)->superfrm_spec = superframe_spec; SCAN_ENTRY(mem_ptr)->coord_pan_id = src_pan_id; SCAN_ENTRY(mem_ptr)->channel = channel; } }
/* * This function indicates that a beacon frame has arrived. We will then need to * parse the contents and add it to the pan descriptor. If the protocol ID * is incorrect, then we trash the descriptor by removing it from the list and * freeing it. */ void mac_beacon_notify_ind(buffer_t *buf, mem_ptr_t *mem_ptr) { /* parse the beacon contents and add it to the descriptor */ nwk_parse_beacon(buf, mem_ptr); /* * if the protocol id is not for zigbee, then remove the * descr from the scan list and free the block of memory. */ if (SCAN_ENTRY(mem_ptr)->prot_id != ZIGBEE_PROTOCOL_ID) mac_scan_descr_free(mem_ptr); }
mem_ptr_t *mac_scan_descr_find_pan(U16 pan_id) { mem_ptr_t *mem_ptr; for (mem_ptr = list_head(scan_list); mem_ptr != NULL; mem_ptr = mem_ptr->next) { if (SCAN_ENTRY(mem_ptr)->coord_pan_id == pan_id) { break; } } return mem_ptr; }
mem_ptr_t *mac_scan_descr_find_addr(address_t *addr) { mem_ptr_t *mem_ptr; for (mem_ptr = list_head(scan_list); mem_ptr != NULL; mem_ptr = mem_ptr->next) { if (SCAN_ENTRY(mem_ptr)->coord_addr.mode == SHORT_ADDR) { if (SCAN_ENTRY(mem_ptr)->coord_addr.short_addr == addr->short_addr) { break; } } else if (SCAN_ENTRY(mem_ptr)->coord_addr.mode == LONG_ADDR) { if (SCAN_ENTRY(mem_ptr)->coord_addr.long_addr == addr->long_addr) { break; } } } return mem_ptr; }