drivers: nrf_802154: Update the IEEE 802.15.4 component

This change adds the following:
- Thread link metric injection support
- key management API
- frame encryption and frame counter injection
- retransmission API

sdk-nrf-802154 commit: 6ed86a9af2a3b2c6d5a9ee5ae88497464f2a57d3

Signed-off-by: Rafał Kuźnia <rafal.kuznia@nordicsemi.no>
This commit is contained in:
Rafał Kuźnia 2021-05-27 12:03:36 +02:00 committed by Carles Cufí
parent d533671f46
commit 74b3b21f60
58 changed files with 5061 additions and 474 deletions

View File

@ -1,8 +1,36 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# 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.
#
#
add_library(nrf-802154-driver-interface INTERFACE)
add_library(nrf-802154-serialization-interface INTERFACE)

View File

@ -1,8 +1,36 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# 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.
#
#
target_include_directories(nrf-802154-driver-interface INTERFACE include)
@ -16,11 +44,13 @@ target_include_directories(nrf-802154-driver
target_sources(nrf-802154-driver
PRIVATE
src/nrf_802154.c
src/nrf_802154_aes_ccm.c
src/nrf_802154_core.c
src/nrf_802154_core_hooks.c
src/nrf_802154_critical_section.c
src/nrf_802154_debug.c
src/nrf_802154_debug_assert.c
src/nrf_802154_encrypt.c
src/nrf_802154_pib.c
src/nrf_802154_peripherals_alloc.c
src/nrf_802154_queue.c
@ -29,24 +59,24 @@ target_sources(nrf-802154-driver
src/nrf_802154_stats.c
src/nrf_802154_swi.c
src/nrf_802154_trx.c
src/nrf_802154_trx_dppi.c
src/nrf_802154_trx_ppi.c
src/mac_features/nrf_802154_csma_ca.c
src/mac_features/nrf_802154_delayed_trx.c
src/mac_features/nrf_802154_filter.c
src/mac_features/nrf_802154_frame_parser.c
src/mac_features/nrf_802154_ie_writer.c
src/mac_features/nrf_802154_ifs.c
src/mac_features/nrf_802154_security_pib_ram.c
src/mac_features/nrf_802154_security_writer.c
src/mac_features/nrf_802154_precise_ack_timeout.c
src/mac_features/ack_generator/nrf_802154_ack_data.c
src/mac_features/ack_generator/nrf_802154_ack_generator.c
src/mac_features/ack_generator/nrf_802154_enh_ack_generator.c
src/mac_features/ack_generator/nrf_802154_imm_ack_generator.c
src/platform/temperature/nrf_802154_temperature_none.c
)
if (NRF52_SERIES)
target_sources(nrf-802154-driver PRIVATE src/nrf_802154_trx_ppi.c)
elseif (NRF53_SERIES)
target_sources(nrf-802154-driver PRIVATE src/nrf_802154_trx_dppi.c)
endif()
)
if (SL_OPENSOURCE)
target_sources(nrf-802154-driver
@ -72,16 +102,8 @@ if (SL_OPENSOURCE OR NRF53_SERIES)
NRF_802154_DELAYED_TRX_ENABLED=0
# Disable IFS
NRF_802154_IFS_ENABLED=0
)
else()
target_compile_definitions(nrf-802154-driver-interface
INTERFACE
# Enable Frame Timestamps
NRF_802154_FRAME_TIMESTAMP_ENABLED=1
# Enable DTRX
NRF_802154_DELAYED_TRX_ENABLED=1
# Enable IFS
NRF_802154_IFS_ENABLED=1
# Disable IE writer
NRF_802154_IE_WRITER_ENABLED=0
)
endif()

View File

@ -635,6 +635,57 @@ bool nrf_802154_transmit_raw_at(const uint8_t * p_data,
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);
/**
* @brief Cancels a delayed transmission scheduled by a call to @ref nrf_802154_transmit_raw_at.
*
@ -1207,7 +1258,9 @@ void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_m
/**
* @brief Adds the address of a peer node for which the provided ACK data
* is to be added to the pending bit list.
* is to be injected into generated ACKs.
*
* Data passed to this function can be either pending bit data or Header IE data.
*
* The pending bit list works differently, depending on the upper layer for which the source
* address matching method is selected:
@ -1216,6 +1269,36 @@ void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_m
* - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1
* For more information, see @ref nrf_802154_src_addr_match_t.
*
* For IE data, specific cases are supported, where additional data will be injected into the IE on pre-transmission:
* - CSL IE - CSL phase will be injected if IE ID is set to @ref IE_CSL_ID
* - Thread link metrics - Link metrics will be injected if
* - IE ID is set to IE_VENDOR_ID
* - OUI is set to IE_VENDOR_THREAD_OUI
* - Thread IE subtype is set to IE_VENDOR_THREAD_ACK_PROBING_ID
*
* For Link metrics to be injected, additional preparation is required. Each byte of injected link metrics needs to be filled
* with a token, indicating what type of data is to be injected pre-transmission. Supported tokens are:
* - @ref IE_VENDOR_THREAD_RSSI_TOKEN - RSSI of the last received frame will be injected,
* - @ref IE_VENDOR_THREAD_MARGIN_TOKEN - RSSI above sensitivity margin of the last received frame will be injected,
* - @ref IE_VENDOR_THREAD_LQI_TOKEN - LQI of the last received frame will be injected.
* Additionally, tokens must be unique in given IE, all bytes prepared for link metrics must be filled with tokens and no more
* than two bytes must be prepared for link metrics.
* If any of those conditions is not met, no data will be injected into the ACK pre-transmission.
*
* To better illustrate, if RSSI is to be inserted into ACKs for specific address,
* following ie data needs to be prepared:
*
* +------------+----------------------+---------------------------------+-----------------------------+
* | Bytes: 0-1 | 2-4 | 5 | 6 |
* +------------+----------------------+---------------------------------+-----------------------------+
* | IE header | IE_VENDOR_THREAD_OUI | IE_VENDOR_THREAD_ACK_PROBING_ID | IE_VENDOR_THREAD_RSSI_TOKEN |
* +------------+----------------------+---------------------------------+-----------------------------+
* | |
* | <------------------IE Vendor-specific data------------------> |
*
* When sending ACK with this data, before transmission, RSSI of the last received frame
* will be written into byte 6.
*
* The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method.
*
* @param[in] p_addr Array of bytes containing the address of the node (little-endian).
@ -1385,6 +1468,32 @@ void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg);
*/
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);
#else // NRF_802154_USE_RAW_API
/**
@ -1406,6 +1515,33 @@ void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data);
*/
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);
#endif // NRF_802154_USE_RAW_API
/**
@ -1674,7 +1810,7 @@ void nrf_802154_ifs_min_lifs_period_set(uint16_t period);
*/
/**
* @brief Gets nRF 802.15.4 Radio Diver Capabilities.
* @brief Gets nRF 802.15.4 Radio Driver Capabilities.
*
* @return Capabilities of the radio driver.
*/
@ -1682,6 +1818,68 @@ nrf_802154_capabilities_t nrf_802154_capabilities_get(void);
/** @} */
/**
* @}
* @defgroup nrf_802154_security Radio driver MAC security feature.
* @{
*/
/**
* @brief Sets nRF 802.15.4 Radio Driver Global MAC Frame Counter.
*
* The driver automatically increments the counter in every outgoing frame
* which uses the Global MAC Frame Counter.
* This call is meant to set the initial value of the frame counter.
*
* @param[in] frame_counter Global MAC Frame Counter to set.
*/
void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter);
/**
* @brief Store the 802.15.4 MAC Security Key inside the nRF 802.15.4 Radio Driver.
*
* @param[in] p_key Pointer to the key to store. Refer to @ref nrf_802154_key_t for details.
* Storing the key copies the content of the key and key ID into the Radio Driver.
* This input parameter can be destroyed after the call.
*
* @note This function is not reentrant and must be called from thread context only.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Storing of key is successful.
* @retval NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED Type of the key is not supported.
* @retval NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED ID mode of the key is not supported.
* @retval NRF_802154_SECURITY_ERROR_ALREADY_PRESENT Failed to store the key - key of such id is already
* present. Remove the key first to overwrite.
* @retval NRF_802154_SECURITY_ERROR_STORAGE_FULL Failed to store the key - storage full.
*/
nrf_802154_security_error_t nrf_802154_security_key_store(nrf_802154_key_t * p_key);
/**
* @brief Remove the 802.15.4 MAC Security Key from the nRF 802.15.4 Radio Driver.
*
* @param[in] p_id Pointer to the ID of the key to remove.
*
* @note This function is not reentrant and must be called from thread context only.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Removal of key is successful.
* @retval NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND Failed to remove the key - no such key found.
*/
nrf_802154_security_error_t nrf_802154_security_key_remove(nrf_802154_key_id_t * p_id);
/**
* @}
* @defgroup nrf_802154_ie_writer Radio driver Information Element data injection feature.
* @{
*/
/**
* @brief Sets the value of CSL period to inject into the CSL information element.
*
* @param[in] period CSL period value.
*/
void nrf_802154_csl_writer_period_set(uint16_t period);
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -108,14 +108,8 @@ extern "C" {
*/
#ifndef NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#if RAAL_SOFTDEVICE || RAAL_REM
#define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 0
#else // RAAL_SOFTDEVICE || RAAL_REM
#define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 1
#endif // RAAL_SOFTDEVICE || RAAL_REM
#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#endif
/**
* @def NRF_802154_INTERNAL_SWI_IRQ_HANDLING
@ -128,14 +122,8 @@ extern "C" {
*/
#ifndef NRF_802154_INTERNAL_SWI_IRQ_HANDLING
#if RAAL_SOFTDEVICE || RAAL_REM
#define NRF_802154_INTERNAL_SWI_IRQ_HANDLING 0
#else // RAAL_SOFTDEVICE || RAAL_REM
#define NRF_802154_INTERNAL_SWI_IRQ_HANDLING 1
#endif // RAAL_SOFTDEVICE || RAAL_REM
#endif // NRF_802154_INTERNAL_SWI_IRQ_HANDLING
#endif
/**
* @def NRF_802154_IRQ_PRIORITY
@ -158,6 +146,16 @@ extern "C" {
#define NRF_802154_SWI_PRIORITY 4
#endif
/**
* @def NRF_802154_ECB_PRIORITY
*
* Interrupt priority for ECB peripheral used for frame encryption.
*
*/
#ifndef NRF_802154_ECB_PRIORITY
#define NRF_802154_ECB_PRIORITY 3
#endif
/**
* @def NRF_802154_USE_RAW_API
*
@ -482,6 +480,59 @@ extern "C" {
#define NRF_802154_STATS_COUNT_RECEIVED_PREAMBLES 1
#endif
/**
* @}
* @defgroup nrf_802154_security Security configuration
* @{
*/
/**
* @def NRF_802154_SECURITY_KEY_STORAGE_SIZE
*
* Configures the number of keys which are available in the Key Storage.
* This configuration is implementation-independent.
*/
#ifndef NRF_802154_SECURITY_KEY_STORAGE_SIZE
#define NRF_802154_SECURITY_KEY_STORAGE_SIZE 3
#endif
/**
* @def NRF_802154_SECURITY_WRITER_ENABLED
*
* Enables the Security Writer module. The module parses the frame being transmitted, validates
* frame's security header and injects frame counter associated with the used key.
*/
#ifndef NRF_802154_SECURITY_WRITER_ENABLED
#define NRF_802154_SECURITY_WRITER_ENABLED 1
#endif
/**
* @def NRF_802154_ENCRYPTION_ENABLED
*
* Enables the frame encryption module. The module uses AES-CCM* algorithm to secure frames
* transmitted by the driver.
*/
#ifndef NRF_802154_ENCRYPTION_ENABLED
#define NRF_802154_ENCRYPTION_ENABLED 1
#endif
/**
* @}
* @defgroup nrf_802154_ie Information Elements configuration
* @{
*/
/**
* @def NRF_802154_IE_WRITER_ENABLED
*
* Enables the Information Element writer module. The module parses frames being transmitted
* for known Information Element IDs. If such elements are found, the writer module shall
* fill the elements with appropriate data.
*/
#ifndef NRF_802154_IE_WRITER_ENABLED
#define NRF_802154_IE_WRITER_ENABLED 1
#endif
#ifdef __cplusplus
}
#endif

View File

