/** * @brief Configure the frame sending * * Prepares the static contents of the frame buffer and * writes settings to the TAL pib. */ static void configure_frame_sending(void) { uint8_t temp_value_8; uint16_t temp_value_16; uint16_t fcf = 0; /* Set initial frame length to MHR length without additional MSDU. */ tx_buffer[0] = FRAME_OVERHEAD; /* Calculate FCF. */ fcf = FCF_FRAMETYPE_DATA | FCF_ACK_REQUEST; fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR); fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR); #if (DST_PAN_ID == SRC_PAN_ID) fcf |= FCF_PAN_ID_COMPRESSION; #endif /* Set FCF in frame. */ convert_16_bit_to_byte_array(fcf, &tx_buffer[PL_POS_FCF_1]); /* Set initial sequence number. */ tx_buffer[PL_POS_SEQ_NUM] = (uint8_t)rand(); /* Set Destination PAN-Id in frame. */ temp_value_16 = DEFAULT_PAN_ID; convert_16_bit_to_byte_array(temp_value_16, &tx_buffer[PL_POS_DST_PAN_ID_START]); /* Set Destination Address in frame. */ temp_value_16 = DST_SHORT_ADDR; convert_16_bit_to_byte_array(temp_value_16, &tx_buffer[PL_POS_DST_ADDR_START]); /* Set Source PAN-Id in frame. */ temp_value_16 = DEFAULT_PAN_ID; tal_pib_set(macPANId, (pib_value_t *)&temp_value_16); #if (DST_PAN_ID != SRC_PAN_ID) convert_16_bit_to_byte_array(temp_value_16, &tx_buffer[PL_POS_DST_ADDR_START + 2]); #endif /* Set Source Address in frame. */ temp_value_16 = OWN_SHORT_ADDR; tal_pib_set(macShortAddress, (pib_value_t *)&temp_value_16); #if (DST_PAN_ID != SRC_PAN_ID) convert_16_bit_to_byte_array(temp_value_16, &tx_buffer[PL_POS_DST_ADDR_START + 4]); #else convert_16_bit_to_byte_array(temp_value_16, &tx_buffer[PL_POS_DST_ADDR_START + 2]); #endif /* Set proper channel. */ temp_value_8 = DEFAULT_CHANNEL; tal_pib_set(phyCurrentChannel, (pib_value_t *)&temp_value_8); }
/* * @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 Configure the frame to be used for Packet Streaming * \param frame_len Length of the frame to be used for Packet Streaming */ void configure_pkt_stream_frames(uint16_t frame_len) { uint8_t index; uint16_t app_frame_length; uint8_t *frame_ptr; uint8_t *temp_frame_ptr; uint16_t fcf = 0; uint16_t temp_value; app_payload_t *tmp; stream_pkt = (frame_info_t *)pkt_buffer; /* * Fill in PHY frame. */ /* Get length of current frame. */ app_frame_length = frame_len - FRAME_OVERHEAD; /* Set payload pointer. */ /* Add 2 octets for FCS. */ frame_ptr = temp_frame_ptr = (uint8_t *)stream_pkt + LARGE_BUFFER_SIZE - app_frame_length - FCS_LEN; tmp = (app_payload_t *)temp_frame_ptr; (tmp->cmd_id) = PKT_STREAM_PKT; temp_frame_ptr++; /* * Assign dummy payload values. * Payload is stored to the end of the buffer avoiding payload copying * by TAL. */ /* 1=> cmd ID*/ for (index = 0; index < (app_frame_length - 1); index++) { *temp_frame_ptr++ = index; /* dummy values */ } /* Source Address */ temp_value = tal_pib.ShortAddress; frame_ptr -= SHORT_ADDR_LEN; convert_16_bit_to_byte_array(temp_value, frame_ptr); /* Source PAN-Id */ #if (DST_PAN_ID == SRC_PAN_ID) /* No source PAN-Id included, but FCF updated. */ fcf |= FCF_PAN_ID_COMPRESSION; #else frame_ptr -= PAN_ID_LEN; temp_value = CCPU_ENDIAN_TO_LE16(SRC_PAN_ID); convert_16_bit_to_byte_array(temp_value, frame_ptr); #endif /* Destination Address */ temp_value = 0XFFFF; frame_ptr -= SHORT_ADDR_LEN; convert_16_bit_to_byte_array(temp_value, frame_ptr); /* Destination PAN-Id */ temp_value = CCPU_ENDIAN_TO_LE16(DST_PAN_ID); frame_ptr -= PAN_ID_LEN; convert_16_bit_to_byte_array(temp_value, frame_ptr); /* Set DSN. */ frame_ptr--; *frame_ptr = (uint8_t)rand(); /* Set the FCF. */ // Reserved frame type so that other apps doesnot receive and process this data fcf |= 0x04 | FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR) | FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR); frame_ptr -= FCF_LEN; convert_16_bit_to_byte_array(CCPU_ENDIAN_TO_LE16(fcf), frame_ptr); /* First element shall be length of PHY frame. */ frame_ptr--; *frame_ptr = (uint8_t)frame_len; /* Finished building of frame. */ stream_pkt->mpdu = frame_ptr; }
/** * @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 Constructs a null data frame * * @return Pointer to the created null data frame, NULL otherwise. */ static buffer_t *build_null_data_frame(void) { bool use_long_addr_dest; frame_info_t *transmit_frame; uint8_t frame_len; uint8_t *frame_ptr; uint16_t fcf = 0; buffer_t *buf_ptr = bmm_buffer_alloc(LARGE_BUFFER_SIZE); if (NULL == buf_ptr) { return NULL; } transmit_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr); /* No data payload, this is a null packet.*/ transmit_frame->msg_type = NULL_FRAME; transmit_frame->buffer_header = buf_ptr; /* No indirect transmission. */ transmit_frame->indirect_in_transit = false; /* Update the payload length. */ frame_len = 2 + // Add 2 octets for FCS 2 + // 2 octets for short Destination Address 2 + // 2 octets for Destination PAN-Id 2 + // 2 octets for short Source Address 3; // 3 octets DSN and FCF /* Get the payload pointer. */ frame_ptr = (uint8_t *)transmit_frame + LARGE_BUFFER_SIZE - 2; /* Add 2 octets for FCS. */ /* * Set Source Address. */ if ((BROADCAST == tal_pib.ShortAddress) || (MAC_NO_SHORT_ADDR_VALUE == tal_pib.ShortAddress) ) { /* Use long address as source address. */ frame_ptr -= 8; frame_len += 6; convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr); fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR); } else { /* Use short address as source address. */ frame_ptr -= 2; convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr); fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR); } /* Shall the Intra-PAN bit set? */ if (tal_pib.PANId == mac_parse_data.src_panid) { /* * Both PAN-Ids are identical. * Set intra-PAN bit. */ fcf |= FCF_PAN_ID_COMPRESSION; } else { /* Set Source PAN-Id. */ frame_ptr -= 2; frame_len += 2; convert_16_bit_to_byte_array(tal_pib.PANId, frame_ptr); } /* Set Destination Address. */ use_long_addr_dest = (FCF_LONG_ADDR == mac_parse_data.src_addr_mode); /* Destination address is set from source address of received frame. */ if (use_long_addr_dest) { frame_ptr -= 8; frame_len += 6; convert_64_bit_to_byte_array(mac_parse_data.src_addr.long_address, frame_ptr); fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR) | FCF_SET_FRAMETYPE(FCF_FRAMETYPE_DATA); } else { frame_ptr -= 2; convert_16_bit_to_byte_array(mac_parse_data.src_addr.short_address, frame_ptr); fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR) | FCF_SET_FRAMETYPE(FCF_FRAMETYPE_DATA); } /* Destination PANId is set from source PANId of received frame. */ frame_ptr -= 2; convert_16_bit_to_byte_array(mac_parse_data.src_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. */ transmit_frame->mpdu = frame_ptr; return buf_ptr; } /* build_null_data_frame() */
/* * \brief Function to transmit frames as per 802.15.4 std. * * \param dst_addr_mode destination address mode - can be 16 or 64 bit * \param dst_addr destination address * \param src_addr_mode source address mode - can be 16 or 64 bit * \param msdu_handle msdu handle for the upper layers to track packets * \param payload data payload pointer * \param payload_length data length * \param ack_req specifies ack requested for frame if set to 1 * * \return MAC_SUCCESS if the TAL has accepted the data for frame * transmission * TAL_BUSY if the TAL is busy servicing the previous tx request */ retval_t transmit_frame(uint8_t dst_addr_mode, uint8_t *dst_addr, uint8_t src_addr_mode, uint8_t msdu_handle, uint8_t *payload, uint8_t payload_length, uint8_t ack_req) { uint8_t i; uint16_t temp_value; uint8_t frame_length; uint8_t *frame_ptr; uint8_t *temp_frame_ptr; uint16_t fcf = 0; /* Prevent multiple transmissions , this code is not reentrant*/ if (node_info.transmitting) { return FAILURE; } node_info.transmitting = true; /* Get length of current frame. */ frame_length = (FRAME_OVERHEAD + payload_length); /* Set payload pointer. */ frame_ptr = temp_frame_ptr = (uint8_t *)node_info.tx_frame_info + LARGE_BUFFER_SIZE - payload_length - FCS_LEN; /* * Payload is stored to the end of the buffer avoiding payload * copying by TAL. */ for (i = 0; i < payload_length; i++) { *temp_frame_ptr++ = *(payload + i); } /* Source address */ if (FCF_SHORT_ADDR == src_addr_mode) { frame_ptr -= SHORT_ADDR_LEN; convert_16_bit_to_byte_array(tal_pib.ShortAddress, frame_ptr); fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_SHORT_ADDR); } else { frame_ptr -= EXT_ADDR_LEN; frame_length += FCF_2_SOURCE_ADDR_OFFSET; convert_64_bit_to_byte_array(tal_pib.IeeeAddress, frame_ptr); fcf |= FCF_SET_SOURCE_ADDR_MODE(FCF_LONG_ADDR); } /* Source PAN-Id */ #if (DST_PAN_ID == SRC_PAN_ID) /* No source PAN-Id included, but FCF updated. */ fcf |= FCF_PAN_ID_COMPRESSION; #else frame_ptr -= PAN_ID_LEN; temp_value = CCPU_ENDIAN_TO_LE16(SRC_PAN_ID); convert_16_bit_to_byte_array(temp_value, frame_ptr); #endif /* Destination address */ if (FCF_SHORT_ADDR == dst_addr_mode) { frame_ptr -= SHORT_ADDR_LEN; //convert_16_bit_to_byte_array(*((uint16_t *)dst_addr), // frame_ptr); memcpy(frame_ptr, (uint8_t *)dst_addr, sizeof(uint16_t)); fcf |= FCF_SET_DEST_ADDR_MODE(FCF_SHORT_ADDR); } else { frame_ptr -= EXT_ADDR_LEN; frame_length += PL_POS_DST_ADDR_START; //convert_64_bit_to_byte_array(*((uint64_t *)dst_addr), // frame_ptr); memcpy(frame_ptr, (uint8_t *)dst_addr, sizeof(uint64_t)); fcf |= FCF_SET_DEST_ADDR_MODE(FCF_LONG_ADDR); } /* Destination PAN-Id */ temp_value = CCPU_ENDIAN_TO_LE16(DST_PAN_ID); frame_ptr -= PAN_ID_LEN; convert_16_bit_to_byte_array(temp_value, frame_ptr); /* Set DSN. */ frame_ptr--; *frame_ptr = node_info.msg_seq_num; node_info.msg_seq_num++; /* Set the FCF. */ fcf |= FCF_FRAMETYPE_DATA; if (ack_req) { fcf |= FCF_ACK_REQUEST; } frame_ptr -= FCF_LEN; convert_16_bit_to_byte_array(CCPU_ENDIAN_TO_LE16(fcf), frame_ptr); /* First element shall be length of PHY frame. */ frame_ptr--; *frame_ptr = frame_length; /* Finished building of frame. */ node_info.tx_frame_info->mpdu = frame_ptr; /* Place msdu handle for tracking */ node_info.tx_frame_info->msduHandle = msdu_handle; /* transmit the frame */ return(tal_tx_frame(node_info.tx_frame_info, CSMA_UNSLOTTED, true)); }
/** * @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() */