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:
parent
d533671f46
commit
74b3b21f60
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
¶ms,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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__
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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__
|
|
@ -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,
|
||||
¶ms,
|
||||
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,
|
||||
¶ms,
|
||||
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, ¶ms, 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, ¶ms, 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
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "nrf.h"
|
||||
#include <nrfx.h>
|
||||
#include <soc/nrfx_coredep.h>
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
*@}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in New Issue