@ -43,129 +43,182 @@
#include <stdint.h>
#include "nrf_802154_config.h"
#define ACK_HEADER_WITH_PENDING 0x12 ///< The first byte of an ACK frame containing a pending bit.
#define ACK_HEADER_WITHOUT_PENDING 0x02 ///< The first byte of an ACK frame without a pending bit.
#define ACK_HEADER_WITH_PENDING 0x12 ///< The first byte of an ACK frame containing a pending bit.
#define ACK_HEADER_WITHOUT_PENDING 0x02 ///< The first byte of an ACK frame without a pending bit.
#define ACK_REQUEST_OFFSET 1 ///< Byte containing the ACK request bit (+1 for the frame length byte).
#define ACK_REQUEST_BIT (1 << 5) ///< ACK request bit.
#define ACK_REQUEST_OFFSET 1 ///< Byte containing the ACK request bit (+1 for the frame length byte).
#define ACK_REQUEST_BIT (1 << 5) ///< ACK request bit.
#define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing the destination address type (+1 for the frame length byte).
#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing the destination address type.
#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing the extended destination address type.
#define DEST_ADDR_TYPE_NONE 0x00 ///< Bits containing a not-present destination address type.
#define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing the short destination address type.
#define DEST_ADDR_OFFSET 6 ///< Offset of the destination address in the Data frame (+1 for the frame length byte).
#define ASN_IN_NONCE_BIT 0x40 ///< Bit containing the ASN in Nonce field.
#define DSN_OFFSET 3 ///< Byte containing the DSN value (+1 for the frame length byte).
#define DSN_SUPPRESS_OFFSET 2 ///< Byte containing the DSN suppression field.
#define DSN_SUPPRESS_BIT 0x01 ///< Bits containing the DSN suppression field.
#define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing the destination address type (+1 for the frame length byte).
#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing the destination address type.
#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing the extended destination address type.
#define DEST_ADDR_TYPE_NONE 0x00 ///< Bits containing a not-present destination address type.
#define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing the short destination address type.
#define DEST_ADDR_OFFSET 6 ///< Offset of the destination address in the Data frame (+1 for the frame length byte).
#define FRAME_COUNTER_SUPPRESS_BIT 0x20 ///< Bit containing the Frame Counter Suppression field.
#define DSN_OFFSET 3 ///< Byte containing the DSN value (+1 for the frame length byte).
#define DSN_SUPPRESS_OFFSET 2 ///< Byte containing the DSN suppression field.
#define DSN_SUPPRESS_BIT 0x01 ///< Bits containing the DSN suppression field.
#define FRAME_PENDING_OFFSET 1 ///< Byte containing a pending bit (+1 for the frame length byte).
#define FRAME_PENDING_BIT (1 << 4) ///< Pending bit.
#define FRAME_COUNTER_SUPPRESS_BIT 0x20 ///< Bit containing the Frame Counter Suppression field.
#define FRAME_TYPE_OFFSET 1 ///< Byte containing the frame type bits (+1 for the frame length byte).
#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing the frame type.
#define FRAME_TYPE_ACK 0x02 ///< Bits containing the ACK frame type.
#define FRAME_TYPE_BEACON 0x00 ///< Bits containing the Beacon frame type.
#define FRAME_TYPE_COMMAND 0x03 ///< Bits containing the Command frame type.
#define FRAME_TYPE_DATA 0x01 ///< Bits containing the Data frame type.
#define FRAME_TYPE_EXTENDED 0x07 ///< Bits containing the Extended frame type.
#define FRAME_TYPE_FRAGMENT 0x06 ///< Bits containing the Fragment or the Frak frame type.
#define FRAME_TYPE_MULTIPURPOSE 0x05 ///< Bits containing the Multipurpose frame type.
#define FRAME_PENDING_OFFSET 1 ///< Byte containing a pending bit (+1 for the frame length byte).
#define FRAME_PENDING_BIT (1 << 4) ///< Pending bit.
#define FRAME_VERSION_OFFSET 2 ///< Byte containing the frame version bits (+1 for the frame length byte).
#define FRAME_VERSION_MASK 0x30 ///< Mask of bits containing the frame version.
#define FRAME_VERSION_0 0x00 ///< Bits containing the frame version 0b00.
#define FRAME_VERSION_1 0x10 ///< Bits containing the frame version 0b01.
#define FRAME_VERSION_2 0x20 ///< Bits containing the frame version 0b10.
#define FRAME_VERSION_3 0x30 ///< Bits containing the frame version 0b11.
#define FRAME_TYPE_OFFSET 1 ///< Byte containing the frame type bits (+1 for the frame length byte).
#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing the frame type.
#define FRAME_TYPE_ACK 0x02 ///< Bits containing the ACK frame type.
#define FRAME_TYPE_BEACON 0x00 ///< Bits containing the Beacon frame type.
#define FRAME_TYPE_COMMAND 0x03 ///< Bits containing the Command frame type.
#define FRAME_TYPE_DATA 0x01 ///< Bits containing the Data frame type.
#define FRAME_TYPE_EXTENDED 0x07 ///< Bits containing the Extended frame type.
#define FRAME_TYPE_FRAGMENT 0x06 ///< Bits containing the Fragment or the Frak frame type.
#define FRAME_TYPE_MULTIPURPOSE 0x05 ///< Bits containing the Multipurpose frame type.
#define IE_HEADER_LENGTH_MASK 0x3f ///< Mask of bits containing the length of an IE header content.
#define IE_PRESENT_OFFSET 2 ///< Byte containing the IE Present bit.
#define IE_PRESENT_BIT 0x02 ///< Bits containing the IE Present field.
#define FRAME_VERSION_OFFSET 2 ///< Byte containing the frame version bits (+1 for the frame length byte).
#define FRAME_VERSION_MASK 0x30 ///< Mask of bits containing the frame version.
#define FRAME_VERSION_0 0x00 ///< Bits containing the frame version 0b00.
#define FRAME_VERSION_1 0x10 ///< Bits containing the frame version 0b01.
#define FRAME_VERSION_2 0x20 ///< Bits containing the frame version 0b10.
#define FRAME_VERSION_3 0x30 ///< Bits containing the frame version 0b11.
#define KEY_ID_MODE_MASK 0x18 ///< Mask of bits containing Key Identifier Mode in the Security Control field.
#define KEY_ID_MODE_0 0 ///< Bits containing the 0x00 Key Identifier Mode.
#define KEY_ID_MODE_1 0x08 ///< Bits containing the 0x01 Key Identifier Mode.
#define KEY_ID_MODE_2 0x10 ///< Bits containing the 0x10 Key Identifier Mode.
#define KEY_ID_MODE_3 0x18 ///< Bits containing the 0x11 Key Identifier Mode.
#define IE_HEADER_LENGTH_MASK 0x3f ///< Mask of bits containing the length of an IE header content.
#define IE_PRESENT_OFFSET 2 ///< Byte containing the IE Present bit.
#define IE_PRESENT_BIT 0x02 ///< Bits containing the IE Present 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.
#define MAC_CMD_DISASSOC_NOTIFY 0x03 ///< Command frame identifier for MAC Disaccociation notification.
#define MAC_CMD_DATA_REQ 0x04 ///< Command frame identifier for MAC Data Requests.
#define MAC_CMD_PANID_CONFLICT 0x05 ///< Command frame identifier for MAC PAN ID conflict notification.
#define MAC_CMD_ORPHAN_NOTIFY 0x06 ///< Command frame identifier for MAC Orphan notification.
#define MAC_CMD_BEACON_REQ 0x07 ///< Command frame identifier for MAC Beacon.
#define MAC_CMD_COORD_REALIGN 0x08 ///< Command frame identifier for MAC Coordinator realignment.
#define MAC_CMD_GTS_REQUEST 0x09 ///< Command frame identifier for MAC GTS request.
#define KEY_ID_MODE_0 0 ///< Value of the 0x00 Key Identifier Mode.
#define KEY_ID_MODE_1 1 ///< Value of the 0x01 Key Identifier Mode.
#define KEY_ID_MODE_2 2 ///< Value of the 0x10 Key Identifier Mode.
#define KEY_ID_MODE_3 3 ///< Value of the 0x11 Key Identifier Mode.
#define PAN_ID_COMPR_OFFSET 1 ///< Byte containing the PAN ID compression bit (+1 for the frame length byte).
#define PAN_ID_COMPR_MASK 0x40 ///< PAN ID compression bit.
#define KEY_ID_MODE_MASK 0x18 ///< Mask of bits containing Key Identifier Mode in the Security Control field.
#define KEY_ID_MODE_BIT_OFFSET 3 ///< Number of bits the Key Identifier Mode is offset in the Security Control field.
#define KEY_ID_MODE_0_MASK 0 ///< Bits containing the 0x00 Key Identifier Mode.
#define KEY_ID_MODE_1_MASK 0x08 ///< Bits containing the 0x01 Key Identifier Mode.
#define KEY_ID_MODE_2_MASK 0x10 ///< Bits containing the 0x10 Key Identifier Mode.
#define KEY_ID_MODE_3_MASK 0x18 ///< Bits containing the 0x11 Key Identifier Mode.
#define PAN_ID_OFFSET 4 ///< Offset of PAN ID in the Data frame (+1 for the frame length byte).
#define KEY_SRC_KEY_ID_MODE_0_SIZE 0 ///< Size of the Key Source field when Key Identifier Mode equals 0.
#define KEY_SRC_KEY_ID_MODE_1_SIZE 0 ///< Size of the Key Source field when Key Identifier Mode equals 1.
#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 PHR_OFFSET 0 ///< Offset of the PHY header in a frame.
#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.
#define MAC_CMD_DISASSOC_NOTIFY 0x03 ///< Command frame identifier for MAC Disaccociation notification.
#define MAC_CMD_DATA_REQ 0x04 ///< Command frame identifier for MAC Data Requests.
#define MAC_CMD_PANID_CONFLICT 0x05 ///< Command frame identifier for MAC PAN ID conflict notification.
#define MAC_CMD_ORPHAN_NOTIFY 0x06 ///< Command frame identifier for MAC Orphan notification.
#define MAC_CMD_BEACON_REQ 0x07 ///< Command frame identifier for MAC Beacon.
#define MAC_CMD_COORD_REALIGN 0x08 ///< Command frame identifier for MAC Coordinator realignment.
#define MAC_CMD_GTS_REQUEST 0x09 ///< Command frame identifier for MAC GTS request.
#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_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).
#define SECURITY_LEVEL_ENC_MIC_32 0x05 ///< Bits containing the 32-bit Encrypted Message Integrity Code (0b101).
#define SECURITY_LEVEL_ENC_MIC_64 0x06 ///< Bits containing the 64-bit Encrypted Message Integrity Code (0b110).
#define SECURITY_LEVEL_ENC_MIC_128 0x07 ///< Bits containing the 128-bit Encrypted Message Integrity Code (0b111).
#define PAN_ID_COMPR_OFFSET 1 ///< Byte containing the PAN ID compression bit (+1 for the frame length byte).
#define PAN_ID_COMPR_MASK 0x40 ///< PAN ID compression bit.
#define SRC_ADDR_TYPE_EXTENDED 0xc0 ///< Bits containing the extended source address type.
#define SRC_ADDR_TYPE_NONE 0x00 ///< Bits containing a not-present source address type.
#define SRC_ADDR_TYPE_MASK 0xc0 ///< Mask of bits containing the source address type.
#define SRC_ADDR_TYPE_OFFSET 2 ///< Byte containing the source address type (+1 for the frame length byte).
#define SRC_ADDR_TYPE_SHORT 0x80 ///< Bits containing the short source address type.
#define PAN_ID_OFFSET 4 ///< Offset of PAN ID in the Data frame (+1 for the frame length byte).
#define SRC_ADDR_OFFSET_SHORT_DST 8 ///< Offset of the source address in the Data frame if the destination address is short.
#define SRC_ADDR_OFFSET_EXTENDED_DST 14 ///< Offset of the source address in the Data frame if the destination address is extended.
#define PHR_OFFSET 0 ///< Offset of the PHY header in a frame.
#define PHR_LENGTH_MASK 0x7f ///< Mask of the PHR length field
#define DSN_SIZE 1 ///< Size of the Sequence Number field.
#define FCF_SIZE 2 ///< Size of the FCF field.
#define FCS_SIZE 2 ///< Size of the FCS field.
#define FRAME_COUNTER_SIZE 4 ///< Size of the Frame Counter field.
#define IE_HEADER_SIZE 4 ///< Size of the obligatory IE Header field elements, including the header termination.
#define IMM_ACK_LENGTH 5 ///< Length of the ACK frame.
#define KEY_ID_MODE_1_SIZE 1 ///< Size of the 0x01 Key Identifier Mode field.
#define KEY_ID_MODE_2_SIZE 5 ///< Size of the 0x10 Key Identifier Mode field.
#define KEY_ID_MODE_3_SIZE 9 ///< Size of the 0x11 Key Identifier Mode field.
#define MAX_PACKET_SIZE 127 ///< Maximum size of the radio packet.
#define MIC_32_SIZE 4 ///< Size of MIC with the MIC-32 and ENC-MIC-32 security attributes.
#define MIC_64_SIZE 8 ///< Size of MIC with the MIC-64 and ENC-MIC-64 security attributes.
#define MIC_128_SIZE 16 ///< Size of MIC with the MIC-128 and ENC-MIC-128 security attributes.
#define PAN_ID_SIZE 2 ///< Size of the PAN ID.
#define PHR_SIZE 1 ///< Size of the PHR field.
#define SECURITY_CONTROL_SIZE 1 ///< Size of the Security Control field.
#define PSDU_OFFSET 1 ///< Offset of the PHY payload.
#define EXTENDED_ADDRESS_SIZE 8 ///< Size of the Extended Mac Address.
#define SHORT_ADDRESS_SIZE 2 ///< Size of the Short Mac Address.
#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_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).
#define SECURITY_LEVEL_ENC_MIC_32 0x05 ///< Bits containing the 32-bit Encrypted Message Integrity Code (0b101).
#define SECURITY_LEVEL_ENC_MIC_64 0x06 ///< Bits containing the 64-bit Encrypted Message Integrity Code (0b110).
#define SECURITY_LEVEL_ENC_MIC_128 0x07 ///< Bits containing the 128-bit Encrypted Message Integrity Code (0b111).
#define SECURITY_LEVEL_MIC_LEVEL_MASK 0x03 ///< Mask of bits encoding the Message Integrity Code length.
#define TURNAROUND_TIME 192UL ///< RX-to-TX or TX-to-RX turnaround time (aTurnaroundTime), in microseconds (us).
#define CCA_TIME 128UL ///< Time required to perform CCA detection (aCcaTime), in microseconds (us).
#define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< Number of symbols in the basic time period used by CSMA-CA algorithm (aUnitBackoffPeriod), in (us).
#define SRC_ADDR_TYPE_EXTENDED 0xc0 ///< Bits containing the extended source address type.
#define SRC_ADDR_TYPE_NONE 0x00 ///< Bits containing a not-present source address type.
#define SRC_ADDR_TYPE_MASK 0xc0 ///< Mask of bits containing the source address type.
#define SRC_ADDR_TYPE_OFFSET 2 ///< Byte containing the source address type (+1 for the frame length byte).
#define SRC_ADDR_TYPE_SHORT 0x80 ///< Bits containing the short source address type.
#define PHY_US_PER_SYMBOL 16 ///< Duration of a single symbol in microseconds (us).
#define PHY_SYMBOLS_PER_OCTET 2 ///< Number of symbols in a single byte (octet).
#define PHY_SHR_SYMBOLS 10 ///< Number of symbols in the Synchronization Header (SHR).
#define SRC_ADDR_OFFSET_SHORT_DST 8 ///< Offset of the source address in the Data frame if the destination address is short.
#define SRC_ADDR_OFFSET_EXTENDED_DST 14 ///< Offset of the source address in the Data frame if the destination address is extended.
#define ED_RESULT_MAX 0xff ///< Maximal ED result.
#define DSN_SIZE 1 ///< Size of the Sequence Number field.
#define FCF_SIZE 2 ///< Size of the FCF field.
#define FCS_SIZE 2 ///< Size of the FCS field.
#define FRAME_COUNTER_SIZE 4 ///< Size of the Frame Counter field.
#define IE_HEADER_SIZE 2 ///< Size of the obligatory IE Header field elements.
#define IMM_ACK_LENGTH 5 ///< Length of the ACK frame.
#define KEY_ID_MODE_1_SIZE 1 ///< Size of the 0x01 Key Identifier Mode field.
#define KEY_ID_MODE_2_SIZE 5 ///< Size of the 0x10 Key Identifier Mode field.
#define KEY_ID_MODE_3_SIZE 9 ///< Size of the 0x11 Key Identifier Mode field.
#define MAX_PACKET_SIZE 127 ///< Maximum size of the radio packet.
#define MIC_32_SIZE 4 ///< Size of MIC with the MIC-32 and ENC-MIC-32 security attributes.
#define MIC_64_SIZE 8 ///< Size of MIC with the MIC-64 and ENC-MIC-64 security attributes.
#define MIC_128_SIZE 16 ///< Size of MIC with the MIC-128 and ENC-MIC-128 security attributes.
#define PAN_ID_SIZE 2 ///< Size of the PAN ID.
#define PHR_SIZE 1 ///< Size of the PHR field.
#define SECURITY_CONTROL_SIZE 1 ///< Size of the Security Control field.
#define BROADCAST_ADDRESS ((uint8_t[SHORT_ADDRESS_SIZE]) {0xff, 0xff}) ///< Broadcast short address.
#define AES_CCM_KEY_SIZE 16 ///< Size of AES CCM Key.
#define MIN_SIFS_PERIOD_US 192 ///< Minimum Short IFS period default value in us.
#define MIN_LIFS_PERIOD_US 640 ///< Minimum Long IFS period default value in us.
#define MAX_SIFS_FRAME_SIZE 18 ///< Maximum frame length which can be followed by the Short Interframe Space.
#define EXTENDED_ADDRESS_SIZE 8 ///< Size of the Extended Mac Address.
#define SHORT_ADDRESS_SIZE 2 ///< Size of the Short Mac Address.
#define NRF_802154_RESERVED_CSMACA_ID (UINT32_MAX - 2) ///< Delayed timeslot identifier reserved for CSMA/CA procedure.
#define NRF_802154_RESERVED_DTX_ID (UINT32_MAX - 3) ///< Delayed timeslot identifier reserved for delayed transmissions.
#define TURNAROUND_TIME 192UL ///< RX-to-TX or TX-to-RX turnaround time (aTurnaroundTime), in microseconds (us).
#define CCA_TIME 128UL ///< Time required to perform CCA detection (aCcaTime), in microseconds (us).
#define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< Number of symbols in the basic time period used by CSMA-CA algorithm (aUnitBackoffPeriod), in (us).
#define PHY_US_PER_SYMBOL 16 ///< Duration of a single symbol in microseconds (us).
#define PHY_SYMBOLS_PER_OCTET 2 ///< Number of symbols in a single byte (octet).
#define PHY_SHR_SYMBOLS 10 ///< Number of symbols in the Synchronization Header (SHR).
#define ED_RESULT_MAX 0xff ///< Maximal ED result.
#define BROADCAST_ADDRESS ((uint8_t[SHORT_ADDRESS_SIZE]) {0xff, 0xff}) ///< Broadcast short address.
#define MIN_SIFS_PERIOD_US 192 ///< Minimum Short IFS period default value in us.
#define MIN_LIFS_PERIOD_US 640 ///< Minimum Long IFS period default value in us.
#define MAX_SIFS_FRAME_SIZE 18 ///< Maximum frame length which can be followed by the Short Interframe Space.
#define NRF_802154_RESERVED_CSMACA_ID (UINT32_MAX - 2) ///< Delayed timeslot identifier reserved for CSMA/CA procedure.
#define NRF_802154_RESERVED_DTX_ID (UINT32_MAX - 3) ///< Delayed timeslot identifier reserved for delayed transmissions.
#define IE_VENDOR_ID 0x00 ///< Vendor-specific IE identifier
#define IE_VENDOR_SIZE_MIN 3 ///< Vendor-specific IE minimum length
#define IE_VENDOR_OUI_OFFSET 0 ///< Vendor-specific IE OUI offset
#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_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
#define IE_VENDOR_THREAD_ACK_SIZE_MIN 5 ///< Thread Vendor-specific ACK Probing IE minimum size
#define IE_VENDOR_THREAD_ACK_SIZE_MAX 6 ///< Thread Vendor-specific ACK Probing IE maximum size
#define IE_VENDOR_THREAD_RSSI_TOKEN 0x01 ///< Thread Vendor-specific ACK Probing IE RSSI value placeholder
#define IE_VENDOR_THREAD_MARGIN_TOKEN 0x02 ///< Thread Vendor-specific ACK Probing IE Link margin value placeholder
#define IE_VENDOR_THREAD_LQI_TOKEN 0x03 ///< Thread Vendor-specific ACK Probing IE LQI value placeholder
#define IE_VENDOR_THREAD_RSSI_FLOOR -130 ///< Thread Vendor-specific ACK Probing RSSI floor value used for scaling
#define IE_VENDOR_THREAD_MARGIN_FLOOR 0 ///< Thread Vendor-specific ACK Probing margin floor value used for scaling
#define IE_VENDOR_THREAD_RSSI_CEIL 0 ///< Thread Vendor-specific ACK Probing RSSI ceil value used for scaling
#define IE_VENDOR_THREAD_MARGIN_CEIL 130 ///< Thread Vendor-specific ACK Probing margin ceil value used for scaling
#define IE_CSL_SYMBOLS_PER_UNIT 10 ///< Number of symbols per phase/period unit
#define IE_CSL_PERIOD_MAX 0xffff ///< Maximum CSL IE phase/period value
#define IE_CSL_SIZE_MIN 4 ///< Minimal size of the CSL IE
#define IE_CSL_ID 0x1a ///< CSL IE identifier
#define IE_HT1 0x7e ///< Information Element Header Termination type 1
#define IE_HT2 0x7f ///< Information Element Header Termination type 2
#define IE_LENGTH_MASK 0x7f ///< Information element length mask
#define IE_LENGTH_OFFSET 0x00 ///< Information element length offset
#define IE_ID_OFFSET_0 0x00 ///< Offset of the octet containing the first part of the IE identifier.
#define IE_ID_OFFSET_1 0x01 ///< Offset of the octed containing the second part of the IE identifier.
#define IE_DATA_OFFSET 0x02 ///< Information element data offset
#define IE_HEADER_ELEMENT_ID_OFFSET 0x07 ///< Bit offset of Element ID field in a Header IE header.
typedef enum
{

View File

@ -73,14 +73,16 @@ typedef uint8_t nrf_802154_state_t;
*/
typedef uint8_t nrf_802154_tx_error_t;
#define NRF_802154_TX_ERROR_NONE 0x00 // !< There is no transmit error.
#define NRF_802154_TX_ERROR_BUSY_CHANNEL 0x01 // !< CCA reported busy channel before the transmission.
#define NRF_802154_TX_ERROR_INVALID_ACK 0x02 // !< Received ACK frame is other than expected.
#define NRF_802154_TX_ERROR_NO_MEM 0x03 // !< No receive buffer is available to receive an ACK.
#define NRF_802154_TX_ERROR_TIMESLOT_ENDED 0x04 // !< Radio timeslot ended during the transmission procedure.
#define NRF_802154_TX_ERROR_NO_ACK 0x05 // !< ACK frame was not received during the timeout period.
#define NRF_802154_TX_ERROR_ABORTED 0x06 // !< Procedure was aborted by another operation.
#define NRF_802154_TX_ERROR_TIMESLOT_DENIED 0x07 // !< Transmission did not start due to a denied timeslot request.
#define NRF_802154_TX_ERROR_NONE 0x00 // !< There is no transmit error.
#define NRF_802154_TX_ERROR_BUSY_CHANNEL 0x01 // !< CCA reported busy channel before the transmission.
#define NRF_802154_TX_ERROR_INVALID_ACK 0x02 // !< Received ACK frame is other than expected.
#define NRF_802154_TX_ERROR_NO_MEM 0x03 // !< No receive buffer is available to receive an ACK.
#define NRF_802154_TX_ERROR_TIMESLOT_ENDED 0x04 // !< Radio timeslot ended during the transmission procedure.
#define NRF_802154_TX_ERROR_NO_ACK 0x05 // !< ACK frame was not received during the timeout period.
#define NRF_802154_TX_ERROR_ABORTED 0x06 // !< Procedure was aborted by another operation.
#define NRF_802154_TX_ERROR_TIMESLOT_DENIED 0x07 // !< Transmission did not start due to a denied timeslot request.
#define NRF_802154_TX_ERROR_KEY_ID_INVALID 0x08 // !< Transmission did not start due to invalid key ID in frame's security header.
#define NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR 0x09 // !< Transmission did not start due a frame counter error.
/**
* @brief Possible errors during the frame reception.
@ -121,6 +123,19 @@ typedef uint8_t nrf_802154_sleep_error_t;
#define NRF_802154_SLEEP_ERROR_NONE 0x00 // !< There is no error.
#define NRF_802154_SLEEP_ERROR_BUSY 0x01 // !< The driver cannot enter the sleep state due to the ongoing operation.
/**
* @brief Possible errors during key handling.
*/
typedef uint8_t nrf_802154_security_error_t;
#define NRF_802154_SECURITY_ERROR_NONE 0x00 // !< There is no error.
#define NRF_802154_SECURITY_ERROR_STORAGE_FULL 0x01 // !< The key storage is full - removal of stored keys is needed.
#define NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND 0x02 // !< The provided key was not found inside the storage.
#define NRF_802154_SECURITY_ERROR_ALREADY_PRESENT 0x03 // !< The storage already has the key of the same ID.
#define NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED 0x04 // !< The provided key type is not supported.
#define NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED 0x05 // !< The provided key id mode is not supported.
#define NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW 0x06 // !< The associated frame counter overflowed.
/**
* @brief Termination level selected for a particular request.
*
@ -148,8 +163,8 @@ typedef struct
*/
typedef uint8_t nrf_802154_ack_data_t;
#define NRF_802154_ACK_DATA_PENDING_BIT 0x00
#define NRF_802154_ACK_DATA_IE 0x01
#define NRF_802154_ACK_DATA_PENDING_BIT 0x00 // !< Frame Pending bit should be set in the Ack.
#define NRF_802154_ACK_DATA_IE 0x01 // !< Header Information Element should be set in the Ack.
/**
* @brief Methods of source address matching.
@ -171,8 +186,7 @@ typedef uint8_t nrf_802154_src_addr_match_t;
/**
* @brief RSSI measurement results.
*/
#define NRF_802154_RSSI_INVALID INT8_MAX
#define NRF_802154_RSSI_INVALID INT8_MAX
/**
* @brief Mode of triggering receive request to Coex arbiter.
@ -227,6 +241,7 @@ typedef uint8_t nrf_802154_ifs_mode_t;
* - @ref NRF_802154_CAPABILITY_ANT_DIVERSITY,
* - @ref NRF_802154_CAPABILITY_IFS,
* - @ref NRF_802154_CAPABILITY_TIMESTAMP
* - @ref NRF_802154_CAPABILITY_SECURITY
*
*/
typedef uint32_t nrf_802154_capabilities_t;
@ -238,6 +253,18 @@ typedef uint32_t nrf_802154_capabilities_t;
#define NRF_802154_CAPABILITY_ANT_DIVERSITY (1UL << 4UL) // !< Antenna diversity supported
#define NRF_802154_CAPABILITY_IFS (1UL << 5UL) // !< Inter-frame spacing supported
#define NRF_802154_CAPABILITY_TIMESTAMP (1UL << 6UL) // !< Frame timestamping supported
#define NRF_802154_CAPABILITY_SECURITY (1UL << 7UL) // !< Frame security supported
/**
* @brief Types of keys which can be used with the nRF 802.15.4 Radio Driver.
*
* Possible values:
* - @ref NRF_802154_KEY_CLEARTEXT,
*
*/
typedef uint32_t nrf_802154_key_type_t;
#define NRF_802154_KEY_CLEARTEXT 0x00 // !< Key stored in clear text.
/**
* @brief Type of structure holding statistic counters.
@ -310,6 +337,51 @@ typedef struct
nrf_802154_stat_timestamps_t timestamps;
} nrf_802154_stats_t;
/**
* @brief Type holding the value of Key Id Mode of the key stored in nRF 802.15.4 Radio Driver.
*/
typedef uint8_t nrf_802154_key_id_mode_t;
/**
* @brief Type holding the value of Key Id for the keys stored in nRF 802.15.4 Radio Driver.
*/
typedef struct
{
nrf_802154_key_id_mode_t mode; // !< Key Id Mode (0..3)
uint8_t * p_key_id; // !< Pointer to the Key Id field
} nrf_802154_key_id_t;
/**
* @brief Type of structure holding a 802.15.4 MAC Security Key.
*/
typedef struct
{
union
{
uint8_t * p_cleartext_key; // !< Pointer to the cleartext representation of the key.
} value; // !< Union holding different representations of the key.
nrf_802154_key_id_t id; // !< Key Id of the key.
nrf_802154_key_type_t type; // !< @ref nrf_802154_key_type_t type of the key used.
uint32_t frame_counter; // !< Frame counter to use in case @ref use_global_frame_counter is set to false.
bool use_global_frame_counter; // !< Whether to use the global frame counter instead of the one defined in this structure.
} nrf_802154_key_t;
/**
* @brief Function pointer used for notifying about transmission failure.
*/
typedef void (* nrf_802154_transmit_failed_notification_t)(const uint8_t * p_frame,
nrf_802154_tx_error_t error);
/**
* @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_transmit_params_t;
/**
*@}
**/

View File

@ -44,9 +44,13 @@
#include <string.h>
#include "mac_features/nrf_802154_frame_parser.h"
#include "mac_features/nrf_802154_ie_writer.h"
#include "mac_features/nrf_802154_security_pib.h"
#include "nrf_802154_ack_data.h"
#include "nrf_802154_encrypt.h"
#include "nrf_802154_const.h"
#include "nrf_802154_pib.h"
#include "nrf_802154_utils_byteorder.h"
#define ENH_ACK_MAX_SIZE MAX_PACKET_SIZE
@ -208,6 +212,36 @@ 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)
{
uint8_t sec_hdr_size = SECURITY_CONTROL_SIZE;
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;
}
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)
{
@ -219,19 +253,19 @@ static void security_control_set(const nrf_802154_frame_parser_mhr_data_t * p_fr
m_ack_data[PHR_OFFSET] += SECURITY_CONTROL_SIZE;
}
static void 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_suppresed,
const uint8_t ** p_sec_end)
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_mode_size = 0;
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_suppresed)
if (!fc_suppressed)
{
p_frame_key_id += FRAME_COUNTER_SIZE;
p_ack_key_id += FRAME_COUNTER_SIZE;
@ -239,26 +273,26 @@ static void security_key_id_set(const nrf_802154_frame_parser_mhr_data_t * p_fra
switch ((*p_ack->p_sec_ctrl) & KEY_ID_MODE_MASK)
{
case KEY_ID_MODE_1:
key_id_mode_size = KEY_ID_MODE_1_SIZE;
case KEY_ID_MODE_1_MASK:
key_id_size = KEY_ID_MODE_1_SIZE;
break;
case KEY_ID_MODE_2:
key_id_mode_size = 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:
key_id_mode_size = KEY_ID_MODE_3_SIZE;
case KEY_ID_MODE_3_MASK:
key_id_size = KEY_ID_MODE_3_SIZE;
break;
default:
break;
}
if (0 != key_id_mode_size)
if (0 != key_id_size)
{
memcpy((uint8_t *)p_ack_key_id, p_frame_key_id, key_id_mode_size);
m_ack_data[PHR_OFFSET] += key_id_mode_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)
@ -282,32 +316,77 @@ static void security_key_id_set(const nrf_802154_frame_parser_mhr_data_t * p_fra
break;
}
*p_sec_end = p_ack_key_id + key_id_mode_size;
*p_sec_end = p_ack_key_id + key_id_size;
return (0 == key_id_size) ? NULL : p_ack_key_id;
}
static void security_header_set(const nrf_802154_frame_parser_mhr_data_t * p_frame,
static bool frame_counter_set(const nrf_802154_frame_parser_mhr_data_t * p_ack_pdata,
const uint8_t * p_ack_key_id)
{
nrf_802154_key_id_t ack_key_id;
uint32_t new_fc_value;
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 (NRF_802154_SECURITY_ERROR_NONE !=
nrf_802154_security_pib_frame_counter_get_next(&new_fc_value, &ack_key_id))
{
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;
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)
{
bool fc_suppressed;
bool security_header_prepared;
if (p_ack->p_sec_ctrl == NULL)
if (((*p_frame->p_sec_ctrl) & SECURITY_LEVEL_MASK) == 0)
{
*p_sec_end = &m_ack_data[p_ack->addressing_end_offset];
return;
// 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);
memcpy((uint8_t *)p_ack->p_sec_ctrl, p_frame->p_sec_ctrl, sec_hdr_size);
m_ack_data[PHR_OFFSET] += 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);
}
}
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);
if (!fc_suppressed)
{
m_ack_data[PHR_OFFSET] += FRAME_COUNTER_SIZE;
}
security_key_id_set(p_frame, p_ack, fc_suppressed, p_sec_end);
return security_header_prepared;
}
/***************************************************************************************************
@ -327,6 +406,62 @@ static void ie_header_set(const uint8_t * p_ie_data, uint8_t ie_data_len, const
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)
{
if (p_ie_data == NULL)
{
// No IEs to terminate.
return;
}
if ((p_ack->p_sec_ctrl == NULL) || ((*p_ack->p_sec_ctrl & SECURITY_LEVEL_MASK) == 0))
{
// 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;
}
uint8_t * p_ack_ie = (uint8_t *)p_sec_end;
uint8_t ie_hdr_term[IE_HEADER_SIZE];
assert(p_ack_ie != NULL);
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);
}
/***************************************************************************************************
* @section Authentication and encryption transformation
**************************************************************************************************/
static bool encryption_prepare(const nrf_802154_frame_parser_mhr_data_t * p_ack)
{
#if NRF_802154_ENCRYPTION_ENABLED
if (p_ack->p_sec_ctrl == NULL)
{
return true;
}
if ((*(p_ack->p_sec_ctrl) & SECURITY_LEVEL_MASK) == 0)
{
return true;
}
return nrf_802154_encrypt_ack_prepare(m_ack_data);
#else // NRF_802154_ENCRYPTION_ENABLED
return true;
#endif // NRF_802154_ENCRYPTION_ENABLED
}
/***************************************************************************************************
@ -340,7 +475,6 @@ void nrf_802154_enh_ack_generator_init(void)
const uint8_t * nrf_802154_enh_ack_generator_create(const uint8_t * p_frame)
{
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;
@ -373,11 +507,44 @@ const uint8_t * nrf_802154_enh_ack_generator_create(const uint8_t * p_frame)
// Set source address and PAN ID.
source_set();
// Set auxiliary security header.
security_header_set(&frame_offsets, &ack_offsets, &p_sec_end);
// 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
{
// Failure to set auxiliary security header: The ACK cannot be created.
ack_buffer_clear();
return NULL;
}
// Set IE header.
ie_header_set(p_ie_data, ie_data_len, p_sec_end);
// Terminate the IE header if needed.
ie_header_terminate(&ack_offsets, p_sec_end, p_ie_data, ie_data_len);
// Prepare encryption.
if (!encryption_prepare(&ack_offsets))
{
// Failure to prepare encryption even though it's required. The ACK cannot be created.
ack_buffer_clear();
return NULL;
}
return m_ack_data;
}
#ifdef TEST
void nrf_802154_enh_ack_generator_module_reset(void)
{
memset(m_ack_data, 0, sizeof(m_ack_data));
}
#endif // TEST

View File

@ -54,8 +54,9 @@ void nrf_802154_enh_ack_generator_init(void);
* @param [in] p_frame Pointer to the buffer that contains PHR and PSDU of the frame
* to respond to.
*
* @returns Pointer to a constant buffer that contains PHR and PSDU
* of the created Enhanced ACK frame.
* @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);

View File

@ -62,11 +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_running; ///< Indicates if CSMA-CA procedure is running.
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.
/**
* @brief Perform appropriate actions for busy channel conditions.
@ -170,11 +171,17 @@ static void frame_transmit(rsch_dly_ts_id_t dly_ts_id)
{
priority_leverage();
nrf_802154_transmit_params_t params =
{
.cca = true,
.immediate = NRF_802154_CSMA_CA_WAIT_FOR_TIMESLOT ? false : true,
.is_retransmission = m_is_retransmission,
};
if (!nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_CSMA_CA,
mp_data,
true,
NRF_802154_CSMA_CA_WAIT_FOR_TIMESLOT ? false : true,
&params,
notify_busy_channel))
{
(void)channel_busy();
@ -273,7 +280,7 @@ static bool channel_busy(void)
return result;
}
void nrf_802154_csma_ca_start(const uint8_t * p_data)
void nrf_802154_csma_ca_start(const uint8_t * p_data, bool is_retransmission)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -285,10 +292,11 @@ void nrf_802154_csma_ca_start(const uint8_t * p_data)
assert(!procedure_is_running());
mp_data = p_data;
m_nb = 0;
m_be = nrf_802154_pib_csmaca_min_be_get();
m_is_running = true;
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;
random_backoff_start();
@ -325,19 +333,32 @@ bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_o
bool nrf_802154_csma_ca_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error)
{
(void)error;
bool result = true;
if (p_frame == mp_data)
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
switch (error)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
/* Below errors mean a failure occurred during the frame processing and the frame cannot be
* transmitted unless a higher layer takes appropriate actions, hence the CSMA-CA procedure
* shall be stopped.
*/
case NRF_802154_TX_ERROR_KEY_ID_INVALID:
/* Fallthrough. */
case NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR:
procedure_stop();
result = true;
break;
result = channel_busy();
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
default:
if (p_frame == mp_data)
{
result = channel_busy();
}
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return result;
}

