drivers: nrf_802154: Update the IEEE 802.15.4 component

This commit adds the following:
- double-buffered encryption
- transmit API modifications
- extended support for retransmissions
- robust Enh-Ack generation

sdk-nrf-802154 commit: 17d8d2bb651c42a513f8463b120bab387ab89588

Signed-off-by: Jedrzej Ciupis <jedrzej.ciupis@nordicsemi.no>
This commit is contained in:
Jedrzej Ciupis 2021-07-12 15:58:52 +02:00 committed by Carles Cufí
parent 74b3b21f60
commit d979c8dc31
59 changed files with 3512 additions and 2622 deletions

View File

@ -61,6 +61,7 @@ target_sources(nrf-802154-driver
src/nrf_802154_trx.c
src/nrf_802154_trx_dppi.c
src/nrf_802154_trx_ppi.c
src/nrf_802154_tx_work_buffer.c
src/mac_features/nrf_802154_csma_ca.c
src/mac_features/nrf_802154_delayed_trx.c
src/mac_features/nrf_802154_filter.c

View File

@ -538,16 +538,19 @@ bool nrf_802154_receive_at_cancel(uint32_t id);
* | <---------------------------- PHR -----------------------------------> |
* @endverbatim
*
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain frame
* length (including PHR and FCS). The following bytes contain data. The CRC is
* computed automatically by the radio hardware. Therefore, the FCS field can
* contain any bytes.
* @param[in] cca If the driver is to perform a CCA procedure before transmission.
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain
* frame length (including FCS). The following bytes contain data.
* The CRC is computed automatically by the radio hardware. Therefore,
* the FCS field can contain any bytes.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit and additional parameters for the procedure.
* If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used.
*
* @retval true The transmission procedure was scheduled.
* @retval false The driver could not schedule the transmission procedure.
*/
bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca);
bool nrf_802154_transmit_raw(uint8_t * p_data,
const nrf_802154_transmit_metadata_t * p_metadata);
#else // NRF_802154_USE_RAW_API
@ -580,16 +583,20 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca);
* | <------------------ length -----------------------------> |
* @endverbatim
*
* @param[in] p_data Pointer to the array with the payload of data to transmit. The array should
* exclude PHR or FCS fields of the 802.15.4 frame.
* @param[in] length Length of the given frame. This value must exclude PHR and FCS fields from
* the given frame (exact size of buffer pointed to by @p p_data).
* @param[in] cca If the driver is to perform a CCA procedure before transmission.
* @param[in] p_data Pointer to the array with the payload of data to transmit. The array
* should exclude PHR or FCS fields of the 802.15.4 frame.
* @param[in] length Length of the given frame. This value must exclude PHR and FCS fields
* from the given frame (exact size of buffer pointed to by @p p_data).
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit and additional parameters for the procedure.
* If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used.
*
* @retval true The transmission procedure was scheduled.
* @retval false The driver could not schedule the transmission procedure.
*/
bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca);
bool nrf_802154_transmit(const uint8_t * p_data,
uint8_t length,
const nrf_802154_transmit_metadata_t * p_metadata);
#endif // NRF_802154_USE_RAW_API
@ -616,75 +623,24 @@ bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca);
* A successfully scheduled transmission can be cancelled by a call
* to @ref nrf_802154_transmit_at_cancel.
*
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain
* the frame length (including PHR and FCS). The following bytes contain data.
* The CRC is computed automatically by the radio hardware. Therefore, the FCS
* field can contain any bytes.
* @param[in] cca If the driver is to perform a CCA procedure before transmission.
* @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler,
* in microseconds (us).
* @param[in] dt Delta of delay time from @p t0, in microseconds (us).
* @param[in] channel Radio channel on which the frame is to be transmitted.
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain
* the frame length (including FCS). The following bytes contain data.
* The CRC is computed automatically by the radio hardware. Therefore,
* the FCS field can contain any bytes.
* @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler,
* in microseconds (us).
* @param[in] dt Delta of delay time from @p t0, in microseconds (us).
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit and additional parameters for the procedure.
* If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used.
*
* @retval true The transmission procedure was scheduled.
* @retval false The driver could not schedule the transmission procedure.
*/
bool nrf_802154_transmit_raw_at(const uint8_t * p_data,
bool cca,
uint32_t t0,
uint32_t dt,
uint8_t channel);
/**
* @brief Requests retransmission at the specified time.
*
* @note This function is implemented in a zero-copy fashion. It passes the given buffer pointer to
* the RADIO peripheral.
*
* @note This function is meant specifically to be used for transmitting frames for which
* @ref nrf_802154_transmit_failed was reported in the original transmission attempt. This
* function does not perform any modifications to the provided frame's content. In particular,
* it performs neither authentication nor confidentiality transform of the frame's content.
* Therefore it must not be called to execute the first transmission attempt of a given frame.
* Doing so might lead to a number of issues such as security breaches and transmissions of
* malformed or incorrect frames.
*
* @note Only a single transmission or only a single retransmission can be scheduled at a time.
*
* This function is asynchronous. It queues the delayed transmission using the Radio Scheduler
* module and performs it at the specified time.
*
* If the delayed retransmission is successfully performed, @ref nrf_802154_transmitted is called.
* If the delayed retransmission cannot be performed or the requested transmission timeslot is
* denied, @ref nrf_802154_transmit_failed with the @ref NRF_802154_TX_ERROR_TIMESLOT_DENIED
* argument is called.
*
* This function is designed to transmit the first symbol of SHR at the given time.
*
* If the requested retransmission time is in the past, the function returns false and does not
* schedule retransmission.
*
* A successfully scheduled retransmission can be cancelled by a call
* to @ref nrf_802154_transmit_at_cancel, similarly to a successfully scheduled transmission.
*
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain
* the frame length (including PHR and FCS). The following bytes contain data.
* The CRC is computed automatically by the radio hardware. Therefore, the FCS
* field can contain any bytes.
* @param[in] cca If the driver is to perform a CCA procedure before transmission.
* @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler,
* in microseconds (us).
* @param[in] dt Delta of delay time from @p t0, in microseconds (us).
* @param[in] channel Radio channel on which the frame is to be transmitted.
*
* @retval true The retransmission procedure was scheduled.
* @retval false The driver could not schedule the retransmission procedure.
*/
bool nrf_802154_retransmit_raw_at(const uint8_t * p_data,
bool cca,
uint32_t t0,
uint32_t dt,
uint8_t channel);
bool nrf_802154_transmit_raw_at(uint8_t * p_data,
uint32_t t0,
uint32_t dt,
const nrf_802154_transmit_at_metadata_t * p_metadata);
/**
* @brief Cancels a delayed transmission scheduled by a call to @ref nrf_802154_transmit_raw_at.
@ -917,53 +873,21 @@ extern void nrf_802154_tx_started(const uint8_t * p_frame);
* @note If ACK was requested for the transmitted frame, this function is called after a proper ACK
* is received. If ACK was not requested, this function is called just after transmission has
* ended.
* @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot be used
* to receive a frame) until @ref nrf_802154_buffer_free_raw is called.
* @note The buffer pointed to by @p p_ack may be modified by the function handler (and other
* modules) until @ref nrf_802154_buffer_free_raw is called.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK.
* The first byte in the buffer is the length of the frame (PHR). The following
* bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes
* FCS. FCS is already verified by the hardware and may be modified by the
* hardware. If ACK was not requested, @p p_ack is set to NULL.
* @param[in] power RSSI of the received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame or 0 if ACK was not requested.
*/
extern void nrf_802154_transmitted_raw(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi);
/**
* @brief Notifies that a frame was transmitted.
*
* This function works like @ref nrf_802154_transmitted_raw and adds a timestamp to the parameter
* list.
*
* @note @p timestamp may be inaccurate due to software latency (IRQ handling).
* @note @p timestamp granularity depends on the granularity of the timer driver in the
* @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack
* is not modified by the radio driver (and cannot be used to receive a frame) until
* @ref nrf_802154_buffer_free_raw is called.
* @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack
* may be modified by the function handler (and other modules) until
* @ref nrf_802154_buffer_free_raw is called.
* @note @ref nrf_802154_transmit_done_metadata_t.data.transmitted.time granularity depends on the
* granularity of the timer driver in the
* platform/timer directory.
* @note Including a timestamp for received frames uses resources like CPU time and memory. If the
* timestamp is not required, use @ref nrf_802154_received instead.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK.
* The first byte in the buffer is the length of the frame (PHR). The following
* bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes
* FCS. FCS is already verified by the hardware and may be modified by the
* hardware. If ACK was not requested, @p p_ack is set to NULL.
* @param[in] power RSSI of the received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame or 0 if ACK was not requested.
* @param[in] time Timestamp taken when the last symbol of ACK is received or 0 if ACK was not
* requested.
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
extern void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi,
uint32_t time);
extern void nrf_802154_transmitted_raw(uint8_t * p_frame,
const nrf_802154_transmit_done_metadata_t * p_metadata);
#else // NRF_802154_USE_RAW_API
@ -973,56 +897,24 @@ extern void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame,
* @note If ACK was requested for the transmitted frame, this function is called after a proper ACK
* is received. If ACK was not requested, this function is called just after transmission has
* ended.
* @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot
* be used to receive a frame) until @ref nrf_802154_buffer_free is
* called.
* @note The buffer pointed to by @p p_ack may be modified by the function handler (and other
* modules) until @ref nrf_802154_buffer_free is called.
* @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack
* is not modified by the radio driver (and cannot be used to receive a frame) until
* @ref nrf_802154_buffer_free_raw is called.
* @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack
* may be modified by the function handler (and other modules) until
* @ref nrf_802154_buffer_free_raw is called.
* @note The next higher layer must handle either @ref nrf_802154_transmitted or
* @ref nrf_802154_transmitted_raw. It should not handle both functions.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to a buffer that contains only the received ACK payload (PSDU
* excluding FCS).
* If ACK was not requested, @p p_ack is set to NULL.
* @param[in] length Length of the received ACK payload or 0 if ACK was not requested.
* @param[in] power RSSI of the received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame or 0 if ACK was not requested.
*/
extern void nrf_802154_transmitted(const uint8_t * p_frame,
uint8_t * p_ack,
uint8_t length,
int8_t power,
uint8_t lqi);
/**
* @brief Notifies that a frame was transmitted.
*
* This function works like @ref nrf_802154_transmitted and adds a timestamp to the parameter
* list.
*
* @note @p timestamp may be inaccurate due to software latency (IRQ handling).
* @note @p timestamp granularity depends on the granularity of the timer driver
* in the platform/timer directory.
* @note @ref nrf_802154_transmit_done_metadata_t.data.transmitted.time granularity depends on the
* granularity of the timer driver in the platform/timer directory.
* @note Including a timestamp for received frames uses resources like CPU time and memory. If the
* timestamp is not required, use @ref nrf_802154_received instead.
*
* @param[in] p_frame Pointer to the buffer containing PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to the buffer containing only the received ACK payload (PSDU
* excluding FCS).
* If ACK was not requested, @p p_ack is set to NULL.
* @param[in] length Length of the received ACK payload.
* @param[in] power RSSI of the received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame or 0 if ACK was not requested.
* @param[in] time Timestamp taken when the last symbol of ACK is received or 0 if ACK was not
* requested.
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
extern void nrf_802154_transmitted_timestamp(const uint8_t * p_frame,
uint8_t * p_ack,
uint8_t length,
int8_t power,
uint8_t lqi,
uint32_t time);
extern void nrf_802154_transmitted(uint8_t * p_frame,
const nrf_802154_transmit_done_metadata_t * p_metadata);
#endif // !NRF_802154_USE_RAW_API
@ -1031,12 +923,17 @@ extern void nrf_802154_transmitted_timestamp(const uint8_t * p_frame,
*
* This function is called if the transmission procedure fails.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not
* transmitted.
* @param[in] error Reason of the failure.
* @note Frame data values in @ref nrf_802154_transmit_done_metadata_t.data are invalid for
* @ref nrf_802154_transmit_failed callout.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not
* transmitted.
* @param[in] error Reason of the failure.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
extern void nrf_802154_transmit_failed(const uint8_t * p_frame,
nrf_802154_tx_error_t error);
extern void nrf_802154_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error,
const nrf_802154_transmit_done_metadata_t * p_metadata);
/**
* @brief Notifies that the energy detection procedure finished.
@ -1464,35 +1361,15 @@ void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg);
* by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected
* to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame.
*
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw.
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit. If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used.
*
* @retval true The chain of CSMA-CA and transmission procedure was scheduled.
* @retval false The driver could not schedule the procedure chain.
*/
void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data);
/**
* @brief Performs the CSMA-CA procedure and retransmits a frame in case of success.
*
* The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted_raw or
* @ref nrf_802154_transmit_failed.
*
* @note This function is meant specifically to be used for transmitting frames for which
* @ref nrf_802154_transmit_failed was reported in the original transmission attempt. This
* function does not perform any modifications to the provided frame's content. In particular,
* it performs neither authentication nor confidentiality transform of the frame's content.
* Therefore it must not be called to execute the first transmission attempt of a given frame.
* Doing so might lead to a number of issues such as security breaches and transmissions of
* malformed or incorrect frames.
*
* @note The driver may be configured to automatically time out waiting for an ACK frame depending
* on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled,
* the CSMA-CA procedure does not time out waiting for an ACK frame if a frame
* with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer
* to time out waiting for the ACK frame. This timer can be started
* by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected
* to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame.
*
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw.
*/
void nrf_802154_retransmit_csma_ca_raw(const uint8_t * p_data);
bool nrf_802154_transmit_csma_ca_raw(uint8_t * p_data,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata);
#else // NRF_802154_USE_RAW_API
@ -1510,37 +1387,18 @@ void nrf_802154_retransmit_csma_ca_raw(const uint8_t * p_data);
* by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected
* to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame.
*
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit.
* @param[in] length Length of the given frame. See also @ref nrf_802154_transmit.
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit.
* @param[in] length Length of the given frame. See also @ref nrf_802154_transmit.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit. If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT
* is used.
*
* @retval true The chain of CSMA-CA and transmission procedure was scheduled.
* @retval false The driver could not schedule the procedure chain.
*/
void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length);
/**
* @brief Performs the CSMA-CA procedure and retransmits a frame in case of success.
*
* The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted_raw or
* @ref nrf_802154_transmit_failed.
*
* @note This function is meant specifically to be used for transmitting frames for which
* @ref nrf_802154_transmit_failed was reported in the original transmission attempt. This
* function does not perform any modifications to the provided frame's content. In particular,
* it performs neither authentication nor confidentiality transform of the frame's content.
* Therefore it must not be called to execute the first transmission attempt of a given frame.
* Doing so might lead to a number of issues such as security breaches and transmissions of
* malformed or incorrect frames.
*
* @note The driver may be configured to automatically time out waiting for an ACK frame depending
* on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled,
* the CSMA-CA procedure does not time out waiting for an ACK frame if a frame
* with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer
* to time out waiting for the ACK frame. This timer can be started
* by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected
* to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame.
*
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit.
* @param[in] length Length of the given frame. See also @ref nrf_802154_transmit.
*/
void nrf_802154_retransmit_csma_ca(const uint8_t * p_data, uint8_t length);
bool nrf_802154_transmit_csma_ca(const uint8_t * p_data,
uint8_t length,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata);
#endif // NRF_802154_USE_RAW_API

View File

@ -105,6 +105,8 @@
#define KEY_SRC_KEY_ID_MODE_2_SIZE 4 ///< Size of the Key Source field when Key Identifier Mode equals 2.
#define KEY_SRC_KEY_ID_MODE_3_SIZE 8 ///< Size of the Key Source field when Key Identifier Mode equals 3.
#define KEY_IDX_SIZE 1 ///< Size of the Key Index field
#define MAC_CMD_COMMAND_ID_SIZE 1 ///< Size of the MAC Command ID field.
#define MAC_CMD_ASSOC_REQ 0x01 ///< Command frame identifier for MAC Association request.
#define MAC_CMD_ASSOC_RESP 0x02 ///< Command frame identifier for MAC Association response.
@ -129,6 +131,7 @@
#define SECURITY_ENABLED_OFFSET 1 ///< Byte containing the Security Enabled bit.
#define SECURITY_ENABLED_BIT 0x08 ///< Bits containing the Security Enabled field.
#define SECURITY_LEVEL_MASK 0x07 ///< Mask of bits containing the Security level field.
#define SECURITY_LEVEL_NONE 0x00 ///< Bits indicating a frame with no security attributes (0b000).
#define SECURITY_LEVEL_MIC_32 0x01 ///< Bits containing the 32-bit Message Integrity Code (0b001).
#define SECURITY_LEVEL_MIC_64 0x02 ///< Bits containing the 64-bit Message Integrity Code (0b010).
#define SECURITY_LEVEL_MIC_128 0x03 ///< Bits containing the 128-bit Message Integrity Code (0b011).
@ -193,7 +196,7 @@
#define IE_VENDOR_THREAD_SUBTYPE_OFFSET 3 ///< Thread Vendor-specific IE subtype offset
#define IE_VENDOR_THREAD_DATA_OFFSET 4 ///< Thread Vendor-specific IE DATA offset
#define IE_VENDOR_THREAD_OUI 0xf4ce36 ///< Thread Vendor-specific IE OUI
#define IE_VENDOR_THREAD_OUI 0xeab89b ///< Thread Vendor-specific IE OUI
#define IE_VENDOR_THREAD_SIZE_MIN 4 ///< Thread Vendor-specific IE minimum length
#define IE_VENDOR_THREAD_ACK_PROBING_ID 0x00 ///< Thread Vendor-specific ACK Probing IE subtype ID

View File

