void bc_delay_cb(frame_info_t *transmit_frame) { retval_t status; status = tal_tx_frame(nwkBroadDelay[minBroadDelayIndex].transmit_frame, CSMA_UNSLOTTED, true); broadDelayBitmap &= ~(1<<minBroadDelayIndex); nwkBroadDelay[minBroadDelayIndex].transmit_frame = NULL; nwkBroadDelay[minBroadDelayIndex].delayCount = 0xFFFFFFFF; broadDelayCount--; if (MAC_SUCCESS == status) { MAKE_MAC_BUSY(); } else { // NwkState = NwkState; //bmm_buffer_free(nwkBroadDelay[minBroadDelayIndex].transmit_frame->buffer_header);//TODO 要多考虑,如果后面还有数据,需要再启动 mac_sleep_trans(); } if (broadDelayCount > 0) { //bubble_sort_broad(); do { status = pal_timer_start(APP_TIMER_UART_TIMEOUT, nwkBroadDelay[++minBroadDelayIndex].delayCount, TIMEOUT_ABSOLUTE, (FUNC_PTR) bc_delay_cb, NULL); if (MAC_SUCCESS != status) { broadDelayBitmap &= ~(1<<minBroadDelayIndex); nwkBroadDelay[minBroadDelayIndex].transmit_frame = NULL; nwkBroadDelay[minBroadDelayIndex].delayCount = 0xFFFFFFFF; broadDelayCount--; } } while (MAC_SUCCESS != status && nwkBroadDelay[minBroadDelayIndex+1].transmit_frame != NULL); } if (broadDelayCount == 0) minBroadDelayIndex = 0; }
/* * @brief Creates and transmits a Null Data frame * * This function creates and transmits a Null Data frame in case the * coordinator does not have pending data to be transmitted. */ void mac_handle_tx_null_data_frame(void) { frame_info_t *tx_frame; retval_t tal_tx_status; buffer_t *buf_ptr; /* * No matching pending item in the queue, * so a Null Data frame is created. */ buf_ptr = build_null_data_frame(); if (NULL != buf_ptr) { tx_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr); /* * Transmission should be done with CSMA-CA or * quickly after the ACK of the data request command. * Here it's done quickly after the ACK w/o CSMA. */ tal_tx_status = tal_tx_frame(tx_frame, NO_CSMA_WITH_IFS, false); if (MAC_SUCCESS == tal_tx_status) { MAKE_MAC_BUSY(); } else { /* * Transmission to TAL failed, free up the buffer used to create * Null Data frame. */ bmm_buffer_free(buf_ptr); } } }
/* * @brief The MLME-GTS.request primitive makes a request for device to * request for GTS or on PANC to allocate or deallocate a GTS for itself * or other devices * * 802.15.4. Section 7.1.7.1. * * @param m The MLME-GTS.request message. */ void mlme_gts_request(uint8_t *m) { mlme_gts_req_t mgr; memcpy(&mgr, BMM_BUFFER_POINTER((buffer_t *)m), sizeof(mlme_gts_req_t)); if (MAC_NO_SHORT_ADDR_VALUE <= tal_pib.ShortAddress || (MAC_NO_SHORT_ADDR_VALUE <= mac_pib.mac_CoordShortAddress && MAC_PAN_COORD_STARTED != mac_state)) { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_NO_SHORT_ADDRESS, mgr.GtsChar); return; } else if (true != mac_pib.mac_GTSPermit || (0 == mgr.GtsChar.GtsLength) || (MAC_ASSOCIATED == mac_state && (mgr.DeviceShortAddr != tal_pib.ShortAddress || MAC_SYNC_TRACKING_BEACON != mac_sync_state || (mgr.GtsChar.GtsCharType == GTS_DEALLOCATE && (!mac_dev_gts_table[mgr.GtsChar.GtsDirection]. GtsStartingSlot || mgr.GtsChar.GtsLength != mac_dev_gts_table[mgr.GtsChar.GtsDirection].GtsLength)) ) ) ) { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_INVALID_PARAMETER, mgr.GtsChar); return; } #ifdef FFD else if (MAC_PAN_COORD_STARTED == mac_state) { if (GTS_ALLOCATE & mgr.GtsChar.GtsCharType) { if (mac_gts_allocate(mgr.GtsChar, mgr.DeviceShortAddr)) { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_SUCCESS, mgr.GtsChar); return; } else { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_NO_DATA, mgr.GtsChar); return; } } else { if (mac_gts_deallocate(mgr.GtsChar, mgr.DeviceShortAddr, true)) { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_SUCCESS, mgr.GtsChar); return; } else { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_NO_DATA, mgr.GtsChar); return; } } } #endif /* FFD */ else if (MAC_ASSOCIATED == mac_state) { frame_info_t *transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER((buffer_t *)m); mac_trx_wakeup(); /* Build the GTS Request command frame. */ uint8_t tal_tx_status; uint8_t frame_len; uint8_t *frame_ptr; uint8_t *temp_frame_ptr; uint16_t fcf; /* * Use the mlme gts request buffer for transmitting * gts request frame. */ frame_info_t *gts_req_frame = (frame_info_t *)(BMM_BUFFER_POINTER((buffer_t *)m)); gts_req_frame->msg_type = GTSREQUEST; gts_req_frame->buffer_header = (buffer_t *)m; /* Get the payload pointer. */ frame_ptr = temp_frame_ptr = (uint8_t *)gts_req_frame + LARGE_BUFFER_SIZE - GTS_REQ_PAYLOAD_LEN - 2; /* Add *2 *octets *for *FCS. **/ /* Update the payload field. */ *frame_ptr++ = GTSREQUEST; /* Build the GTS characteristics info. */ *frame_ptr = *((uint8_t *)&mgr.GtsChar); /* Get the payload pointer again to add the MHR. */ frame_ptr = temp_frame_ptr; /* Update the length. */ frame_len = GTS_REQ_PAYLOAD_LEN + 2 + /* Add 2 octets for FCS */ 2 + /* 2 octets for Destination PAN-Id */ 2 + /* 2 octets for short Destination Address */ 2 + /* 2 octets for short Source Address */ 3; /* 3 octets DSN and FCF */ /* Source address */ frame_ptr -= 2; convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr); frame_ptr -= 2; convert_16_bit_to_byte_array(mac_pib.mac_CoordShortAddress, frame_ptr); fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) | FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) | FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) | FCF_ACK_REQUEST | FCF_PAN_ID_COMPRESSION; /* Destination PAN-Id */ frame_ptr -= 2; convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr); /* Set DSN. */ frame_ptr--; *frame_ptr = mac_pib.mac_DSN++; /* Set the FCF. */ frame_ptr -= 2; convert_spec_16_bit_to_byte_array(fcf, frame_ptr); /* First element shall be length of PHY frame. */ frame_ptr--; *frame_ptr = frame_len; /* Finished building of frame. */ gts_req_frame->mpdu = frame_ptr; tal_tx_status = tal_tx_frame(transmit_frame, CSMA_SLOTTED, true); if (MAC_SUCCESS == tal_tx_status) { uint8_t update_index = mgr.GtsChar.GtsDirection; if (mgr.DeviceShortAddr == mac_pib.mac_CoordShortAddress) { update_index |= 0x02; } if (GTS_DEALLOCATE == mgr.GtsChar.GtsCharType) { mac_dev_gts_table[update_index].GtsLength = 0; mac_dev_gts_table[update_index].GtsStartingSlot = 0; mac_dev_gts_table[update_index].GtsState = GTS_STATE_IDLE; mac_gen_mlme_gts_conf((buffer_t *)m, MAC_SUCCESS, mgr.GtsChar); return; } else { mac_dev_gts_table[update_index].GtsReq_ptr = m; mac_dev_gts_table[update_index].GtsState = GTS_STATE_REQ_SENT; mac_dev_gts_table[update_index].GtsPersistCount = aGTSDescPersistenceTime; mac_dev_gts_table[update_index].GtsLength = mgr.GtsChar.GtsLength; MAKE_MAC_BUSY(); } } else { mac_gen_mlme_gts_conf((buffer_t *)m, tal_tx_status, mgr.GtsChar); } } else { mac_gen_mlme_gts_conf((buffer_t *)m, MAC_INVALID_PARAMETER, mgr.GtsChar); } return; }
/** * @brief Build and transmits data request command frame * * This function builds and tranmits a data request command frame. * * * @param expl_poll Data request due to explicit MLME poll request * @param force_own_long_addr Forces the usage of the Extended Address as * Source Address. This a allows for implicitly * poll for pending data at the coordinator if * the Extended Address was used in the Beacon frame. * @param expl_dest_addr_mode Mode of subsequent destination address to be used * explicitly (0/2/3). * 0: No explicit destination address attached, * use either macCoordShortAddress or * macCoordExtendedAddress * 2: Use explicitly attached address in parameter * expl_dest_addr as destination address as * short address * 3: Use explicitly attached address in parameter * expl_dest_addr as destination address as * extended address * @param expl_dest_addr Explicitly attached destination address for data * request frame. This is to be treated as either not * present, short or extended address, depending on * parameter expl_dest_addr_mode. * @param expl_dest_pan_id Explicitly attached destination PAN-Id (Coordinator * PAN-Id) for data request frame. * This is to be treated only as present, depending on * parameter expl_dest_addr_mode. * * @return True if data request command frame was created and sent to * the TAL successfully, false otherwise. */ bool mac_build_and_tx_data_req(bool expl_poll, bool force_own_long_addr, uint8_t expl_dest_addr_mode, address_field_t *expl_dest_addr, uint16_t expl_dest_pan_id) { retval_t tal_tx_status; bool intrabit = false; uint8_t frame_len; uint8_t *frame_ptr; uint16_t fcf; buffer_t *buf_ptr = bmm_buffer_alloc(LARGE_BUFFER_SIZE); if (NULL == buf_ptr) { return false; } frame_info_t *transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr); /* * If this data request cmd frame was initiated by a device due to implicit * poll, set msgtype to DATAREQUEST_IMPL_POLL. * If this data request cmd frame was initiated by a MLME poll request, * set msgtype to DATAREQUEST. */ if (expl_poll) { transmit_frame->msg_type = DATAREQUEST; } else { transmit_frame->msg_type = DATAREQUEST_IMPL_POLL; } /* * The buffer header is stored as a part of frame_info_t structure before the * frame is given to the TAL. After the transmission of the frame, reuse * the buffer using this pointer. */ transmit_frame->buffer_header = buf_ptr; /* Update the payload length. */ frame_len = DATA_REQ_PAYLOAD_LEN + 2 + // Add 2 octets for FCS 2 + // 2 octets for short Source Address 2 + // 2 octets for short Destination Address 2 + // 2 octets for Destination PAN-Id 3; // 3 octets DSN and FCF /* Get the payload pointer. */ frame_ptr = (uint8_t *)transmit_frame + LARGE_BUFFER_SIZE - DATA_REQ_PAYLOAD_LEN - 2; /* Add 2 octets for FCS. */ /* * Build the command frame id. * This is actually being written into "transmit_frame->layload[0]". */ *frame_ptr = DATAREQUEST; /* Source Address */ /* * Long address needs to be used if a short address is not present * or if we are forced to use the long address. * * This is used for example in cases where the coordinator indicates * pending data for us using our extended address. * * This is also used for transmitting a data request frame * during association, since here we always need to use our * extended address. */ if ((BROADCAST == tal_pib.ShortAddress) || (CCPU_ENDIAN_TO_LE16(MAC_NO_SHORT_ADDR_VALUE) == tal_pib.ShortAddress) || force_own_long_addr) { frame_ptr -= 8; frame_len += 6; // Add further 6 octets for long Source Address /* Build the Source address. */ convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr); fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) | FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR) | FCF_ACK_REQUEST; } else { frame_ptr -= 2; /* Build the Source address. */ convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr); fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) | FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) | FCF_ACK_REQUEST; } /* Source PAN-Id */ /* * In IEEE 802.15.4 the PAN ID Compression bit may always be set. * See page 154: * If the data request command is being sent in response to the receipt * of a beacon frame indicating that data are pending for that device, * the Destination Addressing Mode subfield of the Frame Control field * may be set to zero ..." * In order to keep the implementation simple the address info is also in * this case 2 or 3, i.e. the destination address info is present. * This in return means that the PAN ID Compression bit is always set for * data request frames, except the expl_dest_pan_id parameter is different from * our own PAN-Id PIB attribute. */ if ((expl_dest_addr_mode != FCF_NO_ADDR) && (expl_dest_pan_id != tal_pib.PANId) ) { frame_ptr -= 2; frame_len += 2; // Add further 6 octets for long Source Pan-Id convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr); } else { /* * The source PAN Id is not present since the PAN ID * Compression bit is set. */ /* Set intra-PAN bit. */ intrabit = true; fcf |= FCF_PAN_ID_COMPRESSION; } /* Destination Address */ if (FCF_SHORT_ADDR == expl_dest_addr_mode) { /* An explicit short destination address is requested. */ fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR); frame_ptr -= 2; convert_16_bit_to_byte_array(expl_dest_addr->short_address, frame_ptr); } else if (FCF_LONG_ADDR == expl_dest_addr_mode) { /* An explicit long destination address is requested. */ fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR); frame_ptr -= 8; frame_len += 6; // Add further 6 octets for long Destination Address convert_64_bit_to_byte_array(expl_dest_addr->long_address, frame_ptr); } else { /* No explicit destination address is requested. */ if (CCPU_ENDIAN_TO_LE16(MAC_NO_SHORT_ADDR_VALUE) != mac_pib.mac_CoordShortAddress) { /* * If current value of short address for coordinator PIB is * NOT 0xFFFE, the current value of the short address for * coordinator shall be used as desination address. */ fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR); frame_ptr -= 2; convert_16_bit_to_byte_array(mac_pib.mac_CoordShortAddress, frame_ptr); } else { /* * If current value of short address for coordinator PIB is 0xFFFE, * the current value of the extended address for coordinator * shall be used as desination address. */ fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR); frame_ptr -= 8; frame_len += 6; // Add further 6 octets for long Destination Address convert_64_bit_to_byte_array(mac_pib.mac_CoordExtendedAddress, frame_ptr); } } /* Destination PAN-Id */ frame_ptr -= 2; if (intrabit) { /* Add our PAN-Id. */ convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr); } else { /* * There is an expclicit destination address present AND * the destination PAN-Id is different from our own PAN-ID, * so include the source PAN-id into the frame. */ convert_16_bit_to_byte_array(expl_dest_pan_id, frame_ptr); } /* Set DSN. */ frame_ptr--; *frame_ptr = mac_pib.mac_DSN++; /* Set the FCF. */ frame_ptr -= 2; convert_spec_16_bit_to_byte_array(fcf, frame_ptr); /* First element shall be length of PHY frame. */ frame_ptr--; *frame_ptr = frame_len; /* Finished building of frame. */ transmit_frame->mpdu = frame_ptr; /* Transmission should be done with CSMA-CA and frame retries. */ #ifdef BEACON_SUPPORT /* * Now it gets tricky: * In Beacon network the frame is sent with slotted CSMA-CA only if: * 1) the node is associated, or * 2) the node is idle, but synced before association, * 3) the node is a Coordinator (we assume, that coordinators are always * in sync with their parents). * * In all other cases, the frame has to be sent using unslotted CSMA-CA. */ csma_mode_t cur_csma_mode; if (NON_BEACON_NWK != tal_pib.BeaconOrder) { if ( ((MAC_IDLE == mac_state) && (MAC_SYNC_BEFORE_ASSOC == mac_sync_state)) || #if (MAC_START_REQUEST_CONFIRM == 1) (MAC_ASSOCIATED == mac_state) || (MAC_COORDINATOR == mac_state) #else (MAC_ASSOCIATED == mac_state) #endif /* MAC_START_REQUEST_CONFIRM */ ) { cur_csma_mode = CSMA_SLOTTED; } else { cur_csma_mode = CSMA_UNSLOTTED; } } else { /* In Nonbeacon network the frame is sent with unslotted CSMA-CA. */ cur_csma_mode = CSMA_UNSLOTTED; } tal_tx_status = tal_tx_frame(transmit_frame, cur_csma_mode, true); #else /* No BEACON_SUPPORT */ /* In Nonbeacon build the frame is sent with unslotted CSMA-CA. */ tal_tx_status = tal_tx_frame(transmit_frame, CSMA_UNSLOTTED, true); #endif /* BEACON_SUPPORT */ if (MAC_SUCCESS == tal_tx_status) { MAKE_MAC_BUSY(); return true; } else { /* TAL is busy, hence the data request could not be transmitted */ bmm_buffer_free(buf_ptr); return false; } } /* mac_build_and_tx_data_req() */
/** * @brief Processes a received data request command frame * * This function processes a received data request command frame * at the coordinator, searches for pending indirect data frames * for the originator and initiates the frame transmission of the * data frame with CSMA-CA. * * @param msg Frame reception buffer pointer */ void mac_process_data_request(buffer_t *msg) { /* Buffer pointer to next indirect data frame to be transmitted. */ buffer_t *buf_ptr_next_data; search_t find_buf; frame_info_t *transmit_frame; retval_t tal_tx_status; /* Free the buffer of the received frame. */ bmm_buffer_free(msg); /* Ignore data request if we are not PAN coordinator or coordinator. */ if ((MAC_IDLE == mac_state) || (MAC_ASSOCIATED == mac_state) ) { #if (DEBUG > 0) ASSERT("Neither PAN coordinator nor coordinator" == 0); #endif return; } /* Check the addressing mode */ if (mac_parse_data.src_addr_mode == FCF_SHORT_ADDR) { /* * Look for pending data in the indirect queue for * this short address. */ /* * Assign the function pointer for searching the * data having address of the requested device. */ find_buf.criteria_func = find_short_buffer; /* Update the short address to be searched. */ find_buf.handle = &mac_parse_data.src_addr.short_address; } else if (mac_parse_data.src_addr_mode == FCF_LONG_ADDR) { /* * Look for pending data in the indirect queue for * this long address. */ /* * Assign the function pointer for searching the * data having address of the requested device. */ find_buf.criteria_func = find_long_buffer; /* Update the long address to be searched. */ find_buf.handle = &mac_parse_data.src_addr.long_address; } else { #if (DEBUG > 0) ASSERT("Unexpected addressing mode" == 0); #endif return; } /* * Read from the indirect queue. The removal of items from this queue * will be done after successful transmission of the frame. */ buf_ptr_next_data = qmm_queue_read(&indirect_data_q, &find_buf); /* Note: The find_buf structure is reused below, so do not change this. */ if (NULL == buf_ptr_next_data) { mac_handle_tx_null_data_frame(); return; } else { /* Indirect data found and to be sent. */ transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr_next_data); /* * We need to check whether the source PAN-Id of the previously * received data request frame is identical to the destination PAN-Id * of the pending frame. If not the frame shall not be transmitted, * but a Null Data frame instead. */ if (mac_parse_data.src_panid != convert_byte_array_to_16_bit(&transmit_frame->mpdu[PL_POS_DST_PAN_ID_START]) ) { mac_handle_tx_null_data_frame(); return; } else { /* * The frame to be transmitted next is marked. * This is necessary since the queue needs to be traversed again * to find other pending indirect data frames for this particular * recipient. */ transmit_frame->indirect_in_transit = true; transmit_frame->buffer_header = buf_ptr_next_data; /* * Go through the indirect data queue to find out the frame pending for * the device which has requested for the data. */ /* * Since the buffer header has already been stored in * transmit_frame->buffer_header, it can be reused here for * other purpose. */ /* * It is assumed that the find_buf struct does still have * the original values from above. */ buf_ptr_next_data = qmm_queue_read(&indirect_data_q, &find_buf); /* * Check whether there is another indirect data available * for the same recipient. */ if (NULL != buf_ptr_next_data) { transmit_frame->mpdu[PL_POS_FCF_1] |= FCF_FRAME_PENDING; } } /* * Transmission should be done with CSMA-CA or * quickly after the ACK of the data request command. * Here it's done quickly after the ACK w/o CSMA. */ tal_tx_status = tal_tx_frame(transmit_frame, NO_CSMA_WITH_IFS, false); if (MAC_SUCCESS == tal_tx_status) { MAKE_MAC_BUSY(); } else { /* * TAL rejects frame transmission, since it's too close to the next * beacon transmission. The frame is kept in the indirect queue. */ transmit_frame->indirect_in_transit = false; } } } /* mac_process_data_request() */
static void handle_remote_range_req_frame(uint8_t *curr_frame_ptr) { /* * Store addresses for the ongoing transaction. * This is required for all cases, also for * erroneous cases. */ /* This node is the Initiator. */ range_param.InitiatorAddrSpec.AddrMode = mac_parse_data.dest_addr_mode; range_param.InitiatorAddrSpec.PANId = mac_parse_data.dest_panid; /* Long address also covers short address here. */ ADDR_COPY_DST_SRC_64(range_param.InitiatorAddrSpec.Addr.long_address, mac_parse_data.dest_addr.long_address); /* The transmitter of this frame is the Coordinator. */ /* * Note: Setting the Coordinator address mode here to a value different from * zero actually indicates, that remote ranging is ongoing. */ range_param.CoordinatorAddrSpec.AddrMode = mac_parse_data.src_addr_mode; range_param.CoordinatorAddrSpec.PANId = mac_parse_data.src_panid; /* Long address also covers short address here. */ ADDR_COPY_DST_SRC_64(range_param.CoordinatorAddrSpec.Addr.long_address, mac_parse_data.src_addr.long_address); if (RTB_ROLE_NONE != rtb_role) { /* Ranging is currently already ongoing, do nothing. */ } else if (!rtb_pib.RangingEnabled) { /* Ranging is currently disabled, reject new request. */ range_status.range_error = (range_error_t)RTB_UNSUPPORTED_RANGING; rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME; /* * The role needs to be updated even in error * case to be able to properly release the * frame buffer after the transmission of the * Remote Range confirm frame back to the Coordinator. */ rtb_role = RTB_ROLE_INITIATOR; /* * Reset the PMU average data since no valid PMU average data are available * at this stage. */ reset_pmu_average_data(); } else { uint8_t frame_len; /* * Generally ranging is allowed ... * Now check requested ranging parameters. */ /* Read Frame length field. */ frame_len = *curr_frame_ptr++; if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++) { uint8_t refl_addr_len = IE_REFLECTOR_ADDR_SPEC_LEN_MIN; /* Currently only one RTB Protocol Version is supported. */ rtb_role = RTB_ROLE_INITIATOR; /* * Reset the PMU average data since no valid PMU average data are available * at this stage. */ reset_pmu_average_data(); /* Extract Reflector address information from the frame. */ refl_addr_t *ra = (refl_addr_t *)curr_frame_ptr; range_param.ReflectorAddrSpec.AddrMode = ra->refl_addr_mode; range_param.ReflectorAddrSpec.PANId = ra->refl_pan_id; /* Long address also covers short address here. */ if (ra->refl_addr_mode == FCF_SHORT_ADDR) { range_param.ReflectorAddrSpec.Addr.long_address = 0; ADDR_COPY_DST_SRC_16(range_param.ReflectorAddrSpec.Addr.short_address, ra->refl_addr.short_address); } else { ADDR_COPY_DST_SRC_64(range_param.ReflectorAddrSpec.Addr.long_address, ra->refl_addr.long_address); refl_addr_len += 6; } curr_frame_ptr += refl_addr_len; /* Check whether requested ranging method is supported. */ if (RTB_TYPE == *curr_frame_ptr++) { range_param.method = RTB_TYPE; range_param_pmu.f_start = convert_byte_array_to_16_bit(curr_frame_ptr); curr_frame_ptr += 2; range_param_pmu.f_step = *curr_frame_ptr++; range_param_pmu.f_stop = convert_byte_array_to_16_bit(curr_frame_ptr); curr_frame_ptr += 2; /* * Extract remote range capabilities from * the Coordinator. */ range_param.remote_caps = *curr_frame_ptr++; if (range_param.remote_caps & PMU_REM_CAP_APPLY_MIN_DIST_THRSHLD) { range_param_pmu.apply_min_dist_threshold = true; } else { range_param_pmu.apply_min_dist_threshold = false; } /* * The capabilities for the actual ranging * are not taken from the Coordinator, but * rather from the Initiator itself. */ SET_INITIATOR_CAPS(range_param.caps); /* * Initialize the Ranging Transmit Power to be applied at the * Initiator in case this parameter is not included properly * in this frame. */ range_param.req_tx_power = rtb_pib.RangingTransmitPower; /* Check wether Requested Ranging Transmit Power IE is available. */ if (frame_len == IE_PMU_RANGING_LEN + refl_addr_len + IE_REQ_RANGING_TX_POWER_LEN) { /* * Extract and set requested Ranging Transmit Power * (if changed). */ if (REQ_RANGING_TX_POWER_IE == *curr_frame_ptr++) { /* Overwrite Ranging Transmit Power. */ range_param.req_tx_power = *curr_frame_ptr++; } } if (!pmu_check_pmu_params()) { /* Unsupported ranging parameters, reject new request. */ range_status.range_error = (range_error_t)RTB_INVALID_PARAMETER; rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME; } else { /* * Proper Remote Range Request frame received, * so continue as Initiator. */ #if (RTB_TYPE == RTB_PMU_233R) /* Prepare FEC measurement */ pmu_enable_fec_measurement(); #endif /* (RTB_TYPE == RTB_PMU_233R) */ configure_ranging(); #ifndef RTB_WITHOUT_MAC /* * Block MAC from doing anything else than ranging * until this procedure is finished. */ MAKE_MAC_BUSY(); #endif /* #ifndef RTB_WITHOUT_MAC */ /* * Next a Range Request frame needs to be assembled to be * transmitted to Reflector */ range_status.range_error = RANGE_OK; rtb_state = RTB_INIT_RANGE_REQ_FRAME; } } else { /* Unsupported ranging method, reject new request. */ range_status.range_error = (range_error_t)RTB_UNSUPPORTED_METHOD; rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME; } } else /* if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++) */ { /* Unsupported RTB Protocol Version, reject new request. */ range_status.range_error = (range_error_t)RTB_UNSUPPORTED_PROTOCOL; rtb_state = RTB_INIT_REMOTE_RANGE_CONF_FRAME; } } }
static void handle_range_req_frame(uint8_t *curr_frame_ptr) { /* * Store addresses for the ongoing transaction. * This is required for all cases, also for * erroneous cases. */ /* This node is the Reflector. */ range_param.ReflectorAddrSpec.AddrMode = mac_parse_data.dest_addr_mode; range_param.ReflectorAddrSpec.PANId = mac_parse_data.dest_panid; /* Long address also covers short address here. */ ADDR_COPY_DST_SRC_64(range_param.ReflectorAddrSpec.Addr.long_address, mac_parse_data.dest_addr.long_address); /* The transmitter of this frame is the Initiator. */ range_param.InitiatorAddrSpec.AddrMode = mac_parse_data.src_addr_mode; range_param.InitiatorAddrSpec.PANId = mac_parse_data.src_panid; /* Long address also covers short address here. */ ADDR_COPY_DST_SRC_64(range_param.InitiatorAddrSpec.Addr.long_address, mac_parse_data.src_addr.long_address); if (RTB_ROLE_NONE != rtb_role) { /* Ranging is currently already ongoing, do nothing. */ } else if (!rtb_pib.RangingEnabled) { /* Ranging is currently disabled, reject new request. */ range_status.range_error = (range_error_t)RTB_UNSUPPORTED_RANGING; rtb_state = RTB_INIT_RANGE_ACPT_FRAME; /* * The role needs to be updated even in error * case to be able to properly release the * frame buffer after the transmission of the * Range Accept frame back to the Initiator. */ rtb_role = RTB_ROLE_REFLECTOR; /* * Reset the PMU average data since no valid PMU average data are available * at this stage. */ reset_pmu_average_data(); } else { uint8_t frame_len; rtb_role = RTB_ROLE_REFLECTOR; /* * Reset the PMU average data since no valid PMU average data are available * at this stage. */ reset_pmu_average_data(); /* * Generally ranging is allowed ... * Now check requested ranging parameters. */ /* Read Frame length field. */ frame_len = *curr_frame_ptr++; if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++) { /* Currently only one RTB Protocol Version is supported. */ /* Check whether requested ranging method is supported. */ if (RTB_TYPE == *curr_frame_ptr++) { range_param.method = RTB_TYPE; range_param_pmu.f_start = convert_byte_array_to_16_bit(curr_frame_ptr); curr_frame_ptr += 2; range_param_pmu.f_step = *curr_frame_ptr++; range_param_pmu.f_stop = convert_byte_array_to_16_bit(curr_frame_ptr);; curr_frame_ptr += 2; range_param.caps = *curr_frame_ptr++; /* * Update the received capabilities from the Initiator * to match our own capabilities. * * Note: Other capabilty bits than used for antenna * diversity are not touched here. */ #if (ANTENNA_DIVERSITY == 1) /* * If we allow antenna diversity generally, * use antenna diversity value received from the initiator, * and simply update our own. */ if (rtb_pib.EnableAntennaDiv) { /* * Reflector uses antenna diversity. * Keep Initiator antenna diversity as is. */ range_param.caps |= PMU_CAP_REFLECTOR_ANT; } else { /* * Reflector temporarily does not use antenna diversity, * but keep Initiator antenna diversity as is. */ range_param.caps &= ~(PMU_CAP_REFLECTOR_ANT); } #else /* * Reflector generally does not use antenna diversity, * but keep Initiator antenna diversity as is. */ range_param.caps &= ~(PMU_CAP_REFLECTOR_ANT); #endif /* (ANTENNA_DIVERSITY == 1) */ /* * Initialize the Ranging Transmit Power to be applied at the * Reflector in case this parameter is not included properly * in this frame. */ range_param.req_tx_power = rtb_pib.RangingTransmitPower; /* Check wether Requested Ranging Transmit Power IE is available. */ if (frame_len == IE_PMU_RANGING_LEN + IE_REQ_RANGING_TX_POWER_LEN) { /* * Extract and set requested Ranging Transmit Power * (if changed). */ if (REQ_RANGING_TX_POWER_IE == *curr_frame_ptr++) { /* Overwrite Ranging Transmit Power. */ range_param.req_tx_power = *curr_frame_ptr++; } } pmu_configure_antenna(); if (!pmu_check_pmu_params()) { /* Unsupported ranging parameters, reject new request. */ range_status.range_error = (range_error_t)RTB_INVALID_PARAMETER; rtb_state = RTB_INIT_RANGE_ACPT_FRAME; } else { #if (RTB_TYPE == RTB_PMU_233R) /* Prepare FEC measurement */ pmu_enable_fec_measurement(); #endif /* (RTB_TYPE == RTB_PMU_233R) */ configure_ranging(); #ifndef RTB_WITHOUT_MAC /* * Block MAC from doing anything else than ranging * until this procedure is finished. */ MAKE_MAC_BUSY(); #endif /* #ifndef RTB_WITHOUT_MAC */ /* Next a Range Accept frame needs to be assembled. */ range_status.range_error = RANGE_OK; rtb_state = RTB_INIT_RANGE_ACPT_FRAME; } } else { /* Unsupported ranging method, reject new request. */ range_status.range_error = (range_error_t)RTB_UNSUPPORTED_METHOD; rtb_state = RTB_INIT_RANGE_ACPT_FRAME; } } else /* if (RTB_PROTOCOL_VERSION_01 == *curr_frame_ptr++) */ { /* Unsupported RTB Protocol Version, reject new request. */ range_status.range_error = (range_error_t)RTB_UNSUPPORTED_PROTOCOL; rtb_state = RTB_INIT_RANGE_ACPT_FRAME; } } }
void bc_data_cb(frame_info_t *transmit_frame) { uint8_t index; index = nwkFindPassiveAck(transmit_frame->NwkFrameHeader->srcAddr, transmit_frame->NwkFrameHeader->sequenceNumber); if (index != 0xFF) { if (gNwkPassiveAckTable.table[index].end == false) { do { if (gNwkPassiveAckTable.table[index].realyNeighborNum >= neighborTable.size) break; while (transmit_frame->AppFrameHeader->frameControl.tries != 0)//以后要用这个NWK_MAX_BROADCAST_RETRIES { transmit_frame->AppFrameHeader->AppPayload[transmit_frame->AppFrameHeader->length] ^= transmit_frame->AppFrameHeader->frameControl.tries; transmit_frame->AppFrameHeader->frameControl.tries--; transmit_frame->AppFrameHeader->AppPayload[transmit_frame->AppFrameHeader->length] ^= transmit_frame->AppFrameHeader->frameControl.tries; //mac_trx_wakeup(); retval_t status = FAILURE; transmit_frame->mpdu[3] = mac_pib.mac_DSN++; /* In Nonbeacon build the frame is sent with unslotted CSMA-CA. */ status = tal_tx_frame(transmit_frame, CSMA_UNSLOTTED, true); if (MAC_SUCCESS == status) { MAKE_MAC_BUSY(); /* Start timer to initiate next broadcast data transmission. */ pal_timer_start(gNwkPassiveAckTable.table[index].timerID, ((uint32_t)NWK_PASSIVE_ACK_TIMEOUT), TIMEOUT_RELATIVE, (FUNC_PTR)bc_data_cb, transmit_frame); gNwkPassiveAckTable.table[index].reTryTimes++; } else { break; } return; } }while(0); NwkState = NWK_MODULE_NONE; pal_timer_start(gNwkPassiveAckTable.table[index].timerID, ((uint32_t) (NWK_BROADCAST_DELIVERY_TIME-(gNwkPassiveAckTable.table[index].reTryTimes+1)*NWK_PASSIVE_ACK_TIMEOUT)), TIMEOUT_RELATIVE, (FUNC_PTR)bc_data_cb, transmit_frame); gNwkPassiveAckTable.table[index].end = true; return; } gNwkPassiveAckTable.table[index].end = false; gNwkPassiveAckTable.table[index].reTryTimes = 0; nwkFreePassiveAck(transmit_frame->NwkFrameHeader->srcAddr, transmit_frame->NwkFrameHeader->sequenceNumber); if (transmit_frame != NULL) bmm_buffer_free(transmit_frame->buffer_header); //NwkState = NWK_MODULE_NONE; mac_sleep_trans(); } }
/** * @brief Continue scanning after setting of PIB attributes * * This functions continues scanning once the corresponding PIB * attribute change has been completed depending on the status. * * @param set_status Status of the Request to change the PIB attribute */ void scan_set_complete(retval_t set_status) { switch (mac_scan_state) { #if (MAC_SCAN_ED_REQUEST_CONFIRM == 1) case MAC_SCAN_ED: { if (MAC_SUCCESS == set_status) { MAKE_MAC_BUSY(); tal_ed_start(scan_duration); } else { /* Channel not supported, continue. */ scan_curr_channel++; } } break; #endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) case MAC_SCAN_ACTIVE: if (MAC_SUCCESS == set_status) { /* * The TAL switches ON the transmitter while sending a * beacon request, hence the MAC can call * send_scan_cmd() to send * the beacon directly */ /* Send an beacon request command */ if (!send_scan_cmd(true)) { uint8_t timer_id = T_Scan_Duration; /* * Beacon request could not be transmitted * since there is no buffer available stop * scanning * we call the function usually called by the * scan * duration timer to pretend scanning has * finished */ mac_t_scan_duration_cb((uint8_t *)&timer_id); } } else { /* Channel not supported, continue. */ scan_curr_channel++; } break; #endif /* (MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) case MAC_SCAN_PASSIVE: { if (MAC_SUCCESS == set_status) { uint8_t status = tal_rx_enable(PHY_RX_ON); if (PHY_RX_ON == status) { retval_t timer_status; uint32_t tmr = MAC_CALCULATE_SYMBOL_TIME_SCANDURATION( scan_duration); timer_status = pal_timer_start(T_Scan_Duration, TAL_CONVERT_SYMBOLS_TO_US( tmr), TIMEOUT_RELATIVE, (FUNC_PTR)mac_t_scan_duration_cb, NULL); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == timer_status); #endif if (MAC_SUCCESS != timer_status) { uint8_t timer_id = T_Scan_Duration; /* * Scan duration timer could not be * started so we * call the timer callback function * directly this * will basically shorten scanning * without having * really scanned. */ mac_t_scan_duration_cb((void *)&timer_id); } } else { /* Did not work, continue. */ scan_curr_channel++; scan_proceed(MLME_SCAN_TYPE_PASSIVE, (buffer_t *)mac_conf_buf_ptr); } } else { /* Channel not supported, continue. */ scan_curr_channel++; } } break; #endif /* (MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) */ #if (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) case MAC_SCAN_ORPHAN: if (MAC_SUCCESS == set_status) { /* Send an orphan notification command */ if (!send_scan_cmd(false)) { uint8_t timer_id = T_Scan_Duration; /* * Orphan notification could not be transmitted * since there * is no buffer available stop scanning * we call the function usually called by the * scan duration * timer to pretend scanning has finished */ mac_t_scan_duration_cb((uint8_t *)&timer_id); } } else { /* Channel not supported, continue. */ scan_curr_channel++; } break; #endif /* (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) */ default: break; } } /* scan_set_complete() */
/** * @brief Send a beacon request or orphan notification command frame * * This function sends a beacon request or orphan notification command frame. * An MPDU containing either a beacon request or an orphan notification command * frame is constructed and sent. * * @param beacon_req True if a beacon request command frame shall be sent, * otherwise (false) an orphan notification command frame * will be sent. * * @return True if the frame transmission has been initiated, false otherwise. */ static bool send_scan_cmd(bool beacon_req) { retval_t tal_tx_status; uint8_t frame_len; uint8_t *frame_ptr; uint16_t fcf; uint16_t bc_addr = BROADCAST; /* * mac_scan_cmd_buf_ptr holds the buffer allocated for sending beacon * request or orphan notification command. In active scan the scan * request * buffer is used to send a beacon request and in orphan scan new buffer * is * allocated to send an orphan notification. */ frame_info_t *transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER( (buffer_t *)mac_scan_cmd_buf_ptr); /* Get the payload pointer. */ frame_ptr = (uint8_t *)transmit_frame + LARGE_BUFFER_SIZE - BEAC_REQ_ORPH_NOT_PAYLOAD_LEN - 2; /* Add 2 octets for * FCS. */ transmit_frame->buffer_header = (buffer_t *)mac_scan_cmd_buf_ptr; if (beacon_req) { fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) | FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) | FCF_SET_SOURCE_ADDR_MODE(FCF_NO_ADDR); /* Update the length. */ frame_len = BEAC_REQ_ORPH_NOT_PAYLOAD_LEN + 2 + /* Add 2 octets for FCS */ 2 + /* 2 octets for short Destination Address */ 2 + /* 2 octets for Destination PAN-Id */ 3; /* 3 octets DSN and FCF */ /* Build the command frame id. */ *frame_ptr = transmit_frame->msg_type = BEACONREQUEST; } else { /* Orphan Notification command */ fcf = FCF_SET_FRAMETYPE(FCF_FRAMETYPE_MAC_CMD) | FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) | FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR) | FCF_PAN_ID_COMPRESSION; /* Update the length. */ frame_len = BEAC_REQ_ORPH_NOT_PAYLOAD_LEN + 2 + /* Add 2 octets for FCS */ 2 + /* 2 octets for short Destination Address */ 2 + /* 2 octets for Destination PAN-Id */ 8 + /* 8 octets for long Source Address */ 3; /* 3 octets DSN and FCF */ /* Build the command frame id. */ *frame_ptr = transmit_frame->msg_type = ORPHANNOTIFICATION; /* Orphan notification contains long source address. */ frame_ptr -= 8; convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr); } /* Destination address */ frame_ptr -= 2; convert_16_bit_to_byte_array(bc_addr, frame_ptr); /* Destination PANid */ frame_ptr -= 2; convert_16_bit_to_byte_array(bc_addr, frame_ptr); /* Set DSN. */ frame_ptr--; *frame_ptr = mac_pib.mac_DSN++; /* Set the FCF. */ frame_ptr -= 2; convert_spec_16_bit_to_byte_array(fcf, frame_ptr); /* First element shall be length of PHY frame. */ frame_ptr--; *frame_ptr = frame_len; /* Finished building of frame. */ transmit_frame->mpdu = frame_ptr; #if (TAL_TYPE == AT86RF230B) /* Transmit data without CSMA-CA and no frame retry. */ tal_tx_status = tal_tx_frame(transmit_frame, NO_CSMA_NO_IFS, false); #else /* Transmit data with unslotted CSMA-CA and no frame retry. */ tal_tx_status = tal_tx_frame(transmit_frame, CSMA_UNSLOTTED, false); #endif if (MAC_SUCCESS == tal_tx_status) { MAKE_MAC_BUSY(); return true; } else { return false; } } /* send_scan_cmd() */