View File

@ -60,10 +60,12 @@
* 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] 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.
*/
void nrf_802154_csma_ca_start(const uint8_t * p_data);
void nrf_802154_csma_ca_start(const uint8_t * p_data, bool is_retransmission);
/**
* @brief Aborts the ongoing CSMA-CA procedure.

View File

@ -104,9 +104,9 @@ typedef struct
*/
typedef struct
{
const uint8_t * p_data; ///< Pointer to a buffer containing PHR and PSDU of the frame requested to be transmitted.
bool cca; ///< If CCA should be performed prior to transmission.
uint8_t channel; ///< Channel number on which transmission should be performed.
const 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;
/**
@ -195,28 +195,6 @@ static dly_op_data_t * dly_tx_data_by_id_search(rsch_dly_ts_id_t id)
return &m_dly_tx_data[0];
}
/**
* @brief Check if there are any slots available.
*
* @param[in] p_dly_op_data_pool Pool of slots to check.
* @param[in] pool_len Total number of elements in the pool.
*
* @retval true The pool contains free slots.
* @retval false There are no available slots in the pool.
*/
static bool is_dly_ts_slot_available(const dly_op_data_t * p_dly_op_data_pool, uint32_t pool_len)
{
for (uint32_t i = 0; i < pool_len; i++)
{
if (p_dly_op_data_pool[i].id == NRF_802154_RESERVED_INVALID_ID)
{
return true;
}
}
return false;
}
/**
* @brief Retrieve an available slot from a pool.
*
@ -584,8 +562,7 @@ static void transmit_attempt(dly_op_data_t * p_dly_op_data)
(void)nrf_802154_request_transmit(NRF_802154_TERM_802154,
REQ_ORIG_DELAYED_TRX,
p_dly_op_data->tx.p_data,
p_dly_op_data->tx.cca,
true,
&p_dly_op_data->tx.params,
dly_tx_result_notify);
}
else
@ -725,33 +702,33 @@ void nrf_802154_delayed_trx_init(void)
}
}
bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
bool cca,
uint32_t t0,
uint32_t dt,
uint8_t channel)
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 result = is_dly_ts_slot_available(m_dly_tx_data,
sizeof(m_dly_tx_data) / sizeof(m_dly_tx_data[0]));
dly_op_data_t * p_dly_tx_data = available_dly_tx_slot_get();
bool result = false;
if (result)
if (p_dly_tx_data != NULL)
{
dt -= TX_SETUP_TIME;
dt -= TX_RAMP_UP_TIME;
if (cca)
if (p_params->cca)
{
dt -= nrf_802154_cca_before_tx_duration_get();
}
dly_op_data_t * p_dly_tx_data = available_dly_tx_slot_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.cca = cca;
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.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;
rsch_dly_ts_param_t dly_ts_param =
{
@ -776,16 +753,14 @@ bool nrf_802154_delayed_trx_receive(uint32_t t0,
uint8_t channel,
uint32_t id)
{
bool result = is_dly_ts_slot_available(m_dly_rx_data,
sizeof(m_dly_rx_data) / sizeof(m_dly_rx_data[0]));
dly_op_data_t * p_dly_rx_data = available_dly_rx_slot_get();
bool result = false;
if (result)
if (p_dly_rx_data != NULL)
{
dt -= RX_SETUP_TIME;
dt -= RX_RAMP_UP_TIME;
dly_op_data_t * p_dly_rx_data = available_dly_rx_slot_get();
p_dly_rx_data->op = RSCH_DLY_TS_OP_DRX;
p_dly_rx_data->rx.timeout_timer.dt = timeout + RX_RAMP_UP_TIME;
@ -900,4 +875,37 @@ void nrf_802154_delayed_trx_rx_started_hook(const uint8_t * p_frame)
}
}
bool nrf_802154_delayed_trx_nearest_drx_time_to_midpoint_get(uint32_t * p_drx_time_to_midpoint)
{
bool result = false;
uint32_t min_time_to_start = 0xffffffff;
uint32_t drx_time_to_start;
uint32_t drx_time_to_midpoint;
for (int i = 0; i < sizeof(m_dly_rx_data) / sizeof(m_dly_rx_data[0]); i++)
{
if (m_dly_rx_data[i].state != DELAYED_TRX_OP_STATE_PENDING)
{
continue;
}
result = nrf_802154_rsch_delayed_timeslot_time_to_start_get(m_dly_rx_data[i].id,
&drx_time_to_start);
if (result)
{
min_time_to_start = drx_time_to_start <
min_time_to_start ? drx_time_to_start : min_time_to_start;
drx_time_to_midpoint = min_time_to_start + m_dly_rx_data[i].rx.timeout_timer.dt / 2;
}
}
if (result)
{
*p_drx_time_to_midpoint = drx_time_to_midpoint;
}
return result;
}
#endif // NRF_802154_DELAYED_TRX_ENABLED

View File

@ -70,16 +70,16 @@ void nrf_802154_delayed_trx_init(void);
* 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] cca If the driver is to perform the CCA procedure before the transmission.
* @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.
*/
bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
bool cca,
uint32_t t0,
uint32_t dt,
uint8_t channel);
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);
/**
* @brief Cancels a transmission scheduled by a call to @ref nrf_802154_delayed_trx_transmit.
@ -167,6 +167,18 @@ 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);
/**
* @brief Gets the time in microseconds to the midpoint of the nearest scheduled DRX window.
*
* @param[out] p_drx_time_to_midpoint Pointer to a 32-bit variable where the time to the
* midpoint of the nearest DRX will be stored.
*
* @retval true A pending DRX was scheduled and p_drx_time_to_start contains a valid value.
* @retval false A pending DRX was not scheduled and p_drx_time_to_start was not modified.
*
*/
bool nrf_802154_delayed_trx_nearest_drx_time_to_midpoint_get(uint32_t * p_drx_time_to_midpoint);
/**
*@}
**/

View File

@ -78,4 +78,8 @@
*/
nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_data, uint8_t * p_num_bytes);
/**
*@}
**/
#endif /* NRF_802154_FILTER_H_ */

View File