@ -369,17 +369,101 @@ typedef struct
/**
* @brief Function pointer used for notifying about transmission failure.
*/
typedef void (* nrf_802154_transmit_failed_notification_t)(const uint8_t * p_frame,
typedef void (* nrf_802154_transmit_failed_notification_t)(uint8_t * p_frame,
nrf_802154_tx_error_t error);
/**
* @brief Structure with frame properties associated with the transmission operation.
*
* @note When using to request transmission, parameters contained here influence whether or not
* the security related data transformation will be performed. In particular, the driver may:
* - update frame counter field if the dynamic parts of the frame are not yet updated
* - secure a non-secured frame on-the-fly
* If performed, the above operations are configured by the IEEE 802.15.4 Auxiliary Security
* Header present in the transmitted frame.
*
* @note It is recommended to use values defined in @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT
* to perform the first transmission attempt. Using other values may result in transmitting
* malformed or incorrect frames and creating security breaches.
*
* @note The combination with is_secured = true and dynamic_data_is_set = false is not allowed.
* An attempt to transmit a frame with such parameters will fail unconditionally.
*/
typedef struct
{
bool is_secured; // !< If the frame to be transmitted is already secured (in the sense of IEEE 802.15.4 security operations).
bool dynamic_data_is_set; // !< If dynamic data of the frame frame to be transmitted is set.
} nrf_802154_transmitted_frame_props_t;
/**
* @brief Default initializer for nrf_802154_transmitted_frame_props_t.
*/
#define NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT \
(nrf_802154_transmitted_frame_props_t){ \
.is_secured = false, \
.dynamic_data_is_set = false \
}
/**
* @brief Structure with transmit request metadata for simple transmission request.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted.
bool cca; // !< If the driver is to perform a CCA procedure before transmission.
} nrf_802154_transmit_metadata_t;
/**
* @brief Structure with transmit request metadata for scheduling transmission at a specific time.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted.
bool cca; // !< If the driver is to perform a CCA procedure before transmission.
uint8_t channel; // !< Radio channel on which the frame is to be transmitted.
} nrf_802154_transmit_at_metadata_t;
/**
* @brief Structure with transmit request metadata for transmission preceded by CSMA-CA procedure.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted.
} nrf_802154_transmit_csma_ca_metadata_t;
/**
* @brief Structure that holds transmission result metadata.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the returned frame.
union
{
struct
{
uint8_t * p_ack; // !< If NRF_802154_USE_RAW_API is disabled, p_ack is a pointer to a buffer that contains only the received ACK payload (PSDU excluding FCS).
// If NRF_802154_USE_RAW_API is enabled, p_ack is a pointer to a buffer that contains PHR and PSDU of the received ACK. The first byte
// in the buffer is the length of the frame (PHR). The following bytes contain the ACK frame itself (PSDU). The length byte
// (PHR) includes FCS. FCS is already verified by the hardware and may be modified by the hardware.
// If ACK was not requested or requested but not received, @ref p_ack is set to NULL.
uint8_t length; // !< Length of the received ACK payload or 0 if @ref p_ack is NULL.
int8_t power; // !< RSSI of the received frame or 0 if @ref p_ack is NULL.
uint8_t lqi; // !< LQI of the received frame or 0 if @ref p_ack is NULL.
uint32_t time; // !< Timestamp taken when the last symbol of ACK is received. If @ref p_ack is NULL, this field is set to 0, but is considered invalid.
} transmitted; // !< Result values for a successful frame transmission.
} data; // !< Result values that are valid only for successful operations.
} nrf_802154_transmit_done_metadata_t;
/**
* @brief Structure that holds transmission parameters.
*/
typedef struct
{
bool cca; // !< If the driver is to perform CCA procedure before transmission.
bool immediate; // !< If true, the driver schedules transmission immediately or never. If false, the transmission may be postponed until its preconditions are met.
bool is_retransmission; // !< Indicates if a given transmission attempt is a retransmission.
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted.
bool cca; // !< If the driver is to perform CCA procedure before transmission.
bool immediate; // !< If true, the driver schedules transmission immediately or never. If false, the transmission may be postponed
// until its preconditions are met.
} nrf_802154_transmit_params_t;
/**

View File

@ -328,16 +328,16 @@ static bool addr_index_find(const uint8_t * p_addr,
/**
* @brief Thread implementation of the address matching algorithm.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
* @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
* @retval false Pending bit is to be cleared.
*/
static bool addr_match_thread(const uint8_t * p_frame)
static bool addr_match_thread(const nrf_802154_frame_parser_data_t * p_frame_data)
{
bool extended;
uint32_t location;
const uint8_t * p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame, &extended);
bool extended = nrf_802154_frame_parser_src_addr_is_extended(p_frame_data);
const uint8_t * p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame_data);
// The pending bit is set by default.
if (!m_pending_bit.enabled || (NULL == p_src_addr))
@ -351,18 +351,18 @@ static bool addr_match_thread(const uint8_t * p_frame)
/**
* @brief Zigbee implementation of the address matching algorithm.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
* @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
* @retval false Pending bit is to be cleared.
*/
static bool addr_match_zigbee(const uint8_t * p_frame)
static bool addr_match_zigbee(const nrf_802154_frame_parser_data_t * p_frame_data)
{
uint8_t frame_type;
nrf_802154_frame_parser_mhr_data_t mhr_fields;
uint32_t location;
const uint8_t * p_cmd = p_frame;
bool ret = false;
uint8_t src_addr_type;
uint32_t location;
const uint8_t * p_cmd;
const uint8_t * p_src_addr;
bool ret = false;
// If ack data generator module is disabled do not perform check, return true by default.
if (!m_pending_bit.enabled)
@ -371,31 +371,19 @@ static bool addr_match_zigbee(const uint8_t * p_frame)
}
// Check the frame type.
frame_type = (p_frame[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK);
p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame_data);
src_addr_type = nrf_802154_frame_parser_src_addr_type_get(p_frame_data);
// Parse the MAC header and retrieve the command type.
if (nrf_802154_frame_parser_mhr_parse(p_frame, &mhr_fields))
{
// Note: Security header is not included in the offset.
// If security is to be used at any point, additional calculation
// in nrf_802154_frame_parser_mhr_parse needs to be implemented.
p_cmd += mhr_fields.addressing_end_offset;
}
else
{
// If invalid source or destination addressing mode is detected, assume unknown device.
// Command type cannot be checked, as addressing_end_offset value will be invalid.
return true;
}
p_cmd = nrf_802154_frame_parser_mac_command_id_get(p_frame_data);
// Check frame type and command type.
if ((frame_type == FRAME_TYPE_COMMAND) && (*p_cmd == MAC_CMD_DATA_REQ))
if ((p_cmd != NULL) && (*p_cmd == MAC_CMD_DATA_REQ))
{
// Check addressing type - in long case address, pb should always be 1.
if (mhr_fields.src_addr_size == SHORT_ADDRESS_SIZE)
if (src_addr_type == SRC_ADDR_TYPE_SHORT)
{
// Return true if address is not found on the m_pending_bits list.
ret = !addr_index_find(mhr_fields.p_src_addr,
ret = !addr_index_find(p_src_addr,
&location,
NRF_802154_ACK_DATA_PENDING_BIT,
false);
@ -415,13 +403,13 @@ static bool addr_match_zigbee(const uint8_t * p_frame)
* Function always returns true. It is IEEE 802.15.4 compliant, as per 6.7.3.
* Higher layer should ensure empty data frame with no AR is sent afterwards.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
* @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
*/
static bool addr_match_standard_compliant(const uint8_t * p_frame)
static bool addr_match_standard_compliant(const nrf_802154_frame_parser_data_t * p_frame_data)
{
(void)p_frame;
(void)p_frame_data;
return true;
}
@ -693,22 +681,23 @@ void nrf_802154_ack_data_src_addr_matching_method_set(nrf_802154_src_addr_match_
}
bool nrf_802154_ack_data_pending_bit_should_be_set(const uint8_t * p_frame)
bool nrf_802154_ack_data_pending_bit_should_be_set(
const nrf_802154_frame_parser_data_t * p_frame_data)
{
bool ret;
switch (m_src_matching_method)
{
case NRF_802154_SRC_ADDR_MATCH_THREAD:
ret = addr_match_thread(p_frame);
ret = addr_match_thread(p_frame_data);
break;
case NRF_802154_SRC_ADDR_MATCH_ZIGBEE:
ret = addr_match_zigbee(p_frame);
ret = addr_match_zigbee(p_frame_data);
break;
case NRF_802154_SRC_ADDR_MATCH_ALWAYS_1:
ret = addr_match_standard_compliant(p_frame);
ret = addr_match_standard_compliant(p_frame_data);
break;
default:

View File

@ -45,6 +45,7 @@
#include <stdint.h>
#include "nrf_802154_types.h"
#include "mac_features/nrf_802154_frame_parser.h"
/**
* @brief Initializes the ACK data generator module.
@ -123,12 +124,13 @@ void nrf_802154_ack_data_src_addr_matching_method_set(nrf_802154_src_addr_match_
/**
* @brief Checks if a pending bit is to be set in the ACK frame sent in response to a given frame.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
* @param[in] p_frame_data Pointer to the frame parser data for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
* @retval false Pending bit is to be cleared.
*/
bool nrf_802154_ack_data_pending_bit_should_be_set(const uint8_t * p_frame);
bool nrf_802154_ack_data_pending_bit_should_be_set(
const nrf_802154_frame_parser_data_t * p_frame_data);
/**
* @brief Gets the IE data stored in the list for the source address of the provided frame.

View File

@ -54,9 +54,10 @@ typedef enum
FRAME_VERSION_INVALID
} frame_version_t;
static frame_version_t frame_version_is_2015_or_above(const uint8_t * p_frame)
static frame_version_t frame_version_is_2015_or_above(
const nrf_802154_frame_parser_data_t * p_frame_data)
{
switch (p_frame[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK)
switch (nrf_802154_frame_parser_frame_version_get(p_frame_data))
{
case FRAME_VERSION_0:
case FRAME_VERSION_1:
@ -77,18 +78,18 @@ void nrf_802154_ack_generator_init(void)
nrf_802154_enh_ack_generator_init();
}
const uint8_t * nrf_802154_ack_generator_create(const uint8_t * p_frame)
uint8_t * nrf_802154_ack_generator_create(const nrf_802154_frame_parser_data_t * p_frame_data)
{
// This function should not be called if ACK is not requested.
assert(p_frame[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT);
assert(nrf_802154_frame_parser_ar_bit_is_set(p_frame_data));
switch (frame_version_is_2015_or_above(p_frame))
switch (frame_version_is_2015_or_above(p_frame_data))
{
case FRAME_VERSION_BELOW_2015:
return nrf_802154_imm_ack_generator_create(p_frame);
return nrf_802154_imm_ack_generator_create(p_frame_data);
case FRAME_VERSION_2015_OR_ABOVE:
return nrf_802154_enh_ack_generator_create(p_frame);
return nrf_802154_enh_ack_generator_create(p_frame_data);
default:
return NULL;

View File

@ -42,17 +42,20 @@
#include <stdint.h>
#include "mac_features/nrf_802154_frame_parser.h"
/** Initializes the ACK generator module. */
void nrf_802154_ack_generator_init(void);
/** Creates an ACK in response to the provided frame and inserts it into a radio buffer.
*
* @param [in] p_frame Pointer to the buffer that contains PHR and PSDU of the frame
* to respond to.
* @param [in] p_frame_data Pointer to the parser data of the frame for which an Ack
* will be generated.
*
* @returns Either pointer to a constant buffer that contains PHR and PSDU
* of the created ACK frame, or NULL in case of an invalid frame.
*/
const uint8_t * nrf_802154_ack_generator_create(const uint8_t * p_frame);
uint8_t * nrf_802154_ack_generator_create(
const nrf_802154_frame_parser_data_t * p_frame_data);
#endif // NRF_802154_ACK_GENERATOR_H

View File

@ -56,17 +56,24 @@
static uint8_t m_ack_data[ENH_ACK_MAX_SIZE + PHR_SIZE];
static void ack_buffer_clear(void)
static void ack_buffer_clear(nrf_802154_frame_parser_data_t * p_ack_data)
{
memset(m_ack_data, 0, FCF_SIZE + PHR_SIZE);
memset(&m_ack_data[PHR_OFFSET], 0U, PHR_SIZE + FCF_SIZE);
(void)nrf_802154_frame_parser_data_init(m_ack_data, 0U, PARSE_LEVEL_NONE, p_ack_data);
}
static void sequence_number_set(const uint8_t * p_frame)
static uint8_t sequence_number_set(const nrf_802154_frame_parser_data_t * p_frame_data)
{
if (!nrf_802154_frame_parser_dsn_suppress_bit_is_set(p_frame))
const uint8_t * p_frame_dsn = nrf_802154_frame_parser_dsn_get(p_frame_data);
if (p_frame_dsn != NULL)
{
m_ack_data[DSN_OFFSET] = p_frame[DSN_OFFSET];
m_ack_data[DSN_OFFSET] = *p_frame_dsn;
return DSN_SIZE;
}
return 0U;
}
/***************************************************************************************************
@ -78,51 +85,53 @@ static void fcf_frame_type_set(void)
m_ack_data[FRAME_TYPE_OFFSET] |= FRAME_TYPE_ACK;
}
static void fcf_security_enabled_set(const uint8_t * p_frame)
static void fcf_security_enabled_set(const nrf_802154_frame_parser_data_t * p_frame_data)
{
m_ack_data[SECURITY_ENABLED_OFFSET] |=
(p_frame[SECURITY_ENABLED_OFFSET] & SECURITY_ENABLED_BIT);
if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame_data))
{
m_ack_data[SECURITY_ENABLED_OFFSET] |= SECURITY_ENABLED_BIT;
}
}
static void fcf_frame_pending_set(const uint8_t * p_frame)
static void fcf_frame_pending_set(const nrf_802154_frame_parser_data_t * p_frame_data)
{
if (nrf_802154_ack_data_pending_bit_should_be_set(p_frame))
if (nrf_802154_ack_data_pending_bit_should_be_set(p_frame_data))
{
m_ack_data[FRAME_PENDING_OFFSET] |= FRAME_PENDING_BIT;
}
}
static void fcf_panid_compression_set(const uint8_t * p_frame)
static void fcf_panid_compression_set(const nrf_802154_frame_parser_data_t * p_frame_data)
{
if (p_frame[PAN_ID_COMPR_OFFSET] & PAN_ID_COMPR_MASK)
if (nrf_802154_frame_parser_panid_compression_is_set(p_frame_data))
{
m_ack_data[PAN_ID_COMPR_OFFSET] |= PAN_ID_COMPR_MASK;
}
}
static void fcf_sequence_number_suppression_set(const uint8_t * p_frame)
static void fcf_sequence_number_suppression_set(const nrf_802154_frame_parser_data_t * p_frame_data)
{
if (nrf_802154_frame_parser_dsn_suppress_bit_is_set(p_frame))
if (nrf_802154_frame_parser_dsn_suppress_bit_is_set(p_frame_data))
{
m_ack_data[DSN_SUPPRESS_OFFSET] |= DSN_SUPPRESS_BIT;
}
}
static void fcf_ie_present_set(const uint8_t * p_ie_data)
static void fcf_ie_present_set(bool ie_present)
{
if (p_ie_data != NULL)
if (ie_present)
{
m_ack_data[IE_PRESENT_OFFSET] |= IE_PRESENT_BIT;
}
}
static void fcf_dst_addressing_mode_set(const uint8_t * p_frame)
static void fcf_dst_addressing_mode_set(const nrf_802154_frame_parser_data_t * p_frame_data)
{
if (nrf_802154_frame_parser_src_addr_is_extended(p_frame))
if (nrf_802154_frame_parser_src_addr_is_extended(p_frame_data))
{
m_ack_data[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_EXTENDED;
}
else if (nrf_802154_frame_parser_src_addr_is_short(p_frame))
else if (nrf_802154_frame_parser_src_addr_is_short(p_frame_data))
{
m_ack_data[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_SHORT;
}
@ -142,65 +151,72 @@ static void fcf_frame_version_set(void)
m_ack_data[FRAME_VERSION_OFFSET] |= FRAME_VERSION_2;
}
static void frame_control_set(const uint8_t * p_frame,
const uint8_t * p_ie_data,
nrf_802154_frame_parser_mhr_data_t * p_ack_offsets)
static uint8_t frame_control_set(const nrf_802154_frame_parser_data_t * p_frame_data,
bool ie_present)
{
bool parse_results;
fcf_frame_type_set();
fcf_security_enabled_set(p_frame);
fcf_frame_pending_set(p_frame);
fcf_panid_compression_set(p_frame);
fcf_sequence_number_suppression_set(p_frame);
fcf_ie_present_set(p_ie_data);
fcf_dst_addressing_mode_set(p_frame);
fcf_security_enabled_set(p_frame_data);
fcf_frame_pending_set(p_frame_data);
fcf_panid_compression_set(p_frame_data);
fcf_sequence_number_suppression_set(p_frame_data);
fcf_ie_present_set(ie_present);
fcf_dst_addressing_mode_set(p_frame_data);
fcf_frame_version_set();
fcf_src_addressing_mode_set();
parse_results = nrf_802154_frame_parser_mhr_parse(m_ack_data, p_ack_offsets);
assert(parse_results);
(void)parse_results;
m_ack_data[PHR_OFFSET] = p_ack_offsets->addressing_end_offset - PHR_SIZE + FCS_SIZE;
return FCF_SIZE;
}
/***************************************************************************************************
* @section Addressing fields functions
**************************************************************************************************/
static void destination_set(const nrf_802154_frame_parser_mhr_data_t * p_frame,
const nrf_802154_frame_parser_mhr_data_t * p_ack)
static uint8_t destination_set(const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_frame_parser_data_t * p_ack_data)
{
uint8_t bytes_written = 0U;
uint8_t * p_ack_dst_panid = (uint8_t *)nrf_802154_frame_parser_dst_panid_get(p_ack_data);
uint8_t * p_ack_dst_addr = (uint8_t *)nrf_802154_frame_parser_dst_addr_get(p_ack_data);
const uint8_t * p_frame_src_panid = nrf_802154_frame_parser_src_panid_get(p_frame_data);
const uint8_t * p_frame_dst_panid = nrf_802154_frame_parser_dst_panid_get(p_frame_data);
const uint8_t * p_frame_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame_data);
uint8_t src_addr_size = nrf_802154_frame_parser_src_addr_size_get(p_frame_data);
// Fill the Ack destination PAN ID field.
if (p_ack->p_dst_panid != NULL)
if (p_ack_dst_panid != NULL)
{
const uint8_t * p_dst_panid;
if (p_frame->p_src_panid != NULL)
if (p_frame_src_panid != NULL)
{
p_dst_panid = p_frame->p_src_panid;
p_dst_panid = p_frame_src_panid;
}
else if (p_frame->p_dst_panid != NULL)
else if (p_frame_dst_panid != NULL)
{
p_dst_panid = p_frame->p_dst_panid;
p_dst_panid = p_frame_dst_panid;
}
else
{
p_dst_panid = nrf_802154_pib_pan_id_get();
}
memcpy((uint8_t *)p_ack->p_dst_panid, p_dst_panid, PAN_ID_SIZE);
memcpy(p_ack_dst_panid, p_dst_panid, PAN_ID_SIZE);
bytes_written += PAN_ID_SIZE;
}
// Fill the Ack destination address field.
if (p_frame->p_src_addr != NULL)
if ((p_ack_dst_addr != NULL) && (p_frame_src_addr != NULL))
{
assert(p_ack->p_dst_addr != NULL);
assert(p_ack->dst_addr_size == p_frame->src_addr_size);
assert(nrf_802154_frame_parser_dst_addr_is_extended(p_ack_data) ==
nrf_802154_frame_parser_src_addr_is_extended(p_frame_data));
memcpy((uint8_t *)p_ack->p_dst_addr, p_frame->p_src_addr, p_frame->src_addr_size);
memcpy(p_ack_dst_addr, p_frame_src_addr, src_addr_size);
bytes_written += src_addr_size;
}
return bytes_written;
}
static void source_set(void)
@ -212,180 +228,136 @@ static void source_set(void)
* @section Auxiliary security header functions
**************************************************************************************************/
static uint8_t security_header_size(const nrf_802154_frame_parser_mhr_data_t * p_frame)
static uint8_t security_header_size(const nrf_802154_frame_parser_data_t * p_frame_data)
{
uint8_t sec_hdr_size = SECURITY_CONTROL_SIZE;
uint8_t sec_ctrl_offset = nrf_802154_frame_parser_sec_ctrl_offset_get(p_frame_data);
uint8_t aux_sec_hdr_end = nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(p_frame_data);
if (((*p_frame->p_sec_ctrl) & FRAME_COUNTER_SUPPRESS_BIT) == 0)
{
sec_hdr_size += FRAME_COUNTER_SIZE;
}
switch ((*p_frame->p_sec_ctrl) & KEY_ID_MODE_MASK)
{
case KEY_ID_MODE_1_MASK:
sec_hdr_size += KEY_ID_MODE_1_SIZE;
break;
case KEY_ID_MODE_2_MASK:
sec_hdr_size += KEY_ID_MODE_2_SIZE;
break;
case KEY_ID_MODE_3_MASK:
sec_hdr_size += KEY_ID_MODE_3_SIZE;
break;
default:
break;
}
return sec_hdr_size;
return aux_sec_hdr_end - sec_ctrl_offset;
}
static void security_control_set(const nrf_802154_frame_parser_mhr_data_t * p_frame,
const nrf_802154_frame_parser_mhr_data_t * p_ack)
static uint8_t key_id_size_get(uint8_t key_id_mode)
{
assert(p_frame->p_sec_ctrl != NULL);
// All the bits in the security control byte can be copied.
*(uint8_t *)p_ack->p_sec_ctrl = *p_frame->p_sec_ctrl;
m_ack_data[PHR_OFFSET] += SECURITY_CONTROL_SIZE;
}
static const uint8_t * security_key_id_set(const nrf_802154_frame_parser_mhr_data_t * p_frame,
const nrf_802154_frame_parser_mhr_data_t * p_ack,
bool fc_suppressed,
const uint8_t ** p_sec_end)
{
const uint8_t * p_frame_key_id;
const uint8_t * p_ack_key_id;
uint8_t key_id_size = 0;
p_frame_key_id = p_frame->p_sec_ctrl + SECURITY_CONTROL_SIZE;
p_ack_key_id = p_ack->p_sec_ctrl + SECURITY_CONTROL_SIZE;
if (!fc_suppressed)
switch (key_id_mode)
{
p_frame_key_id += FRAME_COUNTER_SIZE;
p_ack_key_id += FRAME_COUNTER_SIZE;
}
case KEY_ID_MODE_1:
return KEY_ID_MODE_1_SIZE;
switch ((*p_ack->p_sec_ctrl) & KEY_ID_MODE_MASK)
{
case KEY_ID_MODE_1_MASK:
key_id_size = KEY_ID_MODE_1_SIZE;
break;
case KEY_ID_MODE_2:
return KEY_ID_MODE_2_SIZE;
case KEY_ID_MODE_2_MASK:
key_id_size = KEY_ID_MODE_2_SIZE;
break;
case KEY_ID_MODE_3_MASK:
key_id_size = KEY_ID_MODE_3_SIZE;
break;
case KEY_ID_MODE_3:
return KEY_ID_MODE_3_SIZE;
default:
break;
return 0U;
}
if (0 != key_id_size)
{
memcpy((uint8_t *)p_ack_key_id, p_frame_key_id, key_id_size);
m_ack_data[PHR_OFFSET] += key_id_size;
}
switch (*(p_ack->p_sec_ctrl) & SECURITY_LEVEL_MASK)
{
case SECURITY_LEVEL_MIC_32:
case SECURITY_LEVEL_ENC_MIC_32:
m_ack_data[PHR_OFFSET] += MIC_32_SIZE;
break;
case SECURITY_LEVEL_MIC_64:
case SECURITY_LEVEL_ENC_MIC_64:
m_ack_data[PHR_OFFSET] += MIC_64_SIZE;
break;
case SECURITY_LEVEL_MIC_128:
case SECURITY_LEVEL_ENC_MIC_128:
m_ack_data[PHR_OFFSET] += MIC_128_SIZE;
break;
default:
break;
}
*p_sec_end = p_ack_key_id + key_id_size;
return (0 == key_id_size) ? NULL : p_ack_key_id;
}
static bool frame_counter_set(const nrf_802154_frame_parser_mhr_data_t * p_ack_pdata,
const uint8_t * p_ack_key_id)
static uint8_t security_key_id_set(const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_frame_parser_data_t * p_ack_data)
{
const uint8_t * p_frame_key_id = nrf_802154_frame_parser_key_id_get(p_frame_data);
uint8_t * p_ack_key_id = (uint8_t *)nrf_802154_frame_parser_key_id_get(p_ack_data);
uint8_t key_id_size = key_id_size_get(nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(
p_ack_data));
if ((p_ack_key_id != NULL) && (p_frame_key_id != NULL))
{
memcpy(p_ack_key_id, p_frame_key_id, key_id_size);
}
return key_id_size;
}
static bool frame_counter_set(nrf_802154_frame_parser_data_t * p_ack_data,
uint8_t * p_bytes_written)
{
nrf_802154_key_id_t ack_key_id;
uint32_t new_fc_value;
uint8_t * p_frame_counter = (uint8_t *)nrf_802154_frame_parser_frame_counter_get(
p_ack_data);
ack_key_id.mode = ((*p_ack_pdata->p_sec_ctrl) & KEY_ID_MODE_MASK) >> KEY_ID_MODE_BIT_OFFSET;
ack_key_id.p_key_id = (uint8_t *)p_ack_key_id;
if (p_frame_counter == NULL)
{
// The frame counter is suppressed
*p_bytes_written = 0;
return true;
}
ack_key_id.mode = nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(p_ack_data);
ack_key_id.p_key_id = (uint8_t *)nrf_802154_frame_parser_key_id_get(p_ack_data);
if (NRF_802154_SECURITY_ERROR_NONE !=
nrf_802154_security_pib_frame_counter_get_next(&new_fc_value, &ack_key_id))
{
*p_bytes_written = 0;
return false;
}
// Set the frame counter value in security header of the ACK frame
host_32_to_little(new_fc_value,
(uint8_t *)(p_ack_pdata->p_sec_ctrl + SECURITY_CONTROL_SIZE));
m_ack_data[PHR_OFFSET] += FRAME_COUNTER_SIZE;
host_32_to_little(new_fc_value, p_frame_counter);
*p_bytes_written = FRAME_COUNTER_SIZE;
return true;
}
static bool security_header_set(const nrf_802154_frame_parser_mhr_data_t * p_frame,
const nrf_802154_frame_parser_mhr_data_t * p_ack,
const uint8_t ** p_sec_end)
static bool security_header_set(const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_frame_parser_data_t * p_ack_data,
uint8_t * p_bytes_written)
{
bool security_header_prepared;
bool result;
if (((*p_frame->p_sec_ctrl) & SECURITY_LEVEL_MASK) == 0)
uint8_t bytes_written = 0U;
uint8_t fc_bytes_written = 0U;
uint8_t ack_sec_ctrl_offset = nrf_802154_frame_parser_addressing_end_offset_get(
p_ack_data);
uint8_t * ack_sec_ctrl = (uint8_t *)nrf_802154_frame_parser_addressing_end_get(
p_ack_data);
const uint8_t * frame_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame_data);
if ((ack_sec_ctrl == NULL) || (frame_sec_ctrl == NULL))
{
*p_bytes_written = bytes_written;
return true;
}
// All the bits in the security control byte can be copied.
*ack_sec_ctrl = *frame_sec_ctrl;
bytes_written += SECURITY_CONTROL_SIZE;
// Security control field is now ready. The parsing of the frame can advance.
result = nrf_802154_frame_parser_valid_data_extend(p_ack_data,
ack_sec_ctrl_offset + PHR_SIZE,
PARSE_LEVEL_SEC_CTRL_OFFSETS);
assert(result);
(void)result;
if (nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_frame_data) == SECURITY_LEVEL_NONE)
{
// The security level value is zero, therefore no auxiliary security header processing
// is performed according to 802.15.4 specification. This also applies to the frame counter,
// the value of which is left as it is in the message to which the ACK responds.
// The entire auxiliary security header content is simply copied to ACK.
uint8_t sec_hdr_size = security_header_size(p_frame);
uint8_t sec_hdr_size = security_header_size(p_frame_data) - SECURITY_CONTROL_SIZE;
memcpy((uint8_t *)p_ack->p_sec_ctrl, p_frame->p_sec_ctrl, sec_hdr_size);
m_ack_data[PHR_OFFSET] += sec_hdr_size;
memcpy(ack_sec_ctrl + SECURITY_CONTROL_SIZE,
frame_sec_ctrl + SECURITY_CONTROL_SIZE,
sec_hdr_size);
bytes_written += sec_hdr_size;
security_header_prepared = true;
}
else
{
bool fc_suppressed;
const uint8_t * p_ack_key_id;
security_control_set(p_frame, p_ack);
// Frame counter is set by MAC layer when the frame is encrypted.
fc_suppressed = ((*p_ack->p_sec_ctrl) & FRAME_COUNTER_SUPPRESS_BIT);
p_ack_key_id = security_key_id_set(p_frame, p_ack, fc_suppressed, p_sec_end);
if (fc_suppressed)
{
// There is no frame counter filed, so all done here.
security_header_prepared = true;
}
else
{
security_header_prepared = frame_counter_set(p_ack, p_ack_key_id);
}
bytes_written += security_key_id_set(p_frame_data, p_ack_data);
security_header_prepared = frame_counter_set(p_ack_data, &fc_bytes_written);
bytes_written += fc_bytes_written;
}
bytes_written += nrf_802154_frame_parser_mic_size_get(p_ack_data);
*p_bytes_written = bytes_written;
return security_header_prepared;
}
@ -393,9 +365,14 @@ static bool security_header_set(const nrf_802154_frame_parser_mhr_data_t * p_fra
* @section Information Elements
**************************************************************************************************/
static void ie_header_set(const uint8_t * p_ie_data, uint8_t ie_data_len, const uint8_t * p_sec_end)
static void ie_header_set(const uint8_t * p_ie_data,
uint8_t ie_data_len,
nrf_802154_frame_parser_data_t * p_ack_data)
{
uint8_t * p_ack_ie = (uint8_t *)p_sec_end;
uint8_t ie_offset = p_ack_data->helper.aux_sec_hdr_end_offset;
uint8_t * p_ack_ie;
p_ack_ie = (uint8_t *)p_ack_data->p_frame + ie_offset;
if (p_ie_data == NULL)
{
@ -405,32 +382,31 @@ static void ie_header_set(const uint8_t * p_ie_data, uint8_t ie_data_len, const
assert(p_ack_ie != NULL);
memcpy(p_ack_ie, p_ie_data, ie_data_len);
m_ack_data[PHR_OFFSET] += ie_data_len;
#if NRF_802154_IE_WRITER_ENABLED
nrf_802154_ie_writer_prepare(p_ack_ie, p_ack_ie + ie_data_len);
#endif
}
static void ie_header_terminate(const nrf_802154_frame_parser_mhr_data_t * p_ack,
const uint8_t * p_sec_end,
const uint8_t * p_ie_data,
uint8_t ie_data_len)
static uint8_t ie_header_terminate(const uint8_t * p_ie_data,
uint8_t ie_data_len,
nrf_802154_frame_parser_data_t * p_ack_data)
{
if (p_ie_data == NULL)
{
// No IEs to terminate.
return;
return 0U;
}
if ((p_ack->p_sec_ctrl == NULL) || ((*p_ack->p_sec_ctrl & SECURITY_LEVEL_MASK) == 0))
if ((nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data) == false) ||
(nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_ack_data) == SECURITY_LEVEL_NONE))
{
// This code assumes that neither regular frame payload nor Payload IEs can be set by the
// driver. Therefore without security, the Ack has no payload, so termination is not necessary.
return;
return 0U;
}
uint8_t * p_ack_ie = (uint8_t *)p_sec_end;
uint8_t * p_ack_ie = (uint8_t *)p_ack_data->p_frame + p_ack_data->helper.aux_sec_hdr_end_offset;
uint8_t ie_hdr_term[IE_HEADER_SIZE];
assert(p_ack_ie != NULL);
@ -438,27 +414,27 @@ static void ie_header_terminate(const nrf_802154_frame_parser_mhr_data_t * p_ack
host_16_to_little((IE_HT2) << IE_HEADER_ELEMENT_ID_OFFSET, ie_hdr_term);
memcpy(p_ack_ie + ie_data_len, ie_hdr_term, sizeof(ie_hdr_term));
m_ack_data[PHR_OFFSET] += sizeof(ie_hdr_term);
return sizeof(ie_hdr_term);
}
/***************************************************************************************************
* @section Authentication and encryption transformation
**************************************************************************************************/
static bool encryption_prepare(const nrf_802154_frame_parser_mhr_data_t * p_ack)
static bool encryption_prepare(const nrf_802154_frame_parser_data_t * p_ack_data)
{
#if NRF_802154_ENCRYPTION_ENABLED
if (p_ack->p_sec_ctrl == NULL)
if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data) == false)
{
return true;
}
if ((*(p_ack->p_sec_ctrl) & SECURITY_LEVEL_MASK) == 0)
if (nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_ack_data) == SECURITY_LEVEL_NONE)
{
return true;
}
return nrf_802154_encrypt_ack_prepare(m_ack_data);
return nrf_802154_encrypt_ack_prepare(p_ack_data);
#else // NRF_802154_ENCRYPTION_ENABLED
return true;
#endif // NRF_802154_ENCRYPTION_ENABLED
@ -473,68 +449,79 @@ void nrf_802154_enh_ack_generator_init(void)
// Intentionally empty.
}
const uint8_t * nrf_802154_enh_ack_generator_create(const uint8_t * p_frame)
uint8_t * nrf_802154_enh_ack_generator_create(
const nrf_802154_frame_parser_data_t * p_frame_data)
{
nrf_802154_frame_parser_mhr_data_t frame_offsets;
nrf_802154_frame_parser_mhr_data_t ack_offsets;
const uint8_t * p_sec_end = NULL;
bool parse_result = nrf_802154_frame_parser_mhr_parse(p_frame,
&frame_offsets);
nrf_802154_frame_parser_data_t ack_data;
if (!parse_result)
{
return NULL;
}
bool result;
uint8_t bytes_written = 0U;
uint8_t ie_data_len = 0U;
uint8_t ie_data_len = 0;
const uint8_t * p_ie_data = nrf_802154_ack_data_ie_get(
frame_offsets.p_src_addr,
frame_offsets.src_addr_size == EXTENDED_ADDRESS_SIZE,
// coverity[unchecked_value]
const uint8_t * p_ie_data = nrf_802154_ack_data_ie_get(
nrf_802154_frame_parser_src_addr_get(p_frame_data),
nrf_802154_frame_parser_src_addr_is_extended(p_frame_data),
&ie_data_len);
// Clear previously created ACK.
ack_buffer_clear();
ack_buffer_clear(&ack_data);
// Set Frame Control field bits.
frame_control_set(p_frame, p_ie_data, &ack_offsets);
bytes_written = frame_control_set(p_frame_data, p_ie_data != NULL);
m_ack_data[PHR_OFFSET] += bytes_written;
result = nrf_802154_frame_parser_valid_data_extend(&ack_data,
m_ack_data[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FCF_OFFSETS);
assert(result);
(void)result;
// Set valid sequence number in ACK frame.
sequence_number_set(p_frame);
bytes_written = sequence_number_set(p_frame_data);
m_ack_data[PHR_OFFSET] += bytes_written;
// Set destination address and PAN ID.
destination_set(&frame_offsets, &ack_offsets);
bytes_written = destination_set(p_frame_data, &ack_data);
m_ack_data[PHR_OFFSET] += bytes_written;
// Set source address and PAN ID.
source_set();
// Attempt to set auxiliary security header.
if (ack_offsets.p_sec_ctrl == NULL)
{
// There is no auxiliary security header.
p_sec_end = &m_ack_data[ack_offsets.addressing_end_offset];
}
else if (security_header_set(&frame_offsets, &ack_offsets, &p_sec_end))
{
// Security header has been set successfully: intentionally empty.
}
else
if (security_header_set(p_frame_data, &ack_data, &bytes_written) == false)
{
// Failure to set auxiliary security header: The ACK cannot be created.
ack_buffer_clear();
ack_buffer_clear(&ack_data);
return NULL;
}
m_ack_data[PHR_OFFSET] += bytes_written;
result = nrf_802154_frame_parser_valid_data_extend(&ack_data,
m_ack_data[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_AUX_SEC_HDR_END);
assert(result);
(void)result;
// Set IE header.
ie_header_set(p_ie_data, ie_data_len, p_sec_end);
ie_header_set(p_ie_data, ie_data_len, &ack_data);
m_ack_data[PHR_OFFSET] += ie_data_len;
// Terminate the IE header if needed.
ie_header_terminate(&ack_offsets, p_sec_end, p_ie_data, ie_data_len);
bytes_written = ie_header_terminate(p_ie_data, ie_data_len, &ack_data);
m_ack_data[PHR_OFFSET] += bytes_written + FCS_SIZE;
result = nrf_802154_frame_parser_valid_data_extend(&ack_data,
m_ack_data[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FULL);
assert(result);
(void)result;
// Prepare encryption.
if (!encryption_prepare(&ack_offsets))
if (!encryption_prepare(&ack_data))
{
// Failure to prepare encryption even though it's required. The ACK cannot be created.
ack_buffer_clear();
ack_buffer_clear(&ack_data);
return NULL;
}
@ -544,7 +531,7 @@ const uint8_t * nrf_802154_enh_ack_generator_create(const uint8_t * p_frame)
#ifdef TEST
void nrf_802154_enh_ack_generator_module_reset(void)
{
memset(m_ack_data, 0, sizeof(m_ack_data));
memset(m_ack_data, 0U, sizeof(m_ack_data));
}
#endif // TEST

View File

@ -41,6 +41,7 @@
#ifndef NRF_802154_ENH_ACK_GENERATOR_H
#define NRF_802154_ENH_ACK_GENERATOR_H
#include "mac_features/nrf_802154_frame_parser.h"
#include <stdbool.h>
#include <stdint.h>
@ -51,13 +52,14 @@ void nrf_802154_enh_ack_generator_init(void);
*
* This function creates an Enhanced ACK frame and inserts it into a radio buffer.
*
* @param [in] p_frame Pointer to the buffer that contains PHR and PSDU of the frame
* to respond to.
* @param [in] p_frame_data Pointer to the parser data of the frame for which an Ack
* will be generated.
*
* @returns Either pointer to a constant buffer that contains PHR and PSDU
* of the created Enhanced ACK frame, or NULL when the response cannot be
* created.
*/
const uint8_t * nrf_802154_enh_ack_generator_create(const uint8_t * p_frame);
uint8_t * nrf_802154_enh_ack_generator_create(
const nrf_802154_frame_parser_data_t * p_frame_data);
#endif // NRF_802154_ENH_ACK_GENERATOR_H

View File

@ -57,13 +57,21 @@ void nrf_802154_imm_ack_generator_init(void)
memcpy(m_ack_data, ack_data, sizeof(ack_data));
}
const uint8_t * nrf_802154_imm_ack_generator_create(const uint8_t * p_frame)
uint8_t * nrf_802154_imm_ack_generator_create(
const nrf_802154_frame_parser_data_t * p_frame_data)
{
const uint8_t * frame_dsn = nrf_802154_frame_parser_dsn_get(p_frame_data);
if (frame_dsn == NULL)
{
return NULL;
}
// Set valid sequence number in ACK frame.
m_ack_data[DSN_OFFSET] = p_frame[DSN_OFFSET];
m_ack_data[DSN_OFFSET] = *frame_dsn;
// Set pending bit in ACK frame.
if (nrf_802154_ack_data_pending_bit_should_be_set(p_frame))
if (nrf_802154_ack_data_pending_bit_should_be_set(p_frame_data))
{
m_ack_data[FRAME_PENDING_OFFSET] = ACK_HEADER_WITH_PENDING;
}

View File

@ -44,6 +44,8 @@
#include <stdbool.h>
#include <stdint.h>
#include "mac_features/nrf_802154_frame_parser.h"
/** Initializes the Immediate ACK generator module. */
void nrf_802154_imm_ack_generator_init(void);
@ -51,12 +53,13 @@ void nrf_802154_imm_ack_generator_init(void);
*
* This function creates an Immediate ACK frame and inserts it into a radio buffer.
*
* @param [in] p_frame Pointer to the buffer that contains PHR and PSDU of the frame
* to respond to.
* @param [in] p_frame_data Pointer to the parser data of the frame for which an Ack
* will be generated.
*
* @returns Pointer to a constant buffer that contains PHR and PSDU of the created
* Immediate ACK frame.
*/
const uint8_t * nrf_802154_imm_ack_generator_create(const uint8_t * p_frame);
uint8_t * nrf_802154_imm_ack_generator_create(
const nrf_802154_frame_parser_data_t * p_frame_data);
#endif // NRF_802154_IMM_ACK_GENERATOR_H

View File

@ -169,7 +169,7 @@ void nrf_802154_ack_timeout_transmitted_hook(const uint8_t * p_frame)
timeout_timer_stop();
}
bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error)
bool nrf_802154_ack_timeout_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error)
{
(void)error;
assert((p_frame == mp_frame) || (!m_procedure_is_active));

View File

@ -85,7 +85,7 @@ void nrf_802154_ack_timeout_transmitted_hook(const uint8_t * p_frame);
* @retval false TX failed event is not to be propagated to the MAC layer. It is handled
* internally in the ACK timeout module.
*/
bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error);
bool nrf_802154_ack_timeout_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error);
/**
* @brief Handles a TX started event.
@ -96,7 +96,7 @@ bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_t
* @retval false TX started event is not to be propagated to the MAC layer. It is handled
* internally in the ACK timeout module.
*/
bool nrf_802154_ack_timeout_tx_started_hook(const uint8_t * p_frame);
bool nrf_802154_ack_timeout_tx_started_hook(uint8_t * p_frame);
/**
* @brief Handles a RX ACK started event.

View File

@ -62,12 +62,12 @@
#if NRF_802154_CSMA_CA_ENABLED
static uint8_t m_nb; ///< The number of times the CSMA-CA algorithm was required to back off while attempting the current transmission.
static uint8_t m_be; ///< Backoff exponent, which is related to how many backoff periods a device shall wait before attempting to assess a channel.
static uint8_t m_nb; ///< The number of times the CSMA-CA algorithm was required to back off while attempting the current transmission.
static uint8_t m_be; ///< Backoff exponent, which is related to how many backoff periods a device shall wait before attempting to assess a channel.
static const uint8_t * mp_data; ///< Pointer to a buffer containing PHR and PSDU of the frame being transmitted.
static bool m_is_retransmission; ///< Flag that indicates if the current CSMA-CA procedure is a retransmission.
static bool m_is_running; ///< Indicates if CSMA-CA procedure is running.
static uint8_t * mp_data; ///< Pointer to a buffer containing PHR and PSDU of the frame being transmitted.
static nrf_802154_transmitted_frame_props_t m_data_props; ///< Structure containing detailed properties of data in buffer.
static bool m_is_running; ///< Indicates if CSMA-CA procedure is running.
/**
* @brief Perform appropriate actions for busy channel conditions.
@ -173,9 +173,9 @@ static void frame_transmit(rsch_dly_ts_id_t dly_ts_id)
nrf_802154_transmit_params_t params =
{
.cca = true,
.immediate = NRF_802154_CSMA_CA_WAIT_FOR_TIMESLOT ? false : true,
.is_retransmission = m_is_retransmission,
.frame_props = m_data_props,
.cca = true,
.immediate = NRF_802154_CSMA_CA_WAIT_FOR_TIMESLOT ? false : true,
};
if (!nrf_802154_request_transmit(NRF_802154_TERM_NONE,
@ -280,7 +280,8 @@ static bool channel_busy(void)
return result;
}
void nrf_802154_csma_ca_start(const uint8_t * p_data, bool is_retransmission)
void nrf_802154_csma_ca_start(uint8_t * p_data,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -292,11 +293,11 @@ void nrf_802154_csma_ca_start(const uint8_t * p_data, bool is_retransmission)
assert(!procedure_is_running());
mp_data = p_data;
m_is_retransmission = is_retransmission;
m_nb = 0;
m_be = nrf_802154_pib_csmaca_min_be_get();
m_is_running = true;
mp_data = p_data;
m_data_props = p_metadata->frame_props;
m_nb = 0;
m_be = nrf_802154_pib_csmaca_min_be_get();
m_is_running = true;
random_backoff_start();
@ -331,7 +332,7 @@ bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_o
return result;
}
bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error)
bool nrf_802154_csma_ca_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error)
{
bool result = true;
@ -362,7 +363,7 @@ bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_er
return result;
}
bool nrf_802154_csma_ca_tx_started_hook(const uint8_t * p_frame)
bool nrf_802154_csma_ca_tx_started_hook(uint8_t * p_frame)
{
if (p_frame == mp_data)
{

View File

@ -60,12 +60,13 @@
* timed out by the next layer. The ACK timeout timer must start when
* the @ref nrf_802154_tx_started() function is called.
*
* @param[in] p_data Pointer to a buffer the contains PHR and PSDU of the frame
* that is to be transmitted.
* @param[in] is_retransmission Flag that indicates if the CSMA-CA procedure to be started is
* a retransmission.
* @param[in] p_data Pointer to a buffer the contains PHR and PSDU of the frame that is
* to be transmitted.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit.
*/
void nrf_802154_csma_ca_start(const uint8_t * p_data, bool is_retransmission);
void nrf_802154_csma_ca_start(uint8_t * p_data,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata);
/**
* @brief Aborts the ongoing CSMA-CA procedure.
@ -94,7 +95,7 @@ bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_o
* @retval false TX failed event is not to be propagated to the MAC layer. It is handled
* internally in the CSMA-CA module.
*/
bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error);
bool nrf_802154_csma_ca_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error);
/**
* @brief Handles a TX started event.
@ -106,7 +107,7 @@ bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_er
* @retval false TX started event is not to be propagated to the MAC layer. It is handled
* internally in the CSMA-CA module.
*/
bool nrf_802154_csma_ca_tx_started_hook(const uint8_t * p_frame);
bool nrf_802154_csma_ca_tx_started_hook(uint8_t * p_frame);
/**
*@}

View File

@ -104,7 +104,7 @@ typedef struct
*/
typedef struct
{
const uint8_t * p_data; ///< Pointer to a buffer containing PHR and PSDU of the frame requested to be transmitted.
uint8_t * p_data; ///< Pointer to a buffer containing PHR and PSDU of the frame requested to be transmitted.
nrf_802154_transmit_params_t params; ///< Transmission parameters.
uint8_t channel; ///< Channel number on which transmission should be performed.
} dly_tx_data_t;
@ -702,11 +702,10 @@ void nrf_802154_delayed_trx_init(void)
}
}
bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
uint32_t t0,
uint32_t dt,
uint8_t channel)
bool nrf_802154_delayed_trx_transmit(uint8_t * p_data,
uint32_t t0,
uint32_t dt,
const nrf_802154_transmit_at_metadata_t * p_metadata)
{
dly_op_data_t * p_dly_tx_data = available_dly_tx_slot_get();
bool result = false;
@ -716,19 +715,19 @@ bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
dt -= TX_SETUP_TIME;
dt -= TX_RAMP_UP_TIME;
if (p_params->cca)
if (p_metadata->cca)
{
dt -= nrf_802154_cca_before_tx_duration_get();
}
p_dly_tx_data->op = RSCH_DLY_TS_OP_DTX;
p_dly_tx_data->tx.p_data = p_data;
p_dly_tx_data->tx.params.cca = p_params->cca;
p_dly_tx_data->tx.params.immediate = p_params->immediate;
p_dly_tx_data->tx.params.is_retransmission = p_params->is_retransmission;
p_dly_tx_data->tx.channel = channel;
p_dly_tx_data->id = NRF_802154_RESERVED_DTX_ID;
p_dly_tx_data->tx.p_data = p_data;
p_dly_tx_data->tx.params.frame_props = p_metadata->frame_props;
p_dly_tx_data->tx.params.cca = p_metadata->cca;
p_dly_tx_data->tx.params.immediate = true;
p_dly_tx_data->tx.channel = p_metadata->channel;
p_dly_tx_data->id = NRF_802154_RESERVED_DTX_ID;
rsch_dly_ts_param_t dly_ts_param =
{
@ -864,14 +863,20 @@ bool nrf_802154_delayed_trx_abort(nrf_802154_term_t term_lvl, req_originator_t r
void nrf_802154_delayed_trx_rx_started_hook(const uint8_t * p_frame)
{
dly_op_data_t * p_dly_op_data = ongoing_dly_rx_slot_get();
dly_op_data_t * p_dly_op_data = ongoing_dly_rx_slot_get();
nrf_802154_frame_parser_data_t frame_data;
if (p_dly_op_data != NULL)
bool result = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FCF_OFFSETS,
&frame_data);
if ((result) && (p_dly_op_data != NULL))
{
p_dly_op_data->rx.extension_frame.sof_timestamp = nrf_802154_timer_sched_time_get();
p_dly_op_data->rx.extension_frame.psdu_length = p_frame[PHR_OFFSET];
p_dly_op_data->rx.extension_frame.ack_requested = nrf_802154_frame_parser_ar_bit_is_set(
p_frame);
&frame_data);
}
}

View File

@ -69,17 +69,17 @@ void nrf_802154_delayed_trx_init(void);
* Waiting for ACK must be timed out by the next higher layer or the ACK timeout module.
* The ACK timeout timer must start when the @ref nrf_802154_tx_started function is called.
*
* @param[in] p_data Pointer to a buffer containing PHR and PSDU of the frame to be transmitted.
* @param[in] p_params Pointer to the transmission parameters.
* @param[in] t0 Base of delay time in microseconds.
* @param[in] dt Delta of the delay time from @p t0 in microseconds.
* @param[in] channel Number of the channel on which the frame is to be transmitted.
* @param[in] p_data Pointer to a buffer containing PHR and PSDU of the frame to be
* transmitted.
* @param[in] t0 Base of delay time in microseconds.
* @param[in] dt Delta of the delay time from @p t0 in microseconds.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit and additional parameters for the procedure.
*/
bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
uint32_t t0,
uint32_t dt,
uint8_t channel);
bool nrf_802154_delayed_trx_transmit(uint8_t * p_data,
uint32_t t0,
uint32_t dt,
const nrf_802154_transmit_at_metadata_t * p_metadata);
/**
* @brief Cancels a transmission scheduled by a call to @ref nrf_802154_delayed_trx_transmit.

View File

@ -134,12 +134,16 @@ static bool dst_addressing_may_be_present(uint8_t frame_type)
/**
* @brief Get offset of end of addressing fields for given frame assuming its version is 2006.
*
* If given frame contains errors that prevent getting offset, this function returns false. If there
* are no destination address fields in given frame, this function returns true and does not modify
* @p p_num_bytes. If there is destination address in given frame, this function returns true and
* inserts offset of addressing fields end to @p p_num_bytes.
* If given frame contains errors that prevent getting offset, this function returns
* NRF_802154_RX_ERROR_INVALID_FRAME. If there are no destination address fields in given frame,
* this function verifies if the driver is configured as a PAN coordinator or if the frame is a
* beacon.
* If both of those conditions are not met, the function returns
* NRF_802154_RX_ERROR_INVALID_DEST_ADDR.
* Otherwise, this function returns NRF_802154_RX_ERROR_NONE and inserts offset of addressing
* fields end to @p p_num_bytes.
*
* @param[in] p_data Pointer to a buffer containing PHR and PSDU of the incoming frame.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
*
@ -149,13 +153,14 @@ static bool dst_addressing_may_be_present(uint8_t frame_type)
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Detected an error in given frame - it should be
* discarded.
*/
static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(const uint8_t * p_data,
uint8_t * p_num_bytes,
uint8_t frame_type)
static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(
const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes,
uint8_t frame_type)
{
nrf_802154_rx_error_t result;
switch (p_data[DEST_ADDR_TYPE_OFFSET] & DEST_ADDR_TYPE_MASK)
switch (nrf_802154_frame_parser_dst_addr_type_get(p_frame_data))
{
case DEST_ADDR_TYPE_SHORT:
*p_num_bytes = SHORT_ADDR_CHECK_OFFSET;
@ -170,7 +175,7 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(const uint8_t *
case DEST_ADDR_TYPE_NONE:
if (nrf_802154_pib_pan_coord_get() || (frame_type == FRAME_TYPE_BEACON))
{
switch (p_data[SRC_ADDR_TYPE_OFFSET] & SRC_ADDR_TYPE_MASK)
switch (nrf_802154_frame_parser_src_addr_type_get(p_frame_data))
{
case SRC_ADDR_TYPE_SHORT:
case SRC_ADDR_TYPE_EXTENDED:
@ -199,24 +204,24 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(const uint8_t *
/**
* @brief Get offset of end of addressing fields for given frame assuming its version is 2015.
*
* If given frame contains errors that prevent getting offset, this function returns false. If there
* are no destination address fields in given frame, this function returns true and does not modify
* @p p_num_bytes. If there is destination address in given frame, this function returns true and
* inserts offset of addressing fields end to @p p_num_bytes.
* If given frame contains errors that prevent getting offset, this function returns
* NRF_802154_RX_ERROR_INVALID_FRAME.
* Otherwise, this function returns NRF_802154_RX_ERROR_NONE and inserts offset of addressing
* fields end to @p p_num_bytes.
*
* @param[in] p_data Pointer to a buffer containing PHR and PSDU of the incoming frame.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
*
* @retval NRF_802154_RX_ERROR_NONE No errors in given frame were detected - it may be
* further processed.
* @retval NRF_802154_RX_ERROR_INVALID_DEST_ADDR The frame is valid but addressed to another node.
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Detected an error in given frame - it should be
* discarded.
*/
static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(const uint8_t * p_data,
uint8_t * p_num_bytes,
uint8_t frame_type)
static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(
const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes,
uint8_t frame_type)
{
nrf_802154_rx_error_t result;
@ -227,7 +232,8 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(const uint8_t *
case FRAME_TYPE_ACK:
case FRAME_TYPE_COMMAND:
{
uint8_t end_offset = nrf_802154_frame_parser_dst_addr_end_offset_get(p_data);
uint8_t end_offset =
nrf_802154_frame_parser_dst_addressing_end_offset_get(p_frame_data);
if (end_offset == NRF_802154_FRAME_PARSER_INVALID_OFFSET)
{
@ -262,14 +268,13 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(const uint8_t *
/**
* @brief Get offset of end of addressing fields for given frame.
*
* If given frame contains errors that prevent getting offset, this function returns false. If there
* are no destination address fields in given frame, this function returns true and does not modify
* @p p_num_bytes. If there is destination address in given frame, this function returns true and
* inserts offset of addressing fields end to @p p_num_bytes.
* This function relays its arguments to either @ref dst_addressing_end_offset_get_2006
* or @ref dst_addressing_end_offset_get_2015 depending on the frame version.
*
* @param[in] p_data Pointer to a buffer containing PHR and PSDU of the incoming frame.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
* @param[in] frame_version Version of the incoming frame.
*
* @retval NRF_802154_RX_ERROR_NONE No errors in given frame were detected - it may be
* further processed.
@ -277,10 +282,11 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(const uint8_t *
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Detected an error in given frame - it should be
* discarded.
*/
static nrf_802154_rx_error_t dst_addressing_end_offset_get(const uint8_t * p_data,
uint8_t * p_num_bytes,
uint8_t frame_type,
uint8_t frame_version)
static nrf_802154_rx_error_t dst_addressing_end_offset_get(
const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes,
uint8_t frame_type,
uint8_t frame_version)
{
nrf_802154_rx_error_t result;
@ -288,11 +294,11 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get(const uint8_t * p_dat
{
case FRAME_VERSION_0:
case FRAME_VERSION_1:
result = dst_addressing_end_offset_get_2006(p_data, p_num_bytes, frame_type);
result = dst_addressing_end_offset_get_2006(p_frame_data, p_num_bytes, frame_type);
break;
case FRAME_VERSION_2:
result = dst_addressing_end_offset_get_2015(p_data, p_num_bytes, frame_type);
result = dst_addressing_end_offset_get_2015(p_frame_data, p_num_bytes, frame_type);
break;
default:
@ -386,40 +392,39 @@ static bool dst_extended_addr_check(const uint8_t * p_dst_addr)
* Verify if destination addressing of incoming frame allows processing by this node.
* This function checks addressing according to IEEE 802.15.4-2015.
*
* @param[in] p_data Pointer to a buffer containing PHR and PSDU of the incoming frame.
* @param[in] p_frame_data Pointer to the frame parser data.
*
* @retval NRF_802154_RX_ERROR_NONE Destination address of incoming frame allows further processing of the frame.
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Received frame is invalid.
* @retval NRF_802154_RX_ERROR_INVALID_DEST_ADDR Destination address of incoming frame does not allow further processing.
*/
static nrf_802154_rx_error_t dst_addr_check(const uint8_t * p_data, uint8_t frame_type)
static nrf_802154_rx_error_t dst_addr_check(const nrf_802154_frame_parser_data_t * p_frame_data)
{
bool result;
nrf_802154_frame_parser_mhr_data_t mhr_data;
const uint8_t * p_dst_panid = nrf_802154_frame_parser_dst_panid_get(p_frame_data);
const uint8_t * p_dst_addr = nrf_802154_frame_parser_dst_addr_get(p_frame_data);
uint8_t frame_type = nrf_802154_frame_parser_frame_type_get(p_frame_data);
result = nrf_802154_frame_parser_mhr_parse(p_data, &mhr_data);
if (!result)
if (p_dst_panid != NULL)
{
return NRF_802154_RX_ERROR_INVALID_FRAME;
}
if (mhr_data.p_dst_panid != NULL)
{
if (!dst_pan_id_check(mhr_data.p_dst_panid, frame_type))
if (!dst_pan_id_check(p_dst_panid, frame_type))
{
return NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
}
}
switch (mhr_data.dst_addr_size)
if (p_dst_addr == NULL)
{
return NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
}
switch (nrf_802154_frame_parser_dst_addr_size_get(p_frame_data))
{
case SHORT_ADDRESS_SIZE:
return dst_short_addr_check(mhr_data.p_dst_addr) ? NRF_802154_RX_ERROR_NONE :
return dst_short_addr_check(p_dst_addr) ? NRF_802154_RX_ERROR_NONE :
NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
case EXTENDED_ADDRESS_SIZE:
return dst_extended_addr_check(mhr_data.p_dst_addr) ? NRF_802154_RX_ERROR_NONE :
return dst_extended_addr_check(p_dst_addr) ? NRF_802154_RX_ERROR_NONE :
NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
case 0:
@ -437,21 +442,32 @@ static nrf_802154_rx_error_t dst_addr_check(const uint8_t * p_data, uint8_t fram
return NRF_802154_RX_ERROR_INVALID_FRAME;
}
nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_data, uint8_t * p_num_bytes)
nrf_802154_rx_error_t nrf_802154_filter_frame_part(
nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes)
{
nrf_802154_rx_error_t result = NRF_802154_RX_ERROR_INVALID_FRAME;
uint8_t frame_type = p_data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK;
uint8_t frame_version = p_data[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK;
uint8_t frame_type = nrf_802154_frame_parser_frame_type_get(p_frame_data);
uint8_t frame_version = nrf_802154_frame_parser_frame_version_get(p_frame_data);
uint8_t psdu_length = nrf_802154_frame_parser_frame_length_get(p_frame_data);
switch (*p_num_bytes)
{
case FCF_CHECK_OFFSET:
if (p_data[0] < IMM_ACK_LENGTH || p_data[0] > MAX_PACKET_SIZE)
if ((psdu_length < IMM_ACK_LENGTH) || (psdu_length > MAX_PACKET_SIZE))
{
result = NRF_802154_RX_ERROR_INVALID_LENGTH;
break;
}
if (!nrf_802154_frame_parser_valid_data_extend(p_frame_data,
*p_num_bytes,
PARSE_LEVEL_FCF_OFFSETS))
{
result = NRF_802154_RX_ERROR_INVALID_FRAME;
break;
}
if (!frame_type_and_version_filter(frame_type, frame_version))
{
result = NRF_802154_RX_ERROR_INVALID_FRAME;
@ -464,11 +480,22 @@ nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_data, uint8
break;
}
result = dst_addressing_end_offset_get(p_data, p_num_bytes, frame_type, frame_version);
result = dst_addressing_end_offset_get(p_frame_data,
p_num_bytes,
frame_type,
frame_version);
break;
default:
result = dst_addr_check(p_data, frame_type);
if (!nrf_802154_frame_parser_valid_data_extend(p_frame_data,
*p_num_bytes,
PARSE_LEVEL_DST_ADDRESSING_END))
{
result = NRF_802154_RX_ERROR_INVALID_FRAME;
break;
}
result = dst_addr_check(p_frame_data);
break;
}

View File

@ -44,6 +44,7 @@
#include <stdint.h>
#include "nrf_802154_types.h"
#include "mac_features/nrf_802154_frame_parser.h"
/**
* @defgroup nrf_802154_filter Incoming frame filter API
@ -65,7 +66,9 @@
* and does not modify the @p p_num_bytes value. If the verified frame is incorrect, this function
* returns false and the @p p_num_bytes value is undefined.
*
* @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the incoming frame.
* @param[inout] p_frame_data Pointer to a frame parser data of the frame to be filtered.
* The frame filter may increase the frame parse level to either
* PARSE_LEVEL_FCF_OFFSETS or PARSE_LEVEL_DST_ADDRESSING_END.
* @param[inout] p_num_bytes Number of bytes available in @p p_data buffer. This value is either
* set to the requested number of bytes for the next iteration or remains
* unchanged if no more iterations are to be performed during
@ -76,7 +79,9 @@
* @retval NRF_802154_RX_ERROR_INVALID_DEST_ADDR Incoming frame has destination address that
* mismatches the address of this node.
*/
nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_data, uint8_t * p_num_bytes);
nrf_802154_rx_error_t nrf_802154_filter_frame_part(
nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes);
/**
*@}

View File

@ -44,6 +44,7 @@
#include "mac_features/nrf_802154_delayed_trx.h"
#include "nrf_802154_core.h"
#include "nrf_802154_nrfx_addons.h"
#include "nrf_802154_tx_work_buffer.h"
#include "nrf_802154_utils.h"
#include "nrf_802154_utils_byteorder.h"
@ -68,8 +69,11 @@ static uint16_t m_csl_period; ///< CSL period value that will be injected
/**
* @brief Writes CSL phase to previously set memory address.
*
* @param[inout] p_written Flag set to true if CSL IE was written. If CSL IE is not written, the flag
* is not modified.
*/
static void csl_ie_write_commit(void)
static void csl_ie_write_commit(bool * p_written)
{
uint32_t time_remaining;
uint32_t symbols;
@ -105,6 +109,8 @@ static void csl_ie_write_commit(void)
host_16_to_little(csl_phase, mp_csl_phase_addr);
host_16_to_little(m_csl_period, mp_csl_period_addr);
*p_written = true;
}
/**
@ -145,9 +151,10 @@ static void csl_ie_write_reset(void)
/**
* @brief Writes CSL phase to previously set memory address.
*/
static void csl_ie_write_commit(void)
static void csl_ie_write_commit(bool * p_written)
{
// Intentionally empty
(void)p_written;
}
/**
@ -219,8 +226,11 @@ static uint8_t margin_scale(int16_t margin)
/**
* @brief Writes link metrics to previously prepared addresses in a frame.
*
* @param[inout] p_written Flag set to true if link metrics IE was written. If link metrics IE is
* not written, the flag is not modified.
*/
static void link_metrics_ie_write_commit(void)
static void link_metrics_ie_write_commit(bool * p_written)
{
if ((mp_lm_rssi_addr != NULL) || (mp_lm_margin_addr != NULL))
{
@ -229,19 +239,21 @@ static void link_metrics_ie_write_commit(void)
if (mp_lm_rssi_addr != NULL)
{
*mp_lm_rssi_addr = rssi_scale(rssi);
*p_written = true;
}
if (mp_lm_margin_addr != NULL)
{
*mp_lm_margin_addr = margin_scale((int16_t)rssi - ED_MIN_DBM);
*p_written = true;
}
}
if (mp_lm_lqi_addr != NULL)
{
*mp_lm_lqi_addr = (uint8_t)nrf_802154_core_last_frame_lqi_get();
*p_written = true;
}
}
/**
@ -348,17 +360,6 @@ static void ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_addr)
while (nrf_802154_frame_parser_ie_iterator_end(p_iterator, p_end_addr) == false)
{
const uint8_t * p_ie_end_addr = nrf_802154_frame_parser_ie_content_address_get(p_iterator)
+ nrf_802154_frame_parser_ie_length_get(p_iterator);
// Boundary check
if (p_ie_end_addr > p_end_addr)
{
// Reset writer module state
ie_writer_reset();
return;
}
switch (nrf_802154_frame_parser_ie_id_get(p_iterator))
{
case IE_VENDOR_ID:
@ -395,14 +396,17 @@ static void ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_addr)
/**
* @brief Commits data to recognized information elements.
*
* @param[inout] p_written Flag set to true if IE was written. If IE was not written, the flag is
* not modified.
*/
static void ie_writer_commit(void)
static void ie_writer_commit(bool * p_written)
{
assert(m_writer_state == IE_WRITER_PREPARE);
m_writer_state = IE_WRITER_COMMIT;
csl_ie_write_commit();
link_metrics_ie_write_commit();
csl_ie_write_commit(p_written);
link_metrics_ie_write_commit(p_written);
}
void nrf_802154_ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_addr)
@ -414,24 +418,34 @@ void nrf_802154_ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_a
ie_writer_prepare(p_ie_header, p_end_addr);
}
bool nrf_802154_ie_writer_pretransmission(
const uint8_t * p_frame,
bool nrf_802154_ie_writer_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
(void)notify_function;
if (p_params->is_retransmission)
if (p_params->frame_props.dynamic_data_is_set)
{
// Pass.
// The dynamic data in the frame is already set. Pass.
return true;
}
const uint8_t * p_mfr_addr;
uint8_t * p_ie_header;
p_ie_header = (uint8_t *)nrf_802154_frame_parser_ie_header_get(p_frame);
p_mfr_addr = nrf_802154_frame_parser_mfr_address_get(p_frame);
nrf_802154_frame_parser_data_t frame_data;
bool result = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FULL,
&frame_data);
assert(result);
(void)result;
p_ie_header = (uint8_t *)nrf_802154_frame_parser_ie_header_get(&frame_data);
p_mfr_addr = nrf_802154_frame_parser_mfr_get(&frame_data);
if (p_ie_header == NULL)
{
@ -443,7 +457,7 @@ bool nrf_802154_ie_writer_pretransmission(
return true;
}
bool nrf_802154_ie_writer_tx_started_hook(const uint8_t * p_frame)
bool nrf_802154_ie_writer_tx_started_hook(uint8_t * p_frame)
{
(void)p_frame;
@ -452,13 +466,20 @@ bool nrf_802154_ie_writer_tx_started_hook(const uint8_t * p_frame)
return true;
}
ie_writer_commit();
bool written = false;
ie_writer_commit(&written);
ie_writer_reset();
if (written)
{
nrf_802154_tx_work_buffer_is_dynamic_data_updated_set();
}
return true;
}
void nrf_802154_ie_writer_tx_ack_started_hook(const uint8_t * p_ack)
void nrf_802154_ie_writer_tx_ack_started_hook(uint8_t * p_ack)
{
(void)p_ack;
@ -467,8 +488,15 @@ void nrf_802154_ie_writer_tx_ack_started_hook(const uint8_t * p_ack)
return;
}
ie_writer_commit();
bool written = false;
ie_writer_commit(&written);
ie_writer_reset();
if (written)
{
nrf_802154_tx_work_buffer_is_dynamic_data_updated_set();
}
}
#if NRF_802154_DELAYED_TRX_ENABLED

View File

@ -70,7 +70,7 @@
void nrf_802154_ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_addr);
/**
* @brief Pretransmission hook for the IE writer module.
* @brief Transmission setup hook for the IE writer module.
*
* This hook parses the frame in search of header Information Elements and arms
* the IE writer module. The IE writer module shall write data to recognized
@ -87,8 +87,8 @@ void nrf_802154_ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_a
*
* @retval true Always succeeds.
*/
bool nrf_802154_ie_writer_pretransmission(
const uint8_t * p_frame,
bool nrf_802154_ie_writer_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
@ -107,7 +107,7 @@ bool nrf_802154_ie_writer_pretransmission(
* @param[in] p_ack Pointer to the buffer that contains the PHR and PSDU of the ACK frame.
*
*/
void nrf_802154_ie_writer_tx_ack_started_hook(const uint8_t * p_ack);
void nrf_802154_ie_writer_tx_ack_started_hook(uint8_t * p_ack);
/**
* @brief TX started hook for the IE writer module.
@ -125,7 +125,7 @@ void nrf_802154_ie_writer_tx_ack_started_hook(const uint8_t * p_ack);
*
* @retval true Always succeeds.
*/
bool nrf_802154_ie_writer_tx_started_hook(const uint8_t * p_frame);
bool nrf_802154_ie_writer_tx_started_hook(uint8_t * p_frame);
/**
* @brief Sets the value of CSL period to inject into the CSL information element.

View File

@ -90,9 +90,20 @@ static void callback_fired(void * p_context)
/**@brief Checks if the IFS is needed by comparing the addresses of the actual and the last frames. */
static bool is_ifs_needed_by_address(const uint8_t * p_frame)
{
bool is_extended;
nrf_802154_frame_parser_data_t frame_data;
const uint8_t * addr;
bool is_extended;
const uint8_t * addr = nrf_802154_frame_parser_dst_addr_get(p_frame, &is_extended);
bool result = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_ADDRESSING_END,
&frame_data);
assert(result);
(void)result;
addr = nrf_802154_frame_parser_dst_addr_get(&frame_data);
is_extended = nrf_802154_frame_parser_dst_addr_is_extended(&frame_data);
if (!addr)
{
@ -147,7 +158,7 @@ static uint16_t ifs_needed_by_time(uint32_t current_timestamp)
}
bool nrf_802154_ifs_pretransmission(
const uint8_t * p_frame,
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
@ -187,14 +198,14 @@ bool nrf_802154_ifs_pretransmission(
return true;
}
m_context.p_data = (uint8_t *)p_frame;
m_context.params.cca = p_params->cca;
m_context.params.immediate = true;
m_context.params.is_retransmission = p_params->is_retransmission;
m_timer.t0 = m_last_frame_timestamp;
m_timer.dt = dt;
m_timer.callback = callback_fired;
m_timer.p_context = &m_context;
m_context.p_data = p_frame;
m_context.params.frame_props = p_params->frame_props;
m_context.params.cca = p_params->cca;
m_context.params.immediate = true;
m_timer.t0 = m_last_frame_timestamp;
m_timer.dt = dt;
m_timer.callback = callback_fired;
m_timer.p_context = &m_context;
nrf_802154_timer_sched_add(&m_timer, true);
@ -207,8 +218,19 @@ void nrf_802154_ifs_transmitted_hook(const uint8_t * p_frame)
m_last_frame_timestamp = nrf_802154_timer_sched_time_get();
const uint8_t * addr =
nrf_802154_frame_parser_dst_addr_get(p_frame, &m_is_last_address_extended);
nrf_802154_frame_parser_data_t frame_data;
const uint8_t * addr;
bool result = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_ADDRESSING_END,
&frame_data);
assert(result);
(void)result;
addr = nrf_802154_frame_parser_dst_addr_get(&frame_data);
m_is_last_address_extended = nrf_802154_frame_parser_dst_addr_is_extended(&frame_data);
if (!addr)
{

View File

@ -53,7 +53,7 @@
* @retval false Frame is delayed and will be transmistted after a needed IFS.
*/
bool nrf_802154_ifs_pretransmission(
const uint8_t * p_frame,
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);

View File

@ -62,7 +62,7 @@ static void timeout_timer_retry(void);
static uint32_t m_timeout = NRF_802154_PRECISE_ACK_TIMEOUT_DEFAULT_TIMEOUT; ///< ACK timeout in us.
static nrf_802154_timer_t m_timer; ///< Timer used to notify when the ACK frama is not received for too long.
static volatile bool m_procedure_is_active;
static const uint8_t * mp_frame;
static uint8_t * mp_frame;
static void notify_tx_error(bool result)
{
@ -135,7 +135,7 @@ void nrf_802154_ack_timeout_time_set(uint32_t time)
m_timeout = time;
}
bool nrf_802154_ack_timeout_tx_started_hook(const uint8_t * p_frame)
bool nrf_802154_ack_timeout_tx_started_hook(uint8_t * p_frame)
{
mp_frame = p_frame;
timeout_timer_start();
@ -181,7 +181,7 @@ void nrf_802154_ack_timeout_rx_ack_started_hook(void)
timeout_timer_stop();
}
bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error)
bool nrf_802154_ack_timeout_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error)
{
(void)error;
assert((p_frame == mp_frame) || (!m_procedure_is_active));

View File

@ -58,10 +58,10 @@ static bool mode_is_valid(nrf_802154_key_id_mode_t mode)
{
switch (mode)
{
case 0:
case 1:
case 2:
case 3:
case KEY_ID_MODE_0:
case KEY_ID_MODE_1:
case KEY_ID_MODE_2:
case KEY_ID_MODE_3:
return true;
default:

View File

@ -45,6 +45,7 @@
#include "nrf_802154_config.h"
#include "nrf_802154_const.h"
#include "nrf_802154_notification.h"
#include "nrf_802154_tx_work_buffer.h"
#include "nrf_802154_utils_byteorder.h"
#include <assert.h>
@ -52,17 +53,18 @@
#if NRF_802154_SECURITY_WRITER_ENABLED
static bool m_frame_counter_injected; ///< Flag that indicates if frame counter was injected.
/**
* @brief Populates the key ID structure with key ID mode and source.
*
* @param[in] p_sec_hdr Pointer to the parsed security header from which key ID data is to
* be extracted.
* @param[out] p_key_id Pointer to the @ref nrf_802154_key_id_t structure to be populated.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_key_id Pointer to the @ref nrf_802154_key_id_t structure to be populated.
*/
static void key_id_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr,
nrf_802154_key_id_t * p_key_id)
static void key_id_prepare(const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_key_id_t * p_key_id)
{
p_key_id->mode = p_sec_hdr->key_id_mode;
p_key_id->mode = nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(p_frame_data);
switch (p_key_id->mode)
{
@ -77,7 +79,7 @@ static void key_id_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr,
case KEY_ID_MODE_2:
/* Fallthrough */
case KEY_ID_MODE_3:
p_key_id->p_key_id = (uint8_t *)p_sec_hdr->p_key_id;
p_key_id->p_key_id = (uint8_t *)nrf_802154_frame_parser_key_id_get(p_frame_data);
break;
default:
@ -91,9 +93,8 @@ static void key_id_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr,
/**
* @brief Injects frame counter value into given address with security enabled.
*
* @param[in] p_sec_hdr Pointer to the parsed security header containing frame counter address
* where the retrieved frame counter value is to be stored.
* @param[in] p_key_id Pointer to the key identifying which counter shall be retrieved.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[in] p_key_id Pointer to the key identifying which counter shall be retrieved.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Frame counter was injected successfully.
*
@ -101,10 +102,12 @@ static void key_id_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr,
* the frame counter injection.
*/
static nrf_802154_security_error_t frame_counter_inject(
nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr,
nrf_802154_key_id_t * p_key_id)
nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_key_id_t * p_key_id)
{
uint32_t frame_counter;
uint32_t frame_counter;
uint8_t * p_frame_counter =
(uint8_t *)nrf_802154_frame_parser_frame_counter_get(p_frame_data);
nrf_802154_security_error_t err;
err = nrf_802154_security_pib_frame_counter_get_next(&frame_counter, p_key_id);
@ -112,10 +115,10 @@ static nrf_802154_security_error_t frame_counter_inject(
switch (err)
{
case NRF_802154_SECURITY_ERROR_NONE:
if (p_sec_hdr->p_frame_counter != NULL)
if (p_frame_counter != NULL)
{
/* Frame counter suppression is off. Inject the frame counter. */
host_32_to_little(frame_counter, (uint8_t *)p_sec_hdr->p_frame_counter);
host_32_to_little(frame_counter, p_frame_counter);
}
break;
@ -137,37 +140,44 @@ static nrf_802154_security_error_t frame_counter_inject(
/**
* @brief Checks if security is enabled for the given Auxiliary Security Header.
*
* @param[in] p_sec_hdr Parsed frame's Auxiliary Security Header to be checked.
* @param[in] p_frame_data Pointer to the frame parser data to be checked.
*
* @retval true Security is enabled.
* @retbal false Security is disabled.
*/
static bool security_is_enabled(nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr)
static bool security_is_enabled(const nrf_802154_frame_parser_data_t * p_frame_data)
{
return ((NULL != p_sec_hdr->p_sec_ctrl) && (0 != p_sec_hdr->security_lvl));
return (NULL != nrf_802154_frame_parser_sec_ctrl_get(p_frame_data)) &&
(SECURITY_LEVEL_NONE != nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_frame_data));
}
bool nrf_802154_security_writer_pretransmission(
const uint8_t * p_frame,
bool nrf_802154_security_writer_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
if (p_params->is_retransmission)
nrf_802154_frame_parser_data_t frame_data;
nrf_802154_key_id_t key_id;
bool result = false;
m_frame_counter_injected = false;
if (p_params->frame_props.dynamic_data_is_set)
{
// Pass.
// The frame has a frame counter field already set. Pass.
return true;
}
nrf_802154_frame_parser_aux_sec_hdr_t sec_hdr;
nrf_802154_key_id_t key_id;
bool result = false;
/* Prepare Auxiliary Security Header for processing. */
nrf_802154_frame_parser_aux_sec_hdr_parse(p_frame, &sec_hdr);
result = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_AUX_SEC_HDR_END,
&frame_data);
assert(result);
(void)result;
do
{
if (!security_is_enabled(&sec_hdr))
if (!security_is_enabled(&frame_data))
{
/* Security is not enabled. Pass. */
result = true;
@ -175,22 +185,25 @@ bool nrf_802154_security_writer_pretransmission(
}
/* Prepare key ID for key validation. */
key_id_prepare(&sec_hdr, &key_id);
key_id_prepare(&frame_data, &key_id);
nrf_802154_security_error_t err = frame_counter_inject(&sec_hdr, &key_id);
nrf_802154_security_error_t err = frame_counter_inject(&frame_data, &key_id);
switch (err)
{
case NRF_802154_SECURITY_ERROR_NONE:
result = true;
result = true;
m_frame_counter_injected = true;
break;
case NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND:
notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID);
result = false;
break;
case NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW:
notify_function(p_frame, NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR);
result = false;
break;
default:
@ -198,6 +211,7 @@ bool nrf_802154_security_writer_pretransmission(
* handled in the above cases. If it does then it is a bug.
*/
assert(false);
result = false;
}
}
while (0);
@ -205,4 +219,15 @@ bool nrf_802154_security_writer_pretransmission(
return result;
}
bool nrf_802154_security_writer_tx_started_hook(uint8_t * p_frame)
{
if (m_frame_counter_injected)
{
/* Mark dynamic data updated in the work buffer. */
nrf_802154_tx_work_buffer_is_dynamic_data_updated_set();
}
return true;
}
#endif // NRF_802154_SECURITY_WRITER_ENABLED

View File

@ -41,7 +41,7 @@
#include "nrf_802154_types.h"
/**
* @brief Pretransmission hook for the security writer module.
* @brief Transmission setup hook for the security writer module.
*
* This hook parses the frame to check availability of the key identified by the frame's security
* header and injects a frame counter associated with the key. If the frame's security level is
@ -58,9 +58,21 @@
* @retval false Frame security header was not processed successfully.
* @retval true Frame security header was processed successfully.
*/
bool nrf_802154_security_writer_pretransmission(
const uint8_t * p_frame,
bool nrf_802154_security_writer_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
/**
* @brief TX started hook for the security writer module.
*
* Depending on whether @ref nrf_802154_security_writer_tx_setup has injected a frame counter
* into the transmitted frame, this hook marks the frame counter as updated.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU of the transmitted frame.
*
* @retval true Always succeeds.
*/
bool nrf_802154_security_writer_tx_started_hook(uint8_t * p_frame);
#endif // NRF_802154_SECURITY_WRITER_H__

View File

@ -110,6 +110,11 @@ static void tx_buffer_fill(const uint8_t * p_data, uint8_t length)
#endif // !NRF_802154_USE_RAW_API
static inline bool are_frame_properties_valid(const nrf_802154_transmitted_frame_props_t * p_props)
{
return p_props->dynamic_data_is_set || !(p_props->is_secured);
}
void nrf_802154_channel_set(uint8_t channel)
{
bool changed = nrf_802154_pib_channel_get() != channel;
@ -429,23 +434,40 @@ bool nrf_802154_receive(void)
}
#if NRF_802154_USE_RAW_API
bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
bool nrf_802154_transmit_raw(uint8_t * p_data,
const nrf_802154_transmit_metadata_t * p_metadata)
{
bool result;
nrf_802154_transmit_params_t params =
{
.cca = cca,
.immediate = false,
.is_retransmission = false,
};
bool result;
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
result = nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_HIGHER_LAYER,
p_data,
&params,
NULL);
if (p_metadata == NULL)
{
static const nrf_802154_transmit_metadata_t metadata_default =
{
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
.cca = true
};
p_metadata = &metadata_default;
}
nrf_802154_transmit_params_t params =
{
.frame_props = p_metadata->frame_props,
.cca = p_metadata->cca,
.immediate = false
};
result = are_frame_properties_valid(&params.frame_props);
if (result)
{
result = nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_HIGHER_LAYER,
p_data,
&params,
NULL);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
@ -453,24 +475,42 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
#else // NRF_802154_USE_RAW_API
bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca)
bool nrf_802154_transmit(const uint8_t * p_data,
uint8_t length,
const nrf_802154_transmit_metadata_t * p_metadata)
{
bool result;
nrf_802154_transmit_params_t params =
{
.cca = cca,
.immediate = false,
.is_retransmission = false,
};
bool result;
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
tx_buffer_fill(p_data, length);
result = nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_HIGHER_LAYER,
m_tx_buffer,
&params,
NULL);
if (p_metadata == NULL)
{
static const nrf_802154_transmit_metadata_t metadata_default =
{
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
.cca = true
};
p_metadata = &metadata_default;
}
nrf_802154_transmit_params_t params =
{
.frame_props = p_metadata->frame_props,
.cca = p_metadata->cca,
.immediate = false
};
result = are_frame_properties_valid(&params.frame_props);
if (result)
{
tx_buffer_fill(p_data, length);
result = nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_HIGHER_LAYER,
m_tx_buffer,
&params,
NULL);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
@ -479,45 +519,31 @@ bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca)
#endif // NRF_802154_USE_RAW_API
#if NRF_802154_DELAYED_TRX_ENABLED
bool nrf_802154_transmit_raw_at(const uint8_t * p_data,
bool cca,
uint32_t t0,
uint32_t dt,
uint8_t channel)
bool nrf_802154_transmit_raw_at(uint8_t * p_data,
uint32_t t0,
uint32_t dt,
const nrf_802154_transmit_at_metadata_t * p_metadata)
{
bool result;
nrf_802154_transmit_params_t params =
bool result;
nrf_802154_transmit_at_metadata_t metadata_default =
{
.cca = cca,
.immediate = true,
.is_retransmission = false,
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
.cca = true
};
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
result = nrf_802154_delayed_trx_transmit(p_data, &params, t0, dt, channel);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
}
bool nrf_802154_retransmit_raw_at(const uint8_t * p_data,
bool cca,
uint32_t t0,
uint32_t dt,
uint8_t channel)
{
bool result;
nrf_802154_transmit_params_t params =
if (p_metadata == NULL)
{
.cca = cca,
.immediate = true,
.is_retransmission = true,
};
metadata_default.channel = nrf_802154_channel_get();
p_metadata = &metadata_default;
}
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
result = nrf_802154_delayed_trx_transmit(p_data, &params, t0, dt, channel);
result = are_frame_properties_valid(&p_metadata->frame_props);
if (result)
{
result = nrf_802154_delayed_trx_transmit(p_data, t0, dt, p_metadata);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
@ -792,46 +818,62 @@ void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg)
#if NRF_802154_CSMA_CA_ENABLED
#if NRF_802154_USE_RAW_API
void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data)
bool nrf_802154_transmit_csma_ca_raw(uint8_t * p_data,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata)
{
bool result;
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
nrf_802154_csma_ca_start(p_data, false);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
void nrf_802154_retransmit_csma_ca_raw(const uint8_t * p_data)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
nrf_802154_csma_ca_start(p_data, true);
if (p_metadata == NULL)
{
static const nrf_802154_transmit_csma_ca_metadata_t metadata_default =
{
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
};
p_metadata = &metadata_default;
}
result = are_frame_properties_valid(&p_metadata->frame_props);
if (result)
{
nrf_802154_csma_ca_start(p_data, p_metadata);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
}
#else // NRF_802154_USE_RAW_API
void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length)
bool nrf_802154_transmit_csma_ca(const uint8_t * p_data,
uint8_t length,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata)
{
bool result;
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
tx_buffer_fill(p_data, length);
if (p_metadata == NULL)
{
static const nrf_802154_transmit_csma_ca_metadata_t metadata_default =
{
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
};
nrf_802154_csma_ca_start(m_tx_buffer, false);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
void nrf_802154_retransmit_csma_ca(const uint8_t * p_data, uint8_t length)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
tx_buffer_fill(p_data, length);
nrf_802154_csma_ca_start(m_tx_buffer, true);
p_metadata = &metadata_default;
}
result = are_frame_properties_valid(&p_metadata->frame_props);
if (result)
{
tx_buffer_fill(p_data, length);
nrf_802154_csma_ca_start(m_tx_buffer, p_metadata);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
}
#endif // NRF_802154_USE_RAW_API
@ -934,7 +976,7 @@ nrf_802154_capabilities_t nrf_802154_capabilities_get(void)
NRF_802154_CAPABILITY_ACK_TIMEOUT : 0UL);
caps_drv |= ((NRF_802154_SECURITY_WRITER_ENABLED && NRF_802154_ENCRYPTION_ENABLED) ?
NRF_802154_CAPABILITY_SECURITY : 0UL);
NRF_802154_CAPABILITY_SECURITY : 0UL);
/* Both IFS and ACK Timeout features require timer scheduler, however
* using them both at the same time requires that SL is able to schedule
@ -1049,27 +1091,12 @@ __WEAK void nrf_802154_tx_started(const uint8_t * p_frame)
}
#if NRF_802154_USE_RAW_API
__WEAK void nrf_802154_transmitted_raw(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi)
{
uint32_t timestamp = (p_ack == NULL) ? NRF_802154_NO_TIMESTAMP : nrf_802154_stat_timestamp_read(
last_ack_end_timestamp);
nrf_802154_transmitted_timestamp_raw(p_frame, p_ack, power, lqi, timestamp);
}
__WEAK void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi,
uint32_t time)
__WEAK void nrf_802154_transmitted_raw(uint8_t * p_frame,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
(void)p_frame;
(void)power;
(void)lqi;
(void)time;
uint8_t * p_ack = p_metadata->data.transmitted.p_ack;
if (p_ack != NULL)
{
@ -1079,29 +1106,13 @@ __WEAK void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame,
#else // NRF_802154_USE_RAW_API
__WEAK void nrf_802154_transmitted(const uint8_t * p_frame,
uint8_t * p_ack,
uint8_t length,
int8_t power,
uint8_t lqi)
{
uint32_t timestamp = (p_ack == NULL) ? NRF_802154_NO_TIMESTAMP : last_rx_frame_timestamp_get();
__WEAK void nrf_802154_transmitted(uint8_t * p_frame,
const nrf_802154_transmit_done_metadata_t * p_metadata)
nrf_802154_transmitted_timestamp(p_frame, p_ack, length, power, lqi, timestamp);
}
__WEAK void nrf_802154_transmitted_timestamp(const uint8_t * p_frame,
uint8_t * p_ack,
uint8_t length,
int8_t power,
uint8_t lqi,
uint32_t time)
{
(void)p_frame;
(void)length;
(void)power;
(void)lqi;
(void)time;
uint8_t * p_ack = p_metadata->data.transmitted.p_ack;
if (p_ack != NULL)
{
@ -1111,10 +1122,13 @@ __WEAK void nrf_802154_transmitted_timestamp(const uint8_t * p_frame,
#endif // NRF_802154_USE_RAW_API
__WEAK void nrf_802154_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error)
__WEAK void nrf_802154_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
(void)p_frame;
(void)error;
(void)p_metadata;
}
__WEAK void nrf_802154_energy_detected(uint8_t result)

View File

@ -34,10 +34,12 @@
#include "nrf_802154_aes_ccm.h"
#include <assert.h>
#include <string.h>
#include "hal/nrf_ecb.h"
#include "nrf_802154_const.h"
#include "nrf_802154_tx_work_buffer.h"
#include "platform/nrf_802154_irq.h"
#ifndef MIN
@ -84,6 +86,8 @@ static uint8_t m_a[NRF_802154_AES_CCM_BLOCK_SIZE];
static ccm_state_t m_state; ///< State of AES-CCM* transformation
static uint8_t m_auth_tag[MIC_128_SIZE]; ///< Authorization Tag
static bool m_initialized; ///< Flag that indicates whether the module has been initialized.
static uint8_t * mp_ciphertext; ///< Pointer to ciphertext destination buffer.
static uint8_t * mp_work_buffer; ///< Pointer to work buffer that stores the frame being transformed.
static const uint8_t m_mic_size[] = { 0, MIC_32_SIZE, MIC_64_SIZE, MIC_128_SIZE }; ///< Security level - 802.15.4-2015 Standard Table 9.6
@ -365,6 +369,12 @@ static void perform_plain_text_authorization(void)
}
}
static void transformation_finished(void)
{
nrf_802154_tx_work_buffer_is_secured_set();
m_aes_ccm_data.raw_frame = NULL;
}
/**
* @brief Handler to ECB Interrupt Routine
* Performs AES-CCM* calculation in pipeline
@ -403,7 +413,7 @@ static void ecb_irq_handler(void)
offset = (m_state.iteration - 1) * NRF_802154_AES_CCM_BLOCK_SIZE;
len = MIN(m_aes_ccm_data.plain_text_data_len - offset,
NRF_802154_AES_CCM_BLOCK_SIZE);
memcpy(m_aes_ccm_data.plain_text_data + offset, m_m, len);
memcpy(mp_ciphertext + offset, m_m, len);
if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_m))
{
m_state.iteration++;
@ -419,7 +429,7 @@ static void ecb_irq_handler(void)
}
else
{
m_aes_ccm_data.raw_frame = NULL;
transformation_finished();
}
}
break;
@ -428,13 +438,13 @@ static void ecb_irq_handler(void)
two_blocks_xor(m_auth_tag,
mp_ecb_ciphertext,
m_mic_size[m_aes_ccm_data.mic_level]);
memcpy(m_aes_ccm_data.raw_frame +
(m_aes_ccm_data.raw_frame[PHR_OFFSET] - 2 -
memcpy(mp_work_buffer +
(mp_work_buffer[PHR_OFFSET] - FCS_SIZE -
m_mic_size[m_aes_ccm_data.mic_level] +
1),
PHR_SIZE),
m_auth_tag,
m_mic_size[m_aes_ccm_data.mic_level]);
m_aes_ccm_data.raw_frame = NULL;
transformation_finished();
break;
default:
@ -479,10 +489,26 @@ bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_ae
// Store the encryption data for future use
memcpy(&m_aes_ccm_data, p_aes_ccm_data, sizeof(nrf_802154_aes_ccm_data_t));
ptrdiff_t offset = p_aes_ccm_data->raw_frame[PHR_OFFSET] + PHR_SIZE;
if (p_aes_ccm_data->plain_text_data)
{
offset = p_aes_ccm_data->plain_text_data - p_aes_ccm_data->raw_frame;
}
assert((offset >= 0) && (offset <= MAX_PACKET_SIZE + PHR_SIZE));
nrf_802154_tx_work_buffer_plain_text_offset_set(offset);
mp_work_buffer = nrf_802154_tx_work_buffer_enable_for(p_aes_ccm_data->raw_frame);
mp_ciphertext = mp_work_buffer + offset;
memcpy(mp_work_buffer, p_aes_ccm_data->raw_frame, offset);
memset(mp_ciphertext, 0, p_aes_ccm_data->raw_frame[PHR_OFFSET] + PHR_SIZE - offset);
return true;
}
void nrf_802154_aes_ccm_transform_start(const uint8_t * p_frame)
void nrf_802154_aes_ccm_transform_start(uint8_t * p_frame)
{
// Verify that the algorithm's inputs were prepared properly
if ((p_frame != m_aes_ccm_data.raw_frame) || (m_aes_ccm_data.raw_frame == NULL))

View File

@ -82,6 +82,6 @@ bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_ae
*
* @param[in] p_frame Pointer to the buffer that contains a frame being transmitted.
*/
void nrf_802154_aes_ccm_transform_start(const uint8_t * p_frame);
void nrf_802154_aes_ccm_transform_start(uint8_t * p_frame);
#endif // NRF_802154_AES_CCM_H_

View File

@ -62,6 +62,7 @@
#include "nrf_802154_stats.h"
#include "nrf_802154_utils.h"
#include "nrf_802154_trx.h"
#include "nrf_802154_tx_work_buffer.h"
#include "nrf_802154_types.h"
#include "nrf_802154_utils.h"
#include "drivers/nrfx_errors.h"
@ -117,18 +118,22 @@ static rx_buffer_t * const mp_current_rx_buffer = &nrf_802154_rx_buffers[0];
#endif
static const uint8_t * mp_ack; ///< Pointer to Ack frame buffer.
static const uint8_t * mp_tx_data; ///< Pointer to the data to transmit.
static uint32_t m_ed_time_left; ///< Remaining time of the current energy detection procedure [us].
static uint8_t m_ed_result; ///< Result of the current energy detection procedure.
static uint8_t m_last_lqi; ///< LQI of the last received non-ACK frame, corrected for the temperature.
static int8_t m_last_rssi; ///< RSSI of the last received non-ACK frame, corrected for the temperature.
static uint8_t * mp_ack; ///< Pointer to Ack frame buffer.
static uint8_t * mp_tx_data; ///< Pointer to the data to transmit.
static uint32_t m_ed_time_left; ///< Remaining time of the current energy detection procedure [us].
static uint8_t m_ed_result; ///< Result of the current energy detection procedure.
static uint8_t m_last_lqi; ///< LQI of the last received non-ACK frame, corrected for the temperature.
static int8_t m_last_rssi; ///< RSSI of the last received non-ACK frame, corrected for the temperature.
static volatile radio_state_t m_state; ///< State of the radio driver.
static nrf_802154_frame_parser_data_t m_current_rx_frame_data; ///< RX frame parser data.
static volatile radio_state_t m_state; ///< State of the radio driver.
typedef struct
{
bool frame_filtered : 1; ///< If frame being received passed filtering operation.
bool frame_parsed : 1; ///< If frame being received has been parsed
bool frame_parsed_result : 1;
bool rx_timeslot_requested : 1; ///< If timeslot for the frame being received is already requested.
bool tx_with_cca : 1; ///< If currently transmitted frame is transmitted with cca.
bool tx_diminished_prio : 1; ///< If priority of the current transmission should be diminished.
@ -166,6 +171,9 @@ static uint32_t m_listening_start_hp_timestamp;
#endif
static const nrf_802154_transmitted_frame_props_t m_default_frame_props =
NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT;
/***************************************************************************************************
* @section Common core operations
**************************************************************************************************/
@ -192,11 +200,22 @@ static void state_set(radio_state_t state)
request_preconditions_for_state(state);
}
/** Clear RX frame data. */
static void rx_data_clear(void)
{
(void)nrf_802154_frame_parser_data_init(mp_current_rx_buffer->data,
0U,
PARSE_LEVEL_NONE,
&m_current_rx_frame_data);
}
/** Clear flags describing frame being received. */
static void rx_flags_clear(void)
{
m_flags.frame_filtered = false;
m_flags.rx_timeslot_requested = false;
m_flags.frame_parsed = false;
m_flags.frame_parsed_result = false;
}
/** Wait for the RSSI measurement. */
@ -306,7 +325,7 @@ static void receive_failed_notify(nrf_802154_rx_error_t error)
/** Notify MAC layer that transmission of requested frame has started. */
static void transmit_started_notify(void)
{
const uint8_t * p_frame = mp_tx_data;
uint8_t * p_frame = mp_tx_data;
if (nrf_802154_core_hooks_tx_started(p_frame))
{
@ -336,18 +355,33 @@ static void receive_started_notify(void)
/** Notify MAC layer that a frame was transmitted. */
static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, uint8_t lqi)
{
const uint8_t * p_frame = mp_tx_data;
uint8_t * p_frame = mp_tx_data;
nrf_802154_transmit_done_metadata_t metadata = {0};
metadata.data.transmitted.p_ack = p_ack;
metadata.data.transmitted.power = power;
metadata.data.transmitted.lqi = lqi;
if (p_ack == NULL)
{
metadata.data.transmitted.time = NRF_802154_NO_TIMESTAMP;
}
else
{
metadata.data.transmitted.time = nrf_802154_stat_timestamp_read(last_ack_end_timestamp);
}
nrf_802154_critical_section_nesting_allow();
nrf_802154_core_hooks_transmitted(p_frame);
nrf_802154_notify_transmitted(p_frame, p_ack, power, lqi);
nrf_802154_notify_transmitted(p_frame, &metadata);
nrf_802154_critical_section_nesting_deny();
}
/** Notify MAC layer that transmission procedure failed. */
static void transmit_failed_notify(const uint8_t * p_frame, nrf_802154_tx_error_t error)
static void transmit_failed_notify(uint8_t * p_frame, nrf_802154_tx_error_t error)
{
if (nrf_802154_core_hooks_tx_failed(p_frame, error))
{
@ -450,7 +484,14 @@ static uint8_t * rx_buffer_get(void)
*/
static bool ack_is_requested(const uint8_t * p_frame)
{
return nrf_802154_frame_parser_ar_bit_is_set(p_frame);
nrf_802154_frame_parser_data_t frame_data;
bool result = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FCF_OFFSETS,
&frame_data);
return result && nrf_802154_frame_parser_ar_bit_is_set(&frame_data);
}
/***************************************************************************************************
@ -1002,6 +1043,10 @@ static void rx_init(void)
nrf_802154_trx_receive_buffer_set(rx_buffer_get());
}
rx_data_clear();
mp_ack = NULL;
}
/** Initialize TX operation. */
@ -1036,7 +1081,7 @@ static bool tx_init(const uint8_t * p_data, bool cca)
#endif
m_flags.tx_with_cca = cca;
nrf_802154_trx_transmit_frame(p_data,
nrf_802154_trx_transmit_frame(nrf_802154_tx_work_buffer_get(p_data),
cca,
m_trx_transmit_frame_notifications_mask);
@ -1116,7 +1161,7 @@ static void modulated_carrier_init(const uint8_t * p_data)
return;
}
nrf_802154_trx_modulated_carrier((const void *)p_data);
nrf_802154_trx_modulated_carrier(p_data);
}
/***************************************************************************************************
@ -1572,7 +1617,7 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
if (!m_flags.frame_filtered)
{
filter_result = nrf_802154_filter_frame_part(mp_current_rx_buffer->data,
filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data,
&num_data_bytes);
if (filter_result == NRF_802154_RX_ERROR_NONE)
@ -1587,6 +1632,17 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
/* Request boosted preconditions */
nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX);
/* Request next bcc match event just after all frame bytes are received
* but before FCS. This happens 64us before frame is fully received.
* This time is used for preparation of possible ACK transmission
*/
m_flags.frame_parsed = false;
m_flags.frame_parsed_result = false;
bcc = PHR_SIZE +
nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data) +
SECURITY_CONTROL_SIZE;
}
}
else if ((filter_result == NRF_802154_RX_ERROR_INVALID_LENGTH) ||
@ -1611,6 +1667,62 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
// Promiscuous mode, allow incorrect frames. Nothing to do here.
}
}
else if (!m_flags.frame_parsed)
{
if (nrf_802154_frame_parser_security_enabled_bit_is_set(&m_current_rx_frame_data))
{
if (nrf_802154_frame_parser_parse_level_get(&m_current_rx_frame_data) <
PARSE_LEVEL_ADDRESSING_END)
{
// All addressing fields and Security Control byte have been received.
uint8_t parsable_bytes =
PHR_SIZE +
nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data) +
SECURITY_CONTROL_SIZE;
(void)nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
parsable_bytes,
PARSE_LEVEL_SEC_CTRL_OFFSETS);
// Having parsed Security Control field, length of Auxiliary Security Header is
// known. Set BCC there
bcc = PHR_SIZE +
nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(&m_current_rx_frame_data);
}
else if (nrf_802154_frame_parser_parse_level_get(&m_current_rx_frame_data) <
PARSE_LEVEL_AUX_SEC_HDR_END)
{
// All security fields have been received.
uint8_t parsable_bytes =
PHR_SIZE +
nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(&m_current_rx_frame_data);
m_flags.frame_parsed = true;
m_flags.frame_parsed_result = nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
parsable_bytes,
PARSE_LEVEL_AUX_SEC_HDR_END);
}
else
{
// This code should be unreachable.
}
}
else
{
m_flags.frame_parsed = true;
m_flags.frame_parsed_result = nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
PHR_SIZE +
nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data),
PARSE_LEVEL_ADDRESSING_END);
}
}
else
{
// Nothing to do
}
if ((!m_flags.rx_timeslot_requested) && (frame_accepted))
{
@ -1636,6 +1748,16 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
}
}
if (m_flags.frame_filtered &&
m_flags.frame_parsed_result &&
nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
nrf_802154_pib_auto_ack_get())
{
nrf_802154_tx_work_buffer_reset(&m_default_frame_props);
mp_ack = nrf_802154_ack_generator_create(&m_current_rx_frame_data);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return bcc;
@ -1732,6 +1854,7 @@ void nrf_802154_trx_receive_frame_crcerror(void)
assert(m_state == RADIO_STATE_RX);
rx_flags_clear();
rx_data_clear();
// We don't change receive buffer, receive will go to the same that was already used
#if !NRF_802154_DISABLE_BCC_MATCHING
@ -1814,7 +1937,7 @@ void nrf_802154_trx_receive_frame_received(void)
prev_num_data_bytes = num_data_bytes;
// Keep checking consecutive parts of the frame header.
filter_result = nrf_802154_filter_frame_part(mp_current_rx_buffer->data, &num_data_bytes);
filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data, &num_data_bytes);
if (filter_result == NRF_802154_RX_ERROR_NONE)
{
@ -1831,7 +1954,7 @@ void nrf_802154_trx_receive_frame_received(void)
// Timeslot request
if (m_flags.frame_filtered &&
ack_is_requested(p_received_data) &&
nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
!nrf_802154_rsch_timeslot_request(nrf_802154_rx_duration_get(0, true)))
{
// Frame is destined to this node but there is no timeslot to transmit ACK.
@ -1839,6 +1962,7 @@ void nrf_802154_trx_receive_frame_received(void)
nrf_802154_trx_abort();
rx_flags_clear();
rx_data_clear();
// Filter out received ACK frame if promiscuous mode is disabled.
if (((p_received_data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) ||
@ -1865,26 +1989,33 @@ void nrf_802154_trx_receive_frame_received(void)
nrf_802154_sl_ant_div_rx_frame_received_notify();
bool send_ack = false;
bool send_ack = m_flags.frame_filtered &&
nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
nrf_802154_pib_auto_ack_get();
if (m_flags.frame_filtered &&
ack_is_requested(mp_current_rx_buffer->data) &&
nrf_802154_pib_auto_ack_get())
#if NRF_802154_DISABLE_BCC_MATCHING
bool parse_result = nrf_802154_frame_parser_valid_data_extend(&m_current_rx_frame_data,
p_received_data[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FULL);
nrf_802154_tx_work_buffer_reset(&m_default_frame_props);
if (send_ack && parse_result)
{
mp_ack = nrf_802154_ack_generator_create(mp_current_rx_buffer->data);
if (NULL != mp_ack)
{
send_ack = true;
}
mp_ack = nrf_802154_ack_generator_create(&m_current_rx_frame_data);
}
#else
bool parse_result = m_flags.frame_parsed_result;
if (send_ack)
#endif
if (send_ack && parse_result && (NULL != mp_ack))
{
state_set(RADIO_STATE_TX_ACK);
if (is_state_allowed_for_prio(m_rsch_priority, RADIO_STATE_TX_ACK))
{
if (nrf_802154_trx_transmit_ack(mp_ack, ACK_IFS))
if (nrf_802154_trx_transmit_ack(nrf_802154_tx_work_buffer_get(mp_ack), ACK_IFS))
{
// Intentionally empty: transmitting ack, because we can
}
@ -2129,9 +2260,24 @@ static bool ack_match_check_version_not_2(const uint8_t * p_tx_data, const uint8
return true;
}
static bool ack_match_check_version_2(const uint8_t * p_tx_data, const uint8_t * p_ack_data)
static bool ack_match_check_version_2(const uint8_t * p_tx_frame, const uint8_t * p_ack_frame)
{
if ((p_ack_data[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK) != FRAME_VERSION_2)
nrf_802154_frame_parser_data_t tx_data;
nrf_802154_frame_parser_data_t ack_data;
bool parse_result;
parse_result = nrf_802154_frame_parser_data_init(p_tx_frame,
p_tx_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_ADDRESSING_END,
&tx_data);
assert(parse_result);
(void)parse_result;
parse_result = nrf_802154_frame_parser_data_init(p_ack_frame,
p_ack_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_ADDRESSING_END,
&ack_data);
if (nrf_802154_frame_parser_frame_version_get(&ack_data) != FRAME_VERSION_2)
{
return false;
}
@ -2139,22 +2285,19 @@ static bool ack_match_check_version_2(const uint8_t * p_tx_data, const uint8_t *
// Transmitted frame was Version 2
// For frame version 2 sequence number bit may be suppressed and its check fails.
// Verify ACK frame using its destination address.
nrf_802154_frame_parser_mhr_data_t tx_mhr_data;
nrf_802154_frame_parser_mhr_data_t ack_mhr_data;
bool parse_result;
parse_result = nrf_802154_frame_parser_mhr_parse(p_tx_data, &tx_mhr_data);
assert(parse_result);
(void)parse_result;
parse_result = nrf_802154_frame_parser_mhr_parse(p_ack_data, &ack_mhr_data);
const uint8_t * p_tx_src_addr = nrf_802154_frame_parser_src_addr_get(&tx_data);
const uint8_t * p_ack_dst_addr = nrf_802154_frame_parser_dst_addr_get(&ack_data);
uint8_t tx_src_addr_size = nrf_802154_frame_parser_src_addr_size_get(&tx_data);
uint8_t ack_dst_addr_size = nrf_802154_frame_parser_dst_addr_size_get(&ack_data);
if (!parse_result ||
(tx_mhr_data.p_src_addr == NULL) ||
(ack_mhr_data.p_dst_addr == NULL) ||
(tx_mhr_data.src_addr_size != ack_mhr_data.dst_addr_size) ||
(0 != memcmp(tx_mhr_data.p_src_addr,
ack_mhr_data.p_dst_addr,
tx_mhr_data.src_addr_size)))
(p_tx_src_addr == NULL) ||
(p_ack_dst_addr == NULL) ||
(tx_src_addr_size != ack_dst_addr_size) ||
(0 != memcmp(p_tx_src_addr,
p_ack_dst_addr,
tx_src_addr_size)))
{
// Mismatch
return false;
@ -2476,7 +2619,7 @@ bool nrf_802154_core_receive(nrf_802154_term_t term_lvl,
bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl,
req_originator_t req_orig,
const uint8_t * p_data,
uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function)
{
@ -2486,11 +2629,16 @@ bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl,
if (result)
{
// Short-circuit evaluation in place.
if (nrf_802154_core_hooks_pre_transmission(p_data, p_params, &transmit_failed_notify))
{
result = current_operation_terminate(term_lvl, req_orig, true);
if (result)
{
nrf_802154_tx_work_buffer_reset(&p_params->frame_props);
result = nrf_802154_core_hooks_tx_setup(p_data, p_params, &transmit_failed_notify);
}
if (result)
{
m_coex_tx_request_mode = nrf_802154_pib_coex_tx_request_mode_get();
@ -2633,7 +2781,7 @@ bool nrf_802154_core_modulated_carrier(nrf_802154_term_t term_lvl,
if (result)
{
state_set(RADIO_STATE_MODULATED_CARRIER);
mp_tx_data = p_data;
mp_tx_data = (uint8_t *)p_data;
modulated_carrier_init(p_data);
}

View File

@ -146,7 +146,7 @@ bool nrf_802154_core_receive(nrf_802154_term_t term_lvl,
*/
bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl,
req_originator_t req_orig,
const uint8_t * p_data,
uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function);

View File

@ -56,15 +56,18 @@
#include "nrf_802154_types.h"
typedef bool (* abort_hook)(nrf_802154_term_t term_lvl, req_originator_t req_orig);
typedef bool (* pre_transmission_hook)(const uint8_t * p_frame,
typedef bool (* pre_transmission_hook)(uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
typedef bool (* tx_setup_hook)(uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
typedef void (* transmitted_hook)(const uint8_t * p_frame);
typedef bool (* tx_failed_hook)(const uint8_t * p_frame, nrf_802154_tx_error_t error);
typedef bool (* tx_started_hook)(const uint8_t * p_frame);
typedef bool (* tx_failed_hook)(uint8_t * p_frame, nrf_802154_tx_error_t error);
typedef bool (* tx_started_hook)(uint8_t * p_frame);
typedef void (* rx_started_hook)(const uint8_t * p_frame);
typedef void (* rx_ack_started_hook)(void);
typedef void (* tx_ack_started_hook)(const uint8_t * p_ack);
typedef void (* tx_ack_started_hook)(uint8_t * p_ack);
/* Since some compilers do not allow empty initializers for arrays with unspecified bounds,
* NULL pointer is appended to below arrays if the compiler used is not GCC. It is intentionally
@ -97,14 +100,19 @@ static const pre_transmission_hook m_pre_transmission_hooks[] =
#if NRF_802154_IFS_ENABLED
nrf_802154_ifs_pretransmission,
#endif
NULL,
};
static const tx_setup_hook m_tx_setup_hooks[] =
{
#if NRF_802154_IE_WRITER_ENABLED
nrf_802154_ie_writer_pretransmission,
nrf_802154_ie_writer_tx_setup,
#endif
#if NRF_802154_SECURITY_WRITER_ENABLED
nrf_802154_security_writer_pretransmission,
nrf_802154_security_writer_tx_setup,
#endif
#if NRF_802154_ENCRYPTION_ENABLED
nrf_802154_encrypt_pretransmission,
nrf_802154_encrypt_tx_setup,
#endif
NULL,
};
@ -143,6 +151,10 @@ static const tx_started_hook m_tx_started_hooks[] =
nrf_802154_ack_timeout_tx_started_hook,
#endif
#if NRF_802154_SECURITY_WRITER_ENABLED
nrf_802154_security_writer_tx_started_hook,
#endif
#if NRF_802154_IE_WRITER_ENABLED
nrf_802154_ie_writer_tx_started_hook,
#endif
@ -208,7 +220,7 @@ bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_
}
bool nrf_802154_core_hooks_pre_transmission(
const uint8_t * p_frame,
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
@ -233,6 +245,32 @@ bool nrf_802154_core_hooks_pre_transmission(
return result;
}
bool nrf_802154_core_hooks_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
bool result = true;
for (uint32_t i = 0; i < sizeof(m_tx_setup_hooks) / sizeof(m_tx_setup_hooks[0]);
i++)
{
if (m_tx_setup_hooks[i] == NULL)
{
break;
}
result = m_tx_setup_hooks[i](p_frame, p_params, notify_function);
if (!result)
{
break;
}
}
return result;
}
void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame)
{
for (uint32_t i = 0; i < sizeof(m_transmitted_hooks) / sizeof(m_transmitted_hooks[0]); i++)
@ -246,7 +284,7 @@ void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame)
}
}
bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error)
bool nrf_802154_core_hooks_tx_failed(uint8_t * p_frame, nrf_802154_tx_error_t error)
{
bool result = true;
@ -268,7 +306,7 @@ bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_erro
return result;
}
bool nrf_802154_core_hooks_tx_started(const uint8_t * p_frame)
bool nrf_802154_core_hooks_tx_started(uint8_t * p_frame)
{
bool result = true;
@ -317,7 +355,7 @@ void nrf_802154_core_hooks_rx_ack_started(void)
}
}
void nrf_802154_core_hooks_tx_ack_started(const uint8_t * p_ack)
void nrf_802154_core_hooks_tx_ack_started(uint8_t * p_ack)
{
for (uint32_t i = 0; i < sizeof(m_tx_ack_started_hooks) / sizeof(m_tx_ack_started_hooks[0]);
i++)

View File

@ -63,7 +63,8 @@
bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_t req_orig);
/**
* @brief Processes hooks which are to fire before the transmission request.
* @brief Processes hooks which are to fire before the transmission request and before
* attempt to terminate previous operation.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame
* that is to be transmitted.
@ -74,7 +75,24 @@ bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_
* @retval false Hooks have handled the frame - upper layer should not worry about it anymore.
*/
bool nrf_802154_core_hooks_pre_transmission(
const uint8_t * p_frame,
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
/**
* @brief Processes hooks which are to fire before the transmission but after previous operation
* has been already terminated.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame
* that is to be transmitted.
* @param[in] p_params Pointer to the transmission parameters.
* @param[in] notify_function Function to be called to notify transmission failure.
*
* @retval true Frame can be sent immediately.
* @retval false Hooks have handled the frame - upper layer should not worry about it anymore.
*/
bool nrf_802154_core_hooks_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
@ -97,7 +115,7 @@ void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame);
* @retval false TX failed event is not to be propagated to the MAC layer. It is handled
* internally.
*/
bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error);
bool nrf_802154_core_hooks_tx_failed(uint8_t * p_frame, nrf_802154_tx_error_t error);
/**
* @brief Processes hooks for the TX started event.
@ -109,7 +127,7 @@ bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_erro
* @retval false TX started event is not to be propagated to the MAC layer. It is handled
* internally.
*/
bool nrf_802154_core_hooks_tx_started(const uint8_t * p_frame);
bool nrf_802154_core_hooks_tx_started(uint8_t * p_frame);
/**
* @brief Processes hooks for the RX started event.
@ -130,7 +148,7 @@ void nrf_802154_core_hooks_rx_ack_started(void);
* @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the ACK frame
* that is being transmitted.
*/
void nrf_802154_core_hooks_tx_ack_started(const uint8_t * p_ack);
void nrf_802154_core_hooks_tx_ack_started(uint8_t * p_ack);
/**
*@}

View File

@ -61,24 +61,19 @@ static inline void memcpy_rev(void * p_dst, const void * p_src, size_t n)
}
}
static uint8_t mic_length_from_security_level_get(uint8_t security_level)
static bool frame_version_is_2015_or_above(const nrf_802154_frame_parser_data_t * p_frame_data)
{
switch (security_level)
switch (nrf_802154_frame_parser_frame_version_get(p_frame_data))
{
case SECURITY_LEVEL_MIC_32:
case SECURITY_LEVEL_ENC_MIC_32:
return MIC_32_SIZE;
case FRAME_VERSION_0:
case FRAME_VERSION_1:
return false;
case SECURITY_LEVEL_MIC_64:
case SECURITY_LEVEL_ENC_MIC_64:
return MIC_64_SIZE;
case SECURITY_LEVEL_MIC_128:
case SECURITY_LEVEL_ENC_MIC_128:
return MIC_128_SIZE;
case FRAME_VERSION_2:
return true;
default:
return 0;
return true;
}
}
@ -89,22 +84,35 @@ static uint8_t mic_level_from_security_level_get(uint8_t security_level)
return security_level & SECURITY_LEVEL_MIC_LEVEL_MASK;
}
static bool data_frame_a_data_and_m_data_prepare(
const uint8_t * p_frame,
const nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
static bool a_data_and_m_data_prepare(
const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
{
bool result = true;
uint8_t open_payload_len = 0;
if ((nrf_802154_frame_parser_frame_type_get(p_frame_data) == FRAME_TYPE_COMMAND) &&
(!frame_version_is_2015_or_above(p_frame_data)))
{
open_payload_len = MAC_CMD_COMMAND_ID_SIZE;
}
// It is assumed that the provided frame has a placeholder of appropriate length for MIC
// at the end. The algorithm inputs should only contain MAC payload, so the MIC placeholder
// of the below length should be removed
uint8_t mic_length = mic_length_from_security_level_get(p_aux_sec_hdr->security_lvl);
const uint8_t * p_mac_payload = nrf_802154_frame_parser_mac_payload_get(p_frame);
uint8_t mic_len = nrf_802154_frame_parser_mic_size_get(p_frame_data);
uint8_t * p_mac_hdr = (uint8_t *)nrf_802154_frame_parser_psdu_get(p_frame_data);
uint8_t mac_hdr_len =
nrf_802154_frame_parser_mac_header_length_get(p_frame_data) + open_payload_len;
uint8_t * p_mac_payload =
(uint8_t *)(nrf_802154_frame_parser_mac_payload_get(p_frame_data) + open_payload_len);
uint8_t mac_payload_len =
nrf_802154_frame_parser_mac_payload_length_get(p_frame_data) - mic_len - open_payload_len;
switch (p_aux_sec_hdr->security_lvl)
switch (nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_frame_data))
{
case 0:
case SECURITY_LEVEL_NONE:
// No data authenticity nor data confidentiality
p_aes_ccm_data->auth_data = NULL;
p_aes_ccm_data->auth_data_len = 0;
@ -116,12 +124,8 @@ static bool data_frame_a_data_and_m_data_prepare(
case SECURITY_LEVEL_MIC_64:
case SECURITY_LEVEL_MIC_128:
// Data authenticity without data confidentiality
p_aes_ccm_data->auth_data =
(uint8_t *)&p_frame[PSDU_OFFSET];
p_aes_ccm_data->auth_data_len =
nrf_802154_frame_parser_mac_header_length_get(p_frame, p_mac_payload) +
nrf_802154_frame_parser_mac_payload_length_get(p_frame, p_mac_payload) -
mic_length;
p_aes_ccm_data->auth_data = p_mac_hdr;
p_aes_ccm_data->auth_data_len = mac_hdr_len + mac_payload_len;
p_aes_ccm_data->plain_text_data = NULL;
p_aes_ccm_data->plain_text_data_len = 0;
break;
@ -130,14 +134,10 @@ static bool data_frame_a_data_and_m_data_prepare(
case SECURITY_LEVEL_ENC_MIC_64:
case SECURITY_LEVEL_ENC_MIC_128:
// Data authenticity and data confidentiality
p_aes_ccm_data->auth_data =
(uint8_t *)&p_frame[PSDU_OFFSET];
p_aes_ccm_data->auth_data_len =
nrf_802154_frame_parser_mac_header_length_get(p_frame, p_mac_payload);
p_aes_ccm_data->plain_text_data =
(uint8_t *)p_mac_payload;
p_aes_ccm_data->plain_text_data_len =
nrf_802154_frame_parser_mac_payload_length_get(p_frame, p_mac_payload) - mic_length;
p_aes_ccm_data->auth_data = p_mac_hdr;
p_aes_ccm_data->auth_data_len = mac_hdr_len;
p_aes_ccm_data->plain_text_data = p_mac_payload;
p_aes_ccm_data->plain_text_data_len = mac_payload_len;
break;
default:
@ -148,81 +148,19 @@ static bool data_frame_a_data_and_m_data_prepare(
return result;
}
static bool command_frame_a_data_and_m_data_prepare(
const uint8_t * p_frame,
const nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
{
bool result = true;
// It is assumed that the provided frame has a placeholder of appropriate length for MIC
// at the end. The algorithm inputs should only contain MAC payload, so the MIC placeholder
// of the below length should be removed
uint8_t mic_length = mic_length_from_security_level_get(p_aux_sec_hdr->security_lvl);
const uint8_t * p_mac_payload = nrf_802154_frame_parser_mac_payload_get(p_frame);
switch (p_aux_sec_hdr->security_lvl)
{
case 0:
// No data authenticity nor data confidentiality
p_aes_ccm_data->auth_data = NULL;
p_aes_ccm_data->auth_data_len = 0;
p_aes_ccm_data->plain_text_data = NULL;
p_aes_ccm_data->plain_text_data_len = 0;
break;
case SECURITY_LEVEL_MIC_32:
case SECURITY_LEVEL_MIC_64:
case SECURITY_LEVEL_MIC_128:
// Data authenticity without data confidentiality
p_aes_ccm_data->auth_data =
(uint8_t *)&p_frame[PSDU_OFFSET];
p_aes_ccm_data->auth_data_len =
nrf_802154_frame_parser_mac_header_length_get(p_frame, p_mac_payload) +
nrf_802154_frame_parser_mac_payload_length_get(p_frame, p_mac_payload) -
mic_length;
p_aes_ccm_data->plain_text_data = NULL;
p_aes_ccm_data->plain_text_data_len = 0;
break;
case SECURITY_LEVEL_ENC_MIC_32:
case SECURITY_LEVEL_ENC_MIC_64:
case SECURITY_LEVEL_ENC_MIC_128:
// Data authenticity and data confidentiality
p_aes_ccm_data->auth_data =
(uint8_t *)&p_frame[PSDU_OFFSET];
p_aes_ccm_data->auth_data_len =
nrf_802154_frame_parser_mac_header_length_get(p_frame, p_mac_payload) +
MAC_CMD_COMMAND_ID_SIZE;
p_aes_ccm_data->plain_text_data =
(uint8_t *)(nrf_802154_frame_parser_mac_command_id_get(p_frame, p_mac_payload) +
MAC_CMD_COMMAND_ID_SIZE);
p_aes_ccm_data->plain_text_data_len =
nrf_802154_frame_parser_mac_payload_length_get(p_frame, p_mac_payload) -
mic_length -
MAC_CMD_COMMAND_ID_SIZE;
break;
default:
result = false;
break;
}
return result;
}
/**
* @brief Retrieves key to be used for the AES CCM transformation.
*
* @param[in] p_aux_sec_hdr Pointer to Auxiliary Security Header data.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_aes_ccm_data Pointer to AES CCM transformation data to be filled.
*/
static bool aes_ccm_data_key_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
bool aes_ccm_data_key_prepare(const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
{
nrf_802154_key_id_t key_id =
{
.mode = p_aux_sec_hdr->key_id_mode,
.p_key_id = (uint8_t *)p_aux_sec_hdr->p_key_id,
.mode = nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(p_frame_data),
.p_key_id = (uint8_t *)nrf_802154_frame_parser_key_id_get(p_frame_data),
};
return NRF_802154_SECURITY_ERROR_NONE ==
@ -232,17 +170,16 @@ static bool aes_ccm_data_key_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_a
/**
* @brief Generates a CCM nonce.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU of the transmitted frame.
* @param[out] p_nonce Pointer to the buffer to be filled with generated nonce.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_nonce Pointer to the buffer to be filled with generated nonce.
*
* @retval true Nonce was generated successfully.
* @retval false Nonce could not be generated.
*/
static bool aes_ccm_nonce_generate(const uint8_t * p_frame,
const nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr,
uint8_t * p_nonce)
bool aes_ccm_nonce_generate(const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_nonce)
{
if ((p_frame == NULL) || (p_nonce == NULL))
if ((p_frame_data == NULL) || (p_nonce == NULL))
{
return false;
}
@ -255,10 +192,12 @@ static bool aes_ccm_nonce_generate(const uint8_t *
// Byte order for Frame Counter gets reversed as defined
// in 802.15.4-2015 Std Chapters 9.3.1 and Annex B.2
memcpy_rev((p_nonce + offset), p_aux_sec_hdr->p_frame_counter, FRAME_COUNTER_SIZE);
memcpy_rev((p_nonce + offset),
nrf_802154_frame_parser_frame_counter_get(p_frame_data),
FRAME_COUNTER_SIZE);
offset += FRAME_COUNTER_SIZE;
p_nonce[offset] = p_aux_sec_hdr->security_lvl;
p_nonce[offset] = nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_frame_data);
return true;
}
@ -266,31 +205,27 @@ static bool aes_ccm_nonce_generate(const uint8_t *
/**
* @brief Prepares _a_ data and _m_ data strings as defined in IEEE 802.15.4-2015 9.3.4.2.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU of the transmitted frame.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[in] p_aux_sec_hdr Pointer to Auxiliary Security Header data.
* @param[out] p_aes_ccm_data Pointer to AES CCM transformation data to be filled.
*
* @retval true Data was prepared successfully.
* @retval false Data could not be prepared.
*/
static bool aes_ccm_data_a_data_and_m_data_prepare(
const uint8_t * p_frame,
const nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
bool aes_ccm_data_a_data_and_m_data_prepare(
const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
{
bool result;
switch (p_frame[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK)
switch (nrf_802154_frame_parser_frame_type_get(p_frame_data))
{
case FRAME_TYPE_ACK:
// Fallthrough
case FRAME_TYPE_DATA:
result = data_frame_a_data_and_m_data_prepare(p_frame, p_aux_sec_hdr, p_aes_ccm_data);
break;
// Fallthrough
case FRAME_TYPE_COMMAND:
result =
command_frame_a_data_and_m_data_prepare(p_frame, p_aux_sec_hdr, p_aes_ccm_data);
result = a_data_and_m_data_prepare(p_frame_data, p_aes_ccm_data);
break;
case FRAME_TYPE_BEACON:
@ -317,99 +252,106 @@ static bool aes_ccm_data_a_data_and_m_data_prepare(
/**
* @brief Prepares data for AES CCM transformation.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU of the transmitted frame.
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_aes_ccm_data Pointer to AES CCM transformation data to be filled.
*
* @retval true AES CCM transformation data was prepared successfully.
* @retval false AES CCM transformation could not be prepared.
*/
static bool aes_ccm_data_content_prepare(const uint8_t * p_frame,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
static bool aes_ccm_data_content_prepare(const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
{
nrf_802154_frame_parser_aux_sec_hdr_t aux_sec_hdr;
bool retval = false;
do
{
if (!nrf_802154_frame_parser_aux_sec_hdr_parse(p_frame, &aux_sec_hdr))
{
// Return immediately if Auxiliary Security Header could not be retrieved.
break;
}
if (!aes_ccm_data_key_prepare(&aux_sec_hdr, p_aes_ccm_data))
if (!aes_ccm_data_key_prepare(p_frame_data, p_aes_ccm_data))
{
// Return immediately if specified key could not be found
break;
}
if (!aes_ccm_nonce_generate(p_frame, &aux_sec_hdr, p_aes_ccm_data->nonce))
if (!aes_ccm_nonce_generate(p_frame_data, p_aes_ccm_data->nonce))
{
// Return immediately if nonce could not be generated
break;
}
// Fill _a_ data (authenticity) and _m_ data (confidentiality)
if (!aes_ccm_data_a_data_and_m_data_prepare(p_frame, &aux_sec_hdr, p_aes_ccm_data))
if (!aes_ccm_data_a_data_and_m_data_prepare(p_frame_data, p_aes_ccm_data))
{
// Return immediately if transformation data could not be generated
break;
}
// Fill in the remaining data
p_aes_ccm_data->mic_level = mic_level_from_security_level_get(aux_sec_hdr.security_lvl);
p_aes_ccm_data->raw_frame = (uint8_t *)p_frame;
p_aes_ccm_data->mic_level = mic_level_from_security_level_get(
nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_frame_data));
p_aes_ccm_data->raw_frame = (uint8_t *)p_frame_data->p_frame;
retval = true;
}
while (0);
return retval;
}
bool nrf_802154_encrypt_ack_prepare(const uint8_t * p_ack)
bool nrf_802154_encrypt_ack_prepare(const nrf_802154_frame_parser_data_t * p_ack_data)
{
nrf_802154_aes_ccm_data_t aes_ccm_data;
bool success;
bool success = false;
if (aes_ccm_data_content_prepare(p_ack, &aes_ccm_data))
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data))
{
success = true;
}
else if (aes_ccm_data_content_prepare(p_ack_data, &aes_ccm_data))
{
// Algorithm's inputs prepared. Schedule transformation
success = nrf_802154_aes_ccm_transform_prepare(&aes_ccm_data);
}
else
{
// Algorithm's inputs could not be prepared. Only allow for that if security is disabled.
success = !nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack);
// Intentionally empty
}
return success;
}
bool nrf_802154_encrypt_pretransmission(
const uint8_t * p_frame,
bool nrf_802154_encrypt_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
if (p_params->is_retransmission)
if (p_params->frame_props.is_secured)
{
// Pass.
// The frame is already secured. Pass.
return true;
}
nrf_802154_aes_ccm_data_t aes_ccm_data;
bool success;
nrf_802154_frame_parser_data_t frame_data;
nrf_802154_aes_ccm_data_t aes_ccm_data;
bool success = false;
if (aes_ccm_data_content_prepare(p_frame, &aes_ccm_data))
success = nrf_802154_frame_parser_data_init(p_frame,
p_frame[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_FULL,
&frame_data);
assert(success);
(void)success;
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(&frame_data))
{
success = true;
}
else if (aes_ccm_data_content_prepare(&frame_data, &aes_ccm_data))
{
// Algorithm's inputs prepared. Schedule transformation
success = nrf_802154_aes_ccm_transform_prepare(&aes_ccm_data);
}
else
{
// Algorithm's inputs could not be prepared. Only allow for that if security is disabled.
success = !nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame);
success = false;
}
if (!success)
@ -420,14 +362,16 @@ bool nrf_802154_encrypt_pretransmission(
return success;
}
bool nrf_802154_encrypt_tx_started_hook(const uint8_t * p_frame)
bool nrf_802154_encrypt_tx_started_hook(uint8_t * p_frame)
{
// The provided pointer is the original buffer. It doesn't need to be changed,
// because the AES-CCM* module is aware of two separate buffers (original vs work buffer)
nrf_802154_aes_ccm_transform_start(p_frame);
return true;
}
void nrf_802154_encrypt_tx_ack_started_hook(const uint8_t * p_ack)
void nrf_802154_encrypt_tx_ack_started_hook(uint8_t * p_ack)
{
nrf_802154_aes_ccm_transform_start(p_ack);
}

View File

@ -39,6 +39,7 @@
#include <stdint.h>
#include "nrf_802154_types.h"
#include "mac_features/nrf_802154_frame_parser.h"
#ifdef __cplusplus
extern "C" {
@ -47,12 +48,12 @@ extern "C" {
/**
* @brief Prepares encryption data for provided Ack.
*
* @param[in] p_ack Pointer to the buffer that contains the PHR and PSDU of the ACK frame.
* @param[in] p_ack_data Pointer to the ACK frame parser data.
*/
bool nrf_802154_encrypt_ack_prepare(const uint8_t * p_ack);
bool nrf_802154_encrypt_ack_prepare(const nrf_802154_frame_parser_data_t * p_ack_data);
/**
* @brief Pretransmission hook for the encryption module.
* @brief Transmission setup hook for the encryption module.
*
* This hook prepares encryption data for provided frame.
*
@ -64,8 +65,8 @@ bool nrf_802154_encrypt_ack_prepare(const uint8_t * p_ack);
* @retval true Encryption was prepared successfully.
* @retval false Encryption prepare failed.
*/
bool nrf_802154_encrypt_pretransmission(
const uint8_t * p_frame,
bool nrf_802154_encrypt_tx_setup(
uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
@ -78,7 +79,7 @@ bool nrf_802154_encrypt_pretransmission(
*
* @retval true Always succeeds.
*/
bool nrf_802154_encrypt_tx_started_hook(const uint8_t * p_frame);
bool nrf_802154_encrypt_tx_started_hook(uint8_t * p_frame);
/**
* @brief ACK TX started hook for the encryption module.
@ -87,6 +88,6 @@ bool nrf_802154_encrypt_tx_started_hook(const uint8_t * p_frame);
*
* @param[in] p_ack Pointer to the buffer that contains the PHR and PSDU of the ACK frame.
*/
void nrf_802154_encrypt_tx_ack_started_hook(const uint8_t * p_ack);
void nrf_802154_encrypt_tx_ack_started_hook(uint8_t * p_ack);
#endif /* NRF_802154_ENCRYPT_H_ */

View File

@ -39,6 +39,7 @@
#include <stdint.h>
#include "nrf_802154.h"
#include "nrf_802154_types.h"
#ifdef __cplusplus
extern "C" {
@ -90,25 +91,27 @@ void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id);
/**
* @brief Notifies the next higher layer that a frame was transmitted.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to a buffer that containsthat contains PHR and PSDU of ACK frame. NULL if ACK was
* not requested.
* @param[in] power RSSI of the received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame of 0 if ACK was not requested.
* @note This function performs an update of the original frame and modifies @p p_metadata structure
* passed to the public callout.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
void nrf_802154_notify_transmitted(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi);
void nrf_802154_notify_transmitted(uint8_t * p_frame,
nrf_802154_transmit_done_metadata_t * p_metadata);
/**
* @brief Notifies the next higher layer that a frame was not transmitted.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that failed
* the transmission operation.
* @param[in] error An error code indicating the reason of the failure.
* @note This function performs an update of the original frame and prepares
* @ref nrf_802154_transmit_done_metadata_t structure passed to the public callout.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that failed
* the transmission operation.
* @param[in] error An error code indicating the reason of the failure.
*/
void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error);
void nrf_802154_notify_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error);
/**
* @brief Notifies the next higher layer that the energy detection procedure ended.

View File

@ -41,10 +41,12 @@
#include "nrf_802154_notification.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "nrf_802154.h"
#include "nrf_802154_critical_section.h"
#include "nrf_802154_tx_work_buffer.h"
#define RAW_LENGTH_OFFSET 0
#define RAW_PAYLOAD_OFFSET 1
@ -68,28 +70,40 @@ void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
nrf_802154_receive_failed(error, id);
}
void nrf_802154_notify_transmitted(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi)
void nrf_802154_notify_transmitted(uint8_t * p_frame,
nrf_802154_transmit_done_metadata_t * p_metadata)
{
// Update the transmitted frame contents and update frame status flags
nrf_802154_tx_work_buffer_original_frame_update(p_frame,
&p_metadata->frame_props);
// Notify
#if NRF_802154_USE_RAW_API
nrf_802154_transmitted_raw(p_frame, p_ack, power, lqi);
nrf_802154_transmitted_raw(p_frame, p_metadata);
#else // NRF_802154_USE_RAW_API
nrf_802154_transmitted(p_frame + RAW_PAYLOAD_OFFSET,
p_ack == NULL ? NULL : p_ack + RAW_PAYLOAD_OFFSET,
p_ack[RAW_LENGTH_OFFSET],
power,
lqi);
if (p_metadata->data.transmitted.p_ack != NULL)
{
p_metadata->data.transmitted.length = p_metadata->data.transmitted.p_ack[RAW_LENGTH_OFFSET];
p_metadata->data.transmitted.p_ack += RAW_PAYLOAD_OFFSET;
}
nrf_802154_transmitted(p_frame + RAW_PAYLOAD_OFFSET, p_metadata);
#endif // NRF_802154_USE_RAW_API
}
void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error)
void nrf_802154_notify_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error)
{
nrf_802154_transmit_done_metadata_t metadata = {0};
// Update the failed frame contents and update frame status flags
nrf_802154_tx_work_buffer_original_frame_update(p_frame,
&metadata.frame_props);
// Notify
#if NRF_802154_USE_RAW_API
nrf_802154_transmit_failed(p_frame, error);
nrf_802154_transmit_failed(p_frame, error, &metadata);
#else // NRF_802154_USE_RAW_API
nrf_802154_transmit_failed(p_frame + RAW_PAYLOAD_OFFSET, error);
nrf_802154_transmit_failed(p_frame + RAW_PAYLOAD_OFFSET, error, &metadata);
#endif // NRF_802154_USE_RAW_API
}

View File

@ -42,6 +42,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "nrf_802154.h"
@ -49,9 +50,13 @@
#include "nrf_802154_peripherals.h"
#include "nrf_802154_queue.h"
#include "nrf_802154_swi.h"
#include "nrf_802154_tx_work_buffer.h"
#include "nrf_802154_utils.h"
#include "hal/nrf_egu.h"
#define RAW_PAYLOAD_OFFSET 1
#define RAW_LENGTH_OFFSET 0
/** Size of notification queue.
*
* One slot for each receive buffer, one for transmission, one for busy channel and one for energy
@ -59,11 +64,11 @@
*
* One slot is lost due to simplified queue implementation.
*/
#define NTF_QUEUE_SIZE ((NRF_802154_RX_BUFFERS + 3) + 1)
#define NTF_QUEUE_SIZE ((NRF_802154_RX_BUFFERS + 3) + 1)
#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt.
#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task.
#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event.
#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt.
#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task.
#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event.
/// Types of notifications in notification queue.
typedef enum
@ -100,17 +105,16 @@ typedef struct
struct
{
const uint8_t * p_frame; ///< Pointer to frame that was transmitted.
uint8_t * p_ack; ///< Pointer to a buffer containing PHR and PSDU of the received ACK or NULL.
int8_t power; ///< RSSI of received ACK or 0.
uint8_t lqi; ///< LQI of received ACK or 0.
} transmitted; ///< Transmitted frame details.
uint8_t * p_frame; ///< Pointer to frame that was transmitted.
nrf_802154_transmit_done_metadata_t metadata; ///< Metadata structure describing @ref p_frame.
} transmitted; ///< Transmitted frame details.
struct
{
const uint8_t * p_frame; ///< Pointer to frame that was requested to be transmitted, but failed.
nrf_802154_tx_error_t error; ///< An error code that indicates reason of the failure.
} transmit_failed;
uint8_t * p_frame; ///< Pointer to frame that was requested to be transmitted, but failed.
nrf_802154_tx_error_t error; ///< An error code that indicates reason of the failure.
nrf_802154_transmit_done_metadata_t metadata; ///< Metadata structure describing @ref p_frame.
} transmit_failed; ///< Failed transmission details.
struct
{
@ -213,24 +217,17 @@ void swi_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
*
* The notification is triggered from the SWI priority level.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of ACK frame. NULL if ACK was
* not requested.
* @param[in] power RSSI of the received frame, or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame, or 0 if ACK was not requested.
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
void swi_notify_transmitted(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi)
void swi_notify_transmitted(uint8_t * p_frame,
nrf_802154_transmit_done_metadata_t * p_metadata)
{
nrf_802154_ntf_data_t * p_slot = ntf_enter();
p_slot->type = NTF_TYPE_TRANSMITTED;
p_slot->data.transmitted.p_frame = p_frame;
p_slot->data.transmitted.p_ack = p_ack;
p_slot->data.transmitted.power = power;
p_slot->data.transmitted.lqi = lqi;
p_slot->type = NTF_TYPE_TRANSMITTED;
p_slot->data.transmitted.p_frame = p_frame;
p_slot->data.transmitted.metadata = *p_metadata;
ntf_exit();
}
@ -239,17 +236,21 @@ void swi_notify_transmitted(const uint8_t * p_frame,
* @brief Notifies the next higher layer that a frame was not transmitted from the SWI priority
* level.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that failed
* the transmission.
* @param[in] error Reason of the transmission failure.
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that failed
* the transmission.
* @param[in] error Reason of the transmission failure.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
void swi_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error)
void swi_notify_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
nrf_802154_ntf_data_t * p_slot = ntf_enter();
p_slot->type = NTF_TYPE_TRANSMIT_FAILED;
p_slot->data.transmit_failed.p_frame = p_frame;
p_slot->data.transmit_failed.error = error;
p_slot->type = NTF_TYPE_TRANSMIT_FAILED;
p_slot->data.transmit_failed.p_frame = p_frame;
p_slot->data.transmit_failed.error = error;
p_slot->data.transmit_failed.metadata = *p_metadata;
ntf_exit();
}
@ -342,17 +343,28 @@ void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
swi_notify_receive_failed(error, id);
}
void nrf_802154_notify_transmitted(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi)
void nrf_802154_notify_transmitted(uint8_t * p_frame,
nrf_802154_transmit_done_metadata_t * p_metadata)
{
swi_notify_transmitted(p_frame, p_ack, power, lqi);
// Update the transmitted frame contents and update frame status flags
nrf_802154_tx_work_buffer_original_frame_update(p_frame,
&p_metadata->frame_props);
// Notify
swi_notify_transmitted(p_frame, p_metadata);
}
void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error)
void nrf_802154_notify_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error)
{
swi_notify_transmit_failed(p_frame, error);
nrf_802154_transmit_done_metadata_t metadata = {0};
// Update the failed frame contents and update frame status flags
nrf_802154_tx_work_buffer_original_frame_update(p_frame,
&metadata.frame_props);
// Notify
swi_notify_transmit_failed(p_frame, error, &metadata);
}
void nrf_802154_notify_energy_detected(uint8_t result)
@ -407,23 +419,16 @@ static void irq_handler_ntf_event(void)
{
#if NRF_802154_USE_RAW_API
nrf_802154_transmitted_raw(p_slot->data.transmitted.p_frame,
p_slot->data.transmitted.p_ack,
p_slot->data.transmitted.power,
p_slot->data.transmitted.lqi);
&p_slot->data.transmitted.metadata);
#else // NRF_802154_USE_RAW_API
uint8_t * p_ack = NULL;
uint8_t length = 0;
if (p_slot->data.transmitted.p_ack != NULL)
if (p_slot->data.transmitted.metadata.data.transmitted.p_ack != NULL)
{
p_ack = p_slot->data.transmitted.p_ack + RAW_PAYLOAD_OFFSET;
length = p_slot->data.transmitted.p_ack[RAW_LENGTH_OFFSET];
p_slot->data.transmitted.metadata.data.transmitted.length =
p_slot->data.transmitted.metadata.data.transmitted.p_ack[RAW_LENGTH_OFFSET];
p_slot->data.transmitted.metadata.data.transmitted.p_ack += RAW_PAYLOAD_OFFSET;
}
nrf_802154_transmitted(p_slot->data.transmitted.p_frame + RAW_PAYLOAD_OFFSET,
p_ack,
length,
p_slot->data.transmitted.power,
p_slot->data.transmitted.lqi);
&p_slot->data.transmitted.metadata);
#endif
}
break;
@ -431,11 +436,13 @@ static void irq_handler_ntf_event(void)
case NTF_TYPE_TRANSMIT_FAILED:
#if NRF_802154_USE_RAW_API
nrf_802154_transmit_failed(p_slot->data.transmit_failed.p_frame,
p_slot->data.transmit_failed.error);
p_slot->data.transmit_failed.error,
&p_slot->data.transmit_failed.metadata);
#else // NRF_802154_USE_RAW_API
nrf_802154_transmit_failed(
p_slot->data.transmit_failed.p_frame + RAW_PAYLOAD_OFFSET,
p_slot->data.transmit_failed.error);
p_slot->data.transmit_failed.error,
&p_slot->data.transmit_failed.metadata);
#endif
break;
@ -473,3 +480,13 @@ void nrf_802154_notification_swi_irq_handler(void)
irq_handler_ntf_event();
}
}
#if defined(TEST)
void nrf_802154_notification_swi_module_reset(void)
{
m_mcu_cs = 0UL;
memset(&m_notifications_queue_memory, 0U, sizeof(m_notifications_queue_memory));
memset(&m_notifications_queue, 0U, sizeof(m_notifications_queue));
}
#endif // defined(TEST)

View File

@ -100,7 +100,7 @@ bool nrf_802154_request_receive(nrf_802154_term_t term_lvl,
*/
bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl,
req_originator_t req_orig,
const uint8_t * p_data,
uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function);

View File

@ -86,7 +86,7 @@ bool nrf_802154_request_receive(nrf_802154_term_t term_lvl,
bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl,
req_originator_t req_orig,
const uint8_t * p_data,
uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function)
{

View File

@ -115,7 +115,7 @@ typedef struct
nrf_802154_notification_func_t notif_func; ///< Error notified in case of success.
nrf_802154_term_t term_lvl; ///< Request priority.
req_originator_t req_orig; ///< Request originator.
const uint8_t * p_data; ///< Pointer to a buffer containing PHR and PSDU of the frame to transmit.
uint8_t * p_data; ///< Pointer to a buffer containing PHR and PSDU of the frame to transmit.
nrf_802154_transmit_params_t * p_params; ///< Pointer to transmission parameters.
bool * p_result; ///< Transmit request result.
} transmit; ///< Transmit request details.
@ -332,7 +332,7 @@ static void swi_receive(nrf_802154_term_t term_lvl,
*/
static void swi_transmit(nrf_802154_term_t term_lvl,
req_originator_t req_orig,
const uint8_t * p_data,
uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function,
bool * p_result)
@ -561,7 +561,7 @@ bool nrf_802154_request_receive(nrf_802154_term_t term_lvl,
bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl,
req_originator_t req_orig,
const uint8_t * p_data,
uint8_t * p_data,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function)
{

View File

@ -56,6 +56,7 @@
#include "nrf_802154_procedures_duration.h"
#include "nrf_802154_critical_section.h"
#include "mpsl_fem_config_common.h"
#include "mpsl_fem_protocol_api.h"
#include "platform/nrf_802154_irq.h"
@ -192,7 +193,7 @@ typedef struct
static nrf_802154_flags_t m_flags; ///< Flags used to store the current driver state.
/**@brief Value of TIMER internal counter from which the counting is resumed on RADIO.EVENTS_END event. */
/** @brief Value of TIMER internal counter from which the counting is resumed on RADIO.EVENTS_END event. */
static volatile uint32_t m_timer_value_on_radio_end_event;
static volatile bool m_transmit_with_cca;
@ -394,6 +395,42 @@ static void fem_for_tx_reset(bool cca)
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
}
#if defined(NRF52840_XXAA) || \
defined(NRF52833_XXAA) || \
defined(NRF52820_XXAA) || \
defined(NRF52811_XXAA)
/** @brief Applies DEVICE-CONFIG-254.
*
* Shall be called after every RADIO peripheral reset.
*/
static void device_config_254_apply_tx(void)
{
uint32_t ficr_reg1 = *(volatile uint32_t *)0x10000330UL;
/* Check if the device is fixed by testing FICR register value.
*
* Only one of the FICR register is tested to optimize the procedure. All the registers shall
* have consistent values, i.e. all registers contain reset values or all registers contain
* values that shall be written to to the radio registers. If it is not true, then it is
* a hardware bug.
*/
if (ficr_reg1 != 0xffffffffUL)
{
volatile uint32_t * p_radio_reg1 = (volatile uint32_t *)0x4000174cUL;
volatile uint32_t * p_radio_reg2 = (volatile uint32_t *)0x40001584UL;
volatile uint32_t * p_radio_reg3 = (volatile uint32_t *)0x40001588UL;
uint32_t ficr_reg2 = *(volatile uint32_t *)0x10000334UL;
uint32_t ficr_reg3 = *(volatile uint32_t *)0x10000338UL;
*p_radio_reg1 = ficr_reg1;
*p_radio_reg2 = ficr_reg2;
*p_radio_reg3 = ficr_reg3;
}
}
#endif
void nrf_802154_trx_module_reset(void)
{
m_trx_state = TRX_STATE_DISABLED;
@ -426,6 +463,17 @@ void nrf_802154_trx_enable(void)
nrf_radio_reset();
#if defined(NRF52840_XXAA) || \
defined(NRF52833_XXAA) || \
defined(NRF52820_XXAA) || \
defined(NRF52811_XXAA)
// Apply DEVICE-CONFIG-254 if needed.
if (mpsl_fem_device_config_254_apply_get())
{
device_config_254_apply_tx();
}
#endif
nrf_radio_packet_conf_t packet_conf;
nrf_radio_mode_set(NRF_RADIO, NRF_RADIO_MODE_IEEE802154_250KBIT);

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2021, Nordic Semiconductor ASA
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "nrf_802154_const.h"
#include "nrf_802154_tx_work_buffer.h"
static uint8_t m_work_buffer[MAX_PACKET_SIZE + PHR_SIZE]; ///< Work buffer.
static uint8_t * mp_original_frame; ///< Pointer to the original frame the work buffer is currently bound to.
static uint8_t m_plain_text_offset; ///< Offset of encryption plain text.
static bool m_is_secured; ///< Flag that indicates if work buffer has been successfully secured.
static bool m_is_dynamic_data_updated; ///< Flag that indicates if work buffer has had dynamic data successfully updated.
void nrf_802154_tx_work_buffer_reset(const nrf_802154_transmitted_frame_props_t * p_frame_props)
{
mp_original_frame = NULL;
m_plain_text_offset = 0;
if (p_frame_props == NULL)
{
m_is_secured = false;
m_is_dynamic_data_updated = false;
}
else
{
m_is_secured = p_frame_props->is_secured;
m_is_dynamic_data_updated = p_frame_props->dynamic_data_is_set;
}
}
uint8_t * nrf_802154_tx_work_buffer_enable_for(uint8_t * p_original_frame)
{
mp_original_frame = p_original_frame;
return m_work_buffer;
}
const uint8_t * nrf_802154_tx_work_buffer_get(const uint8_t * p_original_frame)
{
return mp_original_frame ? m_work_buffer : p_original_frame;
}
void nrf_802154_tx_work_buffer_original_frame_update(
uint8_t * p_original_frame,
nrf_802154_transmitted_frame_props_t * p_frame_props)
{
assert(p_frame_props != NULL);
p_frame_props->is_secured = m_is_secured;
p_frame_props->dynamic_data_is_set = m_is_dynamic_data_updated;
if (mp_original_frame == NULL)
{
return;
}
uint8_t work_buffer_len = m_work_buffer[PHR_OFFSET] + PHR_SIZE;
if (m_is_dynamic_data_updated && m_is_secured)
{
memcpy(p_original_frame, m_work_buffer, work_buffer_len);
}
else if (m_is_dynamic_data_updated)
{
memcpy(p_original_frame, m_work_buffer, m_plain_text_offset);
}
else if (m_is_secured)
{
memcpy(p_original_frame, m_work_buffer, work_buffer_len - m_plain_text_offset);
}
else
{
// Intentionally empty.
}
}
void nrf_802154_tx_work_buffer_is_secured_set(void)
{
m_is_secured = true;
}
void nrf_802154_tx_work_buffer_is_dynamic_data_updated_set(void)
{
m_is_dynamic_data_updated = true;
}
void nrf_802154_tx_work_buffer_plain_text_offset_set(uint8_t offset)
{
m_plain_text_offset = offset;
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2021, Nordic Semiconductor ASA
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @brief Module that provides work buffer for transmissions.
*
* This module performs the following functions:
* - stores properties of the frame to be transmitted
* - optionally provides an additional work buffer to modify frame data without affecting
* the original frame's contents
*
* By default, the using of work buffer is turned off. If desired, it can be turned on with
* @ref nrf_802154_tx_work_buffer_enable_for.
*
*/
#ifndef NRF_802154_TX_WORK_BUFFER_H_
#define NRF_802154_TX_WORK_BUFFER_H_
#include <stdint.h>
#include <stdbool.h>
#include "nrf_802154_types.h"
/**
* @brief Resets work buffer.
*
* Internal state of the work buffer is completely reset after this call.
* If @p p_frame_props is not NULL, the work buffer properties are set according to the contents
* of the given structure.
*
* @param[in] p_frame_props Pointer to a structure containing the initial properties that will
* be set for the work buffer.
*/
void nrf_802154_tx_work_buffer_reset(const nrf_802154_transmitted_frame_props_t * p_frame_props);
/**
* @brief Enables work buffer for provided frame.
*
* In order to avoid performing potentially hazardous operations on the original buffer containing
* data to be transmitted, a work buffer can be allocated to the original frame. After all necessary
* modifications are performed on the work buffer, its contents can be copied back to the original
* buffer so that its state is always well-defined.
*
* @pre Before enabling the work buffer must be initialized with @ref nrf_802154_tx_work_buffer_reset
*
* @param[in] p_original_frame Pointer to the original frame to be transmitted.
*
* @returns Pointer to a work buffer bound to @p p_original_frame.
*/
uint8_t * nrf_802154_tx_work_buffer_enable_for(uint8_t * p_original_frame);
/**
* @brief Gets buffer to be transmitted.
*
* Depending on whether @p p_original_frame has a work buffer bound, this function either returns
* that work buffer or the original frame, if no such binding exists.
*
* @param[in] p_original_frame Pointer to the original frame to be transmitted.
*
* @returns Pointer to a buffer to be transmitted.
*/
const uint8_t * nrf_802154_tx_work_buffer_get(const uint8_t * p_original_frame);
/**
* @brief Updates the original buffer with its bound work buffer contents.
*
* Processing performed on the work buffer might require copying its contents back to the original
* buffer. This function performs all necessary updates of the original buffer in place.
*
* @param[inout] p_original_frame Pointer to the original frame to be transmitted.
* @param[out] p_frame_props Pointer to a structure to which @ref m_is_secured and
* @ref m_is_dynamic_data_updated flags' values are to be
* stored.
*/
void nrf_802154_tx_work_buffer_original_frame_update(
uint8_t * p_original_frame,
nrf_802154_transmitted_frame_props_t * p_frame_props);
/**
* @brief Marks a work buffer as secured.
*/
void nrf_802154_tx_work_buffer_is_secured_set(void);
/**
* @brief Marks a work buffer as containing updated dynamic data.
*/
void nrf_802154_tx_work_buffer_is_dynamic_data_updated_set(void);
/**
* @brief Sets offset of encryption plain text for the work buffer.
*
* @param[in] offset Offset of encryption plain text to be set.
*/
void nrf_802154_tx_work_buffer_plain_text_offset_set(uint8_t offset);
#endif // NRF_802154_TX_WORK_BUFFER_H_

View File

@ -361,16 +361,19 @@ bool nrf_802154_energy_detection(uint32_t time_us);
* | <---------------------------- PHR -----------------------------------> |
* @endverbatim
*
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain frame
* length (including PHR and FCS). The following bytes contain data. The CRC is
* computed automatically by the radio hardware. Therefore, the FCS field can
* contain any bytes.
* @param[in] cca If the driver is to perform a CCA procedure before transmission.
* @param[in] p_data Pointer to the array with data to transmit. The first byte must contain
* frame length (including FCS). The following bytes contain data.
* The CRC is computed automatically by the radio hardware. Therefore,
* the FCS field can contain any bytes.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit and additional parameters for the procedure.
* If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used.
*
* @retval true The transmission procedure was scheduled.
* @retval false The driver could not schedule the transmission procedure.
*/
bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca);
bool nrf_802154_transmit_raw(uint8_t * p_data,
const nrf_802154_transmit_metadata_t * p_metadata);
/**
* @brief Performs the CSMA-CA procedure and transmits a frame in case of success.
@ -386,35 +389,15 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca);
* by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected
* to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame.
*
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw.
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw.
* @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data
* to transmit. If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used.
*
* @retval true The chain of CSMA-CA and transmission procedure was scheduled.
* @retval false The driver could not schedule the procedure chain.
*/
void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data);
/**
* @brief Performs the CSMA-CA procedure and retransmits a frame in case of success.
*
* The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted_raw or
* @ref nrf_802154_transmit_failed.
*
* @note This function is meant specifically to be used for transmitting frames for which
* @ref nrf_802154_transmit_failed was reported in the original transmission attempt. This
* function does not perform any modifications to the provided frame's content. In particular,
* it performs neither authentication nor confidentiality transform of the frame's content.
* Therefore it must not be called to execute the first transmission attempt of a given frame.
* Doing so might lead to a number of issues such as security breaches and transmissions of
* malformed or incorrect frames.
*
* @note The driver may be configured to automatically time out waiting for an ACK frame depending
* on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If the automatic ACK timeout is disabled,
* the CSMA-CA procedure does not time out waiting for an ACK frame if a frame
* with the ACK request bit set was transmitted. The MAC layer is expected to manage the timer
* to time out waiting for the ACK frame. This timer can be started
* by @ref nrf_802154_tx_started. When the timer expires, the MAC layer is expected
* to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame.
*
* @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw.
*/
void nrf_802154_retransmit_csma_ca_raw(const uint8_t * p_data);
bool nrf_802154_transmit_csma_ca_raw(uint8_t * p_data,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata);
/**
* @brief Notifies the driver that the buffer containing the received frame is not used anymore.

View File

@ -145,36 +145,37 @@ extern void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id);
* @note If ACK was requested for the transmitted frame, this function is called after a proper ACK
* is received. If ACK was not requested, this function is called just after transmission has
* ended.
* @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot be used
* to receive a frame) until @ref nrf_802154_buffer_free_raw is called.
* @note The buffer pointed to by @p p_ack may be modified by the function handler (and other
* modules) until @ref nrf_802154_buffer_free_raw is called.
* @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack
* is not modified by the radio driver (and cannot be used to receive a frame) until
* @ref nrf_802154_buffer_free_raw is called.
* @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack
* may be modified by the function handler (and other modules) until
* @ref nrf_802154_buffer_free_raw is called.
* @note @ref nrf_802154_transmit_done_metadata_t.data.transmitted.time will have value of
* @ref NRF_802154_NO_TIMESTAMP as timestamping is not supported for nRF53 family.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the received ACK.
* The first byte in the buffer is the length of the frame (PHR). The following
* bytes contain the ACK frame itself (PSDU). The length byte (PHR) includes
* FCS. FCS is already verified by the hardware and may be modified by the
* hardware. If ACK was not requested, @p p_ack is set to NULL.
* @param[in] power RSSI of the received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of the received frame or 0 if ACK was not requested.
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
extern void nrf_802154_transmitted_raw(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi);
extern void nrf_802154_transmitted_raw(uint8_t * p_frame,
const nrf_802154_transmit_done_metadata_t * p_metadata);
/**
* @brief Notifies that a frame was not transmitted due to a busy channel.
*
* This function is called if the transmission procedure fails.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not
* transmitted.
* @param[in] error Reason of the failure.
* @note Frame data values in @ref nrf_802154_transmit_done_metadata_t.data are invalid for
* @ref nrf_802154_transmit_failed callout.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not
* transmitted.
* @param[in] error Reason of the failure.
* @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
*/
extern void nrf_802154_transmit_failed(const uint8_t * p_frame,
nrf_802154_tx_error_t error);
extern void nrf_802154_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t error,
const nrf_802154_transmit_done_metadata_t * p_metadata);
#endif /* NRF_802154_CALLOUTS_H_ */

View File

@ -35,6 +35,7 @@
#ifndef NRF_802154_TYPES_H__
#define NRF_802154_TYPES_H__
#include <stdbool.h>
#include <stdint.h>
/**
@ -139,6 +140,79 @@ typedef uint32_t nrf_802154_capabilities_t;
#define NRF_802154_CAPABILITY_TIMESTAMP (1UL << 6UL) // !< Frame timestamping supported
#define NRF_802154_CAPABILITY_SECURITY (1UL << 7UL) // !< Frame security supported
/**
* @brief Structure with frame properties associated with the transmission operation.
*
* @note When using to request transmission, parameters contained here influence whether or not
* the security related data transformation will be performed. In particular, the driver may:
* - update frame counter field if the dynamic parts of the frame are not yet updated
* - secure a non-secured frame on-the-fly
* If performed, the above operations are configured by the IEEE 802.15.4 Auxiliary Security
* Header present in the transmitted frame.
*
* @note It is recommended to use values defined in @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT
* to perform the first transmission attempt. Using other values may result in transmitting
* malformed or incorrect frames and creating security breaches.
*
* @note The combination with is_secured = true and dynamic_data_is_set = false is not allowed.
* An attempt to transmit a frame with such parameters will fail unconditionally.
*/
typedef struct
{
bool is_secured; // !< If the frame to be transmitted is already secured (in the sense of IEEE 802.15.4 security operations).
bool dynamic_data_is_set; // !< If dynamic data of the frame frame to be transmitted is set.
} nrf_802154_transmitted_frame_props_t;
/**
* @brief Default initializer for nrf_802154_transmitted_frame_props_t.
*/
#define NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT \
(nrf_802154_transmitted_frame_props_t){ \
.is_secured = false, \
.dynamic_data_is_set = false \
}
/**
* @brief Structure with transmit request metadata for simple transmission request.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted.
bool cca; // !< If the driver is to perform a CCA procedure before transmission.
} nrf_802154_transmit_metadata_t;
/**
* @brief Structure with transmit request metadata for transmission preceded by CSMA-CA procedure.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted.
} nrf_802154_transmit_csma_ca_metadata_t;
/**
* @brief Structure that holds transmission result metadata.
*/
typedef struct
{
nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the returned frame.
union
{
struct
{
uint8_t * p_ack; // !< If NRF_802154_USE_RAW_API is disabled, p_ack is a pointer to a buffer that contains only the received ACK payload (PSDU excluding FCS).
// If NRF_802154_USE_RAW_API is enabled, p_ack is a pointer to a buffer that contains PHR and PSDU of the received ACK. The first byte
// in the buffer is the length of the frame (PHR). The following bytes contain the ACK frame itself (PSDU). The length byte
// (PHR) includes FCS. FCS is already verified by the hardware and may be modified by the hardware.
// If ACK was not requested or requested but not received, @ref p_ack is set to NULL.
uint8_t length; // !< Length of the received ACK payload or 0 if @ref p_ack is NULL.
int8_t power; // !< RSSI of the received frame or 0 if @ref p_ack is NULL.
uint8_t lqi; // !< LQI of the received frame or 0 if @ref p_ack is NULL.
uint32_t time; // !< Timestamp taken when the last symbol of ACK is received. If @ref p_ack is NULL, this field is set to 0, but is considered invalid.
} transmitted; // !< Result values for a successful frame transmission.
} data; // !< Result values that are valid only for successful operations.
} nrf_802154_transmit_done_metadata_t;
/**
*@}
**/

View File

@ -273,12 +273,6 @@ typedef enum
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET =
SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 34,
/**
* Vendor property for nrf_802154_retransmit_csma_ca_raw serialization.
*/
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RETRANSMIT_CSMA_CA_RAW =
SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 35,
} spinel_prop_vendor_key_t;
/**
@ -331,6 +325,62 @@ typedef enum
SPINEL_DATATYPE_DATA_S /* Data content */ \
)
/**
* @brief Spinel data type description for nrf_802154_transmitted_frame_props_t.
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S \
SPINEL_DATATYPE_BOOL_S /* is_secured */ \
SPINEL_DATATYPE_BOOL_S /* dynamic_data_is_set */
/**
* @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S data type.
*/
#define NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE(frame_props) \
((frame_props).is_secured), ((frame_props).dynamic_data_is_set)
/**
* @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S data type.
*/
#define NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE(frame_props) \
(&(frame_props).is_secured), (&(frame_props).dynamic_data_is_set)
/**
* @brief Spinel data type description for nrf_802154_transmit_metadata_t.
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_METADATA_S \
SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* frame_props */ \
SPINEL_DATATYPE_BOOL_S /* cca */
/**
* @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_METADATA_S data type.
*/
#define NRF_802154_TRANSMIT_METADATA_ENCODE(tx_metadata) \
NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((tx_metadata).frame_props), \
((tx_metadata).cca)
/**
* @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_METADATA_S data type.
*/
#define NRF_802154_TRANSMIT_METADATA_DECODE(tx_metadata) \
NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE((tx_metadata).frame_props), \
(&(tx_metadata).cca)
/**
* @brief Spinel data type description for nrf_802154_transmit_csma_ca_metadata_t.
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S \
SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* frame_props */
/**
* @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S data type.
*/
#define NRF_802154_TRANSMIT_CSMA_CA_METADATA_ENCODE(tx_metadata) \
NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((tx_metadata).frame_props)
/**
* @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S data type.
*/
#define NRF_802154_TRANSMIT_CSMA_CA_METADATA_DECODE(tx_metadata) \
NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE((tx_metadata).frame_props)
/**
* @brief Spinel data type description for SPINEL_PROP_LAST_STATUS.
*/
@ -467,15 +517,20 @@ typedef enum
/**
* @brief Spinel data type description for nrf_802154_transmit_raw
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */ \
SPINEL_DATATYPE_BOOL_S /* CCA */
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW \
SPINEL_DATATYPE_NRF_802154_TRANSMIT_METADATA_S \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */
/**
* @brief Spinel data type description for return value of nrf_802154_transmit_raw
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_RET SPINEL_DATATYPE_BOOL_S
/**
* @brief Spinel data type description for return value of nrf_802154_transmit_csma_ca_raw
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW_RET SPINEL_DATATYPE_BOOL_S
/**
* @brief Spinel data type desription for nrf_802154_auto_pending_bit_set.
*/
@ -547,30 +602,67 @@ typedef enum
/**
* @brief Spinel data type description for nrf_802154_transmit_csma_ca_raw.
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW \
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW \
SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */
/**
* @brief Spinel data type description for nrf_802154_retransmit_csma_ca_raw.
* @brief Spinel data type description for nrf_802154_transmit_done_metadata.
*/
#define SPINEL_DATATYPE_NRF_802154_RETRANSMIT_CSMA_CA_RAW \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_DONE_METADATA_S \
SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* Frame props */ \
SPINEL_DATATYPE_UINT8_S /* Length */ \
SPINEL_DATATYPE_INT8_S /* Power */ \
SPINEL_DATATYPE_UINT8_S /* LQI */ \
SPINEL_DATATYPE_UINT32_S /* Timestamp */ \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Ack frame with its handle */
/**
* @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_DONE_METADATA_S data type.
*
* @param[in] metadata Transmit done metadata structure to be decoded.
* @param[in] ack_handle Variable containing handle to
*/
#define NRF_802154_TRANSMIT_DONE_METADATA_ENCODE(metadata, ack_handle) \
NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((metadata).frame_props), \
(metadata).data.transmitted.length, \
(metadata).data.transmitted.power, \
(metadata).data.transmitted.lqi, \
(metadata).data.transmitted.time, \
NRF_802154_HDATA_ENCODE(ack_handle, \
(metadata).data.transmitted.p_ack, \
((metadata).data.transmitted.p_ack) ? \
((metadata).data.transmitted.p_ack)[0] + 1 : 0)
/**
* @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_DONE_METADATA_S data type.
*
* @param[out] metadata Transmit done metadata structure to which store decoded data.
* @param[out] ack_handle Pointer variable to which store handle of received ACK frame.
* @param[out] ack_length Variable to which store length of the decoded ACK with a handle.
*/
#define NRF_802154_TRANSMIT_DONE_METADATA_DECODE(metadata, ack_handle, ack_length) \
NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE((metadata).frame_props), \
&(metadata).data.transmitted.length, \
&(metadata).data.transmitted.power, \
&(metadata).data.transmitted.lqi, \
&(metadata).data.transmitted.time, \
NRF_802154_HDATA_DECODE(ack_handle, (metadata).data.transmitted.p_ack, ack_length)
/**
* @brief Spinel data type description for nrf_802154_transmitted_raw.
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW \
SPINEL_DATATYPE_UINT32_S /* Handle to transmitted frame */ \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Ack frame with its handle */ \
SPINEL_DATATYPE_INT8_S /* Power */ \
SPINEL_DATATYPE_UINT8_S /* LQI */
#define SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW \
SPINEL_DATATYPE_UINT32_S /* Handle to transmitted frame */ \
SPINEL_DATATYPE_NRF_802154_TRANSMIT_DONE_METADATA_S /* Transmit done metadata */
/**
* @brief Spinel data type description for nrf_802154_transmit_failed.
*/
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED \
SPINEL_DATATYPE_UINT32_S /* Handle to transmitted frame */ \
SPINEL_DATATYPE_UINT8_S /* Error code */
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED \
SPINEL_DATATYPE_UINT32_S /* Handle to transmitted frame */ \
SPINEL_DATATYPE_UINT8_S /* Error code */ \
SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* Frame props */
/**
* @brief Spinel data type description for nrf_802154_capabilities_get.

View File

@ -853,75 +853,8 @@ bail:
return ed_result;
}
void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data)
{
nrf_802154_ser_err_t res;
uint32_t data_handle;
SERIALIZATION_ERROR_INIT(error);
NRF_802154_SPINEL_LOG_BANNER_CALLING();
NRF_802154_SPINEL_LOG_BUFF(p_data, p_data[0]);
bool handle_added = nrf_802154_buffer_mgr_src_add(nrf_802154_spinel_src_buffer_mgr_get(),
p_data,
&data_handle);
SERIALIZATION_ERROR_IF(!handle_added, NRF_802154_SERIALIZATION_ERROR_NO_MEMORY, error, bail);
nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS);
res = nrf_802154_spinel_send_cmd_prop_value_set(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW,
NRF_802154_HDATA_ENCODE(data_handle, p_data, p_data[0]));
SERIALIZATION_ERROR_CHECK(res, error, bail);
res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT);
SERIALIZATION_ERROR_CHECK(res, error, bail);
bail:
SERIALIZATION_ERROR_RAISE_IF_FAILED(error);
return;
}
void nrf_802154_retransmit_csma_ca_raw(const uint8_t * p_data)
{
nrf_802154_ser_err_t res;
uint32_t data_handle;
SERIALIZATION_ERROR_INIT(error);
NRF_802154_SPINEL_LOG_BANNER_CALLING();
NRF_802154_SPINEL_LOG_BUFF(p_data, p_data[0]);
bool handle_added = nrf_802154_buffer_mgr_src_add(nrf_802154_spinel_src_buffer_mgr_get(),
p_data,
&data_handle);
SERIALIZATION_ERROR_IF(!handle_added, NRF_802154_SERIALIZATION_ERROR_NO_MEMORY, error, bail);
nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS);
res = nrf_802154_spinel_send_cmd_prop_value_set(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RETRANSMIT_CSMA_CA_RAW,
SPINEL_DATATYPE_NRF_802154_RETRANSMIT_CSMA_CA_RAW,
NRF_802154_HDATA_ENCODE(data_handle, p_data, p_data[0]));
SERIALIZATION_ERROR_CHECK(res, error, bail);
res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT);
SERIALIZATION_ERROR_CHECK(res, error, bail);
bail:
SERIALIZATION_ERROR_RAISE_IF_FAILED(error);
return;
}
bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
bool nrf_802154_transmit_csma_ca_raw(uint8_t * p_data,
const nrf_802154_transmit_csma_ca_metadata_t * p_metadata)
{
nrf_802154_ser_err_t res;
uint32_t data_handle;
@ -936,6 +869,77 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
p_data,
&data_handle);
if (p_metadata == NULL)
{
static const nrf_802154_transmit_csma_ca_metadata_t metadata_default =
{
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
};
p_metadata = &metadata_default;
}
SERIALIZATION_ERROR_IF(!handle_added, NRF_802154_SERIALIZATION_ERROR_NO_MEMORY, error, bail);
nrf_802154_spinel_response_notifier_lock_before_request(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW);
res = nrf_802154_spinel_send_cmd_prop_value_set(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW,
NRF_802154_TRANSMIT_CSMA_CA_METADATA_ENCODE(*p_metadata),
NRF_802154_HDATA_ENCODE(data_handle, p_data, p_data[0]));
SERIALIZATION_ERROR_CHECK(res, error, bail);
res = net_generic_bool_response_await(&transmit_result,
CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT);
SERIALIZATION_ERROR_CHECK(res, error, bail);
return transmit_result;
bail:
if (handle_added)
{
/* Rollback what we did until an error to avoid memory leak. */
nrf_802154_buffer_mgr_src_remove_by_buffer_handle(
nrf_802154_spinel_src_buffer_mgr_get(),
data_handle);
}
SERIALIZATION_ERROR_RAISE_IF_FAILED(error);
return transmit_result;
}
bool nrf_802154_transmit_raw(uint8_t * p_data,
const nrf_802154_transmit_metadata_t * p_metadata)
{
nrf_802154_ser_err_t res;
uint32_t data_handle;
bool transmit_result = false;
SERIALIZATION_ERROR_INIT(error);
NRF_802154_SPINEL_LOG_BANNER_CALLING();
NRF_802154_SPINEL_LOG_BUFF(p_data, p_data[0]);
bool handle_added = nrf_802154_buffer_mgr_src_add(nrf_802154_spinel_src_buffer_mgr_get(),
p_data,
&data_handle);
if (p_metadata == NULL)
{
static const nrf_802154_transmit_metadata_t metadata_default =
{
.frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
.cca = true
};
p_metadata = &metadata_default;
}
SERIALIZATION_ERROR_IF(!handle_added, NRF_802154_SERIALIZATION_ERROR_NO_MEMORY, error, bail);
nrf_802154_spinel_response_notifier_lock_before_request(
@ -944,8 +948,8 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
res = nrf_802154_spinel_send_cmd_prop_value_set(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW,
NRF_802154_HDATA_ENCODE(data_handle, p_data, p_data[0]),
cca);
NRF_802154_TRANSMIT_METADATA_ENCODE(*p_metadata),
NRF_802154_HDATA_ENCODE(data_handle, p_data, p_data[0]));
SERIALIZATION_ERROR_CHECK(res, error, bail);

View File

@ -279,24 +279,23 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmitted_raw(
const void * p_property_data,
size_t property_data_len)
{
uint32_t frame_handle;
uint32_t remote_ack_handle;
void * p_ack;
size_t ack_hdata_len;
int8_t power;
uint8_t lqi;
void * p_frame;
void * p_ack_local_ptr = NULL;
uint32_t frame_handle;
uint32_t remote_ack_handle;
void * p_ack;
size_t ack_hdata_len;
void * p_frame;
void * p_ack_local_ptr = NULL;
nrf_802154_transmit_done_metadata_t metadata = {0};
spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW,
&frame_handle,
NRF_802154_HDATA_DECODE(remote_ack_handle,
p_ack,
ack_hdata_len),
&power,
&lqi);
NRF_802154_TRANSMIT_DONE_METADATA_DECODE(metadata,
remote_ack_handle,
ack_hdata_len));
p_ack = metadata.data.transmitted.p_ack;
if (siz < 0)
{
@ -347,7 +346,9 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmitted_raw(
return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER;
}
nrf_802154_transmitted_raw(p_frame, p_ack_local_ptr, power, lqi);
// Overwrite ACK frame pointer with a newly allocated one.
metadata.data.transmitted.p_ack = p_ack_local_ptr;
nrf_802154_transmitted_raw(p_frame, &metadata);
return NRF_802154_SERIALIZATION_ERROR_OK;
}
@ -362,15 +363,18 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_failed(
const void * p_property_data,
size_t property_data_len)
{
uint32_t frame_handle;
nrf_802154_tx_error_t tx_error;
void * p_frame;
uint32_t frame_handle;
nrf_802154_tx_error_t tx_error;
void * p_frame;
nrf_802154_transmit_done_metadata_t metadata = {0};
spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED,
&frame_handle,
&tx_error);
&tx_error,
NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE(metadata.
frame_props));
if (siz < 0)
{
@ -399,7 +403,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_failed(
return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER;
}
nrf_802154_transmit_failed(p_frame, tx_error);
nrf_802154_transmit_failed(p_frame, tx_error, &metadata);
return NRF_802154_SERIALIZATION_ERROR_OK;
}
@ -537,6 +541,8 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is(
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_CLEAR:
// fall through
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW:
// fall through
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW:
nrf_802154_spinel_response_notifier_property_notify(property,
p_property_data,
property_data_len);
@ -623,22 +629,21 @@ __WEAK void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
// Intentionally empty
}
__WEAK void nrf_802154_transmitted_raw(const uint8_t * p_data,
uint8_t * p_ack,
int8_t rssi,
uint8_t lqi)
__WEAK void nrf_802154_transmitted_raw(uint8_t * p_data,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
(void)p_data;
(void)p_ack;
(void)rssi;
(void)lqi;
(void)p_metadata;
// Intentionally empty
}
__WEAK void nrf_802154_transmit_failed(const uint8_t * p_data,
nrf_802154_tx_error_t error)
__WEAK void nrf_802154_transmit_failed(uint8_t * p_data,
nrf_802154_tx_error_t error,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
(void)p_data;
(void)error;
(void)p_metadata;
// Intentionally empty
}

View File

@ -659,15 +659,17 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_csma_ca_raw(
const void * p_property_data,
size_t property_data_len)
{
uint32_t remote_frame_handle;
const void * p_frame;
size_t frame_hdata_len;
void * p_local_frame_ptr;
uint32_t remote_frame_handle;
const void * p_frame;
size_t frame_hdata_len;
void * p_local_frame_ptr;
nrf_802154_transmit_csma_ca_metadata_t tx_metadata;
spinel_ssize_t siz = spinel_datatype_unpack(
p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW,
NRF_802154_TRANSMIT_CSMA_CA_METADATA_DECODE(tx_metadata),
NRF_802154_HDATA_DECODE(remote_frame_handle, p_frame, frame_hdata_len));
if (siz < 0)
@ -689,55 +691,18 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_csma_ca_raw(
}
// Transmit the content under the locally accessible pointer
nrf_802154_transmit_csma_ca_raw(p_local_frame_ptr);
bool result = nrf_802154_transmit_csma_ca_raw(p_local_frame_ptr, &tx_metadata);
return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK);
}
/**
* @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_RETRANSMIT_CSMA_CA_RAW.
*
* @param[in] p_property_data Pointer to a buffer that contains data to be decoded.
* @param[in] property_data_len Size of the @ref p_data buffer.
*
*/
static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_retransmit_csma_ca_raw(
const void * p_property_data,
size_t property_data_len)
{
uint32_t remote_frame_handle;
const void * p_frame;
size_t frame_hdata_len;
void * p_local_frame_ptr;
spinel_ssize_t siz = spinel_datatype_unpack(
p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_RETRANSMIT_CSMA_CA_RAW,
NRF_802154_HDATA_DECODE(remote_frame_handle, p_frame, frame_hdata_len));
if (siz < 0)
if (!result)
{
return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
nrf_802154_buffer_mgr_dst_remove_by_local_pointer(nrf_802154_spinel_dst_buffer_mgr_get(),
p_local_frame_ptr);
}
// Map the remote handle to locally accessible pointer and copy the buffer content there
bool frame_added = nrf_802154_buffer_mgr_dst_add(
nrf_802154_spinel_dst_buffer_mgr_get(),
remote_frame_handle,
p_frame,
NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len),
&p_local_frame_ptr);
if (!frame_added)
{
return NRF_802154_SERIALIZATION_ERROR_NO_MEMORY;
}
// Transmit the content under the locally accessible pointer
nrf_802154_retransmit_csma_ca_raw(p_local_frame_ptr);
return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK);
return nrf_802154_spinel_send_cmd_prop_value_is(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW_RET,
result);
}
/**
@ -751,18 +716,18 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_raw(
const void * p_property_data,
size_t property_data_len)
{
uint32_t remote_frame_handle;
const void * p_frame;
size_t frame_hdata_len;
bool cca;
void * p_local_frame_ptr;
uint32_t remote_frame_handle;
const void * p_frame;
size_t frame_hdata_len;
void * p_local_frame_ptr;
nrf_802154_transmit_metadata_t tx_metadata;
spinel_ssize_t siz = spinel_datatype_unpack(
p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW,
NRF_802154_HDATA_DECODE(remote_frame_handle, p_frame, frame_hdata_len),
&cca);
NRF_802154_TRANSMIT_METADATA_DECODE(tx_metadata),
NRF_802154_HDATA_DECODE(remote_frame_handle, p_frame, frame_hdata_len));
if (siz < 0)
{
@ -782,7 +747,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_raw(
return NRF_802154_SERIALIZATION_ERROR_NO_MEMORY;
}
bool result = nrf_802154_transmit_raw(p_local_frame_ptr, cca);
bool result = nrf_802154_transmit_raw(p_local_frame_ptr, &tx_metadata);
if (!result)
{
@ -1032,10 +997,6 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_
return spinel_decode_prop_nrf_802154_transmit_csma_ca_raw(p_property_data,
property_data_len);
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RETRANSMIT_CSMA_CA_RAW:
return spinel_decode_prop_nrf_802154_retransmit_csma_ca_raw(p_property_data,
property_data_len);
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW:
return spinel_decode_prop_nrf_802154_transmit_raw(p_property_data, property_data_len);

View File

@ -278,14 +278,19 @@ bail:
SERIALIZATION_ERROR_RAISE_IF_FAILED(ser_error);
}
void nrf_802154_transmitted_raw(const uint8_t * p_frame,
uint8_t * p_ack,
int8_t power,
uint8_t lqi)
void nrf_802154_transmitted_raw(uint8_t * p_frame,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
uint32_t remote_frame_handle;
uint32_t ack_handle = 0;
uint32_t ack_len = 0;
uint32_t remote_frame_handle;
uint32_t ack_handle = 0;
uint32_t ack_len = 0;
uint8_t * p_ack = p_metadata->data.transmitted.p_ack;
/* Forcefully overwrite frame's properties due to KRKNWK-10114 not being implemented.
* This overwrite makes state of the frame consistent with its properties.
*/
((nrf_802154_transmit_done_metadata_t *)p_metadata)->frame_props =
NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT;
SERIALIZATION_ERROR_INIT(error);
@ -327,9 +332,7 @@ void nrf_802154_transmitted_raw(const uint8_t * p_frame,
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMITTED_RAW,
SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW,
remote_frame_handle,
NRF_802154_HDATA_ENCODE(ack_handle, p_ack, ack_len),
power,
lqi);
NRF_802154_TRANSMIT_DONE_METADATA_ENCODE(*p_metadata, ack_handle));
// Free the local frame pointer no matter the result of serialization
local_transmitted_frame_ptr_free((void *)p_frame);
@ -343,8 +346,9 @@ bail:
return;
}
void nrf_802154_transmit_failed(const uint8_t * p_frame,
nrf_802154_tx_error_t tx_error)
void nrf_802154_transmit_failed(uint8_t * p_frame,
nrf_802154_tx_error_t tx_error,
const nrf_802154_transmit_done_metadata_t * p_metadata)
{
uint32_t remote_frame_handle;
@ -353,6 +357,12 @@ void nrf_802154_transmit_failed(const uint8_t * p_frame,
NRF_802154_SPINEL_LOG_BANNER_CALLING();
NRF_802154_SPINEL_LOG_BUFF(p_frame, p_frame[0]);
/* Forcefully overwrite frame's properties due to KRKNWK-10114 not being implemented.
* This overwrite makes state of the frame consistent with its properties.
*/
((nrf_802154_transmit_done_metadata_t *)p_metadata)->frame_props =
NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT;
// Search for the handle to the original frame buffer based on the local pointer
bool frame_found = nrf_802154_buffer_mgr_dst_search_by_local_pointer(
nrf_802154_spinel_dst_buffer_mgr_get(),
@ -370,7 +380,8 @@ void nrf_802154_transmit_failed(const uint8_t * p_frame,
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_FAILED,
SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED,
remote_frame_handle,
tx_error);
tx_error,
NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE(p_metadata->frame_props));
// Free the local frame pointer no matter the result of serialization
local_transmitted_frame_ptr_free((void *)p_frame);

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
/**
* @file mpsl_fem_config_common.h
*
* @defgroup mpsl_fem_config_common MPSL Front End Module Common Configuration parts
* @ingroup mpsl_fem
*
* The MPSL Front End Module Common Configuration defines structures common for every supported Front End Module.
* @{
*/
#ifndef MPSL_FEM_CONFIG_COMMON_H__
#define MPSL_FEM_CONFIG_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Configuration parameters for pins that enable or disable (or both) either Power Amplifier (PA) or Low Noise Amplifier (LNA).
*/
typedef struct
{
bool enable; /**< Enable toggling for this pin. */
bool active_high; /**< If true, the pin will be active high. Otherwise, the pin will be active low. */
uint8_t gpio_pin; /**< GPIO pin number for the pin. */
uint8_t gpiote_ch_id; /**< The GPIOTE channel used for toggling this pin. */
} mpsl_fem_gpiote_pin_config_t;
/** @brief Sets flag which determines whether DEVICE-CONFIG-254 shall be applied.
*
* @note This function shall be called before initialization of any protocol stack.
*
* @param[in] apply Whether the DEVICE-CONFIG-254 option shall be applied.
*/
void mpsl_fem_device_config_254_apply_set(bool apply);
/** @brief Gets flag which determines whether DEVICE-CONFIG-254 shall be applied.
*
* @retval true DEVICE-CONFIG-254 shall be applied.
* @retval false DEVICE-CONFIG-254 shall not be applied.
*/
bool mpsl_fem_device_config_254_apply_get(void);
#ifdef __cplusplus
}
#endif
#endif // MPSL_FEM_CONFIG_COMMON_H__
/**@} */

View File

@ -1,35 +1,7 @@
/*
* Copyright (c) 2020 - 2021, Nordic Semiconductor ASA
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
/**
@ -77,10 +49,13 @@ typedef struct
/** Implementation of the event. */
union
{
/** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_TIMER. */
struct
{
/** Pointer to a 1-us resolution timer instance. */
NRF_TIMER_Type * p_timer_instance;
/** Counter period parameters */
struct
{
/** Timer value when the Front End Module can start preparing PA/LNA. */
@ -89,10 +64,13 @@ typedef struct
uint32_t end;
/** Time interval in which the timer should start and end. */
} counter_period;
/** Mask of the compare channels that can be used by the Front End Module to schedule its own tasks. */
uint8_t compare_channel_mask;
/** Event generated by the timer, used in case of type equal to @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_TIMER. */
} timer;
/** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_GENERIC. */
struct
{
/** Address of event register. */

View File

@ -32,9 +32,10 @@
*
*/
#include <stdint.h>
#include <nrf.h>
#include "nrf_errno.h"
#include <stdbool.h>
#include <stdint.h>
#include "mpsl_fem_protocol_api.h"
@ -121,6 +122,11 @@ bool mpsl_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
return false;
}
bool mpsl_fem_device_config_254_apply_get(void)
{
return false;
}
int8_t nrf_802154_fal_tx_power_get(const uint8_t channel, const int8_t power)
{
(void)channel;