@ -47,11 +47,19 @@
#include <stdlib.h>
#include "nrf_802154_const.h"
#include "nrf_802154_utils.h"
#include "nrf_802154_utils_byteorder.h"
/***************************************************************************************************
* @section Helper functions
**************************************************************************************************/
// Check if pointer is within the frame
static bool is_within_frame_bounds(const uint8_t * p_frame, const uint8_t * p_ptr)
{
return (p_ptr != NULL) && (p_ptr >= p_frame) && (p_ptr <= &p_frame[p_frame[PHR_OFFSET]]);
}
// Version
static uint8_t frame_version_get(const uint8_t * p_frame)
{
@ -210,11 +218,6 @@ static bool src_panid_is_compressed(const uint8_t * p_frame)
}
// Security
static bool security_is_enabled(const uint8_t * p_frame)
{
return p_frame[SECURITY_ENABLED_OFFSET] & SECURITY_ENABLED_BIT ? true : false;
}
static uint8_t security_offset_get(const uint8_t * p_frame)
{
uint8_t dst_addr_offset = nrf_802154_frame_parser_dst_addr_offset_get(p_frame);
@ -273,13 +276,13 @@ static uint8_t key_id_size_get(const uint8_t * p_frame)
switch (*p_sec_ctrl & KEY_ID_MODE_MASK)
{
case KEY_ID_MODE_1:
case KEY_ID_MODE_1_MASK:
return KEY_ID_MODE_1_SIZE;
case KEY_ID_MODE_2:
case KEY_ID_MODE_2_MASK:
return KEY_ID_MODE_2_SIZE;
case KEY_ID_MODE_3:
case KEY_ID_MODE_3_MASK:
return KEY_ID_MODE_3_SIZE;
default:
@ -294,7 +297,7 @@ static uint8_t ie_offset_get(const uint8_t * p_frame)
uint8_t security_offset = security_offset_get(p_frame);
uint8_t key_id_offset = nrf_802154_frame_parser_key_id_offset_get(p_frame);
if (!security_is_enabled(p_frame))
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame))
{
if (security_offset == NRF_802154_FRAME_PARSER_INVALID_OFFSET)
{
@ -348,6 +351,11 @@ bool nrf_802154_frame_parser_ar_bit_is_set(const uint8_t * p_frame)
return (p_frame[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT) ? true : false;
}
bool nrf_802154_frame_parser_security_enabled_bit_is_set(const uint8_t * p_frame)
{
return p_frame[SECURITY_ENABLED_OFFSET] & SECURITY_ENABLED_BIT ? true : false;
}
/***************************************************************************************************
* @section Offset functions
**************************************************************************************************/
@ -484,9 +492,9 @@ uint8_t nrf_802154_frame_parser_addressing_end_offset_get(const uint8_t * p_fram
uint8_t nrf_802154_frame_parser_sec_ctrl_offset_get(const uint8_t * p_frame)
{
if (!security_is_enabled(p_frame))
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame))
{
return 0;
return NRF_802154_FRAME_PARSER_INVALID_OFFSET;
}
else
{
@ -494,21 +502,33 @@ uint8_t nrf_802154_frame_parser_sec_ctrl_offset_get(const uint8_t * p_frame)
}
}
uint8_t nrf_802154_frame_parser_key_id_offset_get(const uint8_t * p_frame)
uint8_t nrf_802154_frame_parser_frame_counter_offset_get(const uint8_t * p_frame)
{
uint8_t sec_ctrl_offset = nrf_802154_frame_parser_sec_ctrl_offset_get(p_frame);
if (0 == sec_ctrl_offset)
{
return 0;
}
if (NRF_802154_FRAME_PARSER_INVALID_OFFSET == sec_ctrl_offset)
{
return NRF_802154_FRAME_PARSER_INVALID_OFFSET;
}
else if (p_frame[sec_ctrl_offset] & FRAME_COUNTER_SUPPRESS_BIT)
{
return NRF_802154_FRAME_PARSER_INVALID_OFFSET;
}
else
{
return sec_ctrl_offset + SECURITY_CONTROL_SIZE;
}
}
if (p_frame[sec_ctrl_offset] & FRAME_COUNTER_SUPPRESS_BIT)
uint8_t nrf_802154_frame_parser_key_id_offset_get(const uint8_t * p_frame)
{
uint8_t sec_ctrl_offset = nrf_802154_frame_parser_sec_ctrl_offset_get(p_frame);
if (NRF_802154_FRAME_PARSER_INVALID_OFFSET == sec_ctrl_offset)
{
return NRF_802154_FRAME_PARSER_INVALID_OFFSET;
}
else if (p_frame[sec_ctrl_offset] & FRAME_COUNTER_SUPPRESS_BIT)
{
return sec_ctrl_offset + SECURITY_CONTROL_SIZE;
}
@ -522,7 +542,7 @@ uint8_t nrf_802154_frame_parser_ie_header_offset_get(const uint8_t * p_frame)
{
if (!nrf_802154_frame_parser_ie_present_bit_is_set(p_frame))
{
return 0;
return NRF_802154_FRAME_PARSER_INVALID_OFFSET;
}
else
{
@ -651,7 +671,7 @@ bool nrf_802154_frame_parser_mhr_parse(const uint8_t * p_fr
p_fields->addressing_end_offset = offset;
if (security_is_enabled(p_frame))
if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame))
{
p_fields->p_sec_ctrl = &p_frame[offset];
// TODO increment offset...
@ -668,26 +688,368 @@ const uint8_t * nrf_802154_frame_parser_sec_ctrl_get(const uint8_t * p_frame)
{
uint8_t sec_ctrl_offset = nrf_802154_frame_parser_sec_ctrl_offset_get(p_frame);
return ((0 == sec_ctrl_offset) || (NRF_802154_FRAME_PARSER_INVALID_OFFSET == sec_ctrl_offset)) ?
return (NRF_802154_FRAME_PARSER_INVALID_OFFSET == sec_ctrl_offset) ?
NULL : &p_frame[sec_ctrl_offset];
}
bool nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(const uint8_t * p_frame, uint8_t * p_sec_lvl)
{
const uint8_t * p_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame);
if (p_sec_ctrl == NULL)
{
return false;
}
else
{
*p_sec_lvl = *p_sec_ctrl & SECURITY_LEVEL_MASK;
return true;
}
}
bool nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(const uint8_t * p_frame,
uint8_t * p_key_id_mode)
{
const uint8_t * p_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame);
if (p_sec_ctrl == NULL)
{
return false;
}
else
{
switch (*p_sec_ctrl & KEY_ID_MODE_MASK)
{
case KEY_ID_MODE_0_MASK:
*p_key_id_mode = KEY_ID_MODE_0;
return true;
case KEY_ID_MODE_1_MASK:
*p_key_id_mode = KEY_ID_MODE_1;
return true;
case KEY_ID_MODE_2_MASK:
*p_key_id_mode = KEY_ID_MODE_2;
return true;
case KEY_ID_MODE_3_MASK:
*p_key_id_mode = KEY_ID_MODE_3;
return true;
default:
return false;
}
}
}
bool nrf_802154_frame_parser_sec_ctrl_fc_suppress_bit_is_set(const uint8_t * p_frame)
{
const uint8_t * p_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame);
return ((p_sec_ctrl != NULL) && (*p_sec_ctrl & FRAME_COUNTER_SUPPRESS_BIT));
}
bool nrf_802154_frame_parser_sec_ctrl_asn_in_nonce_bit_is_set(const uint8_t * p_frame)
{
const uint8_t * p_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame);
return ((p_sec_ctrl != NULL) && (*p_sec_ctrl & ASN_IN_NONCE_BIT));
}
const uint8_t * nrf_802154_frame_parser_frame_counter_get(const uint8_t * p_frame)
{
uint8_t fc_offset = nrf_802154_frame_parser_frame_counter_offset_get(p_frame);
return (NRF_802154_FRAME_PARSER_INVALID_OFFSET == fc_offset) ? NULL : &p_frame[fc_offset];
}
const uint8_t * nrf_802154_frame_parser_key_id_get(const uint8_t * p_frame)
{
uint8_t key_id_offset = nrf_802154_frame_parser_key_id_offset_get(p_frame);
return ((0 == key_id_offset) || (NRF_802154_FRAME_PARSER_INVALID_OFFSET == key_id_offset)) ?
return (NRF_802154_FRAME_PARSER_INVALID_OFFSET == key_id_offset) ?
NULL : &p_frame[key_id_offset];
}
const uint8_t * nrf_802154_frame_parser_key_id_key_source_get(const uint8_t * p_frame,
uint8_t * p_key_src_len)
{
uint8_t key_id_mode;
bool key_id_mode_present =
nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(p_frame, &key_id_mode);
if (!key_id_mode_present)
{
*p_key_src_len = 0;
return NULL;
}
switch (key_id_mode)
{
case KEY_ID_MODE_0:
*p_key_src_len = KEY_SRC_KEY_ID_MODE_0_SIZE;
return NULL;
case KEY_ID_MODE_1:
*p_key_src_len = KEY_SRC_KEY_ID_MODE_1_SIZE;
return NULL;
case KEY_ID_MODE_2:
*p_key_src_len = KEY_SRC_KEY_ID_MODE_2_SIZE;
return nrf_802154_frame_parser_key_id_get(p_frame);
case KEY_ID_MODE_3:
*p_key_src_len = KEY_SRC_KEY_ID_MODE_3_SIZE;
return nrf_802154_frame_parser_key_id_get(p_frame);
default:
// Unknown key identifier mode
*p_key_src_len = 0;
return NULL;
}
}
bool nrf_802154_frame_parser_key_id_key_index_get(const uint8_t * p_frame,
uint8_t * p_key_index)
{
uint8_t key_id_mode;
bool key_id_mode_present =
nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(p_frame, &key_id_mode);
if (!key_id_mode_present)
{
return false;
}
switch (key_id_mode)
{
case KEY_ID_MODE_0:
return false;
case KEY_ID_MODE_1:
*p_key_index =
*(nrf_802154_frame_parser_key_id_get(p_frame) + KEY_SRC_KEY_ID_MODE_1_SIZE);
return true;
case KEY_ID_MODE_2:
*p_key_index =
*(nrf_802154_frame_parser_key_id_get(p_frame) + KEY_SRC_KEY_ID_MODE_2_SIZE);
return true;
case KEY_ID_MODE_3:
*p_key_index =
*(nrf_802154_frame_parser_key_id_get(p_frame) + KEY_SRC_KEY_ID_MODE_3_SIZE);
return true;
default:
return false;
}
}
bool nrf_802154_frame_parser_aux_sec_hdr_parse(
const uint8_t * p_frame,
nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr)
{
if ((NULL == p_aux_sec_hdr) || (NULL == p_frame))
{
// Invalid parameters.
return false;
}
// Retrieve pointer to the Security Control field.
p_aux_sec_hdr->p_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame);
if (NULL == p_aux_sec_hdr->p_sec_ctrl)
{
// Security is disabled.
return false;
}
// Retrieve the Security Level field.
p_aux_sec_hdr->security_lvl = *p_aux_sec_hdr->p_sec_ctrl & SECURITY_LEVEL_MASK;
// Retrieve the Key Identifier Mode field.
p_aux_sec_hdr->key_id_mode =
(*p_aux_sec_hdr->p_sec_ctrl & KEY_ID_MODE_MASK) >> KEY_ID_MODE_BIT_OFFSET;
// Retrieve the Frame Counter Suppression field.
p_aux_sec_hdr->fc_suppression = *p_aux_sec_hdr->p_sec_ctrl & FRAME_COUNTER_SUPPRESS_BIT;
// Retrieve pointer to the Frame Counter field.
if (p_aux_sec_hdr->fc_suppression)
{
p_aux_sec_hdr->p_frame_counter = NULL;
}
else
{
p_aux_sec_hdr->p_frame_counter = p_aux_sec_hdr->p_sec_ctrl + SECURITY_CONTROL_SIZE;
}
// Retrieve pointer to the Key Identifier field.
if (p_aux_sec_hdr->key_id_mode == KEY_ID_MODE_0)
{
p_aux_sec_hdr->p_key_id = NULL;
}
else if (p_aux_sec_hdr->fc_suppression)
{
p_aux_sec_hdr->p_key_id = p_aux_sec_hdr->p_sec_ctrl + SECURITY_CONTROL_SIZE;
}
else
{
p_aux_sec_hdr->p_key_id = p_aux_sec_hdr->p_frame_counter + FRAME_COUNTER_SIZE;
}
return true;
}
const uint8_t * nrf_802154_frame_parser_ie_header_get(const uint8_t * p_frame)
{
uint8_t ie_header_offset = nrf_802154_frame_parser_ie_header_offset_get(p_frame);
if ((0 == ie_header_offset) || (NRF_802154_FRAME_PARSER_INVALID_OFFSET == ie_header_offset))
return (NRF_802154_FRAME_PARSER_INVALID_OFFSET ==
ie_header_offset) ? NULL : &p_frame[ie_header_offset];
}
const uint8_t * nrf_802154_frame_parser_header_ie_iterator_begin(const uint8_t * p_ie_header)
{
return p_ie_header;
}
const uint8_t * nrf_802154_frame_parser_ie_iterator_next(const uint8_t * p_ie_iterator)
{
return nrf_802154_frame_parser_ie_content_address_get(p_ie_iterator)
+ nrf_802154_frame_parser_ie_length_get(p_ie_iterator);
}
bool nrf_802154_frame_parser_ie_iterator_end(const uint8_t * p_ie_iterator,
const uint8_t * p_end_addr)
{
uint8_t ie_id = nrf_802154_frame_parser_ie_id_get(p_ie_iterator);
return ((nrf_802154_frame_parser_ie_length_get(p_ie_iterator) == 0) &&
((ie_id == IE_HT1) || (ie_id == IE_HT2)))
|| (p_ie_iterator >= p_end_addr);
}
uint8_t nrf_802154_frame_parser_ie_length_get(const uint8_t * p_ie_iterator)
{
return p_ie_iterator[IE_LENGTH_OFFSET] & IE_LENGTH_MASK;
}
uint8_t nrf_802154_frame_parser_ie_id_get(const uint8_t * p_ie_iterator)
{
return (p_ie_iterator[IE_ID_OFFSET_0] >> 7) | (p_ie_iterator[IE_ID_OFFSET_1] << 1);
}
const uint8_t * nrf_802154_frame_parser_ie_content_address_get(const uint8_t * p_ie_iterator)
{
return p_ie_iterator + IE_DATA_OFFSET;
}
uint32_t nrf_802154_frame_parser_ie_vendor_oui_get(const uint8_t * p_ie_iterator)
{
return big_24_to_host((uint8_t *)&p_ie_iterator[IE_DATA_OFFSET + IE_VENDOR_OUI_OFFSET]);
}
uint8_t nrf_802154_frame_parser_ie_vendor_thread_subtype_get(const uint8_t * p_ie_iterator)
{
return p_ie_iterator[IE_DATA_OFFSET + IE_VENDOR_THREAD_SUBTYPE_OFFSET];
}
const uint8_t * nrf_802154_frame_parser_ie_vendor_thread_data_addr_get(
const uint8_t * p_ie_iterator)
{
return nrf_802154_frame_parser_ie_content_address_get(p_ie_iterator) +
IE_VENDOR_THREAD_DATA_OFFSET;
}
uint8_t nrf_802154_frame_parser_frame_length_get(const uint8_t * p_frame)
{
return p_frame[PHR_OFFSET] & PHR_LENGTH_MASK;
}
const uint8_t * nrf_802154_frame_parser_mac_payload_get(const uint8_t * p_frame)
{
if (nrf_802154_frame_parser_ie_present_bit_is_set(p_frame))
{
const uint8_t * p_ie_hdr = nrf_802154_frame_parser_ie_header_get(p_frame);
const uint8_t * p_mfr = nrf_802154_frame_parser_mfr_address_get(p_frame);
const uint8_t * p_ie = nrf_802154_frame_parser_header_ie_iterator_begin(p_ie_hdr);
if (NULL == p_ie_hdr)
{
// Frame is formatted incorrectly. MAC payload cannot be found
return NULL;
}
while (!nrf_802154_frame_parser_ie_iterator_end(p_ie, p_mfr))
{
p_ie = (uint8_t *)nrf_802154_frame_parser_ie_iterator_next(p_ie);
}
const uint8_t * p_estimated_payload = p_ie + IE_DATA_OFFSET;
return (p_estimated_payload == p_mfr) ? NULL : p_estimated_payload;
}
else if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame))
{
return nrf_802154_frame_parser_key_id_get(p_frame) + key_id_size_get(p_frame);
}
else
{
uint8_t addr_end_offset = nrf_802154_frame_parser_addressing_end_offset_get(p_frame);
return (addr_end_offset == NRF_802154_FRAME_PARSER_INVALID_OFFSET) ?
NULL : &p_frame[addr_end_offset];
}
}
uint8_t nrf_802154_frame_parser_mac_payload_length_get(const uint8_t * p_frame,
const uint8_t * p_mac_payload)
{
if (is_within_frame_bounds(p_frame, p_mac_payload))
{
return nrf_802154_frame_parser_mfr_address_get(p_frame) - p_mac_payload;
}
else
{
return nrf_802154_frame_parser_mfr_address_get(p_frame) -
nrf_802154_frame_parser_mac_payload_get(p_frame);
}
}
uint8_t nrf_802154_frame_parser_mac_header_length_get(const uint8_t * p_frame,
const uint8_t * p_mac_payload)
{
if (is_within_frame_bounds(p_frame, p_mac_payload))
{
return p_mac_payload - &p_frame[PSDU_OFFSET];
}
else
{
return nrf_802154_frame_parser_mac_payload_get(p_frame) - &p_frame[PSDU_OFFSET];
}
}
const uint8_t * nrf_802154_frame_parser_mac_command_id_get(const uint8_t * p_frame,
const uint8_t * p_mac_payload)
{
if ((p_frame[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_COMMAND)
{
return NULL;
}
return &p_frame[ie_header_offset];
// This function assumes that MAC commands never have payload IEs. This assumption is based
// on the fact that for AES-CCM* frame encryption, the MAC Command ID field is considered Open
// Payload and the Content field is considered Private Payload. Payload IEs by definition
// are not a part of the MAC header nor they are a part of Open or Private Payload.
// Therefore it is unclear in the specification how the encryption of MAC commands with
// payload IEs present should be performed. In the absence of payload IEs, the Command ID
// field is the first byte of MAC payload.
return is_within_frame_bounds(p_frame, p_mac_payload) ?
p_mac_payload : nrf_802154_frame_parser_mac_payload_get(p_frame);
}
const uint8_t * nrf_802154_frame_parser_mfr_address_get(const uint8_t * p_frame)
{
return p_frame + PHR_SIZE + nrf_802154_frame_parser_frame_length_get(p_frame) - FCS_SIZE;
}

View File

@ -60,6 +60,19 @@ typedef struct
uint8_t addressing_end_offset; ///< Offset of the first byte following addressing fields.
} nrf_802154_frame_parser_mhr_data_t;
/**
* @brief Structure that contains details of Auxiliary Security Header.
*/
typedef struct
{
const uint8_t * p_sec_ctrl; ///< Pointer to the security control field, or NULL if missing.
const uint8_t * p_frame_counter; ///< Pointer to the frame counter field, or NULL if missing.
const uint8_t * p_key_id; ///< Pointer to the key identifier field, or NULL if missing.
uint8_t security_lvl; ///< Value of the security level field.
uint8_t key_id_mode; ///< Value of the key identifier mode field.
bool fc_suppression; ///< Value of the frame counter suppression field.
} nrf_802154_frame_parser_aux_sec_hdr_t;
/**
* @brief Determines if the destination address is extended.
*
@ -210,6 +223,20 @@ uint8_t nrf_802154_frame_parser_src_panid_offset_get(const uint8_t * p_frame);
bool nrf_802154_frame_parser_mhr_parse(const uint8_t * p_frame,
nrf_802154_frame_parser_mhr_data_t * p_fields);
/**
* @brief Gets the pointer and the details of Auxiliary Security Header of a given frame.
*
* @param[in] p_frame Pointer to a frame to parse.
* @param[out] p_aux_sec_hdr Pointer to a structure that contains pointers and details
* of the parsed security header.
*
* @retval true Frame parsed correctly.
* @retval false Parse error. @p p_aux_sec_hdr values are invalid.
*/
bool nrf_802154_frame_parser_aux_sec_hdr_parse(
const uint8_t * p_frame,
nrf_802154_frame_parser_aux_sec_hdr_t * p_aux_sec_hdr);
/**
* @brief Gets the security control field in the provided frame.
*
@ -242,15 +269,67 @@ uint8_t nrf_802154_frame_parser_addressing_end_offset_get(const uint8_t * p_fram
uint8_t nrf_802154_frame_parser_sec_ctrl_offset_get(const uint8_t * p_frame);
/**
* @brief Gets the key identifier field in the provided frame.
* @brief Gets security level from the security control field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
* @param[out] p_sec_lvl Pointer to an integer to be filled with parsed security level value.
*
* @retval true Security level retrieved correctly.
* @retval false Security level could not be retrieved.
*/
bool nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(const uint8_t * p_frame, uint8_t * p_sec_lvl);
/**
* @brief Gets key identifier mode from the security control field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
* @param[out] p_key_id_mode Pointer to an integer to be filled with parsed key identifier mode.
*
* @retval true Key identifier mode retrieved correctly.
* @retval false Key identifier mode could not be retrieved.
*/
bool nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(const uint8_t * p_frame,
uint8_t * p_key_id_mode);
/**
* @brief Determines if frame counter suppression bit in the security control field is set.
*
* @param[in] p_frame Pointer to a frame.
*
* @retval true Frame counter suppression bit is set.
* @retval false Frame counter suppression bit is not set or security control field is not present.
*/
bool nrf_802154_frame_parser_sec_ctrl_fc_suppress_bit_is_set(const uint8_t * p_frame);
/**
* @brief Determines if ASN in nonce bit in the security control field is set.
*
* @param[in] p_frame Pointer to a frame.
*
* @retval true ASN in nonce bit is set.
* @retval false ASN in nonce bit is not set or security control field is not present.
*/
bool nrf_802154_frame_parser_sec_ctrl_asn_in_nonce_bit_is_set(const uint8_t * p_frame);
/**
* @brief Gets the offset of the frame counter field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
*
* @returns Pointer to the first byte of the key identifier field in @p p_frame.
* @returns NULL if the key identifier cannot be retrieved (that is, security is not enabled).
*
* @returns Offset in bytes of the frame counter field, including one byte of the frame length.
* @returns Zero if the frame counter cannot be retrieved (that is, security is not enabled).
*/
const uint8_t * nrf_802154_frame_parser_key_id_get(const uint8_t * p_frame);
uint8_t nrf_802154_frame_parser_frame_counter_offset_get(const uint8_t * p_frame);
/**
* @brief Gets frame counter field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
*
* @returns Pointer to the first byte of the frame counter field in @p p_frame.
* @returns NULL if the frame counter cannot be retrieved (that is, security is not enabled).
*/
const uint8_t * nrf_802154_frame_parser_frame_counter_get(const uint8_t * p_frame);
/**
* @brief Gets the offset of the key identifier field in the provided frame.
@ -263,6 +342,40 @@ const uint8_t * nrf_802154_frame_parser_key_id_get(const uint8_t * p_frame);
*/
uint8_t nrf_802154_frame_parser_key_id_offset_get(const uint8_t * p_frame);
/**
* @brief Gets the key identifier field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
*
* @returns Pointer to the first byte of the key identifier field in @p p_frame.
* @returns NULL if the key identifier cannot be retrieved (that is, security is not enabled).
*/
const uint8_t * nrf_802154_frame_parser_key_id_get(const uint8_t * p_frame);
/**
* @brief Gets key source from the key identifier field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
* @param[out] p_key_src_len Pointer to an integer to be filled with length of the retrieved key source.
*
* @returns Pointer to the first byte of the key source from the key identifier field in @p p_frame.
* @returns NULL if the key source cannot be retrieved.
*/
const uint8_t * nrf_802154_frame_parser_key_id_key_source_get(const uint8_t * p_frame,
uint8_t * p_key_src_len);
/**
* @brief Gets key index from the key identifier field in the provided frame.
*
* @param[in] p_frame Pointer to a frame.
* @param[out] p_key_src_len Pointer to an integer to be filled with the key index value.
*
* @retval true Key index retrieved correctly.
* @retval false Key index could not be retrieved. Value held by the pointer is undefined.
*/
bool nrf_802154_frame_parser_key_id_key_index_get(const uint8_t * p_frame,
uint8_t * p_key_index);
/**
* @brief Determines if the sequence number suppression bit is set.
*
@ -285,6 +398,16 @@ bool nrf_802154_frame_parser_dsn_suppress_bit_is_set(const uint8_t * p_frame);
*/
bool nrf_802154_frame_parser_ie_present_bit_is_set(const uint8_t * p_frame);
/**
* @brief Determines if the Security Enabled bit is set.
*
* @param[in] p_frame Pointer to a frame.
*
* @retval true Security Enabled bit is set.
* @retval false Security Enabled bit is not set.
*/
bool nrf_802154_frame_parser_security_enabled_bit_is_set(const uint8_t * p_frame);
/**
* @brief Determines if the Ack Request (AR) bit is set.
*
@ -318,4 +441,196 @@ const uint8_t * nrf_802154_frame_parser_ie_header_get(const uint8_t * p_frame);
*/
uint8_t nrf_802154_frame_parser_ie_header_offset_get(const uint8_t * p_frame);
/**
* @brief Initializes the IE iterator with given IE header address.
*
* @param[in] p_ie_header Pointer to an IE header.
*
* @returns Information element iterator.
*
*/
const uint8_t * nrf_802154_frame_parser_header_ie_iterator_begin(const uint8_t * p_ie_header);
/**
* @brief Gets next information element iterator.
*
* @param[in] p_ie_iterator Current information element iterator.
*
* @returns Next information element iterator.
*
*/
const uint8_t * nrf_802154_frame_parser_ie_iterator_next(const uint8_t * p_ie_iterator);
/**
* @brief Checks if the current IE is a terminator.
*
* @param[in] p_ie_iterator Information element iterator.
* @param[in] p_end_addr Address past which the iteration shall stop.
*
* @retval true The IE is a terminator or iteration has passed the end address.
* @retval false The IE is not a terminator and iteration has not passed the end address.
*
*/
bool nrf_802154_frame_parser_ie_iterator_end(const uint8_t * p_ie_iterator,
const uint8_t * p_end_addr);
/**
* @brief Gets length of currently iterated IE.
*
* @param[in] p_ie_iterator Information element iterator.
*
* @returns Length of currently iterated information element.
*
*/
uint8_t nrf_802154_frame_parser_ie_length_get(const uint8_t * p_ie_iterator);
/**
* @brief Gets identifier of currently iterated IE.
*
* @param[in] p_ie_iterator Information element iterator.
*
* @returns Identifier of currently iterated information element.
*
*/
uint8_t nrf_802154_frame_parser_ie_id_get(const uint8_t * p_ie_iterator);
/**
* @brief Gets payload address of currently iterated IE.
*
* @param[in] p_ie_iterator Information element iterator.
*
* @returns Current IE payload address.
*
* @note The user must ensure that the payload is properly bounded.
*
*/
const uint8_t * nrf_802154_frame_parser_ie_content_address_get(const uint8_t * p_ie_iterator);
/**
* @brief Gets vendor-specific OUI (organizationally unique identifier) of currently iterated IE.
*
* @param[in] p_ie_iterator Information element iterator.
*
* @note This field is only present in vendor-specific IE. The caller of this function should ensure
* that @p p_ie_iterator points to an IE with:
* - ID: @ref IE_VENDOR_ID ID.
* - IE length: at least @ref IE_VENDOR_SIZE_MIN
* Otherwise, returned value is not OUI.
* See @ref nrf_802154_frame_parser_ie_id_get.
*
* @returns Vendor-specific OUI.
*/
uint32_t nrf_802154_frame_parser_ie_vendor_oui_get(const uint8_t * p_ie_iterator);
/**
* @brief Gets subtype of Thread vendor-specific IE.
*
* @param[in] p_ie_iterator Information element iterator.
*
* @note This field is only present in Thread vendor-specific IE. The caller of this function should ensure
* that @p p_ie_iterator points to an IE with:
* - ID: @ref IE_VENDOR_ID,
* - OUI: @ref IE_VENDOR_THREAD_OUI.
* - IE length: at least @ref IE_VENDOR_THREAD_SIZE_MIN
* Otherwise, returned value is not Thread IE subtype.
* - @ref nrf_802154_frame_parser_ie_id_get,
* - @ref nrf_802154_frame_parser_ie_vendor_oui_get.
*
* @returns subtype of Thread vendor-specific IE.
*/
uint8_t nrf_802154_frame_parser_ie_vendor_thread_subtype_get(const uint8_t * p_ie_iterator);
/**
* @brief Gets vendor-specific IE thread data address of currently iterated IE.
*
* @param[in] p_ie_iterator Information element iterator.
*
* @note This field is only present in Thread vendor-specific IE. The caller of this function should ensure
* that @p p_ie_iterator points to an IE with:
* - ID: @ref IE_VENDOR_ID,
* - OUI: @ref IE_VENDOR_THREAD_OUI,
* - subtype: @ref IE_VENDOR_THREAD_ACK_PROBING_ID.
* - IE length: at least @ref IE_VENDOR_THREAD_ACK_SIZE_MIN
* Otherwise, returned pointer does not point to thread vendor-specific IE data.
* See also:
* - @ref nrf_802154_frame_parser_ie_id_get,
* - @ref nrf_802154_frame_parser_ie_vendor_oui_get,
* - @ref nrf_802154_frame_parser_ie_vendor_thread_subtype_get.
*
* @returns Current vendor-specific IE thread data address.
*/
const uint8_t * nrf_802154_frame_parser_ie_vendor_thread_data_addr_get(
const uint8_t * p_ie_iterator);
/**
* @brief Gets the length of the PHY payload from the PHR.
*
* @param[in] p_frame Pointer to a frame.
*
* @returns Total length of the PHY payload.
*
*/
uint8_t nrf_802154_frame_parser_frame_length_get(const uint8_t * p_frame);
/**
* @brief Gets the MAC payload from the provided frame.
*
* @param[in] p_frame Pointer to a frame.
*
* @returns Pointer to the first byte of MAC payload.
*
*/
const uint8_t * nrf_802154_frame_parser_mac_payload_get(const uint8_t * p_frame);
/**
* @brief Gets the length of the MAC payload from the provided frame.
*
* @param[in] p_frame Pointer to a frame.
* @param[in] p_mac_payload Pointer to the first byte of MAC payload. This parameter is optional
* and if NULL is provided, @ref nrf_802154_frame_parser_mac_payload_get
* is called internally.
*
* @returns Length of the MAC payload in number of bytes.
*/
uint8_t nrf_802154_frame_parser_mac_payload_length_get(const uint8_t * p_frame,
const uint8_t * p_mac_payload);
/**
* @brief Gets the length of the MAC header from the provided frame.
*
* @param[in] p_frame Pointer to a frame.
* @param[in] p_mac_payload Pointer to the first byte of MAC payload. This parameter is optional
* and if NULL is provided, @ref nrf_802154_frame_parser_mac_payload_get
* is called internally.
*
* @returns Length of the MAC header in number of bytes.
*/
uint8_t nrf_802154_frame_parser_mac_header_length_get(const uint8_t * p_frame,
const uint8_t * p_mac_payload);
/**
* @brief Gets the pointer to the MAC Command ID field.
*
* @note If @p p_frame is not a MAC command type frame, this function returns NULL.
*
* @param[in] p_frame Pointer to a frame.
* @param[in] p_mac_payload Pointer to the first byte of MAC payload. This parameter is optional
* and if NULL is provided, @ref nrf_802154_frame_parser_mac_payload_get
* is called internally.
*
* @returns Pointer to the MAC Command ID field.
*/
const uint8_t * nrf_802154_frame_parser_mac_command_id_get(const uint8_t * p_frame,
const uint8_t * p_mac_payload);
/**
* @brief Gets the address of the first MFR byte.
*
* @param[in] p_frame Pointer to a frame.
*
* @returns Address of the first byte of MAC footer.
*
*/
const uint8_t * nrf_802154_frame_parser_mfr_address_get(const uint8_t * p_frame);
#endif // NRF_802154_FRAME_PARSER_H

View File

@ -0,0 +1,483 @@
/*
* 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.
*
*/
/**
* @file
* This file implements the CSL IE injector for the 802.15.4 driver.
*
*/
#include "mac_features/nrf_802154_ie_writer.h"
#include "mac_features/nrf_802154_frame_parser.h"
#include "mac_features/nrf_802154_delayed_trx.h"
#include "nrf_802154_core.h"
#include "nrf_802154_nrfx_addons.h"
#include "nrf_802154_utils.h"
#include "nrf_802154_utils_byteorder.h"
#include <assert.h>
#if NRF_802154_IE_WRITER_ENABLED
typedef enum
{
IE_WRITER_RESET,
IE_WRITER_PREPARE,
IE_WRITER_COMMIT
} writer_state_t;
static writer_state_t m_writer_state = IE_WRITER_RESET; ///< IE writer state
#if NRF_802154_DELAYED_TRX_ENABLED
static uint8_t * mp_csl_phase_addr; ///< Cached CSL information element phase field address
static uint8_t * mp_csl_period_addr; ///< Cached CSL information element period field address
static uint16_t m_csl_period; ///< CSL period value that will be injected to CSL information element
/**
* @brief Writes CSL phase to previously set memory address.
*/
static void csl_ie_write_commit(void)
{
uint32_t time_remaining;
uint32_t symbols;
uint32_t csl_phase;
if ((mp_csl_phase_addr == NULL) || (mp_csl_period_addr == NULL))
{
// CSL writer not armed. Nothing to be done.
return;
}
if (nrf_802154_delayed_trx_nearest_drx_time_to_midpoint_get(&time_remaining) == false)
{
// No delayed DRX is pending. Do not write to the CSL IE.
return;
}
/*
* Note: The csl_ie_write_commit executes after the FRAMESTART event, which is triggered
* by the radio peripheral after the SHR (nRF52840 PS v1.2 -- 6.20.12.6 Transmit sequence).
* The symbol calculation should take into account the time needed for two symbols of the PHR.
* However, since we are measuring time to the DRX midpoint and not to the beginning, there
* is a bit or margin to spare and the calculation does not have to account for the PHR.
*/
symbols = time_remaining / PHY_US_PER_SYMBOL;
csl_phase = symbols / IE_CSL_SYMBOLS_PER_UNIT;
if (csl_phase > IE_CSL_PERIOD_MAX)
{
// CSL phase exceeds the maximum value. Do not write to the CSL IE
return;
}
host_16_to_little(csl_phase, mp_csl_phase_addr);
host_16_to_little(m_csl_period, mp_csl_period_addr);
}
/**
* @brief Finds and prepare memory address where CSL phase will be written.
*
* @param[in] p_iterator Information Element parser iterator.
*
* @retval true The write prepare operation to CSL IE was successful.
* @retval false An improperly formatted CSL IE was detected.
*/
static bool csl_ie_write_prepare(const uint8_t * p_iterator)
{
assert(p_iterator != NULL);
if (nrf_802154_frame_parser_ie_length_get(p_iterator) < IE_CSL_SIZE_MIN)
{
// The IE is too small to be a valid CSL IE.
return false;
}
mp_csl_phase_addr = (uint8_t *)nrf_802154_frame_parser_ie_content_address_get(p_iterator);
mp_csl_period_addr = mp_csl_phase_addr + sizeof(uint16_t);
return true;
}
/**
* @brief Resets CSL writer to pristine state.
*/
static void csl_ie_write_reset(void)
{
mp_csl_phase_addr = NULL;
mp_csl_period_addr = NULL;
}
#else
/**
* @brief Writes CSL phase to previously set memory address.
*/
static void csl_ie_write_commit(void)
{
// Intentionally empty
}
/**
* @brief Finds and prepare memory address where CSL phase will be written.
*
* @param[in] p_iterator Information Element parser iterator.
*
* @retval true The write prepare operation to CSL IE was successful.
* @retval false An improperly formatted CSL IE was detected.
*/
static bool csl_ie_write_prepare(const uint8_t * p_iterator)
{
// Intentionally empty
return true;
}
/**
* @brief Resets CSL writer to pristine state.
*/
static void csl_ie_write_reset(void)
{
// Intentionally empty
}
#endif // NRF_802154_DELAYED_TRX_ENABLED
static uint8_t * mp_lm_rssi_addr; ///< Cached Link Metrics information element RSSI field address
static uint8_t * mp_lm_margin_addr; ///< Cached Link Metrics information element link margin field address
static uint8_t * mp_lm_lqi_addr; ///< Cached Link Metrics information element LQI field address
static uint8_t rssi_scale(int8_t rssi)
{
int16_t rssi_lim; ///< RSSI value after applying limits
int16_t intermediate; ///< RSSI value after casting to a wider type
uint8_t scaled; ///< RSSI value after scaling
// Apply lower limit
rssi_lim =
((int16_t)rssi < IE_VENDOR_THREAD_RSSI_FLOOR) ? IE_VENDOR_THREAD_RSSI_FLOOR : (int16_t)rssi;
// Apply upper limit
rssi_lim = (rssi_lim > IE_VENDOR_THREAD_RSSI_CEIL) ? IE_VENDOR_THREAD_RSSI_CEIL : rssi_lim;
// Cast to a wider type to avoid premature overflow
intermediate = (int16_t)rssi_lim - IE_VENDOR_THREAD_RSSI_FLOOR;
// Scale linearly to range 0 - UINT8_MAX
scaled = (uint8_t)((intermediate * (UINT8_MAX - 0)) /
(IE_VENDOR_THREAD_RSSI_CEIL - IE_VENDOR_THREAD_RSSI_FLOOR));
return scaled;
}
static uint8_t margin_scale(int16_t margin)
{
int16_t margin_lim; ///< Margin value after applying limits
uint8_t scaled; ///< Margin value after scaling
// Apply lower limit
margin_lim = (margin < IE_VENDOR_THREAD_MARGIN_FLOOR) ? IE_VENDOR_THREAD_MARGIN_FLOOR : margin;
// Apply upper limit
margin_lim =
(margin_lim > IE_VENDOR_THREAD_MARGIN_CEIL) ? IE_VENDOR_THREAD_MARGIN_CEIL : margin_lim;
// Scale linearly to range 0 - UINT8_MAX
scaled = (uint8_t)(((margin_lim - IE_VENDOR_THREAD_MARGIN_FLOOR) * (UINT8_MAX - 0)) /
(IE_VENDOR_THREAD_MARGIN_CEIL - IE_VENDOR_THREAD_MARGIN_FLOOR));
return scaled;
}
/**
* @brief Writes link metrics to previously prepared addresses in a frame.
*/
static void link_metrics_ie_write_commit(void)
{
if ((mp_lm_rssi_addr != NULL) || (mp_lm_margin_addr != NULL))
{
int8_t rssi = (uint8_t)nrf_802154_core_last_frame_rssi_get();
if (mp_lm_rssi_addr != NULL)
{
*mp_lm_rssi_addr = rssi_scale(rssi);
}
if (mp_lm_margin_addr != NULL)
{
*mp_lm_margin_addr = margin_scale((int16_t)rssi - ED_MIN_DBM);
}
}
if (mp_lm_lqi_addr != NULL)
{
*mp_lm_lqi_addr = (uint8_t)nrf_802154_core_last_frame_lqi_get();
}
}
/**
* @brief Finds and prepare memory addresses where link metrics will be written.
*
* @param[in] p_iterator Information Element parser iterator.
*
* @retval true The write prepare operation for link metrics was successful.
* @retval false An improperly formatted link metrics IE was detected.
*/
static bool link_metrics_ie_write_prepare(const uint8_t * p_iterator)
{
assert(p_iterator != NULL);
// Initialize the iterator at the start of IE content
uint8_t * p_content_iterator =
(uint8_t *)nrf_802154_frame_parser_ie_vendor_thread_data_addr_get(p_iterator);
uint8_t * ie_end = (uint8_t *)nrf_802154_frame_parser_ie_iterator_next(p_iterator);
if (nrf_802154_frame_parser_ie_length_get(p_iterator) < IE_VENDOR_THREAD_ACK_SIZE_MIN ||
nrf_802154_frame_parser_ie_length_get(p_iterator) > IE_VENDOR_THREAD_ACK_SIZE_MAX)
{
return false;
}
while (p_content_iterator != ie_end)
{
switch (*p_content_iterator)
{
case IE_VENDOR_THREAD_RSSI_TOKEN:
if (mp_lm_rssi_addr != NULL)
{
return false;
}
mp_lm_rssi_addr = p_content_iterator;
break;
case IE_VENDOR_THREAD_MARGIN_TOKEN:
if (mp_lm_margin_addr != NULL)
{
return false;
}
mp_lm_margin_addr = p_content_iterator;
break;
case IE_VENDOR_THREAD_LQI_TOKEN:
if (mp_lm_lqi_addr != NULL)
{
return false;
}
mp_lm_lqi_addr = p_content_iterator;
break;
default:
return false;
}
p_content_iterator++;
}
return true;
}
/**
* @brief Resets the prepared addresses for injecting link metrics into a frame.
*/
static void link_metrics_ie_write_reset(void)
{
mp_lm_rssi_addr = NULL;
mp_lm_margin_addr = NULL;
mp_lm_lqi_addr = NULL;
}
/**
* @brief Resets IE writer to pristine state.
*/
static void ie_writer_reset(void)
{
m_writer_state = IE_WRITER_RESET;
csl_ie_write_reset();
link_metrics_ie_write_reset();
}
/**
* @brief Performs IE write preparations.
*
* This function prepares the write operation for all recognized information elements and
* sets the state to IE_WRITER_PREPARE.
*
* If any of the information elements fails the boundary check or is not properly formatted,
* the writer state shall be set to IE_WRITER_RESET.
*
* @param[in] p_ie_header Pointer to the beginning of header IEs.
* @param[in] p_end_addr Pointer to the first invalid address after p_ie_header.
*/
static void ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_addr)
{
assert(m_writer_state == IE_WRITER_RESET);
m_writer_state = IE_WRITER_PREPARE;
const uint8_t * p_iterator = nrf_802154_frame_parser_header_ie_iterator_begin(p_ie_header);
bool result = true;
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:
if (nrf_802154_frame_parser_ie_length_get(p_iterator) >= IE_VENDOR_SIZE_MIN &&
nrf_802154_frame_parser_ie_vendor_oui_get(p_iterator) == IE_VENDOR_THREAD_OUI)
{
if (nrf_802154_frame_parser_ie_length_get(p_iterator) >=
IE_VENDOR_THREAD_SIZE_MIN &&
nrf_802154_frame_parser_ie_vendor_thread_subtype_get(p_iterator) ==
IE_VENDOR_THREAD_ACK_PROBING_ID)
{
result = link_metrics_ie_write_prepare(p_iterator);
}
}
break;
case IE_CSL_ID:
result = csl_ie_write_prepare(p_iterator);
break;
default:
break;
}
if (result == false)
{
ie_writer_reset();
return;
}
p_iterator = nrf_802154_frame_parser_ie_iterator_next(p_iterator);
}
}
/**
* @brief Commits data to recognized information elements.
*/
static void ie_writer_commit(void)
{
assert(m_writer_state == IE_WRITER_PREPARE);
m_writer_state = IE_WRITER_COMMIT;
csl_ie_write_commit();
link_metrics_ie_write_commit();
}
void nrf_802154_ie_writer_prepare(uint8_t * p_ie_header, const uint8_t * p_end_addr)
{
assert(p_ie_header != NULL);
assert(p_ie_header < p_end_addr);
ie_writer_reset();
ie_writer_prepare(p_ie_header, p_end_addr);
}
bool nrf_802154_ie_writer_pretransmission(
const 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)
{
// 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);
if (p_ie_header == NULL)
{
return true;
}
nrf_802154_ie_writer_prepare(p_ie_header, p_mfr_addr);
return true;
}
bool nrf_802154_ie_writer_tx_started_hook(const uint8_t * p_frame)
{
(void)p_frame;
if (m_writer_state != IE_WRITER_PREPARE)
{
return true;
}
ie_writer_commit();
ie_writer_reset();
return true;
}
void nrf_802154_ie_writer_tx_ack_started_hook(const uint8_t * p_ack)
{
(void)p_ack;
if (m_writer_state != IE_WRITER_PREPARE)
{
return;
}
ie_writer_commit();
ie_writer_reset();
}
#if NRF_802154_DELAYED_TRX_ENABLED
void nrf_802154_ie_writer_csl_period_set(uint16_t period)
{
m_csl_period = period;
}
#endif // NRF_802154_DELAYED_TRX_ENABLED
#endif // NRF_802154_IE_WRITER_ENABLED

View File

@ -0,0 +1,141 @@
/*
* 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.
*
*/
#ifndef NRF_802154_IE_WRITER_H__
#define NRF_802154_IE_WRITER_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_802154_types.h"
/**
* @defgroup nrf_802154_ie_writer 802.15.4 driver Information Element writer
* @{
* @ingroup nrf_802154
* @brief Information element writer module.
*/
/**
* @brief Prepares to write Information Element data to all elements recognized by the module.
*
* Calls to this function put the IE writer module into an armed state.
* In the armed state the addresses of recognized Information Element values
* are latched. The IE writer module shall perform necessary calculations and write
* the results to the latched addresses during the execution of either
* nrf_802154_ie_writer_tx_ack_started_hook or nrf_802154_ie_writer_tx_started_hook hooks.
*
* It is expected, that the layout of the frame does not change while the IE writer is in
* armed state.
*
* If this function detects a malformed header IE, the module state shall be reset to the
* unarmed state. There is no guarantee that all malformed header IEs will be detected, but
* it is guaranteed that the writer module shall never modify memory past the p_end_addr argument.
*
* @param[in] p_ie_header Address of the IE header.
* @param[in] p_end_addr First invalid address after p_ie_header.
*
*/
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.
*
* 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
* Information Elements during the execution of nrf_802154_ie_writer_tx_ack_started_hook
* and nrf_802154_ie_writer_tx_started_hook hooks.
*
* If this function detects a malformed frame, the module state shall be reset to the
* unarmed state. There is no guarantee that all malformed frames will be detected.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU
* of the transmitted frame.
* @param[in] p_params Pointer to the transmission parameters.
* @param[in] notify_function Function to be called to notify transmission failure.
*
* @retval true Always succeeds.
*/
bool nrf_802154_ie_writer_pretransmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
/**
* @brief ACK TX started hook for the IE writer module.
*
* This hook executes during the EVENT_ADDRESS radio event. If the IE writer is armed,
* the IEs recognized by the writer module shall be modified. If IE writer is not armed
* no action shall be performed.
*
* The function writes to memory addresses that were found suitable by the call to
* nrf_802154_ie_writer_prepare function. No parsing of the frame pointed by the p_ack
* argument is performed and the argument itself is ignored due to timing requirements
* that this hook must not exceed.
*
* @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);
/**
* @brief TX started hook for the IE writer module.
*
* This hook executes during the EVENT_ADDRESS radio event. If the IE writer is armed,
* the IEs recognized by the writer module shall be modified. If IE writer is not armed
* no action shall be performed.
*
* The function writes to memory addresses that were found suitable by the call to
* nrf_802154_ie_writer_prepare function. No parsing of the frame pointed by the p_frame
* argument is performed and the argument itself is ignored due to timing requirements
* that this hook must not exceed.
*
* @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_ie_writer_tx_started_hook(const uint8_t * p_frame);
/**
* @brief Sets the value of CSL period to inject into the CSL information element.
*
* @param[in] period CSL period value.
*/
void nrf_802154_ie_writer_csl_period_set(uint16_t period);
/**
*@}
**/
#endif // NRF_802154_IE_WRITER_H__

View File

@ -52,8 +52,8 @@
#if NRF_802154_IFS_ENABLED
typedef struct
{
uint8_t * p_data;
bool cca;
uint8_t * p_data;
nrf_802154_transmit_params_t params;
} ifs_operation_t;
static union
@ -83,8 +83,7 @@ static void callback_fired(void * p_context)
nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_IFS,
p_ctx->p_data,
p_ctx->cca,
true,
&p_ctx->params,
ifs_tx_result_notify);
}
@ -147,9 +146,21 @@ static uint16_t ifs_needed_by_time(uint32_t current_timestamp)
return ifs_period;
}
bool nrf_802154_ifs_pretransmission(const uint8_t * p_frame, bool cca)
bool nrf_802154_ifs_pretransmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
nrf_802154_ifs_mode_t mode = nrf_802154_pib_ifs_mode_get();
(void)notify_function;
nrf_802154_ifs_mode_t mode;
if (p_params->immediate)
{
return true;
}
mode = nrf_802154_pib_ifs_mode_get();
if (mode == NRF_802154_IFS_MODE_DISABLED)
{
@ -176,12 +187,14 @@ bool nrf_802154_ifs_pretransmission(const uint8_t * p_frame, bool cca)
return true;
}
m_context.p_data = (uint8_t *)p_frame;
m_context.cca = cca;
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 = (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;
nrf_802154_timer_sched_add(&m_timer, true);

View File

@ -44,13 +44,18 @@
/**
* @brief Examines the frame before transmission and checks if it needs to be delayed.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU of the transmitted frame.
* @param[in] cca Whether to trigger CCA before transmitting the frame.
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU
* of the transmitted frame.
* @param[in] p_params Pointer to the transmission parameters.
* @param[in] notify_function Function to be called to notify transmission failure.
*
* @retval true Frame will be transmitted right away.
* @retval false Frame is delayed and will be transmistted after a needed IFS.
* @retval true Frame will be transmitted right away.
* @retval false Frame is delayed and will be transmistted after a needed IFS.
*/
bool nrf_802154_ifs_pretransmission(const uint8_t * p_frame, bool cca);
bool nrf_802154_ifs_pretransmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
/**
* @brief Captures the timestamp, length and destination address of the transmitted

View File

@ -0,0 +1,122 @@
/*
* 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.
*
*/
#ifndef NRF_802154_SECURITY_PIB_H__
#define NRF_802154_SECURITY_PIB_H__
#include "nrf_802154_types.h"
/**
* @brief Initialises the Key Storage inside the nRF 802.15.4 Radio Driver.
*
* @return NRF_802154_SECURITY_ERROR_NONE if no error, otherwise the corresponding
* error code.
*/
nrf_802154_security_error_t nrf_802154_security_pib_init(void);
/**
* @brief Deinitialises the Key Storage inside the nRF 802.15.4 Radio Driver.
*
* @return NRF_802154_SECURITY_ERROR_NONE if no error, otherwise the corresponding
* error code.
*/
nrf_802154_security_error_t nrf_802154_security_pib_deinit(void);
/**
* @brief Stores the 802.15.4 MAC Security Key inside the nRF 802.15.4 Radio Driver.
*
* @param[in] p_key Pointer to the key to store. Refer to @ref nrf_802154_key_t for details.
* Storing the key copies the content of the key into the Radio Driver.
* This input parameter can be destroyed after the call.
*
* @note This function is not reentrant and must be called from thread context only.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Storing of key is successful.
* @retval NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED Type of the key is not supported.
* @retval NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED ID mode of the key is not supported.
* @retval NRF_802154_SECURITY_ERROR_ALREADY_PRESENT Failed to store the key - key of such id is already
* present. Remove the key first to overwrite.
* @retval NRF_802154_SECURITY_ERROR_STORAGE_FULL Failed to store the key - storage full.
*/
nrf_802154_security_error_t nrf_802154_security_pib_key_store(nrf_802154_key_t * p_key);
/**
* @brief Removes the 802.15.4 MAC Security Key from the nRF 802.15.4 Radio Driver.
*
* @param[in] p_id Pointer to the ID of the key to remove.
*
* @note This function is not reentrant and must be called from thread context only.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Removal of key is successful.
* @retval NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND Failed to remove the key - no such key found.
*/
nrf_802154_security_error_t nrf_802154_security_pib_key_remove(nrf_802154_key_id_t * p_id);
/**
* @brief Uses the 802.15.4 MAC Security Key stored previously in the nRF 802.15.4 Radio Driver.
*
* @param[in] p_id Pointer to the ID of the key to use.
* @param[out] destination Destination where the key must be copied. In case of
* hardware accelerated solutions this parameter is ignored.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Usage of key is successful.
* @retval NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND Failed to use the key - no such key found.
*/
nrf_802154_security_error_t nrf_802154_security_pib_key_use(nrf_802154_key_id_t * p_id,
void * destination);
/**
* @brief Sets nRF 802.15.4 Radio Driver MAC Global Frame Counter.
*
* @param[in] frame_counter Frame counter to set.
*/
void nrf_802154_security_pib_global_frame_counter_set(uint32_t frame_counter);
/**
* @brief Get the next 802.15.4 global frame counter.
*
* @param[out] p_frame_counter Pointer to the frame counter to populate.
* @param[in] p_id Pointer to the ID of the key to get the frame counter for.
*
* @retval NRF_802154_SECURITY_ERROR_NONE The p_frame_counter field was
* successfully populated.
* @retval NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW No more available frame counters,
* they must be reset.
* @retval NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND The associated key was not found.
*/
nrf_802154_security_error_t nrf_802154_security_pib_frame_counter_get_next(
uint32_t * p_frame_counter,
nrf_802154_key_id_t * p_id);
#endif // NRF_802154_SECURITY_PIB_H__

View File

@ -0,0 +1,272 @@
/*
* 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 "nrf_802154_security_pib.h"
#include "nrf_802154_config.h"
#include "nrf_802154_const.h"
#include <string.h>
#include <stdbool.h>
#include <assert.h>
typedef struct
{
uint8_t key[AES_CCM_KEY_SIZE];
uint8_t id[KEY_ID_MODE_3_SIZE];
nrf_802154_key_id_mode_t mode;
uint32_t frame_counter;
bool use_global_frame_counter;
bool taken;
} table_entry_t;
static table_entry_t m_key_storage[NRF_802154_SECURITY_KEY_STORAGE_SIZE];
static uint32_t m_global_frame_counter;
static bool mode_is_valid(nrf_802154_key_id_mode_t mode)
{
switch (mode)
{
case 0:
case 1:
case 2:
case 3:
return true;
default:
return false;
}
}
static int id_length_get(nrf_802154_key_id_mode_t mode)
{
switch (mode)
{
case 1:
return KEY_ID_MODE_1_SIZE;
case 2:
return KEY_ID_MODE_2_SIZE;
case 3:
return KEY_ID_MODE_3_SIZE;
default:
return 0;
}
}
static bool key_matches(table_entry_t * p_key, nrf_802154_key_id_t * p_id)
{
if (!p_key->taken)
{
return false;
}
if (p_key->mode != p_id->mode)
{
return false;
}
if (p_id->mode == KEY_ID_MODE_0)
{
return true;
}
else if ((p_id->p_key_id == NULL) ||
(memcmp(p_id->p_key_id, p_key->id, id_length_get(p_id->mode)) != 0))
{
return false;
}
else
{
return true;
}
}
static bool key_is_present(nrf_802154_key_id_t * p_id)
{
for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
{
if (key_matches(&m_key_storage[i], p_id))
{
return true;
}
}
return false;
}
nrf_802154_security_error_t nrf_802154_security_pib_init(void)
{
for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
{
m_key_storage[i].taken = false;
}
return NRF_802154_SECURITY_ERROR_NONE;
}
nrf_802154_security_error_t nrf_802154_security_pib_deinit(void)
{
return NRF_802154_SECURITY_ERROR_NONE;
}
nrf_802154_security_error_t nrf_802154_security_pib_key_store(nrf_802154_key_t * p_key)
{
assert(p_key != NULL);
if (p_key->type != NRF_802154_KEY_CLEARTEXT)
{
return NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED;
}
if (!mode_is_valid(p_key->id.mode))
{
return NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED;
}
if (key_is_present(&p_key->id))
{
return NRF_802154_SECURITY_ERROR_ALREADY_PRESENT;
}
for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
{
if (m_key_storage[i].taken == false)
{
memcpy(m_key_storage[i].key,
p_key->value.p_cleartext_key,
sizeof(m_key_storage[i].key));
m_key_storage[i].mode = p_key->id.mode;
memcpy(m_key_storage[i].id, p_key->id.p_key_id, id_length_get(p_key->id.mode));
m_key_storage[i].frame_counter = p_key->frame_counter;
m_key_storage[i].use_global_frame_counter = p_key->use_global_frame_counter;
__DMB();
m_key_storage[i].taken = true;
return NRF_802154_SECURITY_ERROR_NONE;
}
}
return NRF_802154_SECURITY_ERROR_STORAGE_FULL;
}
nrf_802154_security_error_t nrf_802154_security_pib_key_remove(nrf_802154_key_id_t * p_id)
{
assert(p_id != NULL);
for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
{
if (key_matches(&m_key_storage[i], p_id))
{
m_key_storage[i].taken = false;
return NRF_802154_SECURITY_ERROR_NONE;
}
}
return NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND;
}
nrf_802154_security_error_t nrf_802154_security_pib_key_use(nrf_802154_key_id_t * p_id,
void * destination)
{
assert(destination != NULL);
assert(p_id != NULL);
for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
{
if (key_matches(&m_key_storage[i], p_id))
{
memcpy((uint8_t *)destination, m_key_storage[i].key, sizeof(m_key_storage[i].key));
return NRF_802154_SECURITY_ERROR_NONE;
}
}
return NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND;
}
void nrf_802154_security_pib_global_frame_counter_set(uint32_t frame_counter)
{
m_global_frame_counter = frame_counter;
}
nrf_802154_security_error_t nrf_802154_security_pib_frame_counter_get_next(
uint32_t * p_frame_counter,
nrf_802154_key_id_t * p_id)
{
assert(p_frame_counter != NULL);
assert(p_id != NULL);
uint32_t * p_frame_counter_to_use = NULL;
uint32_t fc;
for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
{
if (key_matches(&m_key_storage[i], p_id))
{
if (m_key_storage[i].use_global_frame_counter)
{
p_frame_counter_to_use = &m_global_frame_counter;
}
else
{
p_frame_counter_to_use = &m_key_storage[i].frame_counter;
}
break;
}
}
if (p_frame_counter_to_use == NULL)
{
/* No proper key found. */
return NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND;
}
do
{
fc = __LDREXW(p_frame_counter_to_use);
if (fc == UINT32_MAX)
{
__CLREX();
return NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW;
}
}
while (__STREXW(fc + 1, p_frame_counter_to_use));
*p_frame_counter = *p_frame_counter_to_use - 1;
return NRF_802154_SECURITY_ERROR_NONE;
}

View File

@ -0,0 +1,208 @@
/*
* 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.
*
*/
/**
* @file
* This file implements the security header data injector for the 802.15.4 driver.
*
*/
#include "mac_features/nrf_802154_security_writer.h"
#include "mac_features/nrf_802154_frame_parser.h"
#include "mac_features/nrf_802154_security_pib.h"
#include "nrf_802154_config.h"
#include "nrf_802154_const.h"
#include "nrf_802154_notification.h"
#include "nrf_802154_utils_byteorder.h"
#include <assert.h>
#include <stddef.h>
#if NRF_802154_SECURITY_WRITER_ENABLED
/**
* @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.
*/
static void key_id_prepare(nrf_802154_frame_parser_aux_sec_hdr_t * p_sec_hdr,
nrf_802154_key_id_t * p_key_id)
{
p_key_id->mode = p_sec_hdr->key_id_mode;
switch (p_key_id->mode)
{
case KEY_ID_MODE_0:
/* There is no need to retrieve the key ID as only one key ID with mode 0 is
* supported. Therefore mode 0 unambiguously identifies the key.
*/
break;
case KEY_ID_MODE_1:
/* Fallthrough */
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;
break;
default:
/* Key Identifier Mode is encoded on 2 bits and has 4 possible values, all handled in
* the above cases. Ending up in the default case indicates the frame parser is bugged.
*/
assert(false);
}
}
/**
* @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.
*
* @retval NRF_802154_SECURITY_ERROR_NONE Frame counter was injected successfully.
*
* @returns nrf_802154_security_error_t The security error code that occurred during
* 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)
{
uint32_t frame_counter;
nrf_802154_security_error_t err;
err = nrf_802154_security_pib_frame_counter_get_next(&frame_counter, p_key_id);
switch (err)
{
case NRF_802154_SECURITY_ERROR_NONE:
if (p_sec_hdr->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);
}
break;
case NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND:
/* Fallthrough */
case NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW:
break;
default:
/* nrf_802154_security_pib_frame_counter_get_next function shall not return other
* error codes than those handled in the above cases. If it does then it is a bug.
*/
assert(false);
}
return err;
}
/**
* @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.
*
* @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)
{
return ((NULL != p_sec_hdr->p_sec_ctrl) && (0 != p_sec_hdr->security_lvl));
}
bool nrf_802154_security_writer_pretransmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
if (p_params->is_retransmission)
{
// 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);
do
{
if (!security_is_enabled(&sec_hdr))
{
/* Security is not enabled. Pass. */
result = true;
break;
}
/* Prepare key ID for key validation. */
key_id_prepare(&sec_hdr, &key_id);
nrf_802154_security_error_t err = frame_counter_inject(&sec_hdr, &key_id);
switch (err)
{
case NRF_802154_SECURITY_ERROR_NONE:
result = true;
break;
case NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND:
notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID);
break;
case NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW:
notify_function(p_frame, NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR);
break;
default:
/* frame_counter_inject function shall not return other error codes than those
* handled in the above cases. If it does then it is a bug.
*/
assert(false);
}
}
while (0);
return result;
}
#endif // NRF_802154_SECURITY_WRITER_ENABLED

View File

@ -0,0 +1,66 @@
/*
* 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.
*
*/
#ifndef NRF_802154_SECURITY_WRITER_H__
#define NRF_802154_SECURITY_WRITER_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_802154_types.h"
/**
* @brief Pretransmission 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
* zero, then no processing occurs.
*
* If this function detects a malformed frame, the higher layer is notified of transmission
* failure. A frame is considered malformed if requested key is invalid.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU
* of the transmitted frame.
* @param[in] p_params Pointer to the transmission parameters.
* @param[in] notify_function Function to be called to notify transmission failure.
*
* @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,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
#endif // NRF_802154_SECURITY_WRITER_H__

View File

@ -74,6 +74,8 @@
#include "mac_features/nrf_802154_ack_timeout.h"
#include "mac_features/nrf_802154_csma_ca.h"
#include "mac_features/nrf_802154_delayed_trx.h"
#include "mac_features/nrf_802154_ie_writer.h"
#include "mac_features/nrf_802154_security_pib.h"
#include "mac_features/ack_generator/nrf_802154_ack_data.h"
#include "nrf_802154_sl_ant_div.h"
@ -210,6 +212,7 @@ void nrf_802154_init(void)
nrf_802154_notification_init();
nrf_802154_lp_timer_init();
nrf_802154_pib_init();
nrf_802154_security_pib_init();
nrf_802154_rsch_prio_drop_init();
nrf_802154_random_init();
nrf_802154_request_init();
@ -231,6 +234,7 @@ void nrf_802154_deinit(void)
nrf_802154_temperature_deinit();
nrf_802154_rsch_uninit();
nrf_802154_random_deinit();
nrf_802154_security_pib_deinit();
nrf_802154_lp_timer_deinit();
nrf_802154_clock_deinit();
nrf_802154_core_deinit();
@ -427,15 +431,20 @@ bool nrf_802154_receive(void)
#if NRF_802154_USE_RAW_API
bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
{
bool result;
bool result;
nrf_802154_transmit_params_t params =
{
.cca = cca,
.immediate = false,
.is_retransmission = false,
};
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,
cca,
false,
&params,
NULL);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
@ -446,7 +455,13 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca)
{
bool result;
bool result;
nrf_802154_transmit_params_t params =
{
.cca = cca,
.immediate = false,
.is_retransmission = false,
};
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -454,8 +469,7 @@ bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca)
result = nrf_802154_request_transmit(NRF_802154_TERM_NONE,
REQ_ORIG_HIGHER_LAYER,
m_tx_buffer,
cca,
false,
&params,
NULL);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
@ -471,11 +485,39 @@ bool nrf_802154_transmit_raw_at(const uint8_t * p_data,
uint32_t dt,
uint8_t channel)
{
bool result;
bool result;
nrf_802154_transmit_params_t params =
{
.cca = cca,
.immediate = true,
.is_retransmission = false,
};
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
result = nrf_802154_delayed_trx_transmit(p_data, cca, t0, dt, channel);
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 =
{
.cca = cca,
.immediate = true,
.is_retransmission = 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;
@ -754,7 +796,16 @@ void nrf_802154_transmit_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);
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);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
@ -767,7 +818,18 @@ void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length)
tx_buffer_fill(p_data, length);
nrf_802154_csma_ca_start(m_tx_buffer);
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);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
@ -871,6 +933,9 @@ nrf_802154_capabilities_t nrf_802154_capabilities_get(void)
caps_drv |= (NRF_802154_ACK_TIMEOUT_ENABLED ?
NRF_802154_CAPABILITY_ACK_TIMEOUT : 0UL);
caps_drv |= ((NRF_802154_SECURITY_WRITER_ENABLED && NRF_802154_ENCRYPTION_ENABLED) ?
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
* several timers simultaneously.
@ -894,6 +959,30 @@ uint32_t nrf_802154_time_get(void)
return nrf_802154_timer_sched_time_get();
}
void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter)
{
nrf_802154_security_pib_global_frame_counter_set(frame_counter);
}
nrf_802154_security_error_t nrf_802154_security_key_store(nrf_802154_key_t * p_key)
{
return nrf_802154_security_pib_key_store(p_key);
}
nrf_802154_security_error_t nrf_802154_security_key_remove(nrf_802154_key_id_t * p_id)
{
return nrf_802154_security_pib_key_remove(p_id);
}
#if NRF_802154_DELAYED_TRX_ENABLED && NRF_802154_IE_WRITER_ENABLED
void nrf_802154_csl_writer_period_set(uint16_t period)
{
nrf_802154_ie_writer_csl_period_set(period);
}
#endif
__WEAK void nrf_802154_custom_part_of_radio_init(void)
{
// Intentionally empty

View File

@ -0,0 +1,506 @@
/*
* 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 "nrf_802154_aes_ccm.h"
#include <string.h>
#include "hal/nrf_ecb.h"
#include "nrf_802154_const.h"
#include "platform/nrf_802154_irq.h"
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b)) ///< Leaves the minimum of the two arguments
#endif
#define NRF_802154_AES_CCM_BLOCK_SIZE 16 // Annex B4 Specification of generic CCM* a)
#define NRF_802154_AES_CCM_ADATA_AUTH_FLAG (0x40) // Annex B4.1.2 - Adata flag for authentication transform
#define NRF_802154_AES_CCM_M_BITS_AUTH_FLAG 3 // Annex B4.1.2 - Nr of bits for MIC flag for authentication transform
#define NRF_802154_AES_CCM_AI_FIELD_FLAG_OCTET 0 // AnnnexB4.1.3b) - Position of octet for flags in Ai field
#define NRF_802154_AES_CCM_AI_FIELD_NONCE_OCTET 1 // AnnnexB4.1.3b) - Position of octet for nonce in Ai field
#define NRF_802154_AES_CCM_B0_FIELD_FLAG_OCTET 0 // AnnnexB4.1.2b) - Position of octet for flags in B0 field
#define NRF_802154_AES_CCM_B0_FIELD_NONCE_OCTET 1 // AnnnexB4.1.2b) - Position of octet for nonce in B0 field
#define NRF_802154_AES_CCM_AUTH_DATA_LENGTH_OCTET 0 // AnnnexB4.1.1b) - Position of octet for length of auth data in AddAuthData
#define NRF_802154_AES_CCM_AUTH_DATA_OCTET 2 // AnnnexB4.1.1b) - Position of octet for data of auth data in AddAuthData
/**
* @brief Steps of AES-CCM* algorithm.
*/
typedef enum
{
ADD_AUTH_DATA_AUTH,
PLAIN_TEXT_AUTH,
PLAIN_TEXT_ENCRYPT,
CALCULATE_ENCRYPTED_TAG
} ccm_steps_t;
/**
* @brief Actual state of perfomed AES-CCM* algorithm.
*/
typedef struct
{
ccm_steps_t transformation; // Actual step of transformation
uint8_t iteration; // Iteration of actual step of transformation
} ccm_state_t;
static nrf_802154_aes_ccm_data_t m_aes_ccm_data; ///< AES CCM Frame
static uint8_t m_x[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< CBC-MAC value - Annex B4.1.2 d)
static uint8_t m_b[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< B[i] octet for Authorization Transformatino - Annex B4.1.2 b)
static uint8_t m_m[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< M[i] octet as parsed plaintext blocks - Annex B4.1.3 c)
static uint8_t m_a[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< A[i] octet for Encryption Transformation - Annex B4.1.3 b)
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 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
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
static uint8_t m_ecb_data[48]; ///< ECB data structure for RNG peripheral to access.
static uint8_t * mp_ecb_key; ///< Key: Starts at ecb_data
static uint8_t * mp_ecb_cleartext; ///< Cleartext: Starts at ecb_data + 16 bytes.
static uint8_t * mp_ecb_ciphertext; ///< Ciphertext: Starts at ecb_data + 32 bytes.
static void nrf_ecb_init(void)
{
mp_ecb_key = m_ecb_data;
mp_ecb_cleartext = m_ecb_data + 16;
mp_ecb_ciphertext = m_ecb_data + 32;
nrf_ecb_data_pointer_set(NRF_ECB, m_ecb_data);
}
static void nrf_ecb_set_key(const uint8_t * p_key)
{
memcpy(mp_ecb_key, p_key, 16);
}
static void ecb_irq_handler(void);
/**
* @brief Initializes the ECB peripheral.
*/
static void ecb_init(void)
{
#if !NRF_802154_IRQ_PRIORITY_ALLOWED(NRF_802154_ECB_PRIORITY)
#error NRF_802154_ECB_PRIORITY value out of the allowed range.
#endif
if (!m_initialized)
{
nrf_802154_irq_init(ECB_IRQn, NRF_802154_ECB_PRIORITY, ecb_irq_handler);
m_initialized = true;
}
// TODO: ensure ECB initialization is handled by zephyr
// TODO: what about ECB initialization in baremetal scenario?
nrf_ecb_init();
nrf_802154_irq_clear_pending(ECB_IRQn);
nrf_802154_irq_enable(ECB_IRQn);
nrf_ecb_int_enable(NRF_ECB, NRF_ECB_INT_ENDECB_MASK);
}
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
/**
* @brief Calculates XOR of two blocks of data
*
* @param[inout] p_first First block of data
* @param[in] p_second Second block of data
* @param[in] len Length of blocks
*/
static void two_blocks_xor(uint8_t * p_first, const uint8_t * p_second, uint8_t len)
{
for (uint8_t i = 0; i < len; i++)
{
p_first[i] ^= p_second[i];
}
}
/**
* @brief Forms 16-octet Ai field
* IEEE std 802.15.4-2015, B.4.1.3 Encryption transformation
*
* @param[in] p_frame pointer to AES CCM frame structure
* @param[in] iter counter of actual iteration
* @param[out] p_a pointer to memory for Ai
*/
static void ai_format(const nrf_802154_aes_ccm_data_t * p_frame,
uint16_t iter,
uint8_t * p_a)
{
uint8_t enc_flags = NRF_802154_AES_CCM_L_VALUE - 1;
p_a[NRF_802154_AES_CCM_AI_FIELD_FLAG_OCTET] = enc_flags;
memcpy(&p_a[NRF_802154_AES_CCM_AI_FIELD_NONCE_OCTET],
p_frame->nonce,
NRF_802154_AES_CCM_NONCE_SIZE);
p_a[NRF_802154_AES_CCM_BLOCK_SIZE - 1] = iter;
p_a[NRF_802154_AES_CCM_BLOCK_SIZE - 2] = iter >> 8;
}
/**
* @brief Forms 16-octet B0 field
* IEEE std 802.15.4-2015, B.4.1.2b Encryption transformation
*
* @param[in] p_frame pointer to AES CCM frame structure
* @param[in] flags flags for injection to B0 field
* @param[out] p_b pointer to memory for B0
*/
static void b0_format(const nrf_802154_aes_ccm_data_t * p_frame,
const uint8_t flags,
uint8_t * p_b)
{
p_b[NRF_802154_AES_CCM_B0_FIELD_FLAG_OCTET] = flags;
memcpy(&p_b[NRF_802154_AES_CCM_B0_FIELD_NONCE_OCTET],
p_frame->nonce,
NRF_802154_AES_CCM_NONCE_SIZE);
p_b[NRF_802154_AES_CCM_BLOCK_SIZE - 1] = (p_frame->plain_text_data_len & 0xFF);
p_b[NRF_802154_AES_CCM_BLOCK_SIZE - 2] = 0;
}
/**
* @brief Forms authentication flag
* IEEE std 802.15.4-2015, B.4.1.2 Authentication transformation
*
* @param[in] p_frame pointer to AES CCM frame structure
*
* @return Formatted authorization flags
*/
static uint8_t auth_flags_format(const nrf_802154_aes_ccm_data_t * p_frame)
{
uint8_t auth_flags = 0;
uint8_t m;
auth_flags |= (p_frame->auth_data_len == 0) ? 0 : NRF_802154_AES_CCM_ADATA_AUTH_FLAG;
m = m_mic_size[p_frame->mic_level];
m = (m > 0) ? (m - 2) >> 1 : 0;
auth_flags |= (m << NRF_802154_AES_CCM_M_BITS_AUTH_FLAG);
auth_flags |= NRF_802154_AES_CCM_L_VALUE - 1; // l value
return auth_flags;
}
/**
* @brief Forms additional authentication data from octet string a by 16-octet chunks
* IEEE std 802.15.4-2015, B.4.1.1 Input transformation
*
* @param[in] p_frame pointer to AES CCM frame structure
* @param[in] iter number of chunk
* @param[out] p_b pointer to memory for Bi
*
* @retval true Chunk was formated
* @retval false Otherwise
*/
static bool add_auth_data_get(const nrf_802154_aes_ccm_data_t * p_frame,
uint8_t iter,
uint8_t * p_b)
{
uint8_t offset = 0;
uint8_t len;
if (p_frame->auth_data_len == 0)
{
return false;
}
memset(p_b, 0, NRF_802154_AES_CCM_BLOCK_SIZE);
if (iter == 0)
{
len = MIN(p_frame->auth_data_len, NRF_802154_AES_CCM_BLOCK_SIZE - sizeof(uint16_t));
p_b[NRF_802154_AES_CCM_AUTH_DATA_LENGTH_OCTET] = (p_frame->auth_data_len & 0xFF00) >> 8;
p_b[NRF_802154_AES_CCM_AUTH_DATA_LENGTH_OCTET + 1] = (p_frame->auth_data_len & 0xFF);
memcpy(&p_b[NRF_802154_AES_CCM_AUTH_DATA_OCTET], p_frame->auth_data, len);
return true;
}
offset += NRF_802154_AES_CCM_BLOCK_SIZE - sizeof(uint16_t);
offset += NRF_802154_AES_CCM_BLOCK_SIZE * (iter - 1);
if (offset >= p_frame->auth_data_len)
{
return false;
}
len = MIN(p_frame->auth_data_len - offset, NRF_802154_AES_CCM_BLOCK_SIZE);
memcpy(p_b, p_frame->auth_data + offset, len);
return true;
}
/**
* @brief Forms plain/cipher text data from octet string m/c by 16-octet chunks
* IEEE std 802.15.4-2015, B.4.1.1 Input transformation
*
* @param[in] p_frame pointer to AES CCM frame structure
* @param[in] iter number of chunk
* @param[out] p_b pointer to memory for Bi
*
* @retval true Chunk was formated
* @retval false Otherwise
*/
static bool plain_text_data_get(const nrf_802154_aes_ccm_data_t * p_frame,
uint8_t iter,
uint8_t * p_b)
{
uint8_t offset = 0;
uint8_t len;
if (p_frame->plain_text_data_len == 0)
{
return false;
}
memset(p_b, 0, NRF_802154_AES_CCM_BLOCK_SIZE);
offset += NRF_802154_AES_CCM_BLOCK_SIZE * iter;
if (offset >= p_frame->plain_text_data_len)
{
return false;
}
len = MIN(p_frame->plain_text_data_len - offset, NRF_802154_AES_CCM_BLOCK_SIZE);
memcpy(p_b, p_frame->plain_text_data + offset, len);
return true;
}
/**
* @brief Block of Authorization Transformation iteration
*/
static inline void process_ecb_auth_iteration(void)
{
m_state.iteration++;
two_blocks_xor(mp_ecb_ciphertext, m_b, NRF_802154_AES_CCM_BLOCK_SIZE);
memcpy(mp_ecb_cleartext, mp_ecb_ciphertext, NRF_802154_AES_CCM_BLOCK_SIZE);
nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
}
/**
* @brief Block of Encryption Transformation iteration
*/
static inline void process_ecb_encrypt_iteration(void)
{
ai_format(&m_aes_ccm_data, m_state.iteration, m_a);
memcpy(mp_ecb_cleartext, m_a, NRF_802154_AES_CCM_BLOCK_SIZE);
nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
}
/**
* @brief helper function for plain text encryption in ECB IRQ
*/
static void perform_plain_text_encryption(void)
{
memcpy(m_auth_tag, mp_ecb_ciphertext, m_mic_size[m_aes_ccm_data.mic_level]);
m_state.iteration = 0;
m_state.transformation = PLAIN_TEXT_ENCRYPT;
if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_m))
{
m_state.iteration++;
process_ecb_encrypt_iteration();
}
else
{
if (m_mic_size[m_aes_ccm_data.mic_level] != 0)
{
process_ecb_encrypt_iteration();
m_state.transformation = CALCULATE_ENCRYPTED_TAG;
}
}
}
/**
* @brief helper function for plain text auth in ECB IRQ
*/
static void perform_plain_text_authorization(void)
{
if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_b))
{
process_ecb_auth_iteration();
}
else
{
perform_plain_text_encryption();
}
}
/**
* @brief Handler to ECB Interrupt Routine
* Performs AES-CCM* calculation in pipeline
*/
static void ecb_irq_handler(void)
{
uint8_t len = 0;
uint8_t offset;
if (nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ENDECB))
{
nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ENDECB);
switch (m_state.transformation)
{
case ADD_AUTH_DATA_AUTH:
if (add_auth_data_get(&m_aes_ccm_data, m_state.iteration, m_b))
{
process_ecb_auth_iteration();
}
else
{
m_state.iteration = 0;
m_state.transformation = PLAIN_TEXT_AUTH;
perform_plain_text_authorization();
}
break;
case PLAIN_TEXT_AUTH:
perform_plain_text_authorization();
break;
case PLAIN_TEXT_ENCRYPT:
two_blocks_xor(m_m, mp_ecb_ciphertext, NRF_802154_AES_CCM_BLOCK_SIZE);
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);
if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_m))
{
m_state.iteration++;
process_ecb_encrypt_iteration();
}
else
{
if (m_mic_size[m_aes_ccm_data.mic_level] != 0)
{
m_state.iteration = 0;
m_state.transformation = CALCULATE_ENCRYPTED_TAG;
process_ecb_encrypt_iteration();
}
else
{
m_aes_ccm_data.raw_frame = NULL;
}
}
break;
case CALCULATE_ENCRYPTED_TAG:
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 -
m_mic_size[m_aes_ccm_data.mic_level] +
1),
m_auth_tag,
m_mic_size[m_aes_ccm_data.mic_level]);
m_aes_ccm_data.raw_frame = NULL;
break;
default:
break;
}
}
}
/**
* @brief Start AES-CCM* Authorization Transformation
*/
static void start_ecb_auth_transformation(void)
{
memcpy((uint8_t *)nrf_ecb_data_pointer_get(NRF_ECB) + 16, m_x, 16);
m_state.iteration = 0;
m_state.transformation = ADD_AUTH_DATA_AUTH;
nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ENDECB);
nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
}
bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
{
// Verify that all necessary data is available
if (p_aes_ccm_data->raw_frame == NULL)
{
return false;
}
// Verify that the optional data, if exists, is complete
if (((p_aes_ccm_data->auth_data_len != 0) && (p_aes_ccm_data->auth_data == NULL)) ||
((p_aes_ccm_data->plain_text_data_len != 0) && (p_aes_ccm_data->plain_text_data == NULL)))
{
return false;
}
// Verify that the MIC level is valid
if (p_aes_ccm_data->mic_level > SECURITY_LEVEL_MIC_LEVEL_MASK)
{
return false;
}
// Store the encryption data for future use
memcpy(&m_aes_ccm_data, p_aes_ccm_data, sizeof(nrf_802154_aes_ccm_data_t));
return true;
}
void nrf_802154_aes_ccm_transform_start(const 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))
{
return;
}
uint8_t auth_flags = auth_flags_format(&m_aes_ccm_data);
uint8_t * p_x = m_x;
uint8_t * p_b = m_b;
// initial settings
memset(p_x, 0, NRF_802154_AES_CCM_BLOCK_SIZE);
b0_format(&m_aes_ccm_data, auth_flags, p_b);
two_blocks_xor(p_x, p_b, NRF_802154_AES_CCM_BLOCK_SIZE);
ecb_init();
memset(mp_ecb_key, 0, 48);
nrf_ecb_set_key(m_aes_ccm_data.key);
start_ecb_auth_transformation();
}

View File

@ -0,0 +1,87 @@
/*
* 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.
*
*/
#ifndef NRF_802154_AES_CCM_H_
#define NRF_802154_AES_CCM_H_
#include <stdbool.h>
#include <stdint.h>
#include "nrf_802154_const.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_802154_AES_CCM_L_VALUE 2 // Annex B3.2 Mode of operation d)
#define NRF_802154_AES_CCM_NONCE_SIZE (15 - NRF_802154_AES_CCM_L_VALUE) // Annex B4.1 CCM* mode encryption and authentication transformation b)
/**
* @brief Data necessary for a single AES-CCM* operation.
*/
typedef struct
{
uint8_t key[AES_CCM_KEY_SIZE]; ///< Pointer to AES-CCM* key
uint8_t * auth_data; ///< Pointer to AES-CCM* authorization data
uint64_t auth_data_len; ///< Length of AES-CCM* authorization data
uint8_t * plain_text_data; ///< Pointer to AES-CCM* plain text data for encryption and authorization
uint8_t plain_text_data_len; ///< Length of plain text data
uint8_t nonce[NRF_802154_AES_CCM_NONCE_SIZE]; ///< Pointer to AES-CCM* nonce
uint8_t mic_level; ///< Message Integrity Code level
uint8_t * raw_frame; ///< Pointer to the buffer that contains the PHR and PSDU of the transmitted frame.
} nrf_802154_aes_ccm_data_t;
/**
* @brief Prepares AES-CCM* transformation.
*
* @param[in] p_aes_ccm_data Data to be used for the AES-CCM* transformation.
*
* @retval true The transformation was prepared successfully and can be performed.
* @retval false Provided parameters do not allow for successful transformation.
*/
bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_aes_ccm_data);
/**
* @brief Starts AES-CCM* transformation.
*
* @note This function should not be called until the transformation is prepared with a call to
* @ref nrf_802154_aes_ccm_transform_prepare. Any call to this function that is not paired
* with an earlier prepare call will be ignored silently, i.e. the transformation will
* not be started at all.
*
* @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);
#endif // NRF_802154_AES_CCM_H_

View File

@ -121,6 +121,8 @@ 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 volatile radio_state_t m_state; ///< State of the radio driver.
@ -276,9 +278,9 @@ static uint32_t timer_coord_timestamp_get(void)
static void received_frame_notify(uint8_t * p_data)
{
nrf_802154_notify_received(p_data, // data
rssi_last_measurement_get(), // rssi
lqi_get(p_data)); // lqi
nrf_802154_notify_received(p_data, // data
m_last_rssi, // rssi
m_last_lqi); // lqi
}
/** Allow nesting critical sections and notify MAC layer that a frame was received. */
@ -313,6 +315,13 @@ static void transmit_started_notify(void)
}
/** Notify MAC layer that transmission of ACK frame has started. */
static void transmit_ack_started_notify()
{
nrf_802154_core_hooks_tx_ack_started(mp_ack);
nrf_802154_tx_ack_started(mp_ack);
}
#if !NRF_802154_DISABLE_BCC_MATCHING
/** Notify that reception of a frame has started. */
static void receive_started_notify(void)
@ -338,10 +347,8 @@ static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, uint8_t lqi)
}
/** Notify MAC layer that transmission procedure failed. */
static void transmit_failed_notify(nrf_802154_tx_error_t error)
static void transmit_failed_notify(const uint8_t * p_frame, nrf_802154_tx_error_t error)
{
const uint8_t * p_frame = mp_tx_data;
if (nrf_802154_core_hooks_tx_failed(p_frame, error))
{
nrf_802154_notify_transmit_failed(p_frame, error);
@ -353,7 +360,7 @@ static void transmit_failed_notify_and_nesting_allow(nrf_802154_tx_error_t error
{
nrf_802154_critical_section_nesting_allow();
transmit_failed_notify(error);
transmit_failed_notify(mp_tx_data, error);
nrf_802154_critical_section_nesting_deny();
}
@ -687,11 +694,11 @@ static void operation_terminated_notify(radio_state_t state, bool receiving_psdu
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
transmit_failed_notify(NRF_802154_TX_ERROR_ABORTED);
transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED);
break;
case RADIO_STATE_RX_ACK:
transmit_failed_notify(NRF_802154_TX_ERROR_ABORTED);
transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED);
break;
case RADIO_STATE_ED:
@ -1783,6 +1790,10 @@ void nrf_802154_trx_receive_frame_received(void)
uint8_t * p_received_data = mp_current_rx_buffer->data;
// Latch RSSI and LQI values before sending ACK
m_last_rssi = rssi_last_measurement_get();
m_last_lqi = lqi_get(p_received_data);
#if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
uint32_t receive_end_hp_timestamp = nrf_802154_hp_timer_timestamp_get();
uint32_t listening_start_hp_timestamp = m_listening_start_hp_timestamp;
@ -1963,7 +1974,7 @@ void nrf_802154_trx_transmit_ack_started(void)
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
assert(m_state == RADIO_STATE_TX_ACK);
nrf_802154_tx_ack_started(mp_ack);
transmit_ack_started_notify();
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
@ -2466,8 +2477,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,
bool cca,
bool immediate,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -2477,7 +2487,7 @@ bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl,
if (result)
{
// Short-circuit evaluation in place.
if ((immediate) || (nrf_802154_core_hooks_pre_transmission(p_data, cca)))
if (nrf_802154_core_hooks_pre_transmission(p_data, p_params, &transmit_failed_notify))
{
result = current_operation_terminate(term_lvl, req_orig, true);
@ -2485,16 +2495,16 @@ bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl,
{
m_coex_tx_request_mode = nrf_802154_pib_coex_tx_request_mode_get();
m_trx_transmit_frame_notifications_mask =
make_trx_frame_transmit_notification_mask(cca);
make_trx_frame_transmit_notification_mask(p_params->cca);
m_flags.tx_diminished_prio =
m_coex_tx_request_mode == NRF_802154_COEX_TX_REQUEST_MODE_CCA_DONE;
state_set(cca ? RADIO_STATE_CCA_TX : RADIO_STATE_TX);
state_set(p_params->cca ? RADIO_STATE_CCA_TX : RADIO_STATE_TX);
mp_tx_data = p_data;
// coverity[check_return]
result = tx_init(p_data, cca);
if (immediate)
result = tx_init(p_data, p_params->cca);
if (p_params->immediate)
{
if (!result)
{
@ -2796,6 +2806,16 @@ bool nrf_802154_core_last_rssi_measurement_get(int8_t * p_rssi)
return result;
}
int8_t nrf_802154_core_last_frame_rssi_get(void)
{
return m_last_rssi;
}
uint8_t nrf_802154_core_last_frame_lqi_get(void)
{
return m_last_lqi;
}
bool nrf_802154_core_antenna_update(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);

View File

@ -138,10 +138,7 @@ bool nrf_802154_core_receive(nrf_802154_term_t term_lvl,
* @param[in] term_lvl Termination level of this request. Selects procedures to abort.
* @param[in] req_orig Module that originates this request.
* @param[in] p_data Pointer to a frame to transmit.
* @param[in] cca If the driver is to perform CCA procedure before transmission.
* @param[in] immediate If true, the driver schedules transmission immediately or never.
* If false, the transmission may be postponed until
* the TX preconditions are met.
* @param[in] p_params Pointer to transmission parameters.
* @param[in] notify_function Function called to notify the status of this procedure. May be NULL.
*
* @retval true Entering the transmit state succeeded.
@ -150,8 +147,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,
bool cca,
bool immediate,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function);
/**
@ -250,6 +246,24 @@ bool nrf_802154_core_rssi_measure(void);
*/
bool nrf_802154_core_last_rssi_measurement_get(int8_t * p_rssi);
/**
* Get RSSI of the last received non-ACK frame.
*
* Returns 0 if no frame was received yet.
*
* @returns Temperature-corrected RSSI of the last received frame
*/
int8_t nrf_802154_core_last_frame_rssi_get(void);
/**
* Get LQI of the last received non-ACK frame.
*
* Returns 0 if no frame was received yet.
*
* @returns Temperature-corrected LQI of the last received frame
*/
uint8_t nrf_802154_core_last_frame_lqi_get(void);
/**
* @brief Notifies the core module that the next higher layer requested the change of the antenna.
*/

View File

@ -48,17 +48,23 @@
#include "mac_features/nrf_802154_ack_timeout.h"
#include "mac_features/nrf_802154_csma_ca.h"
#include "mac_features/nrf_802154_delayed_trx.h"
#include "mac_features/nrf_802154_ie_writer.h"
#include "mac_features/nrf_802154_security_writer.h"
#include "mac_features/nrf_802154_ifs.h"
#include "nrf_802154_encrypt.h"
#include "nrf_802154_config.h"
#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, bool cca);
typedef bool (* pre_transmission_hook)(const 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 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);
/* 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
@ -90,6 +96,15 @@ static const pre_transmission_hook m_pre_transmission_hooks[] =
{
#if NRF_802154_IFS_ENABLED
nrf_802154_ifs_pretransmission,
#endif
#if NRF_802154_IE_WRITER_ENABLED
nrf_802154_ie_writer_pretransmission,
#endif
#if NRF_802154_SECURITY_WRITER_ENABLED
nrf_802154_security_writer_pretransmission,
#endif
#if NRF_802154_ENCRYPTION_ENABLED
nrf_802154_encrypt_pretransmission,
#endif
NULL,
};
@ -128,6 +143,14 @@ static const tx_started_hook m_tx_started_hooks[] =
nrf_802154_ack_timeout_tx_started_hook,
#endif
#if NRF_802154_IE_WRITER_ENABLED
nrf_802154_ie_writer_tx_started_hook,
#endif
#if NRF_802154_ENCRYPTION_ENABLED
nrf_802154_encrypt_tx_started_hook,
#endif
NULL,
};
@ -149,6 +172,19 @@ static const rx_ack_started_hook m_rx_ack_started_hooks[] =
NULL,
};
static const tx_ack_started_hook m_tx_ack_started_hooks[] =
{
#if NRF_802154_IE_WRITER_ENABLED
nrf_802154_ie_writer_tx_ack_started_hook,
#endif
#if NRF_802154_ENCRYPTION_ENABLED
nrf_802154_encrypt_tx_ack_started_hook,
#endif
NULL,
};
bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_t req_orig)
{
bool result = true;
@ -171,7 +207,10 @@ bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_
return result;
}
bool nrf_802154_core_hooks_pre_transmission(const uint8_t * p_frame, bool cca)
bool nrf_802154_core_hooks_pre_transmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
bool result = true;
@ -183,7 +222,7 @@ bool nrf_802154_core_hooks_pre_transmission(const uint8_t * p_frame, bool cca)
break;
}
result = m_pre_transmission_hooks[i](p_frame, cca);
result = m_pre_transmission_hooks[i](p_frame, p_params, notify_function);
if (!result)
{
@ -277,3 +316,17 @@ void nrf_802154_core_hooks_rx_ack_started(void)
m_rx_ack_started_hooks[i]();
}
}
void nrf_802154_core_hooks_tx_ack_started(const uint8_t * p_ack)
{
for (uint32_t i = 0; i < sizeof(m_tx_ack_started_hooks) / sizeof(m_tx_ack_started_hooks[0]);
i++)
{
if (m_tx_ack_started_hooks[i] == NULL)
{
break;
}
m_tx_ack_started_hooks[i](p_ack);
}
}

View File

@ -65,15 +65,18 @@ bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_
/**
* @brief Processes hooks which are to fire before the transmission request.
*
* @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame
* that is to be transmitted.
* @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.
*
* @param[in] cca Whether to start with cca or not.
*
* @retval true Frame can be sent immediately.
* @retval false Hooks have handled the frame - upper layer should not worry about it anymore.
* @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_pre_transmission(const uint8_t * p_frame, bool cca);
bool nrf_802154_core_hooks_pre_transmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function);
/**
* @brief Processes hooks for the transmitted event.
@ -121,6 +124,14 @@ void nrf_802154_core_hooks_rx_started(const uint8_t * p_frame);
*/
void nrf_802154_core_hooks_rx_ack_started(void);
/**
* @brief Processes hooks for the TX ACK started event.
*
* @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);
/**
*@}
**/

View File

@ -0,0 +1,433 @@
/*
* 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 "nrf_802154_encrypt.h"
#include <assert.h>
#include <string.h>
#include "nrf_802154_aes_ccm.h"
#include "nrf_802154_const.h"
#include "nrf_802154_pib.h"
#include "nrf_802154_types.h"
#include "mac_features/nrf_802154_frame_parser.h"
#include "mac_features/nrf_802154_security_pib.h"
/**
* @brief Copies memory in reversed byte order.
*
* @note Source and destination buffers must not be NULL.
*
* @param[out] p_dst Pointer to the destination buffer.
* @param[in] p_src Pointer to the source buffer.
* @param[in] n The number of bytes to copy.
*/
static inline void memcpy_rev(void * p_dst, const void * p_src, size_t n)
{
for (size_t i = 0; i < n; i++)
{
*((uint8_t *)p_dst + i) = *((uint8_t *)p_src + n - 1 - i);
}
}
static uint8_t mic_length_from_security_level_get(uint8_t security_level)
{
switch (security_level)
{
case SECURITY_LEVEL_MIC_32:
case SECURITY_LEVEL_ENC_MIC_32:
return MIC_32_SIZE;
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;
default:
return 0;
}
}
static uint8_t mic_level_from_security_level_get(uint8_t security_level)
{
// According to the specification, two least significant bits of the security level
// indicate provided level of data authenticity
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)
{
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);
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;
break;
default:
result = false;
break;
}
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[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)
{
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,
};
return NRF_802154_SECURITY_ERROR_NONE ==
nrf_802154_security_pib_key_use(&key_id, p_aes_ccm_data->key);
}
/**
* @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.
*
* @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)
{
if ((p_frame == NULL) || (p_nonce == NULL))
{
return false;
}
const uint8_t * p_src_addr = nrf_802154_pib_extended_address_get();
uint8_t offset = 0;
memcpy_rev(p_nonce, p_src_addr, EXTENDED_ADDRESS_SIZE);
offset += EXTENDED_ADDRESS_SIZE;
// 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);
offset += FRAME_COUNTER_SIZE;
p_nonce[offset] = p_aux_sec_hdr->security_lvl;
return true;
}
/**
* @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_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 result;
switch (p_frame[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK)
{
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;
case FRAME_TYPE_COMMAND:
result =
command_frame_a_data_and_m_data_prepare(p_frame, p_aux_sec_hdr, p_aes_ccm_data);
break;
case FRAME_TYPE_BEACON:
// Fallthrough
case FRAME_TYPE_EXTENDED:
// Fallthrough
case FRAME_TYPE_FRAGMENT:
// Fallthrough
case FRAME_TYPE_MULTIPURPOSE:
// This frame type is currently unsupported.
result = false;
break;
default:
// No more frame types exist.
result = false;
assert(false);
break;
}
return result;
}
/**
* @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[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)
{
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))
{
// 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))
{
// 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))
{
// 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;
retval = true;
}
while (0);
return retval;
}
bool nrf_802154_encrypt_ack_prepare(const uint8_t * p_ack)
{
nrf_802154_aes_ccm_data_t aes_ccm_data;
bool success;
if (aes_ccm_data_content_prepare(p_ack, &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);
}
return success;
}
bool nrf_802154_encrypt_pretransmission(
const uint8_t * p_frame,
nrf_802154_transmit_params_t * p_params,
nrf_802154_transmit_failed_notification_t notify_function)
{
if (p_params->is_retransmission)
{
// Pass.
return true;
}
nrf_802154_aes_ccm_data_t aes_ccm_data;
bool success;
if (aes_ccm_data_content_prepare(p_frame, &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);
}
if (!success)
{
notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID);
}
return success;
}
bool nrf_802154_encrypt_tx_started_hook(const uint8_t * p_frame)
{
nrf_802154_aes_ccm_transform_start(p_frame);
return true;
}
void nrf_802154_encrypt_tx_ack_started_hook(const uint8_t * p_ack)
{
nrf_802154_aes_ccm_transform_start(p_ack);
}

View File

@ -0,0 +1,92 @@
/*
* 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.
*
*/
#ifndef NRF_802154_ENCRYPT_H_
#define NRF_802154_ENCRYPT_H_
#include <stdbool.h>
#include <stdint.h>
#include "nrf_802154_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @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.
*/
bool nrf_802154_encrypt_ack_prepare(const uint8_t * p_ack);
/**
* @brief Pretransmission hook for the encryption module.
*
* This hook prepares encryption data for provided frame.
*
* @param[in] p_frame Pointer to the buffer that contains the PHR and PSDU
* of the transmitted frame.
* @param[in] p_params Pointer to the transmission parameters.
* @param[in] notify_function Function to be called to notify transmission failure.
*
* @retval true Encryption was prepared successfully.
* @retval false Encryption prepare failed.
*/
bool nrf_802154_encrypt_pretransmission(
const 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 encryption module.
*
* This function triggers the transformation procedure of the provided frame.
*
* @param[in] p_frame Pointer to the buffer that contains a frame being transmitted.
*
* @retval true Always succeeds.
*/
bool nrf_802154_encrypt_tx_started_hook(const uint8_t * p_frame);
/**
* @brief ACK TX started hook for the encryption module.
*
* This function triggers the transformation procedure of the provided Ack.
*
* @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);
#endif /* NRF_802154_ENCRYPT_H_ */

View File

@ -2,6 +2,8 @@
* Copyright (c) 2017 - 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:
*
@ -12,7 +14,7 @@
* 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 the copyright holder nor the names of its
* 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.
*
@ -27,6 +29,7 @@
* 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.
*
*/
/**

View File

@ -92,10 +92,7 @@ bool nrf_802154_request_receive(nrf_802154_term_t term_lvl,
* @param[in] term_lvl Termination level of this request. Selects procedures to abort.
* @param[in] req_orig Module that originates this request.
* @param[in] p_data Pointer to the frame to transmit.
* @param[in] cca If the driver is to perform the CCA procedure before transmission.
* @param[in] immediate If true, the driver schedules transmission immediately or never.
* If false, the transmission can be postponed until the TX
* preconditions are met.
* @param[in] p_params Pointer to transmission parameters.
* @param[in] notify_function Function called to notify the status of this procedure. May be NULL.
*
* @retval true The driver will enter the transmit state.
@ -104,8 +101,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,
bool cca,
bool immediate,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function);
/**

View File

@ -87,16 +87,14 @@ 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,
bool cca,
bool immediate,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function)
{
REQUEST_FUNCTION_PARMS(nrf_802154_core_transmit,
term_lvl,
req_orig,
p_data,
cca,
immediate,
p_params,
notify_function)
}

View File

@ -116,8 +116,7 @@ typedef struct
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.
bool cca; ///< If CCA was requested prior to transmission.
bool immediate; ///< If TX procedure must be performed immediately.
nrf_802154_transmit_params_t * p_params; ///< Pointer to transmission parameters.
bool * p_result; ///< Transmit request result.
} transmit; ///< Transmit request details.
@ -325,10 +324,7 @@ static void swi_receive(nrf_802154_term_t term_lvl,
* @param[in] req_orig Module that originates this request.
* @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the frame to be
* transmitted.
* @param[in] cca If the driver should perform the CCA procedure before transmission.
* @param[in] immediate If true, the driver schedules transmission immediately or never;
* if false, the transmission may be postponed until TX preconditions
* are met.
* @param[in] p_params Pointer to transmission parameters.
* @param[in] notify_function Function called to notify the status of this procedure instead of
* the default notification. If NULL, the default notification
* is used.
@ -337,8 +333,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,
bool cca,
bool immediate,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function,
bool * p_result)
{
@ -348,8 +343,7 @@ static void swi_transmit(nrf_802154_term_t term_lvl,
p_slot->data.transmit.term_lvl = term_lvl;
p_slot->data.transmit.req_orig = req_orig;
p_slot->data.transmit.p_data = p_data;
p_slot->data.transmit.cca = cca;
p_slot->data.transmit.immediate = immediate;
p_slot->data.transmit.p_params = p_params;
p_slot->data.transmit.notif_func = notify_function;
p_slot->data.transmit.p_result = p_result;
@ -568,8 +562,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,
bool cca,
bool immediate,
nrf_802154_transmit_params_t * p_params,
nrf_802154_notification_func_t notify_function)
{
REQUEST_FUNCTION(nrf_802154_core_transmit,
@ -577,8 +570,7 @@ bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl,
term_lvl,
req_orig,
p_data,
cca,
immediate,
p_params,
notify_function)
}
@ -673,8 +665,7 @@ static void irq_handler_req_event(void)
nrf_802154_core_transmit(p_slot->data.transmit.term_lvl,
p_slot->data.transmit.req_orig,
p_slot->data.transmit.p_data,
p_slot->data.transmit.cca,
p_slot->data.transmit.immediate,
p_slot->data.transmit.p_params,
p_slot->data.transmit.notif_func);
break;

View File

@ -34,6 +34,10 @@
#define NRF_802154_MODULE_ID NRF_802154_DRV_MODULE_ID_TRX_PPI
#include "nrf.h"
#ifdef NRF53_SERIES
#include "nrf_802154_trx_ppi_api.h"
#include "nrf_802154_debug_log.h"
@ -235,3 +239,5 @@ void nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)
}
#endif
#endif // NRF53_SERIES

View File

@ -34,6 +34,10 @@
#define NRF_802154_MODULE_ID NRF_802154_DRV_MODULE_ID_TRX_PPI
#include "nrf.h"
#ifdef NRF52_SERIES
#include "nrf_802154_trx_ppi_api.h"
#include <stdbool.h>
@ -280,3 +284,5 @@ void nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)
}
#endif
#endif // NRF52_SERIES

View File

@ -37,6 +37,7 @@
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "nrf.h"
#include <nrfx.h>
#include <soc/nrfx_coredep.h>

View File

@ -0,0 +1,327 @@
/*
* 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 <stdint.h>
#include <string.h>
#include <assert.h>
#ifndef NRF_802154_UTILS_BYTEORDER_H
#define NRF_802154_UTILS_BYTEORDER_H
/**
* @defgroup nrf_802154_utils_byteorder Utils definitions for byte ordering used in the 802.15.4 driver
* @{
* @ingroup nrf_802154
* @brief Definitions of utils for byte ordering used in the 802.15.4 driver.
*/
#if !defined(__BYTE_ORDER__)
/* Couldn't determine endian-ness of the target machine. */
#error "Please define __BYTE_ORDER__!"
#elif defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
/**@brief Write 64-bit value from host byte-order to little-endian byte array.
*
* @param[in] value A 64-bit host-order value to write
* @param[out] p_buffer A little-endian byte array to be populated
*/
static inline void host_64_to_little(uint64_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
memcpy(p_buffer, &value, sizeof(uint64_t));
}
/**@brief Write 32-bit value from host byte-order to little-endian byte array.
*
* @param[in] value A 32-bit host-order value to write
* @param[out] p_buffer A little-endian byte array to be populated
*/
static inline void host_32_to_little(uint32_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
memcpy(p_buffer, &value, sizeof(uint32_t));
}
/**@brief Write 24-bit value from host byte-order to little-endian byte array.
*
* @param[in] value A 32-bit host-order value, whose lower 24 bits will be copied
* @param[out] p_buffer A little-endian byte array to be populated
*/
static inline void host_24_to_little(uint32_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
memcpy(p_buffer, &value, 3);
}
/**@brief Write 16-bit value from host byte-order to little-endian byte array.
*
* @param[in] value A 16-bit host-order value to write
* @param[out] p_buffer A little-endian byte array to be populated
*/
static inline void host_16_to_little(uint16_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
memcpy(p_buffer, &value, sizeof(uint16_t));
}
/**@brief Convert 64-bit value from little-endian byte array to host-order value.
*
* @param[in] p_buffer A little-endian byte array to be read
*
* @returns A 64-bit host-order value
*/
static inline uint64_t little_64_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint64_t value = 0;
memcpy(&value, p_buffer, sizeof(uint64_t));
return value;
}
/**@brief Convert 32-bit value from little-endian byte array to host-order value.
*
* @param[in] p_buffer A little-endian byte array to be read
*
* @returns A 32-bit host-order value
*/
static inline uint32_t little_32_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint32_t value = 0;
memcpy(&value, p_buffer, sizeof(uint32_t));
return value;
}
/**@brief Convert 24-bit value from little-endian byte array to host-order value.
*
* @param[in] p_buffer A little-endian byte array to be read
*
* @returns A 24-bit host-order value
*/
static inline uint32_t little_24_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint32_t value = 0;
memcpy(&value, p_buffer, 3);
return value;
}
/**@brief Convert 16-bit value from little-endian byte array to host-order value.
*
* @param[in] p_buffer A little-endian byte array to be read
*
* @returns A 16-bit host-order value
*/
static inline uint16_t little_16_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint16_t value = 0;
memcpy(&value, p_buffer, sizeof(uint16_t));
return value;
}
/**@brief Write 64-bit value from host byte-order to big-endian byte array.
*
* @param[in] value A 64-bit host-order value to write
* @param[out] p_buffer A big-endian byte array to be populated
*/
static inline void host_64_to_big(uint64_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint8_t shift = (sizeof(uint64_t) - 1) * 8;
for (uint8_t i = 0; i < sizeof(uint64_t); i++, shift -= 8)
{
p_buffer[i] = (value >> shift) & 0xff;
}
}
/**@brief Write 32-bit value from host byte-order to big-endian byte array.
*
* @param[in] value A 32-bit host-order value to write
* @param[out] p_buffer A big-endian byte array to be populated
*/
static inline void host_32_to_big(uint32_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint8_t shift = (sizeof(uint32_t) - 1) * 8;
for (uint8_t i = 0; i < sizeof(uint32_t); i++, shift -= 8)
{
p_buffer[i] = (value >> shift) & 0xff;
}
}
/**@brief Write 24-bit value from host byte-order to big-endian byte array.
*
* @param[in] value A 24-bit host-order value to write
* @param[out] p_buffer A big-endian byte array to be populated
*/
static inline void host_24_to_big(uint32_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint8_t shift = (sizeof(uint32_t) - 2) * 8;
for (uint8_t i = 0; i < sizeof(uint32_t) - 1; i++, shift -= 8)
{
p_buffer[i] = (value >> shift) & 0xff;
}
}
/**@brief Write 16-bit value from host byte-order to big-endian byte array.
*
* @param[in] value A 16-bit host-order value to write
* @param[out] p_buffer A big-endian byte array to be populated
*/
static inline void host_16_to_big(uint16_t value, uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint8_t shift = (sizeof(uint16_t) - 1) * 8;
for (uint8_t i = 0; i < sizeof(uint16_t); i++, shift -= 8)
{
p_buffer[i] = (value >> shift) & 0xff;
}
}
/**@brief Convert 64-bit value from big-endian byte array to host-order value.
*
* @param[in] p_buffer A big-endian byte array to be read
*
* @returns A 64-bit host-order value
*/
static inline uint64_t big_64_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint64_t value = 0;
for (uint8_t i = 0; i < sizeof(uint64_t); i++)
{
value = (value << 8) | p_buffer[i];
}
return value;
}
/**@brief Convert 32-bit value from big-endian byte array to host-order value.
*
* @param[in] p_buffer A big-endian byte array to be read
*
* @returns A 32-bit host-order value
*/
static inline uint32_t big_32_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint32_t value = 0;
for (uint8_t i = 0; i < sizeof(uint32_t); i++)
{
value = (value << 8) | p_buffer[i];
}
return value;
}
/**@brief Convert 24-bit value from big-endian byte array to host-order value.
*
* @param[in] p_buffer A big-endian byte array to be read
*
* @returns A 24-bit host-order value
*/
static inline uint32_t big_24_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint32_t value = 0;
for (uint8_t i = 0; i < sizeof(uint32_t) - 1; i++)
{
value = (value << 8) | p_buffer[i];
}
return value;
}
/**@brief Convert 16-bit value from big-endian byte array to host-order value.
*
* @param[in] p_buffer A big-endian byte array to be read
*
* @returns A 16-bit host-order value
*/
static inline uint16_t big_16_to_host(uint8_t * p_buffer)
{
assert(p_buffer != NULL);
uint16_t value = 0;
for (uint8_t i = 0; i < sizeof(uint16_t); i++)
{
value = (value << 8) | p_buffer[i];
}
return value;
}
#else
/* Most likely the case of big-endian machine. */
#error "Unsupported endian-ness of the target machine"
#endif // __BYTE_ORDER__
/**
*@}
**/
#endif // NRF_802154_UTILS_BYTEORDER_H

View File

@ -42,43 +42,17 @@
#define _POSIX_C_SOURCE 1 // Enable access to POSIX functions (rand_r is not from the std library)
#include "nrf_802154_random.h"
#include "platform/nrf_802154_random.h"
#include <stdlib.h>
#include <stdint.h>
#include "nrf.h"
#if RAAL_SOFTDEVICE
#if defined (__GNUC__)
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wreturn-type\"")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
_Pragma("GCC diagnostic ignored \"-Wpedantic\"")
#endif
#include <nrf_soc.h>
#if defined (__GNUC__)
_Pragma("GCC diagnostic pop")
#endif
#endif // RAAL_SOFTDEVICE
unsigned int m_seed;
void nrf_802154_random_init(void)
{
#if RAAL_SOFTDEVICE
uint32_t result;
do
{
result = sd_rand_application_vector_get((uint8_t *)&m_seed, sizeof(m_seed));
}
while (result != NRF_SUCCESS);
#else // RAAL_SOFTDEVICE
NRF_RNG->TASKS_START = 1;
while (!NRF_RNG->EVENTS_VALRDY);
@ -86,7 +60,6 @@ void nrf_802154_random_init(void)
NRF_RNG->TASKS_STOP = 1;
m_seed = NRF_RNG->VALUE;
#endif // RAAL_SOFTDEVICE
}
void nrf_802154_random_deinit(void)

View File

@ -40,43 +40,17 @@
*
*/
#include "nrf_802154_random.h"
#include "platform/nrf_802154_random.h"
#include <stdlib.h>
#include <stdint.h>
#include "nrf.h"
#if RAAL_SOFTDEVICE
#if defined (__GNUC__)
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wreturn-type\"")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
_Pragma("GCC diagnostic ignored \"-Wpedantic\"")
#endif
#include <nrf_soc.h>
#if defined (__GNUC__)
_Pragma("GCC diagnostic pop")
#endif
#endif // RAAL_SOFTDEVICE
void nrf_802154_random_init(void)
{
uint32_t seed;
#if RAAL_SOFTDEVICE
uint32_t result;
do
{
result = sd_rand_application_vector_get((uint8_t *)&seed, sizeof(seed));
}
while (result != NRF_SUCCESS);
#else // RAAL_SOFTDEVICE
NRF_RNG->TASKS_START = 1;
while (!NRF_RNG->EVENTS_VALRDY);
@ -84,7 +58,6 @@ void nrf_802154_random_init(void)
NRF_RNG->TASKS_STOP = 1;
seed = NRF_RNG->VALUE;
#endif // RAAL_SOFTDEVICE
srand((unsigned int)seed);
}

View File

@ -1,8 +1,36 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# 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.
#
#
target_include_directories(nrf-802154-serialization-interface
INTERFACE

View File

@ -390,6 +390,32 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca);
*/
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);
/**
* @brief Notifies the driver that the buffer containing the received frame is not used anymore.
*
@ -429,10 +455,20 @@ int8_t nrf_802154_tx_power_get(void);
int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level);
/**
* @brief Gets nRF 802.15.4 Radio Diver Capabilities.
* @brief Gets nRF 802.15.4 Radio Driver Capabilities.
*
* @return Capabilities of the radio driver.
*/
nrf_802154_capabilities_t nrf_802154_capabilities_get(void);
/**
* @brief Gets the current time.
*
* The time returned by this function is to be used to calculate timing parameters for
* @ref nrf_802154_transmit_at and @ref nrf_802154_receive_at functions.
*
* @returns Current time in microseconds.
*/
uint32_t nrf_802154_time_get(void);
#endif

View File

@ -33,7 +33,7 @@
*/
/**@file nrf_802154_callouts.h
* @brief Provides function prototypes required by nRF 802.15.4 Radio Diver
* @brief Provides function prototypes required by nRF 802.15.4 Radio Driver
*
* Functions whose prototypes are defined in this file are to be implemented
* by an application using the nRF 802.15.4 Radio Driver.

View File

@ -125,6 +125,7 @@ typedef uint8_t nrf_802154_src_addr_match_t;
* - @ref NRF_802154_CAPABILITY_ANT_DIVERSITY,
* - @ref NRF_802154_CAPABILITY_IFS,
* - @ref NRF_802154_CAPABILITY_TIMESTAMP
* - @ref NRF_802154_CAPABILITY_SECURITY
*
*/
typedef uint32_t nrf_802154_capabilities_t;
@ -136,6 +137,7 @@ typedef uint32_t nrf_802154_capabilities_t;
#define NRF_802154_CAPABILITY_ANT_DIVERSITY (1UL << 4UL) // !< Antenna diversity supported
#define NRF_802154_CAPABILITY_IFS (1UL << 5UL) // !< Inter-frame spacing supported
#define NRF_802154_CAPABILITY_TIMESTAMP (1UL << 6UL) // !< Frame timestamping supported
#define NRF_802154_CAPABILITY_SECURITY (1UL << 7UL) // !< Frame security supported
/**
*@}

View File

@ -266,6 +266,19 @@ typedef enum
*/
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_CLEAR =
SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 33,
/**
* Vendor property for nrf_802154_time_get serialization.
*/
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;
/**
@ -537,6 +550,12 @@ typedef enum
#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */
/**
* @brief Spinel data type description for nrf_802154_retransmit_csma_ca_raw.
*/
#define SPINEL_DATATYPE_NRF_802154_RETRANSMIT_CSMA_CA_RAW \
SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */
/**
* @brief Spinel data type description for nrf_802154_transmitted_raw.
*/
@ -563,6 +582,16 @@ typedef enum
*/
#define SPINEL_DATATYPE_NRF_802154_CAPABILITIES_GET_RET SPINEL_DATATYPE_UINT32_S
/**
* @brief Spinel data type description for nrf_802154_time_get.
*/
#define SPINEL_DATATYPE_NRF_802154_TIME_GET SPINEL_DATATYPE_NULL_S
/**
* @brief Spinel data type description for nrf_802154_time_get_ret.
*/
#define SPINEL_DATATYPE_NRF_802154_TIME_GET_RET SPINEL_DATATYPE_UINT32_S
#ifdef __cplusplus
}
#endif

View File

@ -127,6 +127,21 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_capabilities_get_r
size_t property_data_len,
nrf_802154_capabilities_t * p_capabilities);
/**
* @brief Decode SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET.
*
* @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_property_data buffer.
* @param[out] p_capabilities Decoded capabilities.
*
* @returns zero on success or negative error value on failure.
*
*/
nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret(
const void * p_property_data,
size_t property_data_len,
uint32_t * p_time);
/**
* @brief Decode and dispatch SPINEL_CMD_PROP_VALUE_IS.
*

View File

@ -49,10 +49,10 @@
static uint8_t * buffer_alloc(nrf_802154_buffer_t * p_buffer_pool, size_t buffer_pool_len)
{
nrf_802154_buffer_t * p_buffer = NULL;
bool success = false;
bool retry = false;
uint32_t crit_sect;
nrf_802154_buffer_t * p_buffer = NULL;
bool success = false;
bool retry = false;
uint32_t crit_sect = 0UL;
do
{
@ -96,8 +96,8 @@ static void buffer_free(nrf_802154_buffer_t * p_buffer_to_free,
nrf_802154_buffer_t * p_buffer_pool,
size_t buffer_pool_len)
{
uint32_t crit_sect;
size_t idx =
uint32_t crit_sect = 0UL;
size_t idx =
((uintptr_t)p_buffer_to_free - (uintptr_t)p_buffer_pool) / sizeof(nrf_802154_buffer_t);
assert(idx < buffer_pool_len);

View File

@ -95,7 +95,7 @@ void nrf_802154_kvmap_init(nrf_802154_kvmap_t * p_kvmap,
bool nrf_802154_kvmap_add(nrf_802154_kvmap_t * p_kvmap, const void * p_key, const void * p_value)
{
uint32_t crit_sect;
uint32_t crit_sect = 0UL;
size_t idx;
bool success = true;
@ -132,7 +132,7 @@ bool nrf_802154_kvmap_add(nrf_802154_kvmap_t * p_kvmap, const void * p_key, cons
bool nrf_802154_kvmap_remove(nrf_802154_kvmap_t * p_kvmap, const void * p_key)
{
uint32_t crit_sect;
uint32_t crit_sect = 0UL;
size_t idx;
bool success = true;
@ -171,7 +171,7 @@ bool nrf_802154_kvmap_search(const nrf_802154_kvmap_t * p_kvmap,
const void * p_key,
void * p_value)
{
uint32_t crit_sect;
uint32_t crit_sect = 0UL;
size_t idx;
bool success = true;

View File

@ -279,6 +279,49 @@ bail:
return error;
}
/**
* @brief Wait with timeout for time property to be received.
*
* @param[in] timeout Timeout in us.
* @param[out] p_time Pointer to the time variable which needs to be populated.
*
* @returns zero on success or negative error value on failure.
*
*/
static nrf_802154_ser_err_t time_await(uint32_t timeout,
uint32_t * p_time)
{
nrf_802154_ser_err_t res;
nrf_802154_spinel_notify_buff_t * p_notify_data = NULL;
SERIALIZATION_ERROR_INIT(error);
p_notify_data = nrf_802154_spinel_response_notifier_property_await(
timeout);
SERIALIZATION_ERROR_IF(p_notify_data == NULL,
NRF_802154_SERIALIZATION_ERROR_RESPONSE_TIMEOUT,
error,
bail);
res = nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret(p_notify_data->data,
p_notify_data->data_len,
p_time);
SERIALIZATION_ERROR_CHECK(res, error, bail);
NRF_802154_SPINEL_LOG_BANNER_RESPONSE();
NRF_802154_SPINEL_LOG_VAR_NAMED("%lu", *p_time, "Time");
bail:
if (p_notify_data != NULL)
{
nrf_802154_spinel_response_notifier_free(p_notify_data);
}
return error;
}
void nrf_802154_init(void)
{
nrf_802154_serialization_init();
@ -844,6 +887,40 @@ bail:
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)
{
nrf_802154_ser_err_t res;
@ -1016,6 +1093,34 @@ bail:
return caps;
}
uint32_t nrf_802154_time_get(void)
{
int32_t res;
uint32_t time;
SERIALIZATION_ERROR_INIT(error);
NRF_802154_SPINEL_LOG_BANNER_CALLING();
nrf_802154_spinel_response_notifier_lock_before_request(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET);
res = nrf_802154_spinel_send_cmd_prop_value_set(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET,
SPINEL_DATATYPE_NRF_802154_TIME_GET,
NULL);
SERIALIZATION_ERROR_CHECK(res, error, bail);
res = time_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, &time);
SERIALIZATION_ERROR_CHECK(res, error, bail);
bail:
SERIALIZATION_ERROR_RAISE_IF_FAILED(error);
return time;
}
int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level)
{
return ED_MIN_DBM + (energy_level / ED_RESULT_FACTOR);

View File

@ -473,6 +473,20 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_capabilities_get_r
NRF_802154_SERIALIZATION_ERROR_OK);
}
nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret(
const void * p_property_data,
size_t property_data_len,
uint32_t * p_time)
{
spinel_ssize_t siz = spinel_datatype_unpack(p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_TIME_GET_RET,
p_time);
return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE :
NRF_802154_SERIALIZATION_ERROR_OK);
}
nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is(
const void * p_cmd_data,
size_t cmd_data_len)
@ -512,6 +526,8 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is(
// fall through
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CAPABILITIES_GET:
// fall through
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET:
// fall through
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_SET:
// fall through
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_CLEAR:

View File

@ -694,6 +694,52 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_csma_ca_raw(
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)
{
return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
}
// 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);
}
/**
* @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW.
*
@ -873,6 +919,30 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_capabilities_get(
caps);
}
/**
* @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TIME_GET.
*
* @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_time_get(
const void * p_property_data,
size_t property_data_len)
{
(void)p_property_data;
(void)property_data_len;
uint32_t time;
time = nrf_802154_time_get();
return nrf_802154_spinel_send_cmd_prop_value_is(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET,
SPINEL_DATATYPE_NRF_802154_TIME_GET_RET,
time);
}
nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_cmd_data,
size_t cmd_data_len)
{
@ -962,6 +1032,10 @@ 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);
@ -973,6 +1047,10 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_
return spinel_decode_prop_nrf_802154_capabilities_get(p_property_data,
property_data_len);
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET:
return spinel_decode_prop_nrf_802154_time_get(p_property_data,
property_data_len);
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_SET:
return spinel_decode_prop_nrf_802154_ack_data_set(p_property_data,
property_data_len);

View File

@ -1,8 +1,36 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# 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.
#
#
target_include_directories(nrf-802154-driver-interface INTERFACE include)

View File

@ -286,6 +286,17 @@ bool nrf_802154_rsch_delayed_timeslot_cancel(rsch_dly_ts_id_t dly_ts_id);
bool nrf_802154_rsch_delayed_timeslot_priority_update(rsch_dly_ts_id_t dly_ts_id,
rsch_prio_t dly_ts_prio);
/**
* @brief Retrieves the remaining time until a requested timeslot begins.
*
* @param[in] dly_ts_id ID of the requested timeslot.
* @param[out] p_time_to_start Pointer to a 32-bit variable where time to start will be stored.
*
* @retval true The given timeslot was scheduled and p_time_to_start contains a valid value.
* @retval false The given timeslot was not scheduled and p_time_to_start was not modified.
*/
bool nrf_802154_rsch_delayed_timeslot_time_to_start_get(rsch_dly_ts_id_t dly_ts_id,
uint32_t * p_time_to_start);
/**
* @brief Checks if there is a pending timeslot request.
*

View File

@ -1,8 +1,36 @@
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# 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.
#
#
target_include_directories(nrf-802154-driver-interface INTERFACE include)

View File

@ -2,30 +2,33 @@
* 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.
* 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.
* 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.
* 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.
* 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.
*
*/

View File

@ -2,30 +2,33 @@
* Copyright (c) 2019 - 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.
* 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.
* 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.
* 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.
* 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.
*
*/