diff --git a/libraries/nfc/examples/SendText/SendText.ino b/libraries/nfc/examples/SendText/SendText.ino new file mode 100644 index 000000000..dce3444dd --- /dev/null +++ b/libraries/nfc/examples/SendText/SendText.ino @@ -0,0 +1,27 @@ +/* + SendText.ino + + Written by Chiara Ruggeri (chiara@arduino.org) + + This example for the Arduino Primo board shows how to use + NFC library. + It sets a text message specifying the language code, then + starts the module, so that when a device with NFC is near + to the board the message "Hello World!" will be sent. + + This example code is in the public domain. + +*/ + +#include + +void setup() { + // set the NFC message as first parameter and the language code as second + NFC.setTXTmessage("Hello World!", "en"); + // start the NFC module + NFC.start(); +} + +void loop() { + +} diff --git a/libraries/nfc/examples/SendURL/SendURL.ino b/libraries/nfc/examples/SendURL/SendURL.ino new file mode 100644 index 000000000..9fd20c85f --- /dev/null +++ b/libraries/nfc/examples/SendURL/SendURL.ino @@ -0,0 +1,62 @@ +/* + SendURL.ino + + Written by Chiara Ruggeri (chiara@arduino.org) + + This example for the Arduino Primo board shows how to use + NFC library. + It sets an URI message and then starts the module, so that + when a device with NFC is near to the board the message + http://www.arduino.org will be sent. + A list of all possible URI message can be found here: + + NFC_URI_HTTP_WWW "http://www." + NFC_URI_HTTPS_WWW "https://www." + NFC_URI_HTTP "http:" + NFC_URI_HTTPS "https:" + NFC_URI_TEL "tel:" + NFC_URI_MAILTO "mailto:" + NFC_URI_FTP_ANONYMOUS "ftp://anonymous:anonymous@" + NFC_URI_FTP_FTP "ftp://ftp." + NFC_URI_FTPS "ftps://" + NFC_URI_SFTP, "sftp://" + NFC_URI_SMB "smb://" + NFC_URI_NFS "nfs://" + NFC_URI_FTP "ftp://" + NFC_URI_DAV "dav://" + NFC_URI_NEWS "news:" + NFC_URI_TELNET "telnet://" + NFC_URI_IMAP "imap:" + NFC_URI_RTSP "rtsp://" + NFC_URI_URN "urn:" + NFC_URI_POP "pop:" + NFC_URI_SIP "sip:" + NFC_URI_SIPS "sips:" + NFC_URI_TFTP "tftp:" + NFC_URI_BTSPP "btspp://" + NFC_URI_BTL2CAP "btl2cap://" + NFC_URI_BTGOEP "btgoep://" + NFC_URI_TCPOBEX "tcpobex://" + NFC_URI_IRDAOBEX "irdaobex://" + NFC_URI_FILE "file://" + NFC_URI_URN_EPC_ID "urn:epc:id:" + NFC_URI_URN_EPC_TAG "urn:epc:tag:" + NFC_URI_URN_EPC_PAT "urn:epc:pat:" + NFC_URI_URN_EPC_RAW "urn:epc:raw:" + NFC_URI_URN_EPC "urn:epc:" + NFC_URI_URN_NFC "urn:nfc:" + + This example code is in the public domain. + +*/ + +#include + +void setup() { + NFC.setURImessage("arduino.org", NFC_URI_HTTP_WWW); + NFC.start(); +} + + +void loop() { +} \ No newline at end of file diff --git a/libraries/nfc/examples/StartApp/StartApp.ino b/libraries/nfc/examples/StartApp/StartApp.ino new file mode 100644 index 000000000..0aabca21c --- /dev/null +++ b/libraries/nfc/examples/StartApp/StartApp.ino @@ -0,0 +1,60 @@ +/* + SendText.ino + + Written by Chiara Ruggeri (chiara@arduino.org) + + This example for the Arduino Primo board shows how to use + NFC library. + It sets a app message specifying the package name (for Android) + and the ID application (for Windows phone), then starts the + module, so that when a device with NFC is near to the board + it will try to open the application (if present) or will + look for the app in the store. Finally it register a callback + function that will be called any time an NFC field is detected + (it means that a device is near). + + This example code is in the public domain. + +*/ + +#include + +//specify the package name for windows and android phone and insert the EOL character at the end '\0' +static const char android_package_name[] = {'n', 'o', '.', 'n', 'o', 'r', 'd', 'i', 'c', 's', + 'e', 'm', 'i', '.', 'a', 'n', 'd', 'r', 'o', 'i', + 'd', '.', 'n', 'r', 'f', 't', 'o', 'o', 'l', 'b', + 'o', 'x', '\0'}; + +static const char windows_application_id[] = {'{', 'e', '1', '2', 'd', '2', 'd', 'a', '7', '-', + '4', '8', '8', '5', '-', '4', '0', '0', 'f', '-', + 'b', 'c', 'd', '4', '-', '6', 'c', 'b', 'd', '5', + 'b', '8', 'c', 'f', '6', '2', 'c', '}', '\0'}; + +void setup() { + Serial.begin(9600); + NFC.setAPPmessage(android_package_name, windows_application_id); + NFC.start(); + NFC.registerCallback(myFunction); +} + + +void loop() { +} + +void myFunction(void *context, nfc_t2t_event_t event, const uint8_t *data, size_t dataLength){ + (void)context; + + switch (event) + { + case NFC_T2T_EVENT_FIELD_ON: + Serial.println("******NFC_T2T_EVENT_FIELD_ON******"); + break; + + case NFC_T2T_EVENT_FIELD_OFF: + Serial.println("------NFC_T2T_EVENT_FIELD_OFF------"); + break; + + default: + break; + } +} diff --git a/libraries/nfc/keywords.txt b/libraries/nfc/keywords.txt new file mode 100644 index 000000000..c90fe1d68 --- /dev/null +++ b/libraries/nfc/keywords.txt @@ -0,0 +1,24 @@ +####################################### +# Syntax Coloring Map NFC +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +NFC KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +start KEYWORD2 +stop KEYWORD2 +setTXTmessage KEYWORD2 +setURImessage KEYWORD2 +setAPPmessage KEYWORD2 +setOobPairingKey KEYWORD2 +registerCallback KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/nfc/library.properties b/libraries/nfc/library.properties new file mode 100644 index 000000000..be39397a0 --- /dev/null +++ b/libraries/nfc/library.properties @@ -0,0 +1,11 @@ +name=NFC +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Allows Arduino Primo boards to use the NFC tag onboard +paragraph= +category=Communication +url=http://www.arduino.org/learning/reference/NFC +includes=NFC.h +architectures=nrf52 +precompiled=true \ No newline at end of file diff --git a/libraries/nfc/src/NFC.cpp b/libraries/nfc/src/NFC.cpp new file mode 100644 index 000000000..d46c5ed1c --- /dev/null +++ b/libraries/nfc/src/NFC.cpp @@ -0,0 +1,158 @@ +/* + NFC class for nRF52. + Written by Chiara Ruggeri (chiara@arduino.org) + + Copyright (c) 2016 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Enjoy! +*/ + + +#include "NFC.h" +#include +void nfc_callback(void *context, nfc_t2t_event_t event, const uint8_t *data, size_t dataLength) +{ + NFC.onService(context,event,data,dataLength); + switch (event) { + case NFC_T2T_EVENT_FIELD_ON: + pinMode(LED_RED, OUTPUT); + digitalWrite(LED_RED, LOW); + break; + case NFC_T2T_EVENT_FIELD_OFF: + pinMode(LED_RED, OUTPUT); + digitalWrite(LED_RED, HIGH); + break; + default: + break; + } +} + + +uint8_t ndef_msg_buf[256]; + +void NFCClass::setTXTmessage(const char TXTMessage[], const char language[]){ + + nfc_t2t_setup(nfc_callback, NULL); + uint32_t len = sizeof(ndef_msg_buf); + uint8_t sizeM=strlen(TXTMessage); + uint8_t sizeL=strlen(language); + + NFC_NDEF_MSG_DEF(welcome_msg, 1); + NFC_NDEF_TEXT_RECORD_DESC_DEF(en_text_rec, + UTF_8, + (uint8_t *)language, + sizeL, + (uint8_t *)TXTMessage, + sizeM); + nfc_ndef_msg_record_add( &NFC_NDEF_MSG(welcome_msg), + &NFC_NDEF_TEXT_RECORD_DESC(en_text_rec)); + + nfc_ndef_msg_encode(&NFC_NDEF_MSG(welcome_msg), + ndef_msg_buf, + &len); + + nfc_t2t_payload_set((uint8_t *) ndef_msg_buf, len); + //Serial.println("Send"); +} + +void NFCClass::setURImessage( const char URL[], nfc_uri_id_t type){ + + uint8_t size=strlen(URL); + memset(ndef_msg_buf, 0, 256); + + uint32_t len = sizeof(ndef_msg_buf); + nfc_t2t_setup(nfc_callback, NULL); + nfc_uri_msg_encode( type, + (uint8_t *) URL, + size, + ndef_msg_buf, + &len); + + nfc_t2t_payload_set((uint8_t*)ndef_msg_buf, len); + +} + +void NFCClass::setAPPmessage(const char android_app[], const char windows_app[]){ + + uint8_t sizeA=strlen(android_app); + uint8_t sizeW=strlen(windows_app); + uint32_t len = sizeof(ndef_msg_buf); + + nfc_t2t_setup(nfc_callback, NULL); + nfc_launchapp_msg_encode((uint8_t *)android_app, + sizeA, + (uint8_t *)windows_app, + sizeW, + ndef_msg_buf, + &len); + + nfc_t2t_payload_set((uint8_t *) ndef_msg_buf, len); +} + +// void NFCClass::setOobPairingKey(){ + +// uint8_t key[16]; +// uint8_t random_values_length, rand_values, generated; +// static ble_advdata_tk_value_t oob_auth_key; +// uint32_t len=sizeof(ndef_msg_buf); + +// //try to generate the key randomly +// sd_rand_application_pool_capacity_get(&random_values_length); +// //we need only 16 bytes +// if(random_values_length>16) +// random_values_length=16; +// //wait until values are generated +// do +// sd_rand_application_bytes_available_get(&generated); +// while(generated +#include "util/sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NFC_T2T_SIZEOF_INTERNAL_BYTES 10 ///< T2T internal byte size. +#define NFC_T2T_MAX_PAYLOAD_SIZE 988 ///< Maximum NDEF message size. +#define NFC_T2T_MAX_PAYLOAD_SIZE_RAW 1008 ///< No NDEF-TLV and no implicit lock bytes at the end. + +/** @brief Events passed to the callback function. */ +typedef enum +{ + NFC_T2T_EVENT_NONE, + ///< Not used. + + NFC_T2T_EVENT_FIELD_ON, + ///< NFC tag has detected external NFC field and was selected by an NFC polling device. + + NFC_T2T_EVENT_FIELD_OFF, + ///< External NFC field has been removed. + + NFC_T2T_EVENT_DATA_READ, + ///< NFC polling device has read all tag data. + /**< + * Repeated reading in the same session i.e. before @ref NFC_T2T_EVENT_FIELD_OFF event, + * will not trigger another @ref NFC_T2T_EVENT_DATA_READ event. + */ + + NFC_T2T_EVENT_STOPPED + ///< Reference to the application NFC callback has been released using @ref nfc_t2t_done. +} nfc_t2t_event_t; + +typedef enum +{ + NFC_T2T_PARAM_TESTING, ///< Used for unit tests. + NFC_T2T_PARAM_NFCID1, /**< NFCID1 value, data can be 4, 7, or 10 bytes long (single, double, or triple size). + To use default NFCID1 of specific length pass one byte containing requested length. + Default 7-byte NFCID1 will be used if this parameter was not set. This parameter can be + set before nfc_t2t_setup() to set initial NFCID1 and it can be changed later. */ +} nfc_t2t_param_id_t; + +/** @brief Callback to pass events from NFC T2T Library to application. + * + * @param[in] p_context Application context for callback execution. + * @param[in] event The event that occurred. + * @param[in] p_data Data to send to the application (event specific). + * @param[in] data_length Length of the data. + */ +typedef void (*nfc_t2t_callback_t)(void * p_context, + nfc_t2t_event_t event, + const uint8_t * p_data, + size_t data_length); + +/** @brief Function for registering the application callback for event signaling. + * + * The callback will be called by NFC T2T Library to notify the application of relevant + * events. It will be called from the HAL_NFC callback context. + * + * @param[in] callback Function pointer to the callback. + * @param[in] p_context Pointer to a memory area used by the callback for execution (optional). + * + * @retval NRF_SUCCESS If the application callback was registered successfully. If one + * of the arguments was invalid, an error code is returned. + */ +ret_code_t nfc_t2t_setup(nfc_t2t_callback_t callback, void * p_context); + +/** @brief Function for setting an NFC parameter. + * + * This function allows to set an NFC configuration parameter. + * + * @param[in] id ID of the parameter to set. + * @param[in] p_data Pointer to a buffer containing the data to set. + * @param[in] data_length Size of the buffer containing the data to set. + * + * @retval NRF_SUCCESS If the parameter was set successfully. If one of the arguments + * was invalid (for example, a wrong data length), an error code + * is returned. + */ +ret_code_t nfc_t2t_parameter_set(nfc_t2t_param_id_t id, void * p_data, size_t data_length); + +/** @brief Function for querying an NFC parameter value. + * + * The queried value will be placed into the passed data buffer. If the buffer + * is too small, p_max_data_length will contain the required buffer size. If the + * buffer is big enough, p_max_data_length will contain the actual size of the + * data. + * + * @param[in] id ID of the parameter to query. + * @param[in] p_data Pointer to a buffer receiving the queried data. + * @param[in, out] p_max_data_length Size of the buffer, receives actual size of queried data. + * + * @retval NRF_SUCCESS If the parameter was received successfully. If one of the arguments + * was invalid (for example, the buffer was too small), an error code + * is returned. + */ +ret_code_t nfc_t2t_parameter_get(nfc_t2t_param_id_t id, void * p_data, size_t * p_max_data_length); + +/** @brief Function for registering the payload to send on reception of a READ request. + * + * The payload is considered to only contain the NDEF message to deliver to a + * reader. The required NDEF TLV will be created implicitly by NFC T2T Library. + * + * The pointer to the payload must stay valid for the duration of the library + * execution, or until it is explicitly released. + * + * If the pointer is not NULL, but the length is zero, the paypload is + * considered to be an empty NDEF message. + * + * If a new payload is registered, the previously registered one is considered + * released. + * + * Passing a NULL pointer releases the current payload without registering a + * new one. + * + * If an invalid size is given (too big), the function returns with an error + * and the currently registered payload is left unchanged. + * + * @note Provided pointer must point to RAM region. + * + * @param[in] p_payload Pointer to the memory area in RAM containing the payload to send. + * @param[in] payload_length Size of the payload in bytes. + * + * @retval NRF_SUCCESS If the operation was successful. If one + * of the arguments was invalid, an error code is returned. + */ +ret_code_t nfc_t2t_payload_set(const uint8_t * p_payload, size_t payload_length); + +/** @brief Function for registering the raw payload to send on reception of a READ request. + * + * The payload will be delivered directly as-is to the reader, without + * implicitly adding an NDEF TLV container. This can be used if the + * application wants to define the TLVs itself, for example, to provide a different + * memory layout. + * + * The pointer to the payload must stay valid for the duration of the library + * execution, or until it is explicitly released. + * + * If a new payload is registered, the previously registered one is considered + * released. + * + * Passing a NULL pointer releases the current payload, without registering a + * new one. + * + * If an invalid size is given (too big), the function returns with an error + * and the currently registered payload is left unchanged. + * + * @note Provided pointer must points to RAM region. + * + * @param[in] p_payload Pointer to the memory area in RAM containing the payload to send. + * @param[in] payload_length Size of the payload in bytes. + * + * @retval NRF_SUCCESS If the operation was successful. If one + * of the arguments was invalid, an error code is returned. + */ +ret_code_t nfc_t2t_payload_raw_set(const uint8_t * p_payload, size_t payload_length); + +/** @brief Function for registering the sequence of internal bytes. + * + * This refers to the first 10 bytes of the tag memory. The library will set + * a sensible default for these bytes. The application can use this function + * to override the default. + * + * Passing a NULL pointer reverts back to the default sequence. + * The data will be copied by NFC T2T Library, so the memory does not have to remain valid + * after the function returns. + * + * @note When modifying the internal bytes, remember that they must be consistent + * with the NFC hardware register settings (see @ref nfc_t2t_format_internal). + * + * @param[in] p_data Pointer to the memory area containing the data. + * @param[in] data_length Size of the data in bytes. + * + * @retval NRF_SUCCESS If the operation was successful. If the data was not NULL and the + * data length was not 10, an error code is returned. + */ +ret_code_t nfc_t2t_internal_set(const uint8_t * p_data, size_t data_length); + +/** @brief Function for activating the NFC frontend. + * + * You must call this function so that events are posted to the application + * callback. + * + * @retval NRF_SUCCESS If the NFC frontend was activated successfully. If the lower layer + * could not be started, an error code is returned. + */ +ret_code_t nfc_t2t_emulation_start(void); + +/** @brief Function for deactivating the NFC frontend. + * + * After calling this function, no more events will be posted to the + * application callback. + * + * @retval NRF_SUCCESS If the NFC frontend was deactivated successfully. If the lower layer + * could not be stopped, an error code is returned. + */ +ret_code_t nfc_t2t_emulation_stop(void); + +/** @brief Function for releasing the reference to the application callback. + * + * After calling this function, the passed callback pointer is no longer + * considered valid. + * + * @retval NRF_SUCCESS This function always succeeds. + */ +ret_code_t nfc_t2t_done(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif // NFC_T2T_LIB_H__ diff --git a/libraries/nfc/src/ndef/conn_hand_parser/ble_oob_advdata_parser/nfc_ble_oob_advdata_parser.h b/libraries/nfc/src/ndef/conn_hand_parser/ble_oob_advdata_parser/nfc_ble_oob_advdata_parser.h new file mode 100644 index 000000000..a0872e20f --- /dev/null +++ b/libraries/nfc/src/ndef/conn_hand_parser/ble_oob_advdata_parser/nfc_ble_oob_advdata_parser.h @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nfc_ble_oob_advdata_parser Advertising and Scan Response Data Parser for NFC OOB pairing + * @{ + * @ingroup nfc_ble_pair_msg + * @brief Functions for parsing and decoding data in the Advertising and Scan Response + * Data format for NFC OOB pairing. + */ + +#ifndef NFC_BLE_OOB_ADVDATA_PARSER_H_ +#define NFC_BLE_OOB_ADVDATA_PARSER_H_ + +#include "util/sdk_errors.h" +#include "util/ble_advdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_ADVDATA_APPEARANCE_NOT_PRESENT 0 /**< Appearance AD structure not present. */ + +/**@brief Bluetooth Low Energy GAP device name. */ +typedef struct +{ + ble_advdata_name_type_t name_type; /**< See @ref ble_advdata_name_type_t. */ + uint8_t len; /**< Length of device name. */ + uint8_t * p_name; /**< Pointer to the buffer with device name. */ +} ble_gap_dev_name_t; + +/**@brief BLE Advertising data that is relevant for OOB pairing. */ +typedef struct +{ + ble_gap_dev_name_t device_name; /**< See @ref ble_gap_dev_name_t. */ + ble_gap_addr_t * p_device_addr; /**< See @ref ble_gap_addr_t. */ + ble_advdata_tk_value_t * p_tk_value; /**< See @ref ble_advdata_tk_value_t. */ + uint8_t * p_lesc_confirm_value; /**< LESC OOB confirmation data. */ + uint8_t * p_lesc_random_value; /**< LESC OOB random data. */ + ble_advdata_le_role_t le_role; /**< See @ref ble_advdata_le_role_t. */ + uint16_t appearance; /**< Advertising data Appearance field. */ + uint8_t flags; /**< Advertising data Flags field. */ + uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags data field. */ +} nfc_ble_oob_pairing_data_t; + +/**@brief Function for parsing BLE data encoded in AD Type format. + * + * @details This function parses BLE data encoded in Advertising Data Type format which + * can be generated with @ref ble_advdata_encode function. The result of the parsing is + * stored within @ref nfc_ble_oob_pairing_data_t structure. + * + * @note Currently, module can be used to parse BLE AD Type data, which contains + * AD Structures with following GAP AD Types: Flags, Shortened and Complete Device + * Name, Security Manager TK Value and OOB Flags, Appearance, LE Bluetooth Device + * Address and LE Role. + * + * @warning Before passing \p p_nfc_ble_pairing_data structure to this function, + * it is necessary to provide buffers for AD Structures Data, which are expected to be + * found within parsed buffer. This applies to following GAP AD Types with corresponding + * structures: Shortened and Complete Device Name - @ref ble_gap_dev_name_t, + * LE Bluetooth Device Address - @ref ble_gap_addr_t, Security Manager TK Value - + * @ref ble_advdata_tk_value_t and Security Manager OOB Flags - uint8_t. + * + * @param[in] p_advdata Pointer to the data to be parsed. + * @param[in] len Size of the data to be parsed. + * @param[out] p_nfc_ble_pairing_data Pointer to the structure that will be used + * to hold parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NO_MEM If the provided buffer for device name is + * too small to hold parsed data. + * @retval NRF_ERROR_INVALID_LENGTH If any AD Structure Length field contains + * different value than expected. + * @retval NRF_ERROR_INVALID_PARAM If any AD Structure Data field contains + * invalid parameters. + * @retval NRF_ERROR_NULL If any function pointer parameter is NULL or + * any expected buffer in \p p_nfc_ble_pairing_data + * was not provided. + * @retval NRF_ERROR_NOT_SUPPORTED If any AD Structure Type field contains + * type which is not supported or any AD + * Structure Type occurs more than once. + */ +ret_code_t nfc_ble_oob_advdata_parse(uint8_t const * p_advdata, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data); + + +/**@brief Function for displaying values of basic BLE OOB Advertising data types. + * + * @param[in] p_pairing_data Structure containing parsed data. + */ +void nfc_oob_data_printout(nfc_ble_oob_pairing_data_t const * const p_pairing_data); + +#ifdef __cplusplus +} +#endif + +#endif //NFC_BLE_OOB_ADVDATA_PARSER_H__ + +/** @} */ diff --git a/libraries/nfc/src/ndef/conn_hand_parser/le_oob_rec_parser/nfc_le_oob_rec_parser.c b/libraries/nfc/src/ndef/conn_hand_parser/le_oob_rec_parser/nfc_le_oob_rec_parser.c new file mode 100644 index 000000000..cf9a80102 --- /dev/null +++ b/libraries/nfc/src/ndef/conn_hand_parser/le_oob_rec_parser/nfc_le_oob_rec_parser.c @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_LE_OOB_REC_PARSER) +#include "nfc_le_oob_rec_parser.h" +#include "util/sdk_errors.h" + +/** + * @brief Function for parsing LE OOB record payload. + * + * This function parses LE OOB record payload and extracts BLE OOB Advertising data structure. + * + * @param[in] p_buff Pointer to the record payload. + * @param[in] p_len Pointer to the record payload length. + * @param[in,out] p_nfc_ble_oob_pairing_data Pointer to the structure that will be used to hold + * parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval Other An error code that might have been returned by + * @ref nfc_ble_oob_advdata_parse function. + */ +static ret_code_t nfc_le_oob_payload_parse(uint8_t * p_buff, + uint32_t * const p_len, + nfc_ble_oob_pairing_data_t * const p_nfc_ble_oob_pairing_data) +{ + ret_code_t err_code = nfc_ble_oob_advdata_parse(p_buff, + *p_len, + p_nfc_ble_oob_pairing_data); + return err_code; +} + +ret_code_t nfc_le_oob_rec_parse(nfc_ndef_record_desc_t const * const p_rec_desc, + nfc_ble_oob_pairing_data_t * const p_nfc_ble_oob_pairing_data) +{ + ret_code_t err_code; + + if (p_rec_desc->tnf != TNF_MEDIA_TYPE) + { + return NRF_ERROR_INVALID_DATA; + } + + if (p_rec_desc->type_length != sizeof(le_oob_rec_type_field)) + { + return NRF_ERROR_INVALID_DATA; + } + + if (memcmp(p_rec_desc->p_type, le_oob_rec_type_field, sizeof(le_oob_rec_type_field)) != 0) + { + return NRF_ERROR_INVALID_DATA; + } + + if (p_rec_desc->payload_constructor != (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint8_t const * p_payload = ((nfc_ndef_bin_payload_desc_t*)(p_rec_desc->p_payload_descriptor))->p_payload; + uint32_t payload_lenght = ((nfc_ndef_bin_payload_desc_t*)(p_rec_desc->p_payload_descriptor))->payload_length; + + err_code = nfc_le_oob_payload_parse((uint8_t *) p_payload, + &payload_lenght, + p_nfc_ble_oob_pairing_data); + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_LE_OOB_REC_PARSER) diff --git a/libraries/nfc/src/ndef/connection_handover/ac_rec/nfc_ac_rec.c b/libraries/nfc/src/ndef/connection_handover/ac_rec/nfc_ac_rec.c new file mode 100644 index 000000000..0cb6d1e7b --- /dev/null +++ b/libraries/nfc/src/ndef/connection_handover/ac_rec/nfc_ac_rec.c @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +#ifdef __cplusplus +extern "C" { +#endif +#include "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_AC_REC) + +#include "nfc_ac_rec.h" +#include +//#include "../../../nrf_error.h" +#include "nrf.h" + +#define AC_REC_CPS_BYTE_SIZE 1 ///< Size of the field with CPS data. +#define AC_REC_DATA_REF_LEN_SIZE 1 ///< Size of the Data Reference Length field. +#define AC_REC_AUX_DATA_REF_COUNT_SIZE 1 ///< Size of the Data Reference Length field. + +const uint8_t nfc_ac_rec_type_field[2] = {'a', 'c'}; ///< Alternative Carrier Record type. + +/** + * @brief Function for calculating the payload length of the NFC NDEF Alternative Carrier record. + */ +static uint32_t nfc_ac_rec_payload_size_get(nfc_ac_rec_payload_desc_t const * p_ac_rec_payload_desc) +{ + int32_t i = 0; + // Initialize with size of byte with CPS. + uint32_t payload_size = AC_REC_CPS_BYTE_SIZE; + + // Add Carrier Data Reference size. + payload_size += p_ac_rec_payload_desc->carrier_data_ref.length + AC_REC_DATA_REF_LEN_SIZE; + + // Add Auxiliary Data Reference Count size. + payload_size += AC_REC_AUX_DATA_REF_COUNT_SIZE; + + for (i = 0; i < p_ac_rec_payload_desc->aux_data_ref_count; i++) + { + // Add Auxiliary Data Reference size. + payload_size += p_ac_rec_payload_desc->p_aux_data_ref[i].length + AC_REC_DATA_REF_LEN_SIZE; + } + + return payload_size; +} + + +ret_code_t nfc_ac_rec_payload_constructor(nfc_ac_rec_payload_desc_t * p_nfc_rec_ac_payload_desc, + uint8_t * p_buff, + uint32_t * p_len) +{ + int32_t i = 0; + uint32_t payload_size = nfc_ac_rec_payload_size_get(p_nfc_rec_ac_payload_desc); + + if (p_buff != NULL) + { + // Not enough space in the buffer, return an error. + if (payload_size > *p_len) + { + return NRF_ERROR_NO_MEM; + } + + // Invalid CPS value. + if ( p_nfc_rec_ac_payload_desc->cps & ~NFC_AC_CPS_MASK ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Copy CPS. + *p_buff = p_nfc_rec_ac_payload_desc->cps; + p_buff += AC_REC_CPS_BYTE_SIZE; + + // Copy Carrier Data Reference. + *p_buff = p_nfc_rec_ac_payload_desc->carrier_data_ref.length; + p_buff += AC_REC_DATA_REF_LEN_SIZE; + + memcpy( p_buff, + p_nfc_rec_ac_payload_desc->carrier_data_ref.p_data, + p_nfc_rec_ac_payload_desc->carrier_data_ref.length ); + p_buff += p_nfc_rec_ac_payload_desc->carrier_data_ref.length; + + // Copy Auxiliary Data Reference. + *p_buff = p_nfc_rec_ac_payload_desc->aux_data_ref_count; + p_buff += AC_REC_AUX_DATA_REF_COUNT_SIZE; + + for (i = 0; i < p_nfc_rec_ac_payload_desc->aux_data_ref_count; i++) + { + *p_buff = p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].length; + p_buff += AC_REC_DATA_REF_LEN_SIZE; + + memcpy( p_buff, + p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].p_data, + p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].length ); + p_buff += p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].length; + } + } + + // Assign payload size to the return buffer. + *p_len = payload_size; + + return NRF_SUCCESS; +} + + +void nfc_ac_rec_auxiliary_data_ref_clear(nfc_ndef_record_desc_t * p_ac_rec) +{ + nfc_ac_rec_payload_desc_t * p_ac_rec_payload = + (nfc_ac_rec_payload_desc_t*)p_ac_rec->p_payload_descriptor; + + p_ac_rec_payload->aux_data_ref_count = 0; +} + + +ret_code_t nfc_ac_rec_auxiliary_data_ref_add(nfc_ndef_record_desc_t * p_ac_rec, + uint8_t * p_aux_data, + uint8_t aux_length) +{ + nfc_ac_rec_payload_desc_t * p_ac_rec_payload = + (nfc_ac_rec_payload_desc_t *)p_ac_rec->p_payload_descriptor; + + if (p_ac_rec_payload->aux_data_ref_count >= p_ac_rec_payload->max_aux_data_ref) + { + return NRF_ERROR_NO_MEM; + } + + p_ac_rec_payload->p_aux_data_ref[p_ac_rec_payload->aux_data_ref_count].p_data = p_aux_data; + p_ac_rec_payload->p_aux_data_ref[p_ac_rec_payload->aux_data_ref_count].length = aux_length; + p_ac_rec_payload->aux_data_ref_count++; + + return NRF_SUCCESS; +} + +#ifdef __cplusplus +} +#endif // NRF_MODULE_ENABLED(NFC_AC_REC) +#endif // NRF_MODULE_ENABLED(NFC_AC_REC) diff --git a/libraries/nfc/src/ndef/connection_handover/ble_oob_advdata/nfc_ble_oob_advdata.h b/libraries/nfc/src/ndef/connection_handover/ble_oob_advdata/nfc_ble_oob_advdata.h new file mode 100644 index 000000000..e07458040 --- /dev/null +++ b/libraries/nfc/src/ndef/connection_handover/ble_oob_advdata/nfc_ble_oob_advdata.h @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nfc_ble_oob_advdata Advertising and Scan Response Data Encoder for NFC OOB pairing + * @{ + * @ingroup nfc_ble_pair_msg + * @brief Function for encoding data in the Advertising and Scan Response Data format, which + * can be used to create payload of NFC message intended for initiating the Out-of-Band + * pairing. + */ + +#ifndef NFC_BLE_OOB_ADVDATA_H__ +#define NFC_BLE_OOB_ADVDATA_H__ + +#include +#include "util/ble_advdata.h" +#include "util/app_util.h" +#include "util/sdk_errors.h" + + +/**@brief Function for encoding data in the Advertising and Scan Response data format, which + * is used for NFC OOB pairing. + * + * + * @details This function encodes data into the Advertising and Scan Response data format (AD structures). + * Encoding is based on the selections in the supplied structures. This function uses + * @ref ble_advdata_encode to encode regular data and adds additional AD Structures which are specific + * for NFC OOB pairing: Security Manager TK Value, LESC OOB values, OOB Flags, and LE Role. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. + * \c out: Length of encoded data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. + * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the + * provided buffer or some encoded AD structure is too long and its + * length cannot be encoded with one octet. + */ +ret_code_t nfc_ble_oob_adv_data_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len); + +/**@brief Function for encoding payload field of Security Manager TK Value AD Type. + * + * @param[in] p_tk_value Security Manager TK Value AD Type payload. + * @param[out] p_tk_payload_data Pointer to the buffer where TK payload data will be stored. + * + */ +void nfc_tk_value_payload_encode(ble_advdata_tk_value_t * p_tk_value, + uint8_t * p_tk_payload_data); + +#endif // NFC_BLE_OOB_ADVDATA_H__ + +/** @} */ diff --git a/libraries/nfc/src/ndef/connection_handover/ble_pair_lib/nfc_ble_pair_lib.h b/libraries/nfc/src/ndef/connection_handover/ble_pair_lib/nfc_ble_pair_lib.h new file mode 100644 index 000000000..9452fe3de --- /dev/null +++ b/libraries/nfc/src/ndef/connection_handover/ble_pair_lib/nfc_ble_pair_lib.h @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_BLE_PAIR_LIB_H__ +#define NFC_BLE_PAIR_LIB_H__ + +#include +#include "util/sdk_errors.h" +#include "ble.h" +#include "ble_advertising.h" +#include "peer_manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @addtogroup nfc_api + * + * @defgroup nfc_ble_pair_lib NFC BLE Pairing Library + * @ingroup nfc_api + * @brief @tagAPI52 High-level library for BLE Connection Handover pairing using NFC. + * @{ + */ + +/** + * @brief NFC pairing types. + */ +typedef enum +{ + NFC_PAIRING_MODE_JUST_WORKS, /**< Legacy Just Works pairing without a security key. */ + NFC_PAIRING_MODE_OOB, /**< Legacy OOB pairing with a Temporary Key shared through NFC tag data. */ + NFC_PAIRING_MODE_LESC_JUST_WORKS, /**< LESC pairing without authentication data. */ + NFC_PAIRING_MODE_LESC_OOB, /**< LESC pairing with OOB authentication data. */ + NFC_PAIRING_MODE_GENERIC_OOB, /**< OOB pairing with fallback from LESC to Legacy mode. */ + NFC_PAIRING_MODE_CNT /**< Number of available pairing modes. */ +} nfc_pairing_mode_t; + +/** + * @brief Funtion for initializing NFC tag data and turning on tag emulation. + * + * @warning It is assumed that Peer Manager has already been initialized before calling this function. + * It is also assumed that BLE advertising has already been initialized and it is configured + * to run in the BLE_ADV_MODE_FAST mode. + * + * @param[in] mode Pairing mode, this is the value of the @ref nfc_pairing_mode_t enum. + * @param[in] p_advertising Pointer to the advertising module instance. + * + * @retval NRF_SUCCESS If NFC has been initialized properly. + * @retval NRF_ERROR_INVALID_PARAM If pairing mode is invalid. + * @retval NRF_ERROR_NULL If pointer to the advertising module instance is NULL. + * @retval Other Other error codes might be returned depending on used modules. + */ +ret_code_t nfc_ble_pair_init(ble_advertising_t * const p_advertising, nfc_pairing_mode_t mode); + +/** + * @brief Function for setting pairing data and BLE security mode. + * + * @param[in] mode New pairing mode, this is the value of the @ref nfc_pairing_mode_t enum. + * + * @retval NRF_SUCCESS If new pairing mode has been set correctly. + * @retval NRF_ERROR_INVALID_PARAM If pairing mode is invalid. + * @retval Other Other error codes might be returned depending on used modules. + */ +ret_code_t nfc_ble_pair_mode_set(nfc_pairing_mode_t mode); + +/** + * @brief Function for obtaining the current pairing mode. + * + * @return Current pairing mode. + */ +nfc_pairing_mode_t nfc_ble_pair_mode_get(void); + +/** + * @brief Function for replying to @ref PM_EVT_CONN_SEC_PARAMS_REQ. + * + * @details This function is used to allow dynamic changes in the Peer Manager + * security parameters depending on security parameters + * obtained from the peer. This is essential for dynamic switching + * between Legacy OOB and LESC OOB pairing modes when pairing + * library works in @ref NFC_PAIRING_MODE_GENERIC_OOB mode. + * + * @note This function invokes the @ref pm_conn_sec_params_reply function. + * + * @param[in] p_evt Pointer to the Peer Manager event struct with + * information about peer security parameters. + * + * @retval NRF_SUCCESS If proper reply has been sent or library does not need to reply. + * @retval NRF_ERROR_NULL If pointer to the Peer Manager event is NULL. + * @retval Other Other error codes might be returned by the @ref pm_conn_sec_params_reply function. + */ +ret_code_t nfc_ble_pair_on_pm_params_req(pm_evt_t const * p_evt); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_BLE_PAIR_LIB_H__ diff --git a/libraries/nfc/src/ndef/connection_handover/ble_pair_msg/nfc_ble_pair_msg.h b/libraries/nfc/src/ndef/connection_handover/ble_pair_msg/nfc_ble_pair_msg.h new file mode 100644 index 000000000..0a1db7527 --- /dev/null +++ b/libraries/nfc/src/ndef/connection_handover/ble_pair_msg/nfc_ble_pair_msg.h @@ -0,0 +1,279 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_BLE_PAIR_MSG_H__ +#define NFC_BLE_PAIR_MSG_H__ + +/**@file + * + * @defgroup nfc_modules NDEF message modules + * @ingroup nfc_api + * @brief Implementation of NDEF messages. + * + * @defgroup nfc_ndef_messages Predefined NDEF messages + * @ingroup nfc_modules + * @brief Predefined NDEF messages for standard use. + * + * @defgroup nfc_ble_pair_msg BLE pairing messages + * @{ + * @ingroup nfc_ndef_messages + * + * @brief Generation of NFC NDEF messages used for BLE pairing. + * + */ + +#include +#include "util/ble_advdata.h" +#include "util/sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Types of BLE pairing message. + * + * Use one of these values to choose the type of NDEF BLE pairing message. + */ +typedef enum +{ + NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, ///< Simplified LE OOB message. + NFC_BLE_PAIR_MSG_BLUETOOTH_EP_SHORT, ///< Simplified EP OOB message. + NFC_BLE_PAIR_MSG_FULL ///< BLE Handover Select Message. +} nfc_ble_pair_type_t; + +/** @brief Function for encoding simplified LE OOB messages. + * + * This function encodes a simplified LE OOB message into a buffer. The payload of the LE OOB record + * inside the message can be configured via the advertising data structure. + * + * This function was implemented partially according to "Bluetooth Secure Simple Pairing Using NFC" + * (denotation "NFCForum-AD-BTSSP_1_1" published on 2014-01-09) chapters 3.1, 3.2, 4.3.2, + * and according to "Supplement to the Bluetooth Core Specification" (Version 5, adoption date: + * Dec 02 2014). + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] p_le_advdata Pointer to the BLE advertising data structure for the LE OOB record. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_simplified_le_oob_msg_encode(ble_advdata_t const * const p_le_advdata, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding simplified EP OOB messages. + * + * This function encodes a simplified EP OOB message into a buffer. The payload of the EP OOB record + * inside the message can be configured via the advertising data structure. + * + * This function was implemented partially according to "Bluetooth Secure Simple Pairing Using NFC" + * (denotation "NFCForum-AD-BTSSP_1_1" published on 2014-01-09) chapters 3.1, 3.2, 4.3.1, + * and according to "Supplement to the Bluetooth Core Specification" (Version 5, adoption date: + * Dec 02 2014). + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] p_ep_advdata Pointer to the BLE advertising data structure for the EP OOB record. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_simplified_ep_oob_msg_encode(ble_advdata_t const * const p_ep_advdata, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding BLE Handover Select Messages. + * + * This function encodes a BLE Handover Select Message into a buffer. The payload of the LE OOB record + * and the EP OOB record inside the message can be configured via the advertising data structures. + * + * This function was implemented partially according to "Bluetooth Secure Simple Pairing Using NFC" + * (denotation "NFCForum-AD-BTSSP_1_1" published on 2014-01-09) chapters 3.1, 3.2, 4.1.1 + * and 4.1.2 (combined), and according to "Supplement to the Bluetooth Core Specification" (Version 5, + * adoption date: Dec 02 2014). + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] p_le_advdata Pointer to the BLE advertising data structure for the LE OOB record. + * @param[in] p_ep_advdata Pointer to the BLE advertising data structure for the EP OOB record. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_full_handover_select_msg_encode(ble_advdata_t const * const p_le_advdata, + ble_advdata_t const * const p_ep_advdata, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding any type of BLE pairing messages with default BLE + * advertising data structures. + * + * This function encodes a BLE pairing message into a buffer. The message can be encoded as + * one of the three message types (using @ref nfc_ble_simplified_le_oob_msg_encode, + * @ref nfc_ble_simplified_ep_oob_msg_encode, or @ref nfc_ble_full_handover_select_msg_encode), + * according to the @p nfc_ble_pair_type parameter. LE and EP OOB records use the default + * advertising data structure configuration. Only one field ('Security Manager TK') in the BLE + * advertising data can be configured for both records by specifying the @p p_tk_value parameter. + * + * For LE OOB records, the default BLE advertising data structure configuration fills the required + * fields 'LE Bluetooth Device Address' and 'LE Role' and the optional fields 'Appearance', + * 'Local Name', and 'Flags'. + * + * For EP OOB records, the default BLE advertising data structure configuration fills the required + * field 'Security Manager Out Of Band Flags' and the optional fields 'Appearance', + * 'Local Name', and 'Flags'. + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] nfc_ble_pair_type Type of BLE pairing message. + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK value field is not encoded in the NDEF message. + * @param[in] p_lesc_data Pointer to the LESC OOB data. If NULL, LESC OOB fields are + * not encoded in the NDEF message. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_pair_default_msg_encode(nfc_ble_pair_type_t nfc_ble_pair_type, + ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding any type of BLE pairing messages with default BLE + * advertising data structures and with TK modifier feature. + * + * This function is very similar to the @ref nfc_ble_pair_default_msg_encode function, but + * additionaly enables tracking of TK locations which were encoded in the Connection Handover + * NDEF message. After using this function, you can update the TK value in NDEF by calling + * @ref nfc_tk_group_modifier_update. + * + * @param[in] nfc_ble_pair_type Type of BLE pairing message. + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK value field is not encoded in the NDEF message. + * @param[in] p_lesc_data Pointer to the LESC OOB data. If NULL, LESC OOB values are + * not encoded in the NDEF message. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * @param[in] pp_tk_group Pointer to array of TK locations that should be modified with + * @ref nfc_tk_group_modifier_update function. + * @param[in] max_group_size Maximal number of TK locations that can added to \p pp_tk_group. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_pair_msg_updatable_tk_encode(nfc_ble_pair_type_t nfc_ble_pair_type, + ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + uint8_t * p_buf, + uint32_t * p_len, + uint8_t ** pp_tk_group, + uint8_t max_group_size); + +/**@brief Function for updating the Connection Handover NDEF message with new TK value. + * + * @details This function updates NDEF message with new TK value. This update is applied to all of + * TK locations in the Connection Handover NDEF message. This function can only be used + * after calling @ref nfc_ble_pair_msg_updatable_tk_encode, which is used to encode + * Connection Handover NDEF message. + * + * @param[in] p_tk_value Pointer to the new TK value. The NDEF message will be updated with this + * value. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If pointer to TK locations was NULL. + */ +ret_code_t nfc_tk_group_modifier_update(ble_advdata_tk_value_t * p_tk_value); + +/**@brief Function for adding new location of TK value to the location description structure. + * + * @param[in] p_tk_location New location of TK value in the Connection Handover NDEF message. + * + * @retval NRF_SUCCESS If the operation was successful or if buffer used for holding TK + * locations is NULL. + * @retval NRF_ERROR_NO_MEM If there is no place in the buffer for the new TK value location. + */ +ret_code_t nfc_tk_to_group_add(uint8_t * p_tk_location); + +/**@brief Function for updating the Connection Handover NDEF message with a new LESC OOB values. + * + * @details Updates LESC Confirmation and Random Values based on its locations set by the @ref nfc_lesc_pos_set function. + * + * @param[in] p_ble_lesc_oob_data Pointer to the new LESC OOB data. The NDEF message will be updated with this data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If pointer to the new LESC OOB data is NULL. + * @retval NRF_ERROR_INVALID_STATE If pointer to the LESC OOB data location in NDEF message is NULL. + */ +ret_code_t nfc_lesc_data_update(ble_gap_lesc_oob_data_t * p_ble_lesc_oob_data); + +/**@brief Function for storing pointers to the LESC OOB data inside NDEF message. + * + * @details It allows LESC OOB data update without regenerating entire CH NDEF message. + * + * @param[in] p_confirm Pointer to the LESC Confirmation Value position in the NDEF message. + * @param[in] p_random Pointer to the LESC Random Value position in the NDEF message. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If either of pointers is set to NULL. + */ +ret_code_t nfc_lesc_pos_set(uint8_t * p_confirm, uint8_t * p_random); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_BLE_PAIR_MSG_H__ diff --git a/libraries/nfc/src/ndef/connection_handover/hs_rec/nfc_hs_rec.c b/libraries/nfc/src/ndef/connection_handover/hs_rec/nfc_hs_rec.c new file mode 100644 index 000000000..aceb697d6 --- /dev/null +++ b/libraries/nfc/src/ndef/connection_handover/hs_rec/nfc_hs_rec.c @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_HS_REC) + +#include "nfc_hs_rec.h" +#include "../ac_rec/nfc_ac_rec.h" +//#include "../../../nrf_error.h" + +#define HS_REC_VERSION_SIZE 1 + +const uint8_t nfc_hs_rec_type_field[] = {'H', 's'}; ///< Handover Select record type. + + +ret_code_t nfc_hs_rec_payload_constructor(nfc_hs_rec_payload_desc_t * p_nfc_hs_rec_payload_desc, + uint8_t * p_buff, + uint32_t * p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (p_buff != NULL) + { + // There must be at least 1 free byte in buffer for version byte. + if (*p_len < HS_REC_VERSION_SIZE) + { + return NRF_ERROR_NO_MEM; + } + + // Major/minor version byte. + *p_buff = ( (p_nfc_hs_rec_payload_desc->major_version << 4) & 0xF0) | + ( p_nfc_hs_rec_payload_desc->minor_version & 0x0F); + p_buff += HS_REC_VERSION_SIZE; + + // Decrement remaining buffer size. + *p_len -= HS_REC_VERSION_SIZE; + } + + // Encode local records encapsulated in a message. + err_code = nfc_ndef_msg_encode(p_nfc_hs_rec_payload_desc->p_local_records, p_buff, p_len); + if (err_code!= NRF_SUCCESS) + { + return err_code; + } + + // Add version byte to the total record size. + *p_len += HS_REC_VERSION_SIZE; + + return NRF_SUCCESS; +} + + +void nfc_hs_rec_local_record_clear(nfc_ndef_record_desc_t * p_hs_rec) +{ + nfc_hs_rec_payload_desc_t* p_hs_payload = + (nfc_hs_rec_payload_desc_t*)p_hs_rec->p_payload_descriptor; + + nfc_ndef_msg_clear(p_hs_payload->p_local_records); +} + + +ret_code_t nfc_hs_rec_local_record_add(nfc_ndef_record_desc_t * p_hs_rec, + nfc_ndef_record_desc_t * p_local_rec) +{ + nfc_hs_rec_payload_desc_t* p_hs_payload = + (nfc_hs_rec_payload_desc_t*)p_hs_rec->p_payload_descriptor; + + return nfc_ndef_msg_record_add(p_hs_payload->p_local_records, p_local_rec); +} + +#endif // NRF_MODULE_ENABLED(NFC_HS_REC) diff --git a/libraries/nfc/src/ndef/generic/record/nfc_ndef_record.h b/libraries/nfc/src/ndef/generic/record/nfc_ndef_record.h new file mode 100644 index 000000000..76480c183 --- /dev/null +++ b/libraries/nfc/src/ndef/generic/record/nfc_ndef_record.h @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_RECORD_H__ +#define NFC_NDEF_RECORD_H__ + +#include +#include +#include "compiler_abstraction.h" +#include "util/sdk_errors.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nfc_ndef_record Custom NDEF records + * @{ + * @ingroup nfc_ndef_msg + * + * @brief Generation of NFC NDEF records for NFC messages. + * + */ + + +#define NDEF_RECORD_IL_MASK 0x08 ///< Mask of the ID field presence bit in the flags byte of an NDEF record. +#define NDEF_RECORD_TNF_MASK 0x07 ///< Mask of the TNF value field in the first byte of an NDEF record. +#define NDEF_RECORD_SR_MASK 0x10 ///< Mask of the SR flag. If set, this flag indicates that the PAYLOAD_LENGTH field has a size of 1 byte. Otherwise, PAYLOAD_LENGTH has 4 bytes. +#define NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE 4 ///< Size of the Payload Length field in a long NDEF record. +#define NDEF_RECORD_PAYLOAD_LEN_SHORT_SIZE 1 ///< Size of the Payload Length field in a short NDEF record. +#define NDEF_RECORD_ID_LEN_SIZE 1 ///< Size of the ID Length field in an NDEF record. + + +/** + * @brief Payload constructor type. + + * A payload constructor is a function for constructing the payload of an NDEF + * record. + * + * @param[in] p_payload_descriptor Pointer to the input data for the constructor. + * @param[out] p_buffer Pointer to the payload destination. If NULL, function will + * calculate the expected size of the record payload. + * + * @param[in,out] p_len Size of the available memory to write as input. Size of the generated + * record payload as output. The implementation must check if the payload + * will fit in the provided buffer. This must be checked by the caller function. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +typedef ret_code_t (* p_payload_constructor_t)(void * p_payload_descriptor, + uint8_t * p_buffer, + uint32_t * p_len); + + +/** + * @brief Type Name Format (TNF) Field Values. + * + * Values to specify the TNF of a record. + */ +typedef enum +{ + TNF_EMPTY = 0x00, ///< The value indicates that there is no type or payload associated with this record. + TNF_WELL_KNOWN = 0x01, ///< NFC Forum well-known type [NFC RTD]. + TNF_MEDIA_TYPE = 0x02, ///< Media-type as defined in RFC 2046 [RFC 2046]. + TNF_ABSOLUTE_URI = 0x03, ///< Absolute URI as defined in RFC 3986 [RFC 3986]. + TNF_EXTERNAL_TYPE = 0x04, ///< NFC Forum external type [NFC RTD]. + TNF_UNKNOWN_TYPE = 0x05, ///< The value indicates that there is no type associated with this record. + TNF_UNCHANGED = 0x06, ///< The value is used for the record chunks used in chunked payload. + TNF_RESERVED = 0x07, ///< The value is reserved for future use. +} nfc_ndef_record_tnf_t; + + +/** + * @brief NDEF record descriptor. + */ +typedef struct +{ + nfc_ndef_record_tnf_t tnf; ///< Value of the Type Name Format (TNF) field. + + uint8_t id_length; ///< Length of the ID field. If 0, a record format without ID field is assumed. + uint8_t const * p_id; ///< Pointer to the ID field data. Not relevant if id_length is 0. + + uint8_t type_length; ///< Length of the type field. + uint8_t const * p_type; ///< Pointer to the type field data. Not relevant if type_length is 0. + + p_payload_constructor_t payload_constructor; ///< Pointer to the payload constructor function. + void * p_payload_descriptor; ///< Pointer to the data for the payload constructor function. + +} nfc_ndef_record_desc_t; + +/** + * @brief Record position within the NDEF message. + * + * Values to specify the location of a record within the NDEF message. + */ +typedef enum +{ + NDEF_FIRST_RECORD = 0x80, ///< First record. + NDEF_MIDDLE_RECORD = 0x00, ///< Middle record. + NDEF_LAST_RECORD = 0x40, ///< Last record. + NDEF_LONE_RECORD = 0xC0 ///< Only one record in the message. +} nfc_ndef_record_location_t; + +#define NDEF_RECORD_LOCATION_MASK (NDEF_LONE_RECORD) ///< Mask of the Record Location bits in the NDEF record's flags byte. + +/** + * @brief Binary data descriptor containing the payload for the record. + */ +typedef struct +{ + uint8_t const * p_payload; ///< Pointer to the buffer with the data. + uint32_t payload_length; ///< Length of data in bytes. +} nfc_ndef_bin_payload_desc_t; + +/** + * @brief Macro for creating and initializing an NFC NDEF record descriptor for a generic record. + * + * This macro creates and initializes an instance of type @ref nfc_ndef_record_desc_t. + * + * Use the macro @ref NFC_NDEF_GENERIC_RECORD_DESC to access the NDEF record descriptor instance. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF record encoding must be done in the same variable scope. + * + * @param[in] NAME Name of the created descriptor instance. + * @param[in] TNF Type Name Format (TNF) value for the record. + * @param[in] P_ID Pointer to the ID string. + * @param[in] ID_LEN Length of the ID string. + * @param[in] P_TYPE Pointer to the type string. + * @param[in] TYPE_LEN Length of the type string. + * @param[in] P_PAYLOAD_CONSTRUCTOR Pointer to the payload constructor function. + * The constructor must be of type @ref p_payload_constructor_t. + * @param[in] P_PAYLOAD_DESCRIPTOR Pointer to the data for the payload constructor. + */ +#define NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME, \ + TNF, \ + P_ID, \ + ID_LEN, \ + P_TYPE, \ + TYPE_LEN, \ + P_PAYLOAD_CONSTRUCTOR, \ + P_PAYLOAD_DESCRIPTOR) \ + nfc_ndef_record_desc_t NAME##_ndef_generic_record_desc = \ + { \ + .tnf = TNF, \ + \ + .id_length = ID_LEN, \ + .p_id = P_ID, \ + \ + .type_length = TYPE_LEN, \ + .p_type = P_TYPE, \ + \ + .payload_constructor = (p_payload_constructor_t)P_PAYLOAD_CONSTRUCTOR, \ + .p_payload_descriptor = (void *) P_PAYLOAD_DESCRIPTOR \ + } + + +/** @brief Macro for accessing the NFC NDEF record descriptor instance + * that you created with @ref NFC_NDEF_GENERIC_RECORD_DESC_DEF. + */ +#define NFC_NDEF_GENERIC_RECORD_DESC(NAME) (NAME##_ndef_generic_record_desc) + +/** + * @brief Macro for creating and initializing an NFC NDEF record descriptor for a record with + * binary payload. + * + * This macro creates and initializes a static instance of type @ref nfc_ndef_record_desc_t and a binary data descriptor containing the payload data. + * + * Use the macro @ref NFC_NDEF_RECORD_BIN_DATA to access the NDEF record descriptor instance. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF record encoding must be done in the same variable scope. + * + * @param[in] NAME Name of the created descriptor instance. + * @param[in] TNF Type Name Format (TNF) value for the record. + * @param[in] P_ID Pointer to the ID string. + * @param[in] ID_LEN Length of the ID string. + * @param[in] P_TYPE Pointer to the type string. + * @param[in] TYPE_LEN Length of the type string. + * @param[in] P_PAYLOAD Pointer to the payload data that will be copied to the payload field. + * @param[in] PAYLOAD_LEN Length of the payload. + */ +#define NFC_NDEF_RECORD_BIN_DATA_DEF(NAME, \ + TNF, \ + P_ID, ID_LEN, \ + P_TYPE, \ + TYPE_LEN, \ + P_PAYLOAD, \ + PAYLOAD_LEN) \ + nfc_ndef_bin_payload_desc_t NAME##_nfc_ndef_bin_payload_desc = \ + { \ + .p_payload = P_PAYLOAD, \ + .payload_length = PAYLOAD_LEN \ + }; \ + \ + nfc_ndef_record_desc_t NAME##_nfc_ndef_bin_record_desc = \ + { \ + .tnf = TNF, \ + \ + .id_length = ID_LEN, \ + .p_id = P_ID, \ + \ + .type_length = TYPE_LEN, \ + .p_type = P_TYPE, \ + \ + .payload_constructor = (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy, \ + .p_payload_descriptor = (void *) &NAME##_nfc_ndef_bin_payload_desc \ + } + + +/** @brief Macro for accessing the NFC NDEF record descriptor instance + * that you created with @ref NFC_NDEF_RECORD_BIN_DATA_DEF. + */ +#define NFC_NDEF_RECORD_BIN_DATA(NAME) (NAME##_nfc_ndef_bin_record_desc) + +/** @brief Macro for accessing the binary data descriptor that contains + * the payload of the record that you created with @ref NFC_NDEF_RECORD_BIN_DATA_DEF. + */ +#define NFC_NDEF_BIN_PAYLOAD_DESC(NAME) (NAME##_nfc_ndef_bin_payload_desc) + +/** + * @brief Function for encoding an NDEF record. + * + * This function encodes an NDEF record according to the provided record descriptor. + * + * @param[in] p_ndef_record_desc Pointer to the record descriptor. + * @param[in] record_location Location of the record within the NDEF message. + * @param[out] p_record_buffer Pointer to the record destination. If NULL, function will + * calculate the expected size of the record. + * @param[in,out] p_record_len Size of the available memory for the record as input. Size of the generated + * record as output. + * + * @retval NRF_SUCCESS If the record was encoded successfully. + * @retval NRF_ERROR_NO_MEM If the predicted record size is bigger than the provided buffer space. + * @retval NRF_ERROR_INVALID_PARAM If the location of the record is erroneous. + * @retval Other Other codes might be returned depending on the NDEF record payload constructor implementation. + */ +ret_code_t nfc_ndef_record_encode(nfc_ndef_record_desc_t const * p_ndef_record_desc, + nfc_ndef_record_location_t record_location, + uint8_t * p_record_buffer, + uint32_t * p_record_len); + +/** + * @brief Function for constructing the payload for an NFC NDEF record from binary data. + * + * This function copies data from a binary buffer to the payload field of the NFC NDEF record. + * + * @param[in] p_payload_descriptor Pointer to the descriptor of the binary data location and size. + * + * @param[out] p_buffer Pointer to the payload destination. If NULL, function will + * calculate the expected size of the record payload. + * @param[in,out] p_len Size of the available memory for the payload as input. Size of the copied payload + * as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NO_MEM If the payload size is bigger than the provided buffer space. + */ +ret_code_t nfc_ndef_bin_payload_memcopy(nfc_ndef_bin_payload_desc_t * p_payload_descriptor, + uint8_t * p_buffer, + uint32_t * p_len); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif // NFC_NDEF_RECORD_H__ + diff --git a/libraries/nfc/src/ndef/nfc_ac_rec.c b/libraries/nfc/src/ndef/nfc_ac_rec.c new file mode 100644 index 000000000..a3054babb --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ac_rec.c @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_AC_REC) + +#include "nfc_ac_rec.h" +#include +#include "nrf_error.h" +#include "nrf.h" + +#define AC_REC_CPS_BYTE_SIZE 1 ///< Size of the field with CPS data. +#define AC_REC_DATA_REF_LEN_SIZE 1 ///< Size of the Data Reference Length field. +#define AC_REC_AUX_DATA_REF_COUNT_SIZE 1 ///< Size of the Data Reference Length field. + +const uint8_t nfc_ac_rec_type_field[2] = {'a', 'c'}; ///< Alternative Carrier Record type. + +/** + * @brief Function for calculating the payload length of the NFC NDEF Alternative Carrier record. + */ +static uint32_t nfc_ac_rec_payload_size_get(nfc_ac_rec_payload_desc_t const * p_ac_rec_payload_desc) +{ + int32_t i = 0; + // Initialize with size of byte with CPS. + uint32_t payload_size = AC_REC_CPS_BYTE_SIZE; + + // Add Carrier Data Reference size. + payload_size += p_ac_rec_payload_desc->carrier_data_ref.length + AC_REC_DATA_REF_LEN_SIZE; + + // Add Auxiliary Data Reference Count size. + payload_size += AC_REC_AUX_DATA_REF_COUNT_SIZE; + + for (i = 0; i < p_ac_rec_payload_desc->aux_data_ref_count; i++) + { + // Add Auxiliary Data Reference size. + payload_size += p_ac_rec_payload_desc->p_aux_data_ref[i].length + AC_REC_DATA_REF_LEN_SIZE; + } + + return payload_size; +} + + +ret_code_t nfc_ac_rec_payload_constructor(nfc_ac_rec_payload_desc_t * p_nfc_rec_ac_payload_desc, + uint8_t * p_buff, + uint32_t * p_len) +{ + int32_t i = 0; + uint32_t payload_size = nfc_ac_rec_payload_size_get(p_nfc_rec_ac_payload_desc); + + if (p_buff != NULL) + { + // Not enough space in the buffer, return an error. + if (payload_size > *p_len) + { + return NRF_ERROR_NO_MEM; + } + + // Invalid CPS value. + if ( p_nfc_rec_ac_payload_desc->cps & ~NFC_AC_CPS_MASK ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Copy CPS. + *p_buff = p_nfc_rec_ac_payload_desc->cps; + p_buff += AC_REC_CPS_BYTE_SIZE; + + // Copy Carrier Data Reference. + *p_buff = p_nfc_rec_ac_payload_desc->carrier_data_ref.length; + p_buff += AC_REC_DATA_REF_LEN_SIZE; + + memcpy( p_buff, + p_nfc_rec_ac_payload_desc->carrier_data_ref.p_data, + p_nfc_rec_ac_payload_desc->carrier_data_ref.length ); + p_buff += p_nfc_rec_ac_payload_desc->carrier_data_ref.length; + + // Copy Auxiliary Data Reference. + *p_buff = p_nfc_rec_ac_payload_desc->aux_data_ref_count; + p_buff += AC_REC_AUX_DATA_REF_COUNT_SIZE; + + for (i = 0; i < p_nfc_rec_ac_payload_desc->aux_data_ref_count; i++) + { + *p_buff = p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].length; + p_buff += AC_REC_DATA_REF_LEN_SIZE; + + memcpy( p_buff, + p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].p_data, + p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].length ); + p_buff += p_nfc_rec_ac_payload_desc->p_aux_data_ref[i].length; + } + } + + // Assign payload size to the return buffer. + *p_len = payload_size; + + return NRF_SUCCESS; +} + + +void nfc_ac_rec_auxiliary_data_ref_clear(nfc_ndef_record_desc_t * p_ac_rec) +{ + nfc_ac_rec_payload_desc_t * p_ac_rec_payload = + (nfc_ac_rec_payload_desc_t*)p_ac_rec->p_payload_descriptor; + + p_ac_rec_payload->aux_data_ref_count = 0; +} + + +ret_code_t nfc_ac_rec_auxiliary_data_ref_add(nfc_ndef_record_desc_t * p_ac_rec, + uint8_t * p_aux_data, + uint8_t aux_length) +{ + nfc_ac_rec_payload_desc_t * p_ac_rec_payload = + (nfc_ac_rec_payload_desc_t *)p_ac_rec->p_payload_descriptor; + + if (p_ac_rec_payload->aux_data_ref_count >= p_ac_rec_payload->max_aux_data_ref) + { + return NRF_ERROR_NO_MEM; + } + + p_ac_rec_payload->p_aux_data_ref[p_ac_rec_payload->aux_data_ref_count].p_data = p_aux_data; + p_ac_rec_payload->p_aux_data_ref[p_ac_rec_payload->aux_data_ref_count].length = aux_length; + p_ac_rec_payload->aux_data_ref_count++; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_AC_REC) diff --git a/libraries/nfc/src/ndef/nfc_ac_rec.h b/libraries/nfc/src/ndef/nfc_ac_rec.h new file mode 100644 index 000000000..14328c385 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ac_rec.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_AC_REC_H__ +#define NFC_AC_REC_H__ + +/**@file + * + * @defgroup nfc_ac_rec ac (Alternative carrier) records + * @{ + * @ingroup nfc_ble_pair_msg + * + * @brief Generation of NFC NDEF Alternative Carrier records for NDEF messages. + * + */ + +#include +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AC_REC_CPS_BYTE_SIZE 1 ///< Size of the field with CPS data. +#define AC_REC_DATA_REF_LEN_SIZE 1 ///< Size of the Data Reference Length field. +#define AC_REC_AUX_DATA_REF_COUNT_SIZE 1 ///< Size of the Data Reference Length field. + +/** + * @brief Carrier Power State. + * + * Possible Carrier Power State field values in an Alternative Carrier record. + */ +typedef enum +{ + NFC_AC_CPS_INACTIVE = 0x00, ///< Alternative Carrier inactive. + NFC_AC_CPS_ACTIVE = 0x01, ///< Alternative Carrier active. + NFC_AC_CPS_ACTIVATING = 0x02, ///< Alternative Carrier activating. + NFC_AC_CPS_UNKNOWN = 0x03 ///< Alternative Carrier power status unknown. +} nfc_ac_rec_cps_t; + +#define NFC_AC_CPS_MASK (NFC_AC_CPS_UNKNOWN) ///< Mask of Carrier Power State bits in a first ac record byte. + +/** + * @brief Carrier Data Reference and Auxiliary Data Reference descriptor. + */ +typedef struct +{ + uint8_t length; ///< Length of the data field. + uint8_t * p_data; ///< Pointer to the Data Reference characters. Not relevant if length is 0. +} nfc_ac_rec_data_ref_t; + +/** + * @brief Alternative Carrier record payload descriptor. + */ +typedef struct +{ + nfc_ac_rec_cps_t cps; ///< Carrier Power State value. + nfc_ac_rec_data_ref_t carrier_data_ref; ///< Carrier Data Reference. + uint8_t const max_aux_data_ref; ///< Maximum number of Auxiliary Data Reference fields. + uint8_t aux_data_ref_count; ///< Number of Auxiliary Data Reference fields. + nfc_ac_rec_data_ref_t * p_aux_data_ref; ///< Pointer to the Auxiliary Data Reference fields. +} nfc_ac_rec_payload_desc_t; + + +/** + * @brief Constructor for an NFC NDEF Alternative Carrier record payload. + * + * This function encodes the payload of an Alternative Carrier record as specified in the Connection + * Handover standard. It implements an API compatible with @ref p_payload_constructor_t. + */ +ret_code_t nfc_ac_rec_payload_constructor(nfc_ac_rec_payload_desc_t * p_nfc_rec_ac_payload_desc, + uint8_t * p_buff, + uint32_t * p_len); + +/** + * @brief External reference to the type field of the Alternative Carrier record, defined in the + * file @c nfc_ac_rec.c. It is used in the @ref NFC_NDEF_AC_RECORD_DESC_DEF macro. + */ +extern const uint8_t nfc_ac_rec_type_field[2]; + +/** + * @brief Size of the type field of the Alternative Carrier record, defined in the + * file @c nfc_ac_rec.c. It is used in the @ref NFC_NDEF_AC_RECORD_DESC_DEF macro. + */ +#define NFC_AC_REC_TYPE_LENGTH 2 + +/** + *@brief Macro for creating and initializing an NFC NDEF record descriptor for an Alternative Carrier record. + * + * This macro creates and initializes an instance of type @ref nfc_ndef_record_desc_t and + * an instance of type @ref nfc_ac_rec_payload_desc_t, which together constitute an instance of an Alternative Carrier record. + * + * Use the macro @ref NFC_NDEF_AC_RECORD_DESC to access the NDEF Alternative Carrier record descriptor instance. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_ble_full_handover_select_msg_encode) + * must be done in the same variable scope. + * + * @param[in] NAME Name of the created record descriptor instance. + * @param[in] CPS Carrier Power State value. + * @param[in] CARR_DATA_REF_LEN Length of the Carrier Data Reference field. + * @param[in] P_CARR_DATA_REF Pointer to the Carrier Data Reference field. + * @param[in] MAX_AUX_DATA_REF Maximum number of Auxiliary Data Reference fields. + */ +#define NFC_NDEF_AC_RECORD_DESC_DEF(NAME, \ + CPS, \ + CARR_DATA_REF_LEN, \ + P_CARR_DATA_REF, \ + MAX_AUX_DATA_REF) \ + nfc_ac_rec_data_ref_t NAME##_nfc_ac_rec_aux_data_ref_array[MAX_AUX_DATA_REF]; \ + nfc_ac_rec_payload_desc_t NAME##_nfc_ac_rec_payload_desc = \ + { \ + .cps = CPS, \ + .carrier_data_ref = {CARR_DATA_REF_LEN, P_CARR_DATA_REF}, \ + .max_aux_data_ref = MAX_AUX_DATA_REF, \ + .aux_data_ref_count = 0, \ + .p_aux_data_ref = NAME##_nfc_ac_rec_aux_data_ref_array \ + }; \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME, \ + TNF_WELL_KNOWN, \ + 0, \ + 0, \ + nfc_ac_rec_type_field, \ + NFC_AC_REC_TYPE_LENGTH, \ + nfc_ac_rec_payload_constructor, \ + &(NAME##_nfc_ac_rec_payload_desc)) + +/** + * @brief Macro for accessing the NFC NDEF Alternative Carrier record descriptor + * instance that was created with @ref NFC_NDEF_AC_RECORD_DESC_DEF. + */ +#define NFC_NDEF_AC_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** + * @brief Function for clearing an Auxiliary Data Reference in an NFC NDEF Alternative Carrier record. + * + * This function clears the Auxiliary Data References from the Alternative Carrier record. + * + * @param[in, out] p_ac_rec Pointer to the Alternative Carrier record descriptor. + */ +void nfc_ac_rec_auxiliary_data_ref_clear(nfc_ndef_record_desc_t * p_ac_rec); + +/** + * @brief Function for adding an Auxiliary Data Reference to an NFC NDEF Alternative Carrier record. + * + * @param[in, out] p_ac_rec Pointer to an ac record. + * @param[in] p_aux_data Pointer to the Auxiliary Data Reference data buffer. + * @param[in] aux_length Length of the Auxiliary Data Reference data. + * + * @retval NRF_SUCCESS If the Auxiliary Data Reference was added successfully. + * @retval NRF_ERROR_NO_MEM If the record already contains the maximum number of Auxiliary Data References. + */ +ret_code_t nfc_ac_rec_auxiliary_data_ref_add(nfc_ndef_record_desc_t * p_ac_rec, + uint8_t * p_aux_data, + uint8_t aux_length); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_AC_REC_H__ diff --git a/libraries/nfc/src/ndef/nfc_ac_rec_parser.c b/libraries/nfc/src/ndef/nfc_ac_rec_parser.c new file mode 100644 index 000000000..7100d48ed --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ac_rec_parser.c @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_AC_REC_PARSER) +#include "nfc_ac_rec_parser.h" +#include "util/sdk_macros.h" + +/** + * @brief Function for parsing Data Reference field inside Alternative Carrier record payload. + * + * This function parses Data Reference field inside Alternative Carrier record payload and extracts + * its descriptor. + * + * @param[in,out] pp_buff Pointer to pointer to the remaining payload data. + * @param[in,out] p_len Pointer to the length of remaining payload data. + * @param[in,out] p_ref_field Pointer to the structure that will be used to hold + * parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NULL If provided buffer for Data Reference in \p p_ref_field is + * null. + * @retval NRF_ERROR_NO_MEM If the buffer provided for Data Reference in \p p_ref_field + * does not have enough space to store it. + * @retval NRF_ERROR_INVALID_LENGTH If Data Reference length exceeds record payload. + */ +static ret_code_t ac_rec_reference_field_parse(uint8_t ** const pp_buff, + uint32_t * const p_len, + nfc_ac_rec_data_ref_t * const p_ref_field) +{ + if (p_ref_field->length < **pp_buff) + { + return NRF_ERROR_NO_MEM; + } + p_ref_field->length = **pp_buff; + *pp_buff += AC_REC_DATA_REF_LEN_SIZE; + (*p_len) -= AC_REC_DATA_REF_LEN_SIZE; + + if (*p_len < p_ref_field->length) + { + return NRF_ERROR_INVALID_LENGTH; + } + VERIFY_PARAM_NOT_NULL(p_ref_field->p_data); + memcpy( p_ref_field->p_data, + *pp_buff, + p_ref_field->length ); + *pp_buff += p_ref_field->length; + (*p_len) -= p_ref_field->length; + + return NRF_SUCCESS; +} + +/** + * @brief Function for parsing Alternative Carrier record payload. + * + * This function parses Alternative Carrier record payload and extracts its payload descriptor. + * + * @param[in] p_buff Pointer to the record payload. + * @param[in] p_len Pointer to the record payload length. + * @param[in,out] p_ac_rec_payload_data Pointer to the structure that will be used to hold + * parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NULL If any provided arguments or any needed buffers stored in + * \p p_ac_rec_payload_data are nulls. + * @retval NRF_ERROR_NO_MEM If any from provided buffers does not have enough space + * to store its data. + * @retval NRF_ERROR_INVALID_LENGTH If any length field exceeds record payload. + * @retval NRF_ERROR_INVALID_PARAM If Carrier Power State field has incorrect value. + */ +static ret_code_t nfc_ac_payload_parse(uint8_t * p_buff, + uint32_t * const p_len, + nfc_ac_rec_payload_desc_t * const p_ac_rec_payload_data) +{ + if ( (p_buff == NULL) || (p_len == NULL) || (p_ac_rec_payload_data == NULL) ) + { + return NRF_ERROR_NULL; + } + + if (*p_len < AC_REC_CPS_BYTE_SIZE + AC_REC_DATA_REF_LEN_SIZE + AC_REC_AUX_DATA_REF_COUNT_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + // Copy CPS to ac record payload descriptor. + if (*p_buff & ~NFC_AC_CPS_MASK) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_ac_rec_payload_data->cps = (nfc_ac_rec_cps_t) *p_buff; + p_buff += AC_REC_CPS_BYTE_SIZE; + (*p_len) -= AC_REC_CPS_BYTE_SIZE; + + // Copy Carrier Data Reference to ac record payload descriptor. + ret_code_t err_code = ac_rec_reference_field_parse(&p_buff, + p_len, + &p_ac_rec_payload_data->carrier_data_ref); + VERIFY_SUCCESS(err_code); + + // Copy Auxiliary Data Reference to ac record payload descriptor. + if ( p_ac_rec_payload_data->aux_data_ref_count < *p_buff) + { + return NRF_ERROR_NO_MEM; + } + p_ac_rec_payload_data->aux_data_ref_count = *p_buff; + p_buff += AC_REC_AUX_DATA_REF_COUNT_SIZE; + (*p_len) -= AC_REC_AUX_DATA_REF_COUNT_SIZE; + + if (p_ac_rec_payload_data->aux_data_ref_count != 0) + { + VERIFY_PARAM_NOT_NULL(p_ac_rec_payload_data->p_aux_data_ref); + } + + for (uint8_t i = 0; i < p_ac_rec_payload_data->aux_data_ref_count; i++) + { + err_code = ac_rec_reference_field_parse(&p_buff, + p_len, + &(p_ac_rec_payload_data->p_aux_data_ref[i])); + VERIFY_SUCCESS(err_code); + } + + // Check if all payload data were parsed. + if (*p_len != 0) + { + return NRF_ERROR_INVALID_LENGTH; + } + + return NRF_SUCCESS; +} + +ret_code_t nfc_ac_rec_parse(nfc_ndef_record_desc_t const * const p_rec_desc, + nfc_ac_rec_payload_desc_t * const p_ac_rec_payload_data) +{ + ret_code_t err_code; + + if (p_rec_desc->tnf != TNF_WELL_KNOWN) + { + return NRF_ERROR_INVALID_DATA; + } + + if (p_rec_desc->type_length != sizeof(nfc_ac_rec_type_field)) + { + return NRF_ERROR_INVALID_DATA; + } + + if (memcmp(p_rec_desc->p_type, nfc_ac_rec_type_field, sizeof(nfc_ac_rec_type_field)) != 0) + { + return NRF_ERROR_INVALID_DATA; + } + + if (p_rec_desc->payload_constructor != (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint8_t const * p_payload = + ((nfc_ndef_bin_payload_desc_t *)(p_rec_desc->p_payload_descriptor))->p_payload; + uint32_t payload_length = + ((nfc_ndef_bin_payload_desc_t *)(p_rec_desc->p_payload_descriptor))->payload_length; + + err_code = nfc_ac_payload_parse((uint8_t *) p_payload, + &payload_length, + p_ac_rec_payload_data); + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_AC_REC_PARSER) diff --git a/libraries/nfc/src/ndef/nfc_ac_rec_parser.h b/libraries/nfc/src/ndef/nfc_ac_rec_parser.h new file mode 100644 index 000000000..9f45f2739 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ac_rec_parser.h @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nfc_ac_rec_parser Alternative Carrier records parser + * @{ + * @ingroup nfc_ble_pair_msg + * @brief Functions for parsing and decoding Alternative Carrier records. + */ + +#ifndef __NFC_AC_REC_PARSER_H__ +#define __NFC_AC_REC_PARSER_H__ + +#include "nfc_ndef_record.h" +#include "nfc_ac_rec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for parsing general record description as Alternative Carrier record. + * + * This function checks if record description matches the Alternative Carrier record and extracts + * its payload structure. It is required for the record description to use binary payload + * descriptor. + * + * @param[in] p_rec_desc Pointer to the record descriptor. + * @param[in,out] p_ac_rec_payload_data Pointer to the structure that will be used to hold + * parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_INVALID_DATA If the NDEF record type or TNF is incorrect. + * @retval NRF_ERROR_NOT_SUPPORTED If the payload descriptor is not binary. + * @retval NRF_ERROR_NULL If any provided arguments or any needed buffers stored in + * \p p_ac_rec_payload_data are nulls. + * @retval NRF_ERROR_NO_MEM If any from provided buffers does not have enough space + * to store its data. + * @retval NRF_ERROR_INVALID_LENGTH If any length field exceeds record payload. + * @retval NRF_ERROR_INVALID_PARAM If Carrier Power State field has incorrect value. + */ +ret_code_t nfc_ac_rec_parse(nfc_ndef_record_desc_t const * const p_rec_desc, + nfc_ac_rec_payload_desc_t * const p_ac_rec_payload_data); + +#ifdef __cplusplus +} +#endif + +#endif // __NFC_AC_REC_PARSER_H__ + +/** @} */ diff --git a/libraries/nfc/src/ndef/nfc_ble_oob_advdata.c b/libraries/nfc/src/ndef/nfc_ble_oob_advdata.c new file mode 100644 index 000000000..9a3e50551 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_oob_advdata.c @@ -0,0 +1,402 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_BLE_OOB_ADVDATA) + +#include "nfc_ble_oob_advdata.h" +#include "util/sdk_common.h" +#include "nfc_ble_pair_msg.h" +#include "nfc_ble_pair_common.h" + + +/** + * @brief Macro for verifying basic parameters used for encoding single BLE AD Type. + * + * It verifies if provided buffer is NULL and if there is enough space for the encoded data. + * In case of NULL pointer buffer, necessary space for current AD Type is calculated. + * + * @param[in] P_ENCODED_DATA Buffer for the encoded data. + * @param[in] P_OFFSET Pointer to index of the first free cell in the buffer. + * @param[in] AD_TYPE_SIZE Size of the single AD Type. + * @param[in] MAX_SIZE Maximal size of the provided buffer. + */ +#define NFC_BLE_OOB_ADVDATA_INPUT_VERIFY( P_ENCODED_DATA, P_OFFSET, AD_TYPE_SIZE, MAX_SIZE) \ + if ( (P_ENCODED_DATA) == NULL ) \ + { \ + *(P_OFFSET) += (AD_TYPE_SIZE); \ + return NRF_SUCCESS; \ + } \ + if ( *(P_OFFSET) + (AD_TYPE_SIZE) > (MAX_SIZE) ) \ + { \ + return NRF_ERROR_DATA_SIZE; \ + } + +/**@brief Function for encoding data of Security Manager OOB Flags AD Type. + * + * @param[in] oob_flags Security Manager OOB Flags AD Type payload. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_offset \c in: Offset of \p p_encoded_data buffer before this AD type encoding. + * \c out: Offset of \p p_encoded_data buffer after this AD type encoding. + * @param[in] max_size Size of \p p_encoded_data buffer. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer size is too small. + */ +static ret_code_t sec_mgr_oob_flags_encode(uint8_t oob_flags, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + NFC_BLE_OOB_ADVDATA_INPUT_VERIFY(p_encoded_data, p_offset, AD_TYPE_OOB_FLAGS_SIZE, max_size); + + // Encode flags. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_OOB_FLAGS_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = oob_flags; + *p_offset += AD_TYPE_OOB_FLAGS_DATA_SIZE; + + return NRF_SUCCESS; +} + +/**@brief Function for encoding data of Security Manager TK Value AD Type. + * + * @param[in] p_tk_value Security Manager TK Value AD Type payload. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_offset \c in: Offset of \p p_encoded_data buffer before this AD type encoding. + * \c out: Offset of \p p_encoded_data buffer after this AD type encoding. + * @param[in] max_size Size of \p p_encoded_data buffer. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer size is too small. + */ +static ret_code_t tk_value_encode(ble_advdata_tk_value_t * p_tk_value, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + + NFC_BLE_OOB_ADVDATA_INPUT_VERIFY(p_encoded_data, p_offset, AD_TYPE_TK_VALUE_SIZE, max_size); + + // Encode TK Value. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_TK_VALUE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Remember location of TK in the buffer if this feature was enabled. + err_code = nfc_tk_to_group_add(&p_encoded_data[*p_offset]); + VERIFY_SUCCESS(err_code); + + nfc_tk_value_payload_encode(p_tk_value, &p_encoded_data[*p_offset]); + (*p_offset) += AD_TYPE_TK_VALUE_DATA_SIZE; + + return NRF_SUCCESS; +} + +/**@brief Function for encoding LESC OOB data in the CH NDEF message. + * + * @param[in] p_lesc_value Pointer to the LESC OOB values to be encoded. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_offset \c in: Offset of \p p_encoded_data buffer before this AD type encoding. + * \c out: Offset of \p p_encoded_data buffer after this AD type encoding. + * @param[in] max_size Size of \p p_encoded_data buffer. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer size is too small. + */ +static ret_code_t lesc_value_encode(ble_gap_lesc_oob_data_t * p_lesc_value, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + + NFC_BLE_OOB_ADVDATA_INPUT_VERIFY(p_encoded_data, p_offset, AD_TYPE_LESC_SIZE, max_size); + + // Encode LESC Confirm Value. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_CONFIRM_VALUE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE; + *p_offset += AD_TYPE_FIELD_SIZE; + + memcpy(&p_encoded_data[*p_offset], p_lesc_value->c, sizeof(p_lesc_value->c)); + + uint8_t *p_confirm = &p_encoded_data[*p_offset]; + + (*p_offset) += AD_TYPE_CONFIRM_VALUE_DATA_SIZE; + + // Encode LESC Random Value. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_RANDOM_VALUE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE; + *p_offset += AD_TYPE_FIELD_SIZE; + + memcpy(&p_encoded_data[*p_offset], p_lesc_value->r, sizeof(p_lesc_value->r)); + + uint8_t *p_random = &p_encoded_data[*p_offset]; + + (*p_offset) += AD_TYPE_RANDOM_VALUE_DATA_SIZE; + + // Remember location of LESC OOB data in the buffer in case of key changes. + err_code = nfc_lesc_pos_set(p_confirm, p_random); + + return err_code; +} + +/**@brief Function for encoding data of LE Role AD Type. + * + * @param[in] le_role LE Role AD Type payload. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_offset \c in: Offset of \p p_encoded_data buffer before this AD type encoding. + * \c out: Offset of \p p_encoded_data buffer after this AD type encoding. + * @param[in] max_size Size of \p p_encoded_data buffer. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer size is too small. + * @retval NRF_ERROR_INVALID_PARAM If \p le_role parameter has invalid value. + */ +static ret_code_t le_role_encode(ble_advdata_le_role_t le_role, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + NFC_BLE_OOB_ADVDATA_INPUT_VERIFY(p_encoded_data, p_offset, AD_TYPE_LE_ROLE_SIZE, max_size); + + // Encode LE Role. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_LE_ROLE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_ROLE; + *p_offset += AD_TYPE_FIELD_SIZE; + switch (le_role) + { + case BLE_ADVDATA_ROLE_ONLY_PERIPH: + p_encoded_data[*p_offset] = NFC_BLE_ADVDATA_ROLE_ENCODED_ONLY_PERIPH; + break; + case BLE_ADVDATA_ROLE_ONLY_CENTRAL: + p_encoded_data[*p_offset] = NFC_BLE_ADVDATA_ROLE_ENCODED_ONLY_CENTRAL; + break; + case BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED: + p_encoded_data[*p_offset] = NFC_BLE_ADVDATA_ROLE_ENCODED_BOTH_PERIPH_PREFERRED; + break; + case BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED: + p_encoded_data[*p_offset] = NFC_BLE_ADVDATA_ROLE_ENCODED_BOTH_CENTRAL_PREFERRED; + break; + default: + return NRF_ERROR_INVALID_PARAM; + } + *p_offset += AD_TYPE_LE_ROLE_DATA_SIZE; + + return NRF_SUCCESS; +} + +/**@brief Function for calculating the size of Local Name AD Type. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_len Size of the buffer that is necessary to encode Local Name AD Type. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval Other Other error codes might be returned depending on + * @ref sd_ble_gap_device_name_get function. + */ +__STATIC_INLINE ret_code_t nfc_ble_oob_name_size_calc(ble_advdata_t const * const p_advdata, + uint16_t * const p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t device_len; + + if (p_advdata->name_type == BLE_ADVDATA_SHORT_NAME) + { + device_len = p_advdata->short_name_len; + } + else + { + err_code = sd_ble_gap_device_name_get(NULL, &device_len); + } + + *p_len += AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE + device_len; + return err_code; +} + +/**@brief Function for calculating the size of AD Types which are encoded by @ref ble_advdata_encode function. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_len Size of the buffer that is necessary to encode AD Types. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval Other Other error codes might be returned depending on + * @ref nfc_ble_oob_name_size_calc function. + */ +static ret_code_t nfc_ble_oob_adv_data_size_calc(ble_advdata_t const * const p_advdata, + uint16_t * const p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (p_advdata->include_ble_device_addr) + { + *p_len += AD_TYPE_BLE_DEVICE_ADDR_SIZE; + } + if (p_advdata->include_appearance) + { + *p_len += AD_TYPE_APPEARANCE_SIZE; + } + if (p_advdata->flags != 0) + { + *p_len += AD_TYPE_FLAGS_SIZE; + } + if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) + { + err_code = nfc_ble_oob_name_size_calc(p_advdata, p_len); + } + return err_code; +} + +#if ADVANCED_ADVDATA_SUPPORT == 0 +/**@brief Function for verifying if BLE advertising data structure contains only supported AD Types + * by this encoding module. + * + * @param[in] advdata Structure with BLE advertising data. + * + * @retval NRF_SUCCESS If the verification was successful. + * @retval NRF_ERROR_INVALID_PARAM If there is any AD type which is not supported by this + * module. + */ +static ret_code_t nfc_ble_oob_adv_data_check(ble_advdata_t advdata) +{ + advdata.p_sec_mgr_oob_flags = NULL; + advdata.p_tk_value = NULL; + advdata.le_role = BLE_ADVDATA_ROLE_NOT_PRESENT; + advdata.include_ble_device_addr = false; + advdata.include_appearance = false; + advdata.flags = 0; + advdata.name_type = BLE_ADVDATA_NO_NAME; + advdata.short_name_len = 0; + advdata.p_lesc_data = NULL; + + ble_advdata_t pattern_advdata; + memset(&pattern_advdata, 0, sizeof(ble_advdata_t)); + + if ( memcmp( &pattern_advdata, &advdata, sizeof(ble_advdata_t)) == 0 ) + { + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } +} +#endif //ADVANCED_ADVDATA_SUPPORT + +ret_code_t nfc_ble_oob_adv_data_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t max_size = *p_len; + uint16_t offset = 0; + +#if ADVANCED_ADVDATA_SUPPORT + // In this mode, you cannot count the NDEF message length. + VERIFY_FALSE(p_encoded_data == NULL, NRF_ERROR_INVALID_PARAM); +#else + // Verify ADV data structure. + err_code = nfc_ble_oob_adv_data_check(*p_advdata); + VERIFY_SUCCESS(err_code); +#endif //ADVANCED_ADVDATA_SUPPORT + + // Encode Security Manager OOB Flags. + if (p_advdata->p_sec_mgr_oob_flags != NULL) + { + err_code = sec_mgr_oob_flags_encode(*p_advdata->p_sec_mgr_oob_flags, + p_encoded_data, + &offset, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode LESC keys + if (p_advdata->p_lesc_data != NULL) + { + err_code = lesc_value_encode(p_advdata->p_lesc_data, p_encoded_data, &offset, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Security Manager TK value. + if (p_advdata->p_tk_value != NULL) + { + err_code = tk_value_encode(p_advdata->p_tk_value, p_encoded_data, &offset, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode LE Role. + if (BLE_ADVDATA_ROLE_NOT_PRESENT != p_advdata->le_role) + { + err_code = le_role_encode(p_advdata->le_role, p_encoded_data, &offset, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode remaining AD Types or precalculate necessary buffer space. + if (p_encoded_data != NULL) + { + uint16_t adv_data_size = max_size - offset; + err_code = ble_advdata_encode(p_advdata, p_encoded_data + offset, &adv_data_size); + *p_len = offset + adv_data_size; + } + else + { + err_code = nfc_ble_oob_adv_data_size_calc(p_advdata, &offset); + *p_len = offset; + } + + return err_code; +} + +void nfc_tk_value_payload_encode(ble_advdata_tk_value_t * p_tk_value, + uint8_t * p_tk_payload_data) +{ + for (uint8_t i = 0; i < AD_TYPE_TK_VALUE_DATA_SIZE; i++) + { + *(p_tk_payload_data++) = p_tk_value->tk[i]; + } +} + +#endif // NRF_MODULE_ENABLED(NFC_BLE_OOB_ADVDATA) diff --git a/libraries/nfc/src/ndef/nfc_ble_oob_advdata.h b/libraries/nfc/src/ndef/nfc_ble_oob_advdata.h new file mode 100644 index 000000000..e07458040 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_oob_advdata.h @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nfc_ble_oob_advdata Advertising and Scan Response Data Encoder for NFC OOB pairing + * @{ + * @ingroup nfc_ble_pair_msg + * @brief Function for encoding data in the Advertising and Scan Response Data format, which + * can be used to create payload of NFC message intended for initiating the Out-of-Band + * pairing. + */ + +#ifndef NFC_BLE_OOB_ADVDATA_H__ +#define NFC_BLE_OOB_ADVDATA_H__ + +#include +#include "util/ble_advdata.h" +#include "util/app_util.h" +#include "util/sdk_errors.h" + + +/**@brief Function for encoding data in the Advertising and Scan Response data format, which + * is used for NFC OOB pairing. + * + * + * @details This function encodes data into the Advertising and Scan Response data format (AD structures). + * Encoding is based on the selections in the supplied structures. This function uses + * @ref ble_advdata_encode to encode regular data and adds additional AD Structures which are specific + * for NFC OOB pairing: Security Manager TK Value, LESC OOB values, OOB Flags, and LE Role. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. + * \c out: Length of encoded data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. + * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the + * provided buffer or some encoded AD structure is too long and its + * length cannot be encoded with one octet. + */ +ret_code_t nfc_ble_oob_adv_data_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len); + +/**@brief Function for encoding payload field of Security Manager TK Value AD Type. + * + * @param[in] p_tk_value Security Manager TK Value AD Type payload. + * @param[out] p_tk_payload_data Pointer to the buffer where TK payload data will be stored. + * + */ +void nfc_tk_value_payload_encode(ble_advdata_tk_value_t * p_tk_value, + uint8_t * p_tk_payload_data); + +#endif // NFC_BLE_OOB_ADVDATA_H__ + +/** @} */ diff --git a/libraries/nfc/src/ndef/nfc_ble_oob_advdata_parser.c b/libraries/nfc/src/ndef/nfc_ble_oob_advdata_parser.c new file mode 100644 index 000000000..9302c7dc4 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_oob_advdata_parser.c @@ -0,0 +1,524 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_BLE_OOB_ADVDATA_PARSER) +#include "nfc_ble_oob_advdata_parser.h" +#include "util/app_util.h" +#include "nfc_ble_pair_common.h" + +#define NRF_LOG_MODULE_NAME ble_oob_ad_parser +#include "util/nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* Workaround for using NRF_LOG_RAW_INFO() macro only when logging level is "DEBUG" */ +#if (NRF_LOG_LEVEL > 3) +#define NRF_BLE_OOB_AD_PARSER_LOG_DEBUG(...) NRF_LOG_RAW_INFO(__VA_ARGS__) +#else // (NRF_LOG_LEVEL > 3) +#define NRF_BLE_OOB_AD_PARSER_LOG_DEBUG(...) +#endif // (NRF_LOG_LEVEL > 3) + +#define EARLY_TERMINATOR 0 /* Value of AD Structure Length field indicating an early + termination of Advertising or Scan Response Data. */ +#define FIELD_LEN_INC_VAL 1 /* Incorrect Value of AD Structure Length field. */ + +/** @brief Values used with @ref ad_type_counter_t. */ +typedef enum +{ + AD_TYPE_NOT_PRESENT = 0, /* Value indicating that AD type is not present. */ + AD_TYPE_OCCUR_THRES = 1 /* Maximal occurrence number of any AD type within the buffer */ +} ad_type_counter_values_t; + +/**@brief Internal module structure indicating how many BLE AD fields of the same type are in the buffer. */ +typedef struct +{ + uint8_t name_type; /* Number of Short and Full Device Name AD Structures. */ + uint8_t addr_type; /* Number of LE Bluetooth Device Address AD Structures. */ + uint8_t appear_type; /* Number of Appearance AD Structures. */ + uint8_t flags_type; /* Number of Flags AD Structures. */ + uint8_t le_role_type; /* Number of LE Role AD Structures. */ + uint8_t tk_type; /* Number of Security Manager TK AD Structures. */ + uint8_t sec_mgr_oob_flags_type; /* Number of Security Manager OOB Flags AD Structures. */ + uint8_t lesc_confirm_type; /* Number of LESC OOB Confirmation Value AD Structures. */ + uint8_t lesc_random_type; /* Number of LESC OOB Random Value AD Structures. */ +} ad_type_counter_t; + +/**@brief Decodes and stores AD Data from Flags AD Structure. */ +__STATIC_INLINE ret_code_t flags_decode(uint8_t const * p_flags_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_FLAGS_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_nfc_ble_pairing_data->flags = *p_flags_data; + + return NRF_SUCCESS; +} + +void nfc_oob_data_printout(nfc_ble_oob_pairing_data_t const * const p_pairing_data) +{ + NRF_LOG_RAW_INFO("\r\n"); + NRF_LOG_INFO("BLE Advertising data contents"); + NRF_LOG_INFO("Device name: \"%s\"", NRF_LOG_PUSH((char *)p_pairing_data->device_name.p_name)); + NRF_LOG_INFO("Device Address: "); + + for (int i=0; i < BLE_GAP_ADDR_LEN; ++i) + { + NRF_LOG_RAW_INFO("%02X ", p_pairing_data->p_device_addr->addr[i]); + } + NRF_LOG_RAW_INFO("\r\n"); + + if (p_pairing_data->p_tk_value != NULL) + { + NRF_LOG_INFO("Device Temporary Key present."); + for (int i=0; i < BLE_GAP_SEC_KEY_LEN; ++i) + { + NRF_BLE_OOB_AD_PARSER_LOG_DEBUG("%02X ", p_pairing_data->p_tk_value->tk[i]); + } + NRF_BLE_OOB_AD_PARSER_LOG_DEBUG("\r\n"); + } + else + { + NRF_LOG_INFO("Device Temporary Key not present."); + } + + if (p_pairing_data->p_lesc_confirm_value != NULL && p_pairing_data->p_lesc_random_value) + { + NRF_LOG_INFO("LESC Confirmation Value present."); + for (int i=0; i < BLE_GAP_SEC_KEY_LEN; ++i) + { + NRF_BLE_OOB_AD_PARSER_LOG_DEBUG("%02X ", p_pairing_data->p_lesc_confirm_value[i]); + } + NRF_BLE_OOB_AD_PARSER_LOG_DEBUG("\r\n"); + + NRF_LOG_INFO("LESC Random Value present."); + for (int i=0; i < BLE_GAP_SEC_KEY_LEN; ++i) + { + NRF_BLE_OOB_AD_PARSER_LOG_DEBUG("%02X ", p_pairing_data->p_lesc_random_value[i]); + } + NRF_BLE_OOB_AD_PARSER_LOG_DEBUG("\r\n"); + } + else + { + NRF_LOG_INFO("LESC data not present."); + } + + NRF_LOG_RAW_INFO("\r\n"); +} + +/**@brief Decodes and stores AD Data that is common for Short and Full Device Name AD Structures. */ +static ret_code_t name_decode(uint8_t const * p_name_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + uint8_t * p_name = p_nfc_ble_pairing_data->device_name.p_name; + uint8_t * p_name_len = &p_nfc_ble_pairing_data->device_name.len; + + VERIFY_PARAM_NOT_NULL(p_name); + if (*p_name_len < len) + { + return NRF_ERROR_NO_MEM; + } + + memcpy(p_name, p_name_data, len); + *p_name_len = len; + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from Short Device Name AD Structure. */ +__STATIC_INLINE ret_code_t short_name_decode(uint8_t const * p_short_name_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + p_nfc_ble_pairing_data->device_name.name_type = BLE_ADVDATA_SHORT_NAME; + + return name_decode(p_short_name_data, len, p_nfc_ble_pairing_data); +} + +/**@brief Decodes and stores AD Data from Full Device Name AD Structure. */ +__STATIC_INLINE ret_code_t full_name_decode(uint8_t const * p_full_name_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + p_nfc_ble_pairing_data->device_name.name_type = BLE_ADVDATA_FULL_NAME; + + return name_decode(p_full_name_data, len, p_nfc_ble_pairing_data); +} + +/**@brief Decodes and stores AD Data from Security Manager TK AD Structure. */ +static ret_code_t tk_value_decode(uint8_t const * p_tk_value_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_TK_VALUE_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + ble_advdata_tk_value_t * p_tk_value = p_nfc_ble_pairing_data->p_tk_value; + VERIFY_PARAM_NOT_NULL(p_tk_value); + + memcpy(p_tk_value->tk, p_tk_value_data, AD_TYPE_TK_VALUE_DATA_SIZE); + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from Security Manager TK AD Structure. */ +static ret_code_t lesc_confirm_value_decode(uint8_t const * p_lesc_confirm_value_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_CONFIRM_VALUE_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + uint8_t * p_lesc_confirm_data = p_nfc_ble_pairing_data->p_lesc_confirm_value; + VERIFY_PARAM_NOT_NULL(p_lesc_confirm_data); + + memcpy(p_lesc_confirm_data, p_lesc_confirm_value_data, AD_TYPE_CONFIRM_VALUE_DATA_SIZE); + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from Security Manager TK AD Structure. */ +static ret_code_t lesc_random_value_decode(uint8_t const * p_lesc_random_value_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_RANDOM_VALUE_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + uint8_t * p_lesc_random_data = p_nfc_ble_pairing_data->p_lesc_random_value; + VERIFY_PARAM_NOT_NULL(p_lesc_random_data); + + memcpy(p_lesc_random_data, p_lesc_random_value_data, AD_TYPE_RANDOM_VALUE_DATA_SIZE); + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from Security Manager OOB Flags AD Structure. */ +static ret_code_t sec_mgr_oob_flags_decode(uint8_t const * p_sec_mgr_oob_flags_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_OOB_FLAGS_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + VERIFY_PARAM_NOT_NULL(p_nfc_ble_pairing_data->p_sec_mgr_oob_flags); + *(p_nfc_ble_pairing_data->p_sec_mgr_oob_flags) = *(p_sec_mgr_oob_flags_data); + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from Appearance AD Structure. */ +static ret_code_t appearance_decode(uint8_t const * p_appearance_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_APPEARANCE_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_nfc_ble_pairing_data->appearance = uint16_decode(p_appearance_data); + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from LE Bluetooth Device Address AD Structure. */ +static ret_code_t ble_device_addr_decode(uint8_t const * p_dev_addr_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + ble_gap_addr_t * p_device_addr = p_nfc_ble_pairing_data->p_device_addr; + VERIFY_PARAM_NOT_NULL(p_device_addr); + + memcpy(p_device_addr->addr, p_dev_addr_data, BLE_GAP_ADDR_LEN); + p_device_addr->addr_type = *(p_dev_addr_data + BLE_GAP_ADDR_LEN); + + return NRF_SUCCESS; +} + +/**@brief Decodes and stores AD Data from LE Role AD Structure. */ +static ret_code_t le_role_decode(uint8_t const * p_le_role_data, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + if (len != AD_TYPE_LE_ROLE_DATA_SIZE) + { + return NRF_ERROR_INVALID_LENGTH; + } + + uint8_t le_role = *p_le_role_data; + switch (le_role) + { + case NFC_BLE_ADVDATA_ROLE_ENCODED_ONLY_PERIPH: + p_nfc_ble_pairing_data->le_role = BLE_ADVDATA_ROLE_ONLY_PERIPH; + break; + + case NFC_BLE_ADVDATA_ROLE_ENCODED_ONLY_CENTRAL: + p_nfc_ble_pairing_data->le_role = BLE_ADVDATA_ROLE_ONLY_CENTRAL; + break; + + case NFC_BLE_ADVDATA_ROLE_ENCODED_BOTH_PERIPH_PREFERRED: + p_nfc_ble_pairing_data->le_role = BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED; + break; + + case NFC_BLE_ADVDATA_ROLE_ENCODED_BOTH_CENTRAL_PREFERRED: + p_nfc_ble_pairing_data->le_role = BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED; + break; + + default: + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + +/**@brief Validates if Length field of AD structure is correct. */ +__STATIC_INLINE ret_code_t field_length_validate(uint8_t field_length, uint8_t index, uint8_t len) +{ + if ( (field_length == FIELD_LEN_INC_VAL) || (index + field_length >= len) ) + { + return NRF_ERROR_INVALID_LENGTH; + } + else + { + return NRF_SUCCESS; + } +} + +/**@brief Validates which AD types were not present in parsed data and checks if any + * AD Type occured more than once. + */ +__STATIC_INLINE ret_code_t field_type_validate(nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data, + ad_type_counter_t * ad_type_counter) +{ + /* Reset AD type fields which were not present in parsed buffer. */ + if (ad_type_counter->name_type == AD_TYPE_NOT_PRESENT) + { + p_nfc_ble_pairing_data->device_name.p_name = NULL; + p_nfc_ble_pairing_data->device_name.len = 0; + p_nfc_ble_pairing_data->device_name.name_type = BLE_ADVDATA_NO_NAME; + } + if ( (ad_type_counter->addr_type == AD_TYPE_NOT_PRESENT) && + (p_nfc_ble_pairing_data->p_device_addr != NULL) ) + { + p_nfc_ble_pairing_data->p_device_addr = NULL; + } + if ( (ad_type_counter->tk_type == AD_TYPE_NOT_PRESENT) && + (p_nfc_ble_pairing_data->p_tk_value != NULL) ) + { + p_nfc_ble_pairing_data->p_tk_value = NULL; + } + if ( (ad_type_counter->lesc_confirm_type == AD_TYPE_NOT_PRESENT) && + (p_nfc_ble_pairing_data->p_lesc_confirm_value != NULL) ) + { + p_nfc_ble_pairing_data->p_lesc_confirm_value = NULL; + } + if ( (ad_type_counter->lesc_random_type == AD_TYPE_NOT_PRESENT) && + (p_nfc_ble_pairing_data->p_lesc_random_value != NULL) ) + { + p_nfc_ble_pairing_data->p_lesc_random_value = NULL; + } + if ( (ad_type_counter->sec_mgr_oob_flags_type == AD_TYPE_NOT_PRESENT) && + (p_nfc_ble_pairing_data->p_sec_mgr_oob_flags != NULL) ) + { + p_nfc_ble_pairing_data->p_sec_mgr_oob_flags = NULL; + } + if (ad_type_counter->appear_type == AD_TYPE_NOT_PRESENT) + { + p_nfc_ble_pairing_data->appearance = BLE_ADVDATA_APPEARANCE_NOT_PRESENT; + } + if (ad_type_counter->flags_type == AD_TYPE_NOT_PRESENT) + { + p_nfc_ble_pairing_data->flags = 0; + } + if (ad_type_counter->le_role_type == AD_TYPE_NOT_PRESENT) + { + p_nfc_ble_pairing_data->le_role = BLE_ADVDATA_ROLE_NOT_PRESENT; + } + + /* Check if any AD Type was doubled. */ + if ( (ad_type_counter->name_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->addr_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->tk_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->sec_mgr_oob_flags_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->appear_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->flags_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->le_role_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->lesc_confirm_type > AD_TYPE_OCCUR_THRES) || + (ad_type_counter->lesc_random_type > AD_TYPE_OCCUR_THRES) ) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + return NRF_SUCCESS; +} + +ret_code_t nfc_ble_oob_advdata_parse(uint8_t const * p_advdata, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data) +{ + ret_code_t err_code = NRF_SUCCESS; + uint8_t index = 0; + + ad_type_counter_t ad_type_counter; + memset(&ad_type_counter, AD_TYPE_NOT_PRESENT, sizeof(ad_type_counter_t)); + + if ( (p_nfc_ble_pairing_data == NULL) || (p_advdata == NULL) ) + { + return NRF_ERROR_NULL; + } + + while (index < len) + { + uint8_t field_length = p_advdata[index]; + if (field_length == EARLY_TERMINATOR) + { + return NRF_SUCCESS; + } + err_code = field_length_validate(field_length, index, len); + VERIFY_SUCCESS(err_code); + + uint8_t field_type = p_advdata[index + AD_LENGTH_FIELD_SIZE]; + uint8_t const * p_field_data = &p_advdata[index + AD_DATA_OFFSET]; + uint8_t field_data_len = field_length - AD_TYPE_FIELD_SIZE; + + switch (field_type) + { + case BLE_GAP_AD_TYPE_FLAGS: + ++ad_type_counter.flags_type; + err_code = flags_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME: + ++ad_type_counter.name_type; + err_code = short_name_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME: + ++ad_type_counter.name_type; + err_code = full_name_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE: + ++ad_type_counter.tk_type; + err_code = tk_value_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE: + ++ad_type_counter.lesc_confirm_type; + err_code = lesc_confirm_value_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE: + ++ad_type_counter.lesc_random_type; + err_code = lesc_random_value_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS: + ++ad_type_counter.sec_mgr_oob_flags_type; + err_code = sec_mgr_oob_flags_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_APPEARANCE: + ++ad_type_counter.appear_type; + err_code = appearance_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS: + ++ad_type_counter.addr_type; + err_code = ble_device_addr_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + case BLE_GAP_AD_TYPE_LE_ROLE: + ++ad_type_counter.le_role_type; + err_code = le_role_decode(p_field_data, + field_data_len, + p_nfc_ble_pairing_data); + break; + + default: + /* AD Structure Type field unknown for parser. */ + return NRF_ERROR_NOT_SUPPORTED; + } + + VERIFY_SUCCESS(err_code); + + index += field_length + AD_LENGTH_FIELD_SIZE; + } + + err_code = field_type_validate(p_nfc_ble_pairing_data, &ad_type_counter); + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_BLE_OOB_ADVDATA_PARSER) diff --git a/libraries/nfc/src/ndef/nfc_ble_oob_advdata_parser.h b/libraries/nfc/src/ndef/nfc_ble_oob_advdata_parser.h new file mode 100644 index 000000000..a0872e20f --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_oob_advdata_parser.h @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nfc_ble_oob_advdata_parser Advertising and Scan Response Data Parser for NFC OOB pairing + * @{ + * @ingroup nfc_ble_pair_msg + * @brief Functions for parsing and decoding data in the Advertising and Scan Response + * Data format for NFC OOB pairing. + */ + +#ifndef NFC_BLE_OOB_ADVDATA_PARSER_H_ +#define NFC_BLE_OOB_ADVDATA_PARSER_H_ + +#include "util/sdk_errors.h" +#include "util/ble_advdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_ADVDATA_APPEARANCE_NOT_PRESENT 0 /**< Appearance AD structure not present. */ + +/**@brief Bluetooth Low Energy GAP device name. */ +typedef struct +{ + ble_advdata_name_type_t name_type; /**< See @ref ble_advdata_name_type_t. */ + uint8_t len; /**< Length of device name. */ + uint8_t * p_name; /**< Pointer to the buffer with device name. */ +} ble_gap_dev_name_t; + +/**@brief BLE Advertising data that is relevant for OOB pairing. */ +typedef struct +{ + ble_gap_dev_name_t device_name; /**< See @ref ble_gap_dev_name_t. */ + ble_gap_addr_t * p_device_addr; /**< See @ref ble_gap_addr_t. */ + ble_advdata_tk_value_t * p_tk_value; /**< See @ref ble_advdata_tk_value_t. */ + uint8_t * p_lesc_confirm_value; /**< LESC OOB confirmation data. */ + uint8_t * p_lesc_random_value; /**< LESC OOB random data. */ + ble_advdata_le_role_t le_role; /**< See @ref ble_advdata_le_role_t. */ + uint16_t appearance; /**< Advertising data Appearance field. */ + uint8_t flags; /**< Advertising data Flags field. */ + uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags data field. */ +} nfc_ble_oob_pairing_data_t; + +/**@brief Function for parsing BLE data encoded in AD Type format. + * + * @details This function parses BLE data encoded in Advertising Data Type format which + * can be generated with @ref ble_advdata_encode function. The result of the parsing is + * stored within @ref nfc_ble_oob_pairing_data_t structure. + * + * @note Currently, module can be used to parse BLE AD Type data, which contains + * AD Structures with following GAP AD Types: Flags, Shortened and Complete Device + * Name, Security Manager TK Value and OOB Flags, Appearance, LE Bluetooth Device + * Address and LE Role. + * + * @warning Before passing \p p_nfc_ble_pairing_data structure to this function, + * it is necessary to provide buffers for AD Structures Data, which are expected to be + * found within parsed buffer. This applies to following GAP AD Types with corresponding + * structures: Shortened and Complete Device Name - @ref ble_gap_dev_name_t, + * LE Bluetooth Device Address - @ref ble_gap_addr_t, Security Manager TK Value - + * @ref ble_advdata_tk_value_t and Security Manager OOB Flags - uint8_t. + * + * @param[in] p_advdata Pointer to the data to be parsed. + * @param[in] len Size of the data to be parsed. + * @param[out] p_nfc_ble_pairing_data Pointer to the structure that will be used + * to hold parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NO_MEM If the provided buffer for device name is + * too small to hold parsed data. + * @retval NRF_ERROR_INVALID_LENGTH If any AD Structure Length field contains + * different value than expected. + * @retval NRF_ERROR_INVALID_PARAM If any AD Structure Data field contains + * invalid parameters. + * @retval NRF_ERROR_NULL If any function pointer parameter is NULL or + * any expected buffer in \p p_nfc_ble_pairing_data + * was not provided. + * @retval NRF_ERROR_NOT_SUPPORTED If any AD Structure Type field contains + * type which is not supported or any AD + * Structure Type occurs more than once. + */ +ret_code_t nfc_ble_oob_advdata_parse(uint8_t const * p_advdata, + uint8_t len, + nfc_ble_oob_pairing_data_t * p_nfc_ble_pairing_data); + + +/**@brief Function for displaying values of basic BLE OOB Advertising data types. + * + * @param[in] p_pairing_data Structure containing parsed data. + */ +void nfc_oob_data_printout(nfc_ble_oob_pairing_data_t const * const p_pairing_data); + +#ifdef __cplusplus +} +#endif + +#endif //NFC_BLE_OOB_ADVDATA_PARSER_H__ + +/** @} */ diff --git a/libraries/nfc/src/ndef/nfc_ble_pair_common.c b/libraries/nfc/src/ndef/nfc_ble_pair_common.c new file mode 100644 index 000000000..3d995c795 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_pair_common.c @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_CH_COMMON) +#include "nfc_ble_pair_common.h" + +#include + +/* Record Payload Type for Bluetooth Carrier Configuration LE record */ +const uint8_t le_oob_rec_type_field[] = +{ + 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', '/', 'v', 'n', 'd', '.', + 'b', 'l', 'u', 'e', 't', 'o', 'o', 't', 'h', '.', 'l', 'e', '.', 'o', 'o', 'b' +}; + +#endif // NRF_MODULE_ENABLED(NFC_CH_COMMON) diff --git a/libraries/nfc/src/ndef/nfc_ble_pair_common.h b/libraries/nfc/src/ndef/nfc_ble_pair_common.h new file mode 100644 index 000000000..ff9c264a5 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_pair_common.h @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_BLE_PAIR_COMMON_H__ +#define NFC_BLE_PAIR_COMMON_H__ + +#include +#include "util/ble_advdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nfc_ble_pair_common Common data for Connection Handover and Connection Handover Parser modules + * @{ + * @ingroup nfc_ble_pair_msg + */ + +#define AD_TYPE_LE_ROLE_DATA_SIZE 1UL /**< Data size (in octets) of the LE Role AD type. */ +#define AD_TYPE_LE_ROLE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_LE_ROLE_DATA_SIZE) /**< Size (in octets) of the LE Role AD type. */ +#define AD_TYPE_TK_VALUE_DATA_SIZE (sizeof(ble_advdata_tk_value_t)) /**< Data size (in octets) of the Security Manager TK value AD type. */ +#define AD_TYPE_TK_VALUE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_TK_VALUE_DATA_SIZE) /**< Size (in octets) of the Security Manager TK value AD type. */ +#define AD_TYPE_OOB_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Security Manager OOB Flags AD type. */ +#define AD_TYPE_OOB_FLAGS_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_OOB_FLAGS_DATA_SIZE) /**< Size (in octets) of the Security Manager OOB Flags AD type. */ + +#define AD_TYPE_CONFIRM_VALUE_DATA_SIZE 16UL /**< Data size (in octets) of the LESC Confirmation value. */ +#define AD_TYPE_CONFIRM_VALUE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_CONFIRM_VALUE_DATA_SIZE) /**< Size (in octets) of the LESC Confirmation value AD type. */ +#define AD_TYPE_RANDOM_VALUE_DATA_SIZE 16UL /**< Data size (in octets) of the LESC Random value. */ +#define AD_TYPE_RANDOM_VALUE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_RANDOM_VALUE_DATA_SIZE) /**< Size (in octets) of the LESC Random value AD type. */ +#define AD_TYPE_LESC_SIZE (AD_TYPE_RANDOM_VALUE_SIZE + \ + AD_TYPE_CONFIRM_VALUE_SIZE) /**< Total size (in octets) of the LESC OOB AD data fields in NDEF message. */ + +#define AD_TYPE_SEC_MGR_OOB_FLAG_SET 1U /**< Security Manager OOB Flag set. Flag selection is done using _POS defines */ +#define AD_TYPE_SEC_MGR_OOB_FLAG_CLEAR 0U /**< Security Manager OOB Flag clear. Flag selection is done using _POS defines */ +#define AD_TYPE_SEC_MGR_OOB_FLAG_OOB_DATA_PRESENT_POS 0UL /**< Security Manager OOB Data Present Flag position. */ +#define AD_TYPE_SEC_MGR_OOB_FLAG_OOB_LE_SUPPORTED_POS 1UL /**< Security Manager OOB Low Energy Supported Flag position. */ +#define AD_TYPE_SEC_MGR_OOB_FLAG_SIM_LE_AND_EP_POS 2UL /**< Security Manager OOB Simultaneous LE and BR/EDR to Same Device Capable Flag position. */ +#define AD_TYPE_SEC_MGR_OOB_ADDRESS_TYPE_PUBLIC 0UL /**< Security Manager OOB Public Address type. */ +#define AD_TYPE_SEC_MGR_OOB_ADDRESS_TYPE_RANDOM 1UL /**< Security Manager OOB Random Address type. */ +#define AD_TYPE_SEC_MGR_OOB_FLAG_ADDRESS_TYPE_POS 3UL /**< Security Manager OOB Address type Flag (0 = Public Address, 1 = Random Address) position. */ + +/**@brief Payload field values of LE Role BLE GAP AD Type. Corresponds with @ref ble_advdata_le_role_t enum. */ +typedef enum +{ + NFC_BLE_ADVDATA_ROLE_ENCODED_ONLY_PERIPH = 0, /**< Only Peripheral Role supported. */ + NFC_BLE_ADVDATA_ROLE_ENCODED_ONLY_CENTRAL, /**< Only Central Role supported. */ + NFC_BLE_ADVDATA_ROLE_ENCODED_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */ + NFC_BLE_ADVDATA_ROLE_ENCODED_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */ +} nfc_ble_advdata_le_role_encoded_t; + +/** + * @brief External reference to the type field of the Bluetooth LE Carrier Configuration NDEF record, defined + * in the file @c nfc_ble_pair_common.c + */ +extern const uint8_t le_oob_rec_type_field[32]; + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_BLE_PAIR_COMMON_H__ diff --git a/libraries/nfc/src/ndef/nfc_ble_pair_lib.c b/libraries/nfc/src/ndef/nfc_ble_pair_lib.c new file mode 100644 index 000000000..98cb49eb9 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_pair_lib.c @@ -0,0 +1,576 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_BLE_PAIR_LIB) + +#include "nfc_ble_pair_lib.h" +#include "util/sdk_macros.h" +#include "util/app_error.h" +#include "nrf_drv_rng.h" +#include "nfc_t2t_lib.h" +#include "nfc_ble_pair_msg.h" +#include "nrf_sdh_ble.h" +#include "nrf_ble_lesc.h" + +#define NRF_LOG_MODULE_NAME nfc_ble_pair +#if NFC_BLE_PAIR_LIB_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_BLE_PAIR_LIB_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_BLE_PAIR_LIB_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR NFC_BLE_PAIR_LIB_DEBUG_COLOR +#else // NFC_BLE_PAIR_LIB_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif // NFC_BLE_PAIR_LIB_LOG_ENABLED +#include "util/nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +// Verify bonding and keys distribution settings. +#if ((BLE_NFC_SEC_PARAM_BOND) && \ + !(BLE_NFC_SEC_PARAM_KDIST_OWN_ENC) && \ + !(BLE_NFC_SEC_PARAM_KDIST_OWN_ID) && \ + !(BLE_NFC_SEC_PARAM_KDIST_PEER_ENC) && \ + !(BLE_NFC_SEC_PARAM_KDIST_PEER_ID)) + #error "At least one of the BLE_NFC_SEC_PARAM_KDIST flags must be set to 1 when bonding is enabled." +#endif + +// Macro for verifying if the pairing mode argument is valid +#define VERIFY_PAIRING_MODE(arg) \ + if ((arg) >= NFC_PAIRING_MODE_CNT) \ + { \ + return NRF_ERROR_INVALID_PARAM; \ + } + +#define TK_MAX_NUM 1 /**< Maximal number of TK locations in NDEF message buffer. */ +#define NDEF_MSG_BUFF_SIZE 256 /**< Size of buffer for the NDEF pairing message. */ + +#define BLE_NFC_SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ +#define BLE_NFC_SEC_PARAM_IO_CAPS BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ + +static ble_advertising_t * m_p_advertising = NULL; /**< Pointer to the advertising module instance. */ + +static uint8_t m_ndef_msg_buf[NDEF_MSG_BUFF_SIZE]; /**< NFC tag NDEF message buffer. */ +static ble_advdata_tk_value_t m_oob_auth_key; /**< Temporary Key buffer used in OOB legacy pairing mode. */ +static uint8_t * m_tk_group[TK_MAX_NUM]; /**< Locations of TK in NDEF message. */ +static nfc_pairing_mode_t m_pairing_mode; /**< Current pairing mode. */ +static ble_gap_sec_params_t m_sec_param; /**< Current Peer Manager secure parameters configuration. */ + +static uint8_t m_connections = 0; /**< Number of active connections. */ + +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context); + +NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + +/** + * @brief Generates random values to a given buffer + * + * @param[out] p_buff Buffer for random values + * @param[in] size Number of bytes to generate + * + * @returns Number of generated bytes + */ +static uint8_t random_vector_generate(uint8_t * p_buff, uint8_t size) +{ + uint8_t available; + ret_code_t err_code = NRF_SUCCESS; + + nrf_drv_rng_bytes_available(&available); + + uint8_t length = (size < available) ? size : available; + err_code = nrf_drv_rng_rand(p_buff, length); + APP_ERROR_CHECK(err_code); + return length; +} + +/** + * @brief Prints generated key to the log console + * + * @param[in] lenght TK value length + */ +static void random_vector_log(uint8_t length) +{ + NRF_LOG_INFO("TK Random Value:"); + for (uint32_t i = 0; i < length; i++) + { + NRF_LOG_RAW_INFO(" %02X",(int)m_oob_auth_key.tk[i]); + } + NRF_LOG_RAW_INFO("\r\n"); +} + +/** + * @brief Function for handling NFC events. + * + * @details Starts advertising and generates new OOB keys on the NFC_T2T_EVENT_FIELD_ON event. + * + * @param[in] p_context Context for callback execution, not used in this callback implementation. + * @param[in] event Event generated by hal NFC lib. + * @param[in] p_data Received/transmitted data or NULL, not used in this callback implementation. + * @param[in] data_length Size of the received/transmitted packet, not used in this callback implementation. + */ +static void nfc_callback(void * p_context, + nfc_t2t_event_t event, + uint8_t const * p_data, + size_t data_length) +{ + UNUSED_PARAMETER(p_context); + UNUSED_PARAMETER(p_data); + UNUSED_PARAMETER(data_length); + + ret_code_t err_code = NRF_SUCCESS; + nfc_pairing_mode_t pairing_mode; + + switch (event) + { + case NFC_T2T_EVENT_FIELD_ON: + NRF_LOG_DEBUG("NFC_EVENT_FIELD_ON"); + + pairing_mode = nfc_ble_pair_mode_get(); + + if ((pairing_mode == NFC_PAIRING_MODE_OOB) || + (pairing_mode == NFC_PAIRING_MODE_GENERIC_OOB)) + { + // Generate Authentication OOB Key and update NDEF message content. + uint8_t length = random_vector_generate(m_oob_auth_key.tk, BLE_GAP_SEC_KEY_LEN); + random_vector_log(length); + err_code = nfc_tk_group_modifier_update(&m_oob_auth_key); + APP_ERROR_CHECK(err_code); + } + + // Start advertising when NFC field is sensed and there is a place for another connection. + if (m_connections < NRF_SDH_BLE_PERIPHERAL_LINK_COUNT) + { + err_code = ble_advertising_start(m_p_advertising, BLE_ADV_MODE_FAST); + if (err_code != NRF_ERROR_INVALID_STATE) + { + APP_ERROR_CHECK(err_code); + } + } + + break; + + case NFC_T2T_EVENT_FIELD_OFF: + NRF_LOG_DEBUG("NFC_EVENT_FIELD_OFF"); + break; + + default: + break; + } +} + +/** + * @brief Function for setting the Peer Manager secure mode used in device pairing. + * + * @param[in] mode NFC pairing mode, this is the value of @ref nfc_pairing_mode_t enum + * + * @retval NRF_SUCCESS If new secure mode has been set correctly. + * @retval NRF_ERROR_INVALID_PARAM If pairing mode is invalid. + * @retval Other Other error codes might be returned depending on used modules. + */ +static ret_code_t pm_secure_mode_set(nfc_pairing_mode_t mode) +{ + ret_code_t err_code = NRF_SUCCESS; + + // Check if pairing mode is valid. + VERIFY_PAIRING_MODE(mode); + + memset(&m_sec_param, 0x00, sizeof(m_sec_param)); + + // Pairing mode specific security parameters. + switch (mode) + { + case NFC_PAIRING_MODE_JUST_WORKS: + // Disable pairing with OOB data. + m_sec_param.mitm = 0; + m_sec_param.oob = 0; + m_sec_param.lesc = 0; + break; + + case NFC_PAIRING_MODE_OOB: + // Enable legacy pairing with OOB data - TK value. + m_sec_param.mitm = 1; + m_sec_param.oob = 1; + m_sec_param.lesc = 0; + break; + + case NFC_PAIRING_MODE_LESC_OOB: + case NFC_PAIRING_MODE_LESC_JUST_WORKS: + // Enable LESC pairing - OOB and MITM flags are cleared because it is the central device + // who decides if the connection will be authorized with LESC OOB data. + m_sec_param.mitm = 0; + m_sec_param.oob = 0; + m_sec_param.lesc = 1; + break; + + case NFC_PAIRING_MODE_GENERIC_OOB: + // MITM, OOB and LESC flags are changing dynamically depending on central device pairing flags. + break; + + default: + return NRF_ERROR_INVALID_PARAM; + } + + // Common security parameters to be used for all security procedures. + m_sec_param.min_key_size = BLE_NFC_SEC_PARAM_MIN_KEY_SIZE; + m_sec_param.max_key_size = BLE_NFC_SEC_PARAM_MAX_KEY_SIZE; + m_sec_param.keypress = BLE_NFC_SEC_PARAM_KEYPRESS; + m_sec_param.io_caps = BLE_NFC_SEC_PARAM_IO_CAPS; + m_sec_param.bond = BLE_NFC_SEC_PARAM_BOND; + +#if (BLE_NFC_SEC_PARAM_BOND) + // If bonding is enabled, set key distribution flags. + m_sec_param.kdist_own.enc = BLE_NFC_SEC_PARAM_KDIST_OWN_ENC; + m_sec_param.kdist_own.id = BLE_NFC_SEC_PARAM_KDIST_OWN_ID; + m_sec_param.kdist_peer.enc = BLE_NFC_SEC_PARAM_KDIST_PEER_ENC; + m_sec_param.kdist_peer.id = BLE_NFC_SEC_PARAM_KDIST_PEER_ID; +#else + // If bonding is not enabled, no keys can be distributed. + m_sec_param.kdist_own.enc = 0; + m_sec_param.kdist_own.id = 0; + m_sec_param.kdist_peer.enc = 0; + m_sec_param.kdist_peer.id = 0; +#endif + + // Update Peer Manager security parameter settings. + err_code = pm_sec_params_set(&m_sec_param); + + return err_code; +} + + + /**@brief Function for preparing the BLE pairing data for the NFC tag. + * + * @details This function does not stop and start the NFC tag data emulation. + * + * @param[in] mode Pairing mode for which the tag data will be prepared. + * + * @retval NRF_SUCCESS If new tag pairing data has been set correctly. + * @retval NRF_ERROR_INVALID_PARAM If pairing mode is invalid. + * @retval NRF_ERROR_NULL If LESC oob data is missing. + * @retval Other Other error codes might be returned depending on used modules. + */ +ret_code_t nfc_ble_pair_data_set(nfc_pairing_mode_t mode) +{ + ret_code_t err_code = NRF_SUCCESS; + + // Check if pairing mode is valid + VERIFY_PAIRING_MODE(mode); + + // Provide information about available buffer size to encoding function. + uint32_t ndef_msg_len = sizeof(m_ndef_msg_buf); + + switch (mode) + { + case NFC_PAIRING_MODE_OOB: + // Encode NDEF message with Secure Simple Pairing OOB optional data - TK value. + err_code = nfc_ble_pair_msg_updatable_tk_encode(NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, + &m_oob_auth_key, + NULL, + m_ndef_msg_buf, + &ndef_msg_len, + m_tk_group, + TK_MAX_NUM); + break; + + case NFC_PAIRING_MODE_JUST_WORKS: + // Encode NDEF message with Secure Simple Pairing OOB data. + err_code = nfc_ble_pair_default_msg_encode(NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, + NULL, + NULL, + m_ndef_msg_buf, + &ndef_msg_len); + break; + + case NFC_PAIRING_MODE_LESC_OOB: + { + // Generate LESC OOB data + err_code = nrf_ble_lesc_own_oob_data_generate(); + VERIFY_SUCCESS(err_code); + + ble_gap_lesc_oob_data_t * p_lesc_oob_data = nrf_ble_lesc_own_oob_data_get(); + VERIFY_PARAM_NOT_NULL(p_lesc_oob_data); + + // Encode NDEF message with BLE LESC OOB pairing data - LESC random and confirmation values. + err_code = nfc_ble_pair_default_msg_encode(NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, + NULL, + p_lesc_oob_data, + m_ndef_msg_buf, + &ndef_msg_len); + } break; + + case NFC_PAIRING_MODE_LESC_JUST_WORKS: + err_code = nfc_ble_pair_default_msg_encode(NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, + NULL, + NULL, + m_ndef_msg_buf, + &ndef_msg_len); + break; + + case NFC_PAIRING_MODE_GENERIC_OOB: + { + // Generate LESC OOB data + err_code = nrf_ble_lesc_own_oob_data_generate(); + VERIFY_SUCCESS(err_code); + + ble_gap_lesc_oob_data_t * p_lesc_oob_data = nrf_ble_lesc_own_oob_data_get(); + VERIFY_PARAM_NOT_NULL(p_lesc_oob_data); + + // Encode NDEF message with Secure Simple Pairing OOB data - TK value and LESC Random and Confirmation Keys. + err_code = nfc_ble_pair_msg_updatable_tk_encode(NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, + &m_oob_auth_key, + p_lesc_oob_data, + m_ndef_msg_buf, + &ndef_msg_len, + m_tk_group, + TK_MAX_NUM); + } break; + + default: + return NRF_ERROR_INVALID_PARAM; + } + + VERIFY_SUCCESS(err_code); + + // Update NFC tag data + err_code = nfc_t2t_payload_set(m_ndef_msg_buf, ndef_msg_len); + + return err_code; +} + +ret_code_t nfc_ble_pair_init(ble_advertising_t * const p_advertising, nfc_pairing_mode_t mode) +{ + ret_code_t err_code = NRF_SUCCESS; + + // Check if pairing mode is valid + VERIFY_PAIRING_MODE(mode); + + // Check if pointer to the advertising module instance is not NULL + VERIFY_PARAM_NOT_NULL(p_advertising); + + m_p_advertising = p_advertising; + m_pairing_mode = mode; + + // Initialize RNG peripheral for authentication OOB data generation + err_code = nrf_drv_rng_init(NULL); + if (err_code != NRF_ERROR_INVALID_STATE && + err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED) + { + VERIFY_SUCCESS(err_code); + } + + // Start NFC + err_code = nfc_t2t_setup(nfc_callback, NULL); + VERIFY_SUCCESS(err_code); + + // Set Peer Manager pairing mode + err_code = pm_secure_mode_set(mode); + VERIFY_SUCCESS(err_code); + + // Generate LESC OOB data + err_code = nrf_ble_lesc_own_oob_data_generate(); + APP_ERROR_CHECK(err_code); + + // Set proper NFC data according to the pairing mode + err_code = nfc_ble_pair_data_set(mode); + VERIFY_SUCCESS(err_code); + + // Turn on tag emulation + err_code = nfc_t2t_emulation_start(); + + return err_code; +} + +ret_code_t nfc_ble_pair_mode_set(nfc_pairing_mode_t mode) +{ + ret_code_t err_code = NRF_SUCCESS; + + // Check if pairing mode is valid + VERIFY_PAIRING_MODE(mode); + + if (mode != m_pairing_mode) + { + m_pairing_mode = mode; + + // Update Peer Manager settings according to the new pairing mode + err_code = pm_secure_mode_set(mode); + VERIFY_SUCCESS(err_code); + + // NFC tag emulation must be turned off during changes in payload + err_code = nfc_t2t_emulation_stop(); + VERIFY_SUCCESS(err_code); + + // Update NFC tag data + err_code = nfc_ble_pair_data_set(mode); + VERIFY_SUCCESS(err_code); + + // Turn on tag emulation after changes + err_code = nfc_t2t_emulation_start(); + VERIFY_SUCCESS(err_code); + } + + return NRF_SUCCESS; +} + +nfc_pairing_mode_t nfc_ble_pair_mode_get(void) +{ + return m_pairing_mode; +} + +/** + * @brief Generates new key pair for LESC pairing. + * + * @details If device is in the @ref NFC_PAIRING_MODE_LESC_OOB mode or in + * the @ref NFC_PAIRING_MODE_GENERIC_OOB mode, NFC Connection Handover + * message is also updated with newly generated LESC OOB data. + * + * @retval NRF_SUCCESS If new tag pairing data has been set correctly. + * @retval Other Other error codes might be returned depending on used modules. + */ +static ret_code_t generate_lesc_keys(void) +{ + ret_code_t err_code = NRF_SUCCESS; + + // Generate new LESC keys + err_code = nrf_ble_lesc_keypair_generate(); + VERIFY_SUCCESS(err_code); + + if ((m_pairing_mode == NFC_PAIRING_MODE_LESC_OOB) || + (m_pairing_mode == NFC_PAIRING_MODE_GENERIC_OOB)) + { + // Generate LESC OOB data. + err_code = nrf_ble_lesc_own_oob_data_generate(); + VERIFY_SUCCESS(err_code); + + // Update NDEF message with new LESC OOB data. + err_code = nfc_lesc_data_update(nrf_ble_lesc_own_oob_data_get()); + VERIFY_SUCCESS(err_code); + } + + return NRF_SUCCESS; +} + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + ret_code_t err_code = NRF_SUCCESS; + + switch (p_ble_evt->header.evt_id) + { + // Upon authorization key request, reply with Temporary Key that was read from the NFC tag + case BLE_GAP_EVT_AUTH_KEY_REQUEST: + NRF_LOG_DEBUG("BLE_GAP_EVT_AUTH_KEY_REQUEST"); + + err_code = sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_AUTH_KEY_TYPE_OOB, + m_oob_auth_key.tk); + APP_ERROR_CHECK(err_code); + break; + + case BLE_GAP_EVT_CONNECTED: + m_connections++; + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_connections--; + // Intentional fallthrough. + + case BLE_GAP_EVT_AUTH_STATUS: + // Generate new LESC key pair and OOB data + if ((m_pairing_mode == NFC_PAIRING_MODE_LESC_OOB) || + (m_pairing_mode == NFC_PAIRING_MODE_LESC_JUST_WORKS) || + (m_pairing_mode == NFC_PAIRING_MODE_GENERIC_OOB)) + { + err_code = generate_lesc_keys(); + if (err_code != NRF_ERROR_BUSY) + { + APP_ERROR_CHECK(err_code); + } + } + break; + + default: + break; + } +} + +ret_code_t nfc_ble_pair_on_pm_params_req(pm_evt_t const * p_evt) +{ + ret_code_t err_code = NRF_SUCCESS; + + NRF_LOG_DEBUG("PM_EVT_CONN_SEC_PARAMS_REQ"); + + // Dynamic security parameters changes are needed only + // by NFC_PAIRING_MODE_GENERIC_OOB pairing mode. + if (m_pairing_mode == NFC_PAIRING_MODE_GENERIC_OOB) + { + // Check if pointer to the Peer Manager event is not NULL. + VERIFY_PARAM_NOT_NULL(p_evt); + + // Set up proper MITM, OOB and LESC flags depending on peer LESC flag + // to support either Legacy OOB or LESC OOB pairing mode. + if (p_evt->params.conn_sec_params_req.p_peer_params->lesc) + { + NRF_LOG_DEBUG("LESC OOB mode flags set."); + + m_sec_param.mitm = 0; + m_sec_param.oob = 0; + m_sec_param.lesc = 1; + } + else + { + NRF_LOG_DEBUG("Legacy OOB mode flags set."); + + m_sec_param.mitm = 1; + m_sec_param.oob = 1; + m_sec_param.lesc = 0; + } + + // Reply with new security parameters to the Peer Manager. + err_code = pm_conn_sec_params_reply(p_evt->conn_handle, + &m_sec_param, + p_evt->params.conn_sec_params_req.p_context); + } + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_BLE_PAIR_LIB) diff --git a/libraries/nfc/src/ndef/nfc_ble_pair_lib.h b/libraries/nfc/src/ndef/nfc_ble_pair_lib.h new file mode 100644 index 000000000..9452fe3de --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_pair_lib.h @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_BLE_PAIR_LIB_H__ +#define NFC_BLE_PAIR_LIB_H__ + +#include +#include "util/sdk_errors.h" +#include "ble.h" +#include "ble_advertising.h" +#include "peer_manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @addtogroup nfc_api + * + * @defgroup nfc_ble_pair_lib NFC BLE Pairing Library + * @ingroup nfc_api + * @brief @tagAPI52 High-level library for BLE Connection Handover pairing using NFC. + * @{ + */ + +/** + * @brief NFC pairing types. + */ +typedef enum +{ + NFC_PAIRING_MODE_JUST_WORKS, /**< Legacy Just Works pairing without a security key. */ + NFC_PAIRING_MODE_OOB, /**< Legacy OOB pairing with a Temporary Key shared through NFC tag data. */ + NFC_PAIRING_MODE_LESC_JUST_WORKS, /**< LESC pairing without authentication data. */ + NFC_PAIRING_MODE_LESC_OOB, /**< LESC pairing with OOB authentication data. */ + NFC_PAIRING_MODE_GENERIC_OOB, /**< OOB pairing with fallback from LESC to Legacy mode. */ + NFC_PAIRING_MODE_CNT /**< Number of available pairing modes. */ +} nfc_pairing_mode_t; + +/** + * @brief Funtion for initializing NFC tag data and turning on tag emulation. + * + * @warning It is assumed that Peer Manager has already been initialized before calling this function. + * It is also assumed that BLE advertising has already been initialized and it is configured + * to run in the BLE_ADV_MODE_FAST mode. + * + * @param[in] mode Pairing mode, this is the value of the @ref nfc_pairing_mode_t enum. + * @param[in] p_advertising Pointer to the advertising module instance. + * + * @retval NRF_SUCCESS If NFC has been initialized properly. + * @retval NRF_ERROR_INVALID_PARAM If pairing mode is invalid. + * @retval NRF_ERROR_NULL If pointer to the advertising module instance is NULL. + * @retval Other Other error codes might be returned depending on used modules. + */ +ret_code_t nfc_ble_pair_init(ble_advertising_t * const p_advertising, nfc_pairing_mode_t mode); + +/** + * @brief Function for setting pairing data and BLE security mode. + * + * @param[in] mode New pairing mode, this is the value of the @ref nfc_pairing_mode_t enum. + * + * @retval NRF_SUCCESS If new pairing mode has been set correctly. + * @retval NRF_ERROR_INVALID_PARAM If pairing mode is invalid. + * @retval Other Other error codes might be returned depending on used modules. + */ +ret_code_t nfc_ble_pair_mode_set(nfc_pairing_mode_t mode); + +/** + * @brief Function for obtaining the current pairing mode. + * + * @return Current pairing mode. + */ +nfc_pairing_mode_t nfc_ble_pair_mode_get(void); + +/** + * @brief Function for replying to @ref PM_EVT_CONN_SEC_PARAMS_REQ. + * + * @details This function is used to allow dynamic changes in the Peer Manager + * security parameters depending on security parameters + * obtained from the peer. This is essential for dynamic switching + * between Legacy OOB and LESC OOB pairing modes when pairing + * library works in @ref NFC_PAIRING_MODE_GENERIC_OOB mode. + * + * @note This function invokes the @ref pm_conn_sec_params_reply function. + * + * @param[in] p_evt Pointer to the Peer Manager event struct with + * information about peer security parameters. + * + * @retval NRF_SUCCESS If proper reply has been sent or library does not need to reply. + * @retval NRF_ERROR_NULL If pointer to the Peer Manager event is NULL. + * @retval Other Other error codes might be returned by the @ref pm_conn_sec_params_reply function. + */ +ret_code_t nfc_ble_pair_on_pm_params_req(pm_evt_t const * p_evt); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_BLE_PAIR_LIB_H__ diff --git a/libraries/nfc/src/ndef/nfc_ble_pair_msg.c b/libraries/nfc/src/ndef/nfc_ble_pair_msg.c new file mode 100644 index 000000000..131514aad --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_pair_msg.c @@ -0,0 +1,411 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_BLE_PAIR_MSG) + +#include "nfc_ble_pair_msg.h" +#include "nfc_hs_rec.h" +#include "nfc_ac_rec.h" +#include "nfc_le_oob_rec.h" +#include "nfc_ep_oob_rec.h" +#include "nfc_ndef_msg.h" +#include "util/sdk_macros.h" + +/** + * @brief Descriptor of TK value locations in Connection Handover NDEF message. + */ +typedef struct +{ + uint8_t ** pp_tk_group; /**< Pointer to array of pointer with TK locations in CH NDEF message. */ + uint8_t tk_num; /**< Number of valid TK locations. */ + uint8_t tk_max_num; /**< Maximal number of possible TK locations. */ +} nfc_ble_tk_group_t; + +/** + * @brief Descriptor of LESC OOB data in Connection Handover NDEF message. + */ +typedef struct +{ + uint8_t * confirm; /**< Pointer to the LESC OOB confirmation value in the CH NDEF message. */ + uint8_t * random; /**< Pointer to the LESC OOB random value in the CH NDEF message. */ +} nfc_ble_lesc_data_pos_t; + +static nfc_ble_lesc_data_pos_t m_lesc_pos = {NULL, NULL}; /**< Descriptor used to update LESC keys in the NDEF Message */ +static nfc_ble_tk_group_t m_tk_group; /**< Descriptor used to find TK locations in the NDEF Message which require update. */ +static bool m_tk_modifier_on = false; /**< Flag indicating that TK modifier feature is on. */ + +/* Default value for Security Manager Out Of Band Flags field in BLE AD structure */ +/* which is used for EP OOB Record payload */ +static const uint8_t sec_mgr_oob_flags = + (AD_TYPE_SEC_MGR_OOB_FLAG_SET << AD_TYPE_SEC_MGR_OOB_FLAG_OOB_DATA_PRESENT_POS) | + (AD_TYPE_SEC_MGR_OOB_FLAG_SET << AD_TYPE_SEC_MGR_OOB_FLAG_OOB_LE_SUPPORTED_POS) | + (AD_TYPE_SEC_MGR_OOB_FLAG_CLEAR << AD_TYPE_SEC_MGR_OOB_FLAG_SIM_LE_AND_EP_POS) | + (AD_TYPE_SEC_MGR_OOB_ADDRESS_TYPE_RANDOM << AD_TYPE_SEC_MGR_OOB_FLAG_ADDRESS_TYPE_POS); + +/**@brief Function for configuring TK group modifier feature. + * + * @details This function configures the structure which is responsible for tracking TK locations. + * These locations can be afterwards easily accessed with @ref nfc_tk_group_modifier_update + * and modified. + * + * @param[in] pp_tk_group Pointer to array of TK locations that should be modified with + * @ref nfc_tk_group_modifier_update function. + * @param[in] max_group_size Maximal number of TK locations that can added to \p pp_tk_group. + */ +__STATIC_INLINE void nfc_tk_group_modifier_config(uint8_t ** pp_tk_group, uint8_t max_group_size) +{ + m_tk_group.pp_tk_group = pp_tk_group; + m_tk_group.tk_num = 0; + m_tk_group.tk_max_num = max_group_size; +} + +/** @brief Function for creating an AD structure with common configuration for EP and LE OOB records. + * + * This function creates an AD structure and initializes its fields with default content. Only + * fields that are common for both EP and LE OOB records are filled. + * + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK field of the returned AD structure is empty. + * @param[out] p_adv_data Pointer to BLE AD structure with common configuration for EP + * and LE OOB records. + */ +static void common_adv_data_create(ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + ble_advdata_t * const p_adv_data) +{ + memset((uint8_t *) p_adv_data, 0, sizeof(ble_advdata_t)); + + /* Set common configuration of AD structure for both Bluetooth EP and LE record */ + p_adv_data->include_appearance = true; + p_adv_data->name_type = BLE_ADVDATA_FULL_NAME; + p_adv_data->p_tk_value = NULL; + if (p_tk_value != NULL) + { + p_adv_data->p_tk_value = p_tk_value; + } + + p_adv_data->p_lesc_data = p_lesc_data; +} + +/** @brief Function for creating an AD structure with default configuration for an LE OOB record. + * + * This function creates an AD structure and initializes its fields with default content for + * LE OOB record payload. + * + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK field of the returned AD structure is empty. + * @param[out] p_le_adv_data Pointer to BLE AD structure with default configuration + * for LE OOB record. + */ +static void le_oob_specific_adv_data_create(ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + ble_advdata_t * const p_le_adv_data) +{ + /* Create default configuration which is common for both EP and LE OOB Records */ + common_adv_data_create(p_tk_value, p_lesc_data, p_le_adv_data); + + /* LE specific configuration */ + p_le_adv_data->include_ble_device_addr = true; + p_le_adv_data->le_role = BLE_ADVDATA_ROLE_ONLY_PERIPH; + p_le_adv_data->flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; +} + +/** @brief Function for creating an AD structure with default configuration for an EP OOB record. + * + * This function creates an AD structure and initializes its fields with default content for + * EP OOB record payload. + * + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK field of the returned AD structure is empty. + * @param[out] p_ep_adv_data Pointer to BLE AD structure with default configuration + * for EP OOB record. + */ +static void ep_oob_specific_adv_data_create(ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + ble_advdata_t * const p_ep_adv_data) +{ + /* Create default configuration which is common for both EP and LE OOB Records */ + common_adv_data_create(p_tk_value, p_lesc_data, p_ep_adv_data); + + /* EP specific configuration */ + p_ep_adv_data->p_sec_mgr_oob_flags = (uint8_t *) &sec_mgr_oob_flags; +} + +ret_code_t nfc_ble_simplified_le_oob_msg_encode(ble_advdata_t const * const p_le_advdata, + uint8_t * p_buf, + uint32_t * p_len) +{ + ret_code_t err_code; + + /* Create NFC NDEF message description, capacity - 1 record */ + NFC_NDEF_MSG_DEF(nfc_le_oob_msg, 1); + + /* Create NFC NDEF LE OOB Record description without record ID field */ + NFC_NDEF_LE_OOB_RECORD_DESC_DEF(nfc_le_oob_rec, 0, p_le_advdata); + + /* Add LE OOB Record as lone record to message */ + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_le_oob_msg), + &NFC_NDEF_LE_OOB_RECORD_DESC(nfc_le_oob_rec)); + VERIFY_SUCCESS(err_code); + VERIFY_PARAM_NOT_NULL(p_le_advdata); + + if (!m_tk_modifier_on) + { + nfc_tk_group_modifier_config(NULL, 0); + } + + /* Encode whole message into buffer */ + err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_le_oob_msg), + p_buf, + p_len); + + return err_code; +} + +ret_code_t nfc_ble_simplified_ep_oob_msg_encode(ble_advdata_t const * const p_ep_advdata, + uint8_t * p_buf, + uint32_t * p_len) +{ + ret_code_t err_code; + + /* Create NFC NDEF message description, capacity - 1 record */ + NFC_NDEF_MSG_DEF(nfc_ep_oob_msg, 1); + + /* Create NFC NDEF EP OOB Record description without record ID field */ + NFC_NDEF_EP_OOB_RECORD_DESC_DEF(nfc_ep_oob_rec, 0, p_ep_advdata); + + /* Add EP OOB Record as lone record to message */ + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_ep_oob_msg), + &NFC_NDEF_EP_OOB_RECORD_DESC(nfc_ep_oob_rec)); + VERIFY_SUCCESS(err_code); + VERIFY_PARAM_NOT_NULL(p_ep_advdata); + + if (!m_tk_modifier_on) + { + nfc_tk_group_modifier_config(NULL, 0); + } + + /* Encode whole message into buffer */ + err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_ep_oob_msg), + p_buf, + p_len); + + return err_code; +} + +ret_code_t nfc_ble_full_handover_select_msg_encode(ble_advdata_t const * const p_le_advdata, + ble_advdata_t const * const p_ep_advdata, + uint8_t * p_buf, + uint32_t * p_len) +{ + ret_code_t err_code; + + // Carrier reference buffers for ac records. + uint8_t carrier_le_reference = '0'; + uint8_t carrier_ep_reference = '1'; + + // Create ac records for both message types. + NFC_NDEF_AC_RECORD_DESC_DEF(ac_rec_le, NFC_AC_CPS_ACTIVE, 1, &carrier_le_reference, 1); + NFC_NDEF_AC_RECORD_DESC_DEF(ac_rec_ep, NFC_AC_CPS_ACTIVE, 1, &carrier_ep_reference, 1); + + // Create a Hs record and assign existing ac records to it. + NFC_NDEF_HS_RECORD_DESC_DEF(hs_rec, 1, 3, 2); + err_code = nfc_hs_rec_local_record_add(&NFC_NDEF_HS_RECORD_DESC(hs_rec), + &NFC_NDEF_AC_RECORD_DESC(ac_rec_le)); + VERIFY_SUCCESS(err_code); + err_code = nfc_hs_rec_local_record_add(&NFC_NDEF_HS_RECORD_DESC(hs_rec), + &NFC_NDEF_AC_RECORD_DESC(ac_rec_ep)); + VERIFY_SUCCESS(err_code); + + // Create LE and EP records with different record IDs. + NFC_NDEF_LE_OOB_RECORD_DESC_DEF(nfc_le_oob_rec, carrier_le_reference, p_le_advdata); + NFC_NDEF_EP_OOB_RECORD_DESC_DEF(nfc_ep_oob_rec, carrier_ep_reference, p_ep_advdata); + + // Create full NDEF Handover Select message for Connection Handover and assign Hs, + // LE and EP records to it. + NFC_NDEF_MSG_DEF(nfc_hs_full_msg, 3); + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_hs_full_msg), + &NFC_NDEF_HS_RECORD_DESC(hs_rec)); + VERIFY_SUCCESS(err_code); + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_hs_full_msg), + &NFC_NDEF_LE_OOB_RECORD_DESC(nfc_le_oob_rec)); + VERIFY_SUCCESS(err_code); + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_hs_full_msg), + &NFC_NDEF_EP_OOB_RECORD_DESC(nfc_ep_oob_rec)); + VERIFY_SUCCESS(err_code); + + VERIFY_PARAM_NOT_NULL(p_le_advdata); + VERIFY_PARAM_NOT_NULL(p_ep_advdata); + + if (!m_tk_modifier_on) + { + nfc_tk_group_modifier_config(NULL, 0); + } + + /* Encode whole message into buffer */ + err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_hs_full_msg), + p_buf, + p_len); + + return err_code; +} + +ret_code_t nfc_ble_pair_default_msg_encode(nfc_ble_pair_type_t nfc_ble_pair_type, + ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + uint8_t * p_buf, + uint32_t * p_len) +{ + ble_advdata_t le_adv_data; + ble_advdata_t ep_adv_data; + ret_code_t err_code = NRF_SUCCESS; + + switch (nfc_ble_pair_type) + { + + case NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT: + le_oob_specific_adv_data_create(p_tk_value, p_lesc_data, &le_adv_data); + err_code = nfc_ble_simplified_le_oob_msg_encode(&le_adv_data, p_buf, p_len); + break; + + case NFC_BLE_PAIR_MSG_BLUETOOTH_EP_SHORT: + ep_oob_specific_adv_data_create(p_tk_value, NULL, &ep_adv_data); + err_code = nfc_ble_simplified_ep_oob_msg_encode(&ep_adv_data, p_buf, p_len); + break; + + case NFC_BLE_PAIR_MSG_FULL: + le_oob_specific_adv_data_create(p_tk_value, p_lesc_data, &le_adv_data); + ep_oob_specific_adv_data_create(p_tk_value, NULL, &ep_adv_data); + err_code = nfc_ble_full_handover_select_msg_encode(&le_adv_data, + &ep_adv_data, + p_buf, + p_len); + break; + + } + + return err_code; +} + +ret_code_t nfc_ble_pair_msg_updatable_tk_encode(nfc_ble_pair_type_t nfc_ble_pair_type, + ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + uint8_t * p_buf, + uint32_t * p_len, + uint8_t ** pp_tk_group, + uint8_t max_group_size) +{ + ret_code_t err_code = NRF_SUCCESS; + + m_tk_modifier_on = true; + nfc_tk_group_modifier_config(pp_tk_group, max_group_size); + err_code = nfc_ble_pair_default_msg_encode(nfc_ble_pair_type, p_tk_value, + p_lesc_data, p_buf, p_len); + m_tk_modifier_on = false; + + return err_code; +} + +ret_code_t nfc_tk_group_modifier_update(ble_advdata_tk_value_t * p_tk_value) +{ + VERIFY_PARAM_NOT_NULL(m_tk_group.pp_tk_group); + for (uint8_t tk_index = 0; tk_index < m_tk_group.tk_num; ++tk_index) + { + uint8_t * p_tk_payload_data = m_tk_group.pp_tk_group[tk_index]; + nfc_tk_value_payload_encode(p_tk_value, p_tk_payload_data); + } + return NRF_SUCCESS; +} + +ret_code_t nfc_tk_to_group_add(uint8_t * p_tk_location) +{ + // Feature was disabled. + if (m_tk_group.pp_tk_group == NULL) + { + return NRF_SUCCESS; + } + + if (m_tk_group.tk_num < m_tk_group.tk_max_num) + { + m_tk_group.pp_tk_group[m_tk_group.tk_num++] = p_tk_location; + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NO_MEM; + } +} + +ret_code_t nfc_lesc_pos_set(uint8_t * p_confirm, uint8_t * p_random) +{ + if ((p_confirm != NULL) && (p_random != NULL)) + { + m_lesc_pos.confirm = p_confirm; + m_lesc_pos.random = p_random; + + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NULL; + } +} + +ret_code_t nfc_lesc_data_update(ble_gap_lesc_oob_data_t * p_ble_lesc_oob_data) +{ + if (p_ble_lesc_oob_data != NULL) + { + if ((m_lesc_pos.confirm != NULL) && (m_lesc_pos.random != NULL)) + { + memcpy(m_lesc_pos.confirm, p_ble_lesc_oob_data->c, AD_TYPE_CONFIRM_VALUE_DATA_SIZE); + memcpy(m_lesc_pos.random, p_ble_lesc_oob_data->r, AD_TYPE_RANDOM_VALUE_DATA_SIZE); + + return NRF_SUCCESS; + } + + return NRF_ERROR_INVALID_STATE; + } + else + { + return NRF_ERROR_NULL; + } +} + +#endif // NRF_MODULE_ENABLED(NFC_BLE_PAIR_MSG) diff --git a/libraries/nfc/src/ndef/nfc_ble_pair_msg.h b/libraries/nfc/src/ndef/nfc_ble_pair_msg.h new file mode 100644 index 000000000..0a1db7527 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ble_pair_msg.h @@ -0,0 +1,279 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_BLE_PAIR_MSG_H__ +#define NFC_BLE_PAIR_MSG_H__ + +/**@file + * + * @defgroup nfc_modules NDEF message modules + * @ingroup nfc_api + * @brief Implementation of NDEF messages. + * + * @defgroup nfc_ndef_messages Predefined NDEF messages + * @ingroup nfc_modules + * @brief Predefined NDEF messages for standard use. + * + * @defgroup nfc_ble_pair_msg BLE pairing messages + * @{ + * @ingroup nfc_ndef_messages + * + * @brief Generation of NFC NDEF messages used for BLE pairing. + * + */ + +#include +#include "util/ble_advdata.h" +#include "util/sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Types of BLE pairing message. + * + * Use one of these values to choose the type of NDEF BLE pairing message. + */ +typedef enum +{ + NFC_BLE_PAIR_MSG_BLUETOOTH_LE_SHORT, ///< Simplified LE OOB message. + NFC_BLE_PAIR_MSG_BLUETOOTH_EP_SHORT, ///< Simplified EP OOB message. + NFC_BLE_PAIR_MSG_FULL ///< BLE Handover Select Message. +} nfc_ble_pair_type_t; + +/** @brief Function for encoding simplified LE OOB messages. + * + * This function encodes a simplified LE OOB message into a buffer. The payload of the LE OOB record + * inside the message can be configured via the advertising data structure. + * + * This function was implemented partially according to "Bluetooth Secure Simple Pairing Using NFC" + * (denotation "NFCForum-AD-BTSSP_1_1" published on 2014-01-09) chapters 3.1, 3.2, 4.3.2, + * and according to "Supplement to the Bluetooth Core Specification" (Version 5, adoption date: + * Dec 02 2014). + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] p_le_advdata Pointer to the BLE advertising data structure for the LE OOB record. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_simplified_le_oob_msg_encode(ble_advdata_t const * const p_le_advdata, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding simplified EP OOB messages. + * + * This function encodes a simplified EP OOB message into a buffer. The payload of the EP OOB record + * inside the message can be configured via the advertising data structure. + * + * This function was implemented partially according to "Bluetooth Secure Simple Pairing Using NFC" + * (denotation "NFCForum-AD-BTSSP_1_1" published on 2014-01-09) chapters 3.1, 3.2, 4.3.1, + * and according to "Supplement to the Bluetooth Core Specification" (Version 5, adoption date: + * Dec 02 2014). + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] p_ep_advdata Pointer to the BLE advertising data structure for the EP OOB record. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_simplified_ep_oob_msg_encode(ble_advdata_t const * const p_ep_advdata, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding BLE Handover Select Messages. + * + * This function encodes a BLE Handover Select Message into a buffer. The payload of the LE OOB record + * and the EP OOB record inside the message can be configured via the advertising data structures. + * + * This function was implemented partially according to "Bluetooth Secure Simple Pairing Using NFC" + * (denotation "NFCForum-AD-BTSSP_1_1" published on 2014-01-09) chapters 3.1, 3.2, 4.1.1 + * and 4.1.2 (combined), and according to "Supplement to the Bluetooth Core Specification" (Version 5, + * adoption date: Dec 02 2014). + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] p_le_advdata Pointer to the BLE advertising data structure for the LE OOB record. + * @param[in] p_ep_advdata Pointer to the BLE advertising data structure for the EP OOB record. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_full_handover_select_msg_encode(ble_advdata_t const * const p_le_advdata, + ble_advdata_t const * const p_ep_advdata, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding any type of BLE pairing messages with default BLE + * advertising data structures. + * + * This function encodes a BLE pairing message into a buffer. The message can be encoded as + * one of the three message types (using @ref nfc_ble_simplified_le_oob_msg_encode, + * @ref nfc_ble_simplified_ep_oob_msg_encode, or @ref nfc_ble_full_handover_select_msg_encode), + * according to the @p nfc_ble_pair_type parameter. LE and EP OOB records use the default + * advertising data structure configuration. Only one field ('Security Manager TK') in the BLE + * advertising data can be configured for both records by specifying the @p p_tk_value parameter. + * + * For LE OOB records, the default BLE advertising data structure configuration fills the required + * fields 'LE Bluetooth Device Address' and 'LE Role' and the optional fields 'Appearance', + * 'Local Name', and 'Flags'. + * + * For EP OOB records, the default BLE advertising data structure configuration fills the required + * field 'Security Manager Out Of Band Flags' and the optional fields 'Appearance', + * 'Local Name', and 'Flags'. + * + * @note To be able to encode the message, a SoftDevice must be enabled and configured. + * + * @param[in] nfc_ble_pair_type Type of BLE pairing message. + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK value field is not encoded in the NDEF message. + * @param[in] p_lesc_data Pointer to the LESC OOB data. If NULL, LESC OOB fields are + * not encoded in the NDEF message. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_pair_default_msg_encode(nfc_ble_pair_type_t nfc_ble_pair_type, + ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + uint8_t * p_buf, + uint32_t * p_len); + +/** @brief Function for encoding any type of BLE pairing messages with default BLE + * advertising data structures and with TK modifier feature. + * + * This function is very similar to the @ref nfc_ble_pair_default_msg_encode function, but + * additionaly enables tracking of TK locations which were encoded in the Connection Handover + * NDEF message. After using this function, you can update the TK value in NDEF by calling + * @ref nfc_tk_group_modifier_update. + * + * @param[in] nfc_ble_pair_type Type of BLE pairing message. + * @param[in] p_tk_value Pointer to the authentication Temporary Key (TK). If NULL, + * TK value field is not encoded in the NDEF message. + * @param[in] p_lesc_data Pointer to the LESC OOB data. If NULL, LESC OOB values are + * not encoded in the NDEF message. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * @param[in] pp_tk_group Pointer to array of TK locations that should be modified with + * @ref nfc_tk_group_modifier_update function. + * @param[in] max_group_size Maximal number of TK locations that can added to \p pp_tk_group. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +ret_code_t nfc_ble_pair_msg_updatable_tk_encode(nfc_ble_pair_type_t nfc_ble_pair_type, + ble_advdata_tk_value_t * const p_tk_value, + ble_gap_lesc_oob_data_t * const p_lesc_data, + uint8_t * p_buf, + uint32_t * p_len, + uint8_t ** pp_tk_group, + uint8_t max_group_size); + +/**@brief Function for updating the Connection Handover NDEF message with new TK value. + * + * @details This function updates NDEF message with new TK value. This update is applied to all of + * TK locations in the Connection Handover NDEF message. This function can only be used + * after calling @ref nfc_ble_pair_msg_updatable_tk_encode, which is used to encode + * Connection Handover NDEF message. + * + * @param[in] p_tk_value Pointer to the new TK value. The NDEF message will be updated with this + * value. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If pointer to TK locations was NULL. + */ +ret_code_t nfc_tk_group_modifier_update(ble_advdata_tk_value_t * p_tk_value); + +/**@brief Function for adding new location of TK value to the location description structure. + * + * @param[in] p_tk_location New location of TK value in the Connection Handover NDEF message. + * + * @retval NRF_SUCCESS If the operation was successful or if buffer used for holding TK + * locations is NULL. + * @retval NRF_ERROR_NO_MEM If there is no place in the buffer for the new TK value location. + */ +ret_code_t nfc_tk_to_group_add(uint8_t * p_tk_location); + +/**@brief Function for updating the Connection Handover NDEF message with a new LESC OOB values. + * + * @details Updates LESC Confirmation and Random Values based on its locations set by the @ref nfc_lesc_pos_set function. + * + * @param[in] p_ble_lesc_oob_data Pointer to the new LESC OOB data. The NDEF message will be updated with this data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If pointer to the new LESC OOB data is NULL. + * @retval NRF_ERROR_INVALID_STATE If pointer to the LESC OOB data location in NDEF message is NULL. + */ +ret_code_t nfc_lesc_data_update(ble_gap_lesc_oob_data_t * p_ble_lesc_oob_data); + +/**@brief Function for storing pointers to the LESC OOB data inside NDEF message. + * + * @details It allows LESC OOB data update without regenerating entire CH NDEF message. + * + * @param[in] p_confirm Pointer to the LESC Confirmation Value position in the NDEF message. + * @param[in] p_random Pointer to the LESC Random Value position in the NDEF message. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If either of pointers is set to NULL. + */ +ret_code_t nfc_lesc_pos_set(uint8_t * p_confirm, uint8_t * p_random); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_BLE_PAIR_MSG_H__ diff --git a/libraries/nfc/src/ndef/nfc_ep_oob_rec.c b/libraries/nfc/src/ndef/nfc_ep_oob_rec.c new file mode 100644 index 000000000..e805c9a27 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ep_oob_rec.c @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_EP_OOB_REC) + +#include "nfc_ep_oob_rec.h" +#include "util/sdk_errors.h" +#include "ble_gap.h" +#include "util/app_util.h" + +/* NFC OOB EP definitions */ +#define NFC_EP_OOB_REC_GAP_ADDR_LEN BLE_GAP_ADDR_LEN +#define NFC_EP_OOB_REC_OOB_DATA_LEN_SIZE 2UL +#define NFC_EP_OOB_REC_PAYLOAD_PREFIX_LEN (NFC_EP_OOB_REC_GAP_ADDR_LEN + \ + NFC_EP_OOB_REC_OOB_DATA_LEN_SIZE) + +/* Record Payload Type for Bluetooth Carrier Configuration EP record */ +const uint8_t ndef_ep_oob_record_type[] = +{ + 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', '/', 'v', 'n', 'd', '.', + 'b', 'l', 'u', 'e', 't', 'o', 'o', 't', 'h', '.', 'e', 'p', '.', 'o', 'o', 'b' +}; + +/** + * @brief Function for validating AD structure content for a Bluetooth Carrier Configuration EP record. + * + * This function validates AD structure content. LE Bluetooth Device Address and LE Role + * fields must not be included. Security Manager OOB Flags structure is required. + * + * @param[in] p_ble_advdata Pointer to the description of the payload. + * + * @retval NRF_SUCCESS If the validation was successful. + * @retval NRF_ERROR_INVALID_PARAM Otherwise. + */ +static ret_code_t nfc_ep_oob_adv_data_check(ble_advdata_t const * const p_ble_advdata) +{ + if ((true == p_ble_advdata->include_ble_device_addr) || + (BLE_ADVDATA_ROLE_NOT_PRESENT != p_ble_advdata->le_role) || + (NULL == p_ble_advdata->p_sec_mgr_oob_flags)) + { + return NRF_ERROR_INVALID_PARAM; + } + + /* If Flags field in AD structure is present, the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag + must be set. */ + if ((0 != p_ble_advdata->flags) && + ((p_ble_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)) + { + return NRF_ERROR_INVALID_PARAM; + } + return NRF_SUCCESS; +} + +/** + * @brief Function for encoding device address to Bluetooth Carrier Configuration EP record. + * + * This fuction is used to encode device address to Bluetooth Carrier Configuration EP record. + * + * @param[in] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in] max_len Available memory in the buffer. + * + * @retval NRF_SUCCESS If the encoding was successful. + * @retval NRF_ERROR_NO_MEM If available memory was not enough. + * @retval NRF_ERROR_xxx If any other error occured. + */ +static ret_code_t nfc_ep_oob_bluetooth_device_address_encode(uint8_t * const p_encoded_data, + uint16_t max_len) +{ + ret_code_t err_code = NRF_SUCCESS; + ble_gap_addr_t device_address; + + memset(&device_address, 0x00, sizeof(device_address)); + + if (NFC_EP_OOB_REC_GAP_ADDR_LEN > max_len) + { + return NRF_ERROR_NO_MEM; + } + + /* Get BLE address */ + err_code = sd_ble_gap_addr_get(&device_address); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + /* Encode Bluetooth EP device address */ + memcpy(p_encoded_data, device_address.addr, NFC_EP_OOB_REC_GAP_ADDR_LEN); + + return NRF_SUCCESS; +} + +ret_code_t nfc_ep_oob_payload_constructor(ble_advdata_t * p_ble_advdata, + uint8_t * p_buff, + uint32_t * p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + uint8_t * p_ad_data = NULL; + uint16_t payload_len, ad_data_len; + + /* Check correctness of the configuration structure */ + err_code = nfc_ep_oob_adv_data_check(p_ble_advdata); + if (NRF_SUCCESS != err_code) + { + return err_code; + } + + if (p_buff != NULL) + { + /* Validate if there is enough memory for OOB payload length field and BLE device address */ + if (NFC_EP_OOB_REC_PAYLOAD_PREFIX_LEN > *p_len) + { + return NRF_ERROR_NO_MEM; + } + + /* Set proper memory offset in payload buffer for AD structure and count available memory. + * Bluetooth EP device address and OOB payload length field must be inserted before the AD payload */ + p_ad_data = (uint8_t *) (p_buff + NFC_EP_OOB_REC_PAYLOAD_PREFIX_LEN); + ad_data_len = *p_len - NFC_EP_OOB_REC_PAYLOAD_PREFIX_LEN; + if ( *p_len - NFC_EP_OOB_REC_PAYLOAD_PREFIX_LEN > UINT16_MAX ) + { + ad_data_len = UINT16_MAX; + } + } + + /* Encode AD structures into NFC record payload */ + err_code = nfc_ble_oob_adv_data_encode(p_ble_advdata, p_ad_data, &ad_data_len); + if (NRF_SUCCESS != err_code) + { + return err_code; + } + + /* Now as the final payload length is known OOB payload length field, and Bluetooth device + * address can be encoded */ + payload_len = ad_data_len + NFC_EP_OOB_REC_PAYLOAD_PREFIX_LEN; + if (p_buff != NULL) + { + p_buff += uint16_encode(payload_len, p_buff); + err_code = nfc_ep_oob_bluetooth_device_address_encode(p_buff, p_ad_data - p_buff); + if (NRF_SUCCESS != err_code) + { + return err_code; + } + } + + /* Update total payload length */ + *p_len = payload_len; + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_EP_OOB_REC) diff --git a/libraries/nfc/src/ndef/nfc_ep_oob_rec.h b/libraries/nfc/src/ndef/nfc_ep_oob_rec.h new file mode 100644 index 000000000..348672546 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ep_oob_rec.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_EP_OOB_REC_H__ +#define NFC_EP_OOB_REC_H__ + +/**@file + * + * @defgroup nfc_ep_oob_rec EP OOB records + * @{ + * @ingroup nfc_ble_pair_msg + * + * @brief Generation of NFC NDEF EP OOB records for NDEF messages. + * + */ + +#include +#include "nfc_ndef_record.h" +#include "nfc_ble_oob_advdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Size of the type field of the Bluetooth Carrier Configuration EP record, defined in the + * file @c nfc_ep_oob_rec.c. It is used in the @ref NFC_NDEF_EP_OOB_RECORD_DESC_DEF macro. + */ +#define NFC_EP_OOB_REC_TYPE_LENGTH 32 + +/** + * @brief External reference to the type field of the Bluetooth Carrier Configuration EP record, defined + * in the file @c nfc_ep_oob_rec.c. It is used in the @ref NFC_NDEF_EP_OOB_RECORD_DESC_DEF macro. + */ +extern const uint8_t ndef_ep_oob_record_type[NFC_EP_OOB_REC_TYPE_LENGTH]; + +/** + * @brief Function for constructing the payload for a Bluetooth Carrier Configuration EP record. + * + * This function encodes the record payload according to the BLE AD structure. It implements + * an API compatible with @ref p_payload_constructor_t. + * + * @param[in] p_ble_advdata Pointer to the description of the payload. + * @param[out] p_buff Pointer to payload destination. If NULL, function will + * calculate the expected size of the record payload. + * + * @param[in,out] p_len Size of available memory to write as input. Size of generated + * payload as output. + * + * @retval NRF_SUCCESS If the record payload was encoded successfully. + * @retval NRF_ERROR_NO_MEM If available memory was not enough for record payload to be encoded. + * @retval Other If any other error occurred during record payload encoding. + */ +ret_code_t nfc_ep_oob_payload_constructor(ble_advdata_t * p_ble_advdata, + uint8_t * p_buff, + uint32_t * p_len); + +/** @brief Macro for generating a description of an NFC NDEF Bluetooth Carrier Configuration EP record. + * + * This macro declares and initializes an instance of an NFC NDEF record description + * for a Bluetooth Carrier Configuration EP record. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_ble_simplified_ep_oob_msg_encode) + * must be done in the same variable scope. + * + * @param[in] NAME Name for accessing record descriptor. + * @param[in] PAYLOAD_ID NDEF record header Payload ID field (Limited to one byte). + * If 0, no ID is present in the record description. + * @param[in] P_BLE_ADVDATA Pointer to the encoded BLE advertising data structure. This + * data is used to create the record payload. + */ +#define NFC_NDEF_EP_OOB_RECORD_DESC_DEF(NAME, \ + PAYLOAD_ID, \ + P_BLE_ADVDATA) \ + uint8_t NAME##_ndef_ep_oob_record_id = (PAYLOAD_ID); \ + uint8_t NAME##_ndef_ep_oob_record_id_length = ((PAYLOAD_ID) != 0) ? 1 : 0; \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF( NAME, \ + TNF_MEDIA_TYPE, \ + &NAME##_ndef_ep_oob_record_id, \ + NAME##_ndef_ep_oob_record_id_length, \ + (ndef_ep_oob_record_type), \ + sizeof(ndef_ep_oob_record_type), \ + nfc_ep_oob_payload_constructor, \ + (P_BLE_ADVDATA)) \ + +/** + * @brief Macro for accessing the NFC NDEF Bluetooth Carrier Configuration EP record descriptor + * instance that was created with @ref NFC_NDEF_EP_OOB_RECORD_DESC_DEF. + */ +#define NFC_NDEF_EP_OOB_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_EP_OOB_REC_H__ diff --git a/libraries/nfc/src/ndef/nfc_hs_rec.c b/libraries/nfc/src/ndef/nfc_hs_rec.c new file mode 100644 index 000000000..9a96f1288 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_hs_rec.c @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_HS_REC) + +#include "nfc_hs_rec.h" +#include "nfc_ac_rec.h" +#include "nrf_error.h" + +#define HS_REC_VERSION_SIZE 1 + +const uint8_t nfc_hs_rec_type_field[] = {'H', 's'}; ///< Handover Select record type. + + +ret_code_t nfc_hs_rec_payload_constructor(nfc_hs_rec_payload_desc_t * p_nfc_hs_rec_payload_desc, + uint8_t * p_buff, + uint32_t * p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (p_buff != NULL) + { + // There must be at least 1 free byte in buffer for version byte. + if (*p_len < HS_REC_VERSION_SIZE) + { + return NRF_ERROR_NO_MEM; + } + + // Major/minor version byte. + *p_buff = ( (p_nfc_hs_rec_payload_desc->major_version << 4) & 0xF0) | + ( p_nfc_hs_rec_payload_desc->minor_version & 0x0F); + p_buff += HS_REC_VERSION_SIZE; + + // Decrement remaining buffer size. + *p_len -= HS_REC_VERSION_SIZE; + } + + // Encode local records encapsulated in a message. + err_code = nfc_ndef_msg_encode(p_nfc_hs_rec_payload_desc->p_local_records, p_buff, p_len); + if (err_code!= NRF_SUCCESS) + { + return err_code; + } + + // Add version byte to the total record size. + *p_len += HS_REC_VERSION_SIZE; + + return NRF_SUCCESS; +} + + +void nfc_hs_rec_local_record_clear(nfc_ndef_record_desc_t * p_hs_rec) +{ + nfc_hs_rec_payload_desc_t* p_hs_payload = + (nfc_hs_rec_payload_desc_t*)p_hs_rec->p_payload_descriptor; + + nfc_ndef_msg_clear(p_hs_payload->p_local_records); +} + + +ret_code_t nfc_hs_rec_local_record_add(nfc_ndef_record_desc_t * p_hs_rec, + nfc_ndef_record_desc_t * p_local_rec) +{ + nfc_hs_rec_payload_desc_t* p_hs_payload = + (nfc_hs_rec_payload_desc_t*)p_hs_rec->p_payload_descriptor; + + return nfc_ndef_msg_record_add(p_hs_payload->p_local_records, p_local_rec); +} + +#endif // NRF_MODULE_ENABLED(NFC_HS_REC) diff --git a/libraries/nfc/src/ndef/nfc_hs_rec.h b/libraries/nfc/src/ndef/nfc_hs_rec.h new file mode 100644 index 000000000..a363e3ca6 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_hs_rec.h @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_HS_REC_H__ +#define NFC_HS_REC_H__ + +/**@file + * + * @defgroup nfc_hs_rec Hs (Handover Select) records + * @{ + * @ingroup nfc_ble_pair_msg + * + * @brief Generation of NFC NDEF Handover Select records for NDEF messages. + * + */ + +#include +#include "nfc_ndef_record.h" +#include "nfc_ndef_msg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Handover Select record payload descriptor. + */ +typedef struct +{ + uint8_t major_version; ///< Major version number of the supported Connection Handover specification. + uint8_t minor_version; ///< Minor version number of the supported Connection Handover specification. + nfc_ndef_msg_desc_t * p_local_records; ///< Pointer to a message encapsulating local records. +} nfc_hs_rec_payload_desc_t; + + +/** + * @brief Constructor for an NFC NDEF Handover Select record payload. + * + * This function encodes the payload of a Handover Select record as specified in the Connection + * Handover standard. It implements an API compatible with @ref p_payload_constructor_t. + */ + +ret_code_t nfc_hs_rec_payload_constructor(nfc_hs_rec_payload_desc_t * p_nfc_hs_rec_payload_desc, + uint8_t * p_buff, + uint32_t * p_len); + +/** + * @brief An external reference to the type field of the Handover Select record, defined in the + * file @c nfc_hs_rec.c. It is used in the @ref NFC_NDEF_HS_RECORD_DESC_DEF macro. + */ +extern const uint8_t nfc_hs_rec_type_field[]; + +/** + * @brief Size of the type field of the Handover Select record, defined in the + * file @c nfc_hs_rec.c. It is used in the @ref NFC_NDEF_HS_RECORD_DESC_DEF macro. + */ +#define NFC_HS_REC_TYPE_LENGTH 2 + +/** + * @brief Macro for creating and initializing an NFC NDEF record descriptor for a Handover Select record. + * + * This macro creates and initializes an instance of type @ref nfc_ndef_record_desc_t and + * an instance of type @ref nfc_hs_rec_payload_desc_t, which together constitute an instance of a Handover Select record. + * + * Use the macro @ref NFC_NDEF_HS_RECORD_DESC to access the NDEF Handover Select record descriptor instance. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_ble_full_handover_select_msg_encode) + * must be done in the same variable scope. + * + * @param[in] NAME Name of the created record descriptor instance. + * @param[in] MAJOR_VERSION Major version number of the supported Connection Handover specification. + * @param[in] MINOR_VERSION Minor version number of the supported Connection Handover specification. + * @param[in] MAX_RECORDS Maximum number of local records (ac records plus optional err record). + */ +#define NFC_NDEF_HS_RECORD_DESC_DEF(NAME, \ + MAJOR_VERSION, \ + MINOR_VERSION, \ + MAX_RECORDS) \ + NFC_NDEF_MSG_DEF(NAME, MAX_RECORDS); \ + nfc_hs_rec_payload_desc_t NAME##_nfc_hs_rec_payload_desc = \ + { \ + .major_version = MAJOR_VERSION, \ + .minor_version = MINOR_VERSION, \ + .p_local_records = &NFC_NDEF_MSG(NAME) \ + }; \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME, \ + TNF_WELL_KNOWN, \ + 0, \ + 0, \ + nfc_hs_rec_type_field, \ + NFC_HS_REC_TYPE_LENGTH, \ + nfc_hs_rec_payload_constructor, \ + &(NAME##_nfc_hs_rec_payload_desc)) + +/** + * @brief Macro for accessing the NFC NDEF Handover Select record descriptor + * instance that was created with @ref NFC_NDEF_HS_RECORD_DESC_DEF. + */ +#define NFC_NDEF_HS_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** + * @brief Function for clearing local records in the NFC NDEF Handover Select record. + * + * This function clears local records from the Handover Select record. + * + * @param[in, out] p_hs_rec Pointer to the Handover Select record descriptor. + */ +void nfc_hs_rec_local_record_clear(nfc_ndef_record_desc_t * p_hs_rec); + +/** + * @brief Function for adding a local record to an NFC NDEF Handover Select record. + * + * @param[in, out] p_hs_rec Pointer to a Handover Select record. + * @param[in] p_local_rec Pointer to a local record to add. + * + * @retval NRF_SUCCESS If the local record was added successfully. + * @retval NRF_ERROR_NO_MEM If the Handover Select record already contains the maximum number of local records. + */ +ret_code_t nfc_hs_rec_local_record_add(nfc_ndef_record_desc_t * p_hs_rec, + nfc_ndef_record_desc_t * p_local_rec); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_HS_REC_H__ diff --git a/libraries/nfc/src/ndef/nfc_launchapp_msg.c b/libraries/nfc/src/ndef/nfc_launchapp_msg.c new file mode 100644 index 000000000..0fc5ec200 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_launchapp_msg.c @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_LAUNCHAPP_MSG) + +#include +#include +#include "nfc_launchapp_rec.h" +#include "nfc_launchapp_msg.h" +#include "nrf_error.h" +#include "util/sdk_macros.h" + +ret_code_t nfc_launchapp_msg_encode(uint8_t const * p_android_package_name, + uint8_t android_package_name_length, + uint8_t const * p_win_app_id, + uint8_t win_app_id_length, + uint8_t * p_buf, + uint32_t * p_len) +{ + ret_code_t err_code; + + /* Create NFC NDEF message description, capacity - 2 records */ + NFC_NDEF_MSG_DEF(nfc_launchapp_msg, 2); + + /* Create NFC NDEF Windows Phone LaunchApp Record description */ + NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF(nfc_win_launchapp_rec, + p_win_app_id, + win_app_id_length); + + /* Create NFC NDEF Android Application Record description */ + NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC_DEF(nfc_and_launchapp_rec, + p_android_package_name, + android_package_name_length); + + if (p_win_app_id != NULL) + { + /* Add Windows Phone LaunchApp Record as first record to message */ + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_launchapp_msg), + &NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC(nfc_win_launchapp_rec)); + VERIFY_SUCCESS(err_code); + } + if (p_android_package_name != NULL) + { + /* Add Android Application Record as second record to message */ + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_launchapp_msg), + &NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC(nfc_and_launchapp_rec)); + VERIFY_SUCCESS(err_code); + } + VERIFY_FALSE(NFC_NDEF_MSG(nfc_launchapp_msg).record_count == 0, + NRF_ERROR_INVALID_PARAM); + + /* Encode whole message into buffer */ + err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_launchapp_msg), + p_buf, + p_len); + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_LAUNCHAPP_MSG) diff --git a/libraries/nfc/src/ndef/nfc_launchapp_msg.h b/libraries/nfc/src/ndef/nfc_launchapp_msg.h new file mode 100644 index 000000000..bdfaaacd7 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_launchapp_msg.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_LAUNCHAPP_MSG_H__ +#define NFC_LAUNCHAPP_MSG_H__ + +/** @file + * + * @defgroup nfc_launchapp_msg Launch app messages + * @{ + * @ingroup nfc_ndef_messages + * + * @brief Generation of NFC NDEF messages that can be used to launch apps. + * + */ + +#include +#include "nfc_ndef_msg.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @brief Function for encoding an NFC NDEF launch app message. + * + * This function encodes an NFC NDEF message into a buffer. + * + * @param[in] p_android_package_name Pointer to the Android package name string. + * If NULL, the Android Application Record will be skipped. + * @param[in] android_package_name_length Length of the Android package name. + * @param[in] p_win_app_id Pointer to the Windows application ID string (GUID). + * If NULL, the Windows LaunchApp record will be skipped. + * @param[in] win_app_id_length Length of the Windows application ID. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the description was successfully created. + * @retval NRF_ERROR_INVALID_PARAM If both p_android_package_name and windows_application_id were + * invalid (equal to NULL). + * @retval NRF_ERROR_NO_MEM If the predicted message size is bigger than the provided + * buffer space. + * @retval Other Other codes might be returned depending on + * the function @ref nfc_ndef_msg_encode + */ +ret_code_t nfc_launchapp_msg_encode(uint8_t const * p_android_package_name, + uint8_t android_package_name_length, + uint8_t const * p_win_app_id, + uint8_t win_app_id_length, + uint8_t * p_buf, + uint32_t * p_len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + #endif // NFC_LAUNCHAPP_MSG_H__ + + diff --git a/libraries/nfc/src/ndef/nfc_launchapp_rec.c b/libraries/nfc/src/ndef/nfc_launchapp_rec.c new file mode 100644 index 000000000..0e804fcd2 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_launchapp_rec.c @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_LAUNCHAPP_REC) + +#include "nfc_launchapp_rec.h" +#include +#include "nrf_error.h" +#include "util/app_util.h" +#include "nfc_ndef_record.h" + +/* Record Payload Type for NFC NDEF Android Application Record */ +const uint8_t ndef_android_launchapp_rec_type[] = +{ + 'a', 'n', 'd', 'r', 'o', 'i', 'd', '.', 'c','o', 'm', ':', 'p', 'k', 'g' +}; + +/* Record Payload Type for NFC NDEF Windows LaunchApp record */ +const uint8_t ndef_windows_launchapp_rec_type[] = +{ + 'w', 'i', 'n', 'd', 'o', 'w', 's', '.', 'c', 'o', 'm', '/', 'L', 'a', 'u', + 'n', 'c', 'h', 'A', 'p', 'p' +}; +/* Platform type used in Record Payload of NFC NDEF Windows LaunchApp record */ +const uint8_t ndef_windows_launchapp_plat_type[] = +{ + 'W', 'i', 'n', 'd', 'o', 'w', 's', 'P', 'h', 'o', 'n', 'e' +}; + +#define WIN_LAUNCHAPP_EMPTY_PARAMETER 0x20 ///< The empty parameter value for the Windows LaunchApp Record. + +ret_code_t nfc_win_launchapp_payload_constructor(win_launchapp_payload_desc_t * p_input, + uint8_t * p_buff, + uint32_t * p_len) +{ + + win_launchapp_payload_desc_t * launch_desc = (win_launchapp_payload_desc_t *) p_input; + + uint32_t temp_len = (uint32_t)launch_desc->platform_length + launch_desc->app_id_length + 7; + + if (p_buff != NULL) + { + if (temp_len > *p_len) + { + return NRF_ERROR_NO_MEM; + } + + *p_buff++ = 0x00; // platform count: 1 + *p_buff++ = 0x01; // -||- + + *p_buff++ = launch_desc->platform_length; + memcpy(p_buff, launch_desc->platform, launch_desc->platform_length); // platform + p_buff += launch_desc->platform_length; + + + *p_buff++ = launch_desc->app_id_length; + memcpy(p_buff, launch_desc->app_id, launch_desc->app_id_length); + p_buff += launch_desc->app_id_length; + + *p_buff++ = 0x00; // parameters length 1B + *p_buff++ = 0x01; // -||- + *p_buff++ = WIN_LAUNCHAPP_EMPTY_PARAMETER; // empty parameter + } + + *p_len = temp_len; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_LAUNCHAPP_REC) diff --git a/libraries/nfc/src/ndef/nfc_launchapp_rec.h b/libraries/nfc/src/ndef/nfc_launchapp_rec.h new file mode 100644 index 000000000..a7071912c --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_launchapp_rec.h @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_LAUNCHAPP_REC_H__ +#define NFC_LAUNCHAPP_REC_H__ + +/**@file + * + * @defgroup nfc_launchapp_rec Launch app records + * @{ + * @ingroup nfc_launchapp_msg + * + * @brief Generation of NFC NDEF record descriptions that launch apps. + * + */ + +#include +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Size of the type field of the Android Application Record, defined in the file + * @c nfc_launchapp_rec.c. It is used in the @ref NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC macro. + */ +#define NFC_ANDROID_REC_TYPE_LENGTH 15 + +/** + * @brief Size of the type field of the Windows LaunchApp Record, defined in the file + * @c nfc_launchapp_rec.c. It is used in the @ref NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF macro. + */ +#define NFC_WINDOWS_REC_TYPE_LENGTH 21 + +/** + * @brief Size of the platform type, which is used to encode payload field of the Windows LaunchApp + * Record, defined in the file @c nfc_launchapp_rec.c. It is used in the + * @ref NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF macro. + */ +#define NFC_WINDOWS_PLAT_TYPE_LENGTH 12 + +/** + * @brief Type of description of payload of Windows LaunchApp record. + */ +typedef struct +{ + const uint8_t * platform; + uint8_t platform_length; + const uint8_t * app_id; + uint8_t app_id_length; +} win_launchapp_payload_desc_t; + +/** + * @brief External reference to the type field of the NFC NDEF Android Application Record, defined in the + * file @c nfc_launchapp_rec.c. It is used in the @ref NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC_DEF macro. + */ +extern const uint8_t ndef_android_launchapp_rec_type[NFC_ANDROID_REC_TYPE_LENGTH]; + +/** + * @brief External reference to the type field of the NFC NDEF Windows LaunchApp record, defined in the + * file @c nfc_launchapp_rec.c. It is used in the @ref NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF macro. + */ +extern const uint8_t ndef_windows_launchapp_rec_type[NFC_WINDOWS_REC_TYPE_LENGTH]; + +/** + * @brief External reference to the platform type, which is used to encode payload field of the NFC NDEF + * Windows LaunchApp record. This constant is defined in the file @c nfc_launchapp_rec.c and is used in + * the macro @ref NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF. + */ +extern const uint8_t ndef_windows_launchapp_plat_type[NFC_WINDOWS_PLAT_TYPE_LENGTH]; + +/** + * @brief Function for constructing the payload for a Windows LaunchApp record. + * + * This function encodes the payload according to the LaunchApp record definition. It implements an API + * compatible with p_payload_constructor_t. + * + * @param[in] p_input Pointer to the description of the payload. + * @param[out] p_buff Pointer to payload destination. If NULL, function will + * calculate the expected size of the LaunchApp record payload. + * + * @param[in,out] p_len Size of available memory to write as input. Size of generated + * payload as output. + * + * @retval NRF_SUCCESS Always success. + */ +ret_code_t nfc_win_launchapp_payload_constructor(win_launchapp_payload_desc_t * p_input, + uint8_t * p_buff, + uint32_t * p_len); + +/** @brief Macro for generating a description of an NFC NDEF Android Application Record (AAR). + * + * This macro declares and initializes an instance of an NFC NDEF record description + * of an Android Application Record (AAR). + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_launchapp_msg_encode) must be done + * in the same variable scope. + * + * @param[in] NAME Name for accessing record descriptor. + * @param[in] P_PACKAGE_NAME Pointer to the Android package name string. + * @param[in] PACKAGE_NAME_LENGTH Length of the Android package name. + */ +#define NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC_DEF(NAME, \ + P_PACKAGE_NAME, \ + PACKAGE_NAME_LENGTH) \ + NFC_NDEF_RECORD_BIN_DATA_DEF(NAME, \ + TNF_EXTERNAL_TYPE, \ + NULL, \ + 0, \ + ndef_android_launchapp_rec_type, \ + sizeof(ndef_android_launchapp_rec_type), \ + (P_PACKAGE_NAME), \ + (PACKAGE_NAME_LENGTH)) + +/** + * @brief Macro for accessing the NFC NDEF Android Application Record descriptor + * instance that was created with @ref NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC_DEF. + */ +#define NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC(NAME) NFC_NDEF_RECORD_BIN_DATA(NAME) + +/** @brief Macro for generating a description of an NFC NDEF Windows LaunchApp record. + * + * This macro declares and initializes an instance of an NFC NDEF record description + * of a Windows LaunchApp record. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_launchapp_msg_encode) must be done + * in the same variable scope. + * + * @param[in] NAME Name for accessing record descriptor. + * @param[in] P_WIN_APP_ID Pointer to the Windows application ID string (GUID). + * @param[in] WIN_APP_ID_LENGTH Length of the Windows application ID. + * + * @return Pointer to the description of the record. + */ +#define NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF(NAME, \ + P_WIN_APP_ID, \ + WIN_APP_ID_LENGTH) \ + win_launchapp_payload_desc_t NAME##_ndef_win_launchapp_rec_payload_desc = \ + { \ + .platform = ndef_windows_launchapp_plat_type, \ + .platform_length = sizeof(ndef_windows_launchapp_plat_type), \ + .app_id = (P_WIN_APP_ID), \ + .app_id_length = WIN_APP_ID_LENGTH \ + }; \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME, \ + TNF_ABSOLUTE_URI, \ + NULL, \ + 0, \ + ndef_windows_launchapp_rec_type, \ + sizeof(ndef_windows_launchapp_rec_type), \ + nfc_win_launchapp_payload_constructor, \ + &NAME##_ndef_win_launchapp_rec_payload_desc) \ + +/** + * @brief Macro for accessing the NFC NDEF Windows LaunchApp Record descriptor + * instance that was created with @ref NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF. + */ +#define NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_LAUNCHAPP_REC diff --git a/libraries/nfc/src/ndef/nfc_le_oob_rec.c b/libraries/nfc/src/ndef/nfc_le_oob_rec.c new file mode 100644 index 000000000..417ce9a3a --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_le_oob_rec.c @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_LE_OOB_REC) + +#include "nfc_le_oob_rec.h" +#include "util/sdk_errors.h" +#include "ble_gap.h" +#include "nfc_ble_pair_common.h" + +/** + * @brief Function for validating AD structure content for a Bluetooth Carrier Configuration LE record. + * + * This function validates AD structure content. LE Bluetooth Device Address and LE Role + * fields are required. Security Manager Out Of Band Flags structure must not be included. + * + * @param[in] p_ble_advdata Pointer to the description of the payload. + * + * @retval NRF_SUCCESS If the validation was successful. + * @retval NRF_ERROR_INVALID_PARAM Otherwise. + */ +static ret_code_t nfc_le_oob_adv_data_check(ble_advdata_t const * const p_ble_advdata) +{ + if ((false == p_ble_advdata->include_ble_device_addr) || + (BLE_ADVDATA_ROLE_NOT_PRESENT == p_ble_advdata->le_role) || + (NULL != p_ble_advdata->p_sec_mgr_oob_flags)) + { + return NRF_ERROR_INVALID_PARAM; + } + + /* If Flags field in AD structure is present, the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag + must be set. */ + if ((0 != p_ble_advdata->flags) && + ((p_ble_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + +ret_code_t nfc_le_oob_payload_constructor(ble_advdata_t * p_ble_advdata, + uint8_t * p_buff, + uint32_t * p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + + /* Check correctness of the configuration structure */ + err_code = nfc_le_oob_adv_data_check(p_ble_advdata); + if (NRF_SUCCESS != err_code) + { + return err_code; + } + + /* Encode AD structures into NFC record payload */ + uint16_t buff_len = *p_len; + if (*p_len > UINT16_MAX) + { + buff_len = UINT16_MAX; + } + err_code = nfc_ble_oob_adv_data_encode(p_ble_advdata, p_buff, &buff_len); + + /* Update total payload length */ + *p_len = (uint32_t) buff_len; + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_LE_OOB_REC) diff --git a/libraries/nfc/src/ndef/nfc_le_oob_rec.h b/libraries/nfc/src/ndef/nfc_le_oob_rec.h new file mode 100644 index 000000000..85bbc8a2b --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_le_oob_rec.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_LE_OOB_REC_H__ +#define NFC_LE_OOB_REC_H__ + +/**@file + * + * @defgroup nfc_le_oob_rec LE OOB records + * @{ + * @ingroup nfc_ble_pair_msg + * + * @brief Generation of NFC NDEF LE OOB records for NDEF messages. + * + */ + +#include +#include "nfc_ndef_record.h" +#include "nfc_ble_oob_advdata.h" +#include "nfc_ble_pair_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for constructing the payload for a Bluetooth Carrier Configuration LE record. + * + * This function encodes the record payload according to the BLE AD structure. It implements + * an API compatible with @ref p_payload_constructor_t + * + * @param[in] p_ble_advdata Pointer to the description of the payload. + * @param[out] p_buff Pointer to payload destination. If NULL, function will + * calculate the expected size of the record payload. + * + * @param[in,out] p_len Size of available memory to write as input. Size of generated + * payload as output. + * + * @retval NRF_SUCCESS If the record payload was encoded successfully. + * @retval Other If the record payload encoding failed. + */ +ret_code_t nfc_le_oob_payload_constructor(ble_advdata_t * p_ble_advdata, + uint8_t * p_buff, + uint32_t * p_len); + +/** @brief Macro for generating a description of an NFC NDEF Bluetooth Carrier Configuration LE Record. + * + * This macro declares and initializes an instance of an NFC NDEF record description + * for a Bluetooth Carrier Configuration LE record. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_ble_simplified_le_oob_msg_encode) + * must be done in the same variable scope. + * + * @param[in] NAME Name for accessing record descriptor. + * @param[in] PAYLOAD_ID NDEF record header Payload ID field (Limited to one byte). + * If 0, no ID is present in the record description. + * @param[in] P_BLE_ADVDATA Pointer to the encoded BLE advertising data structure. This + * data is used to create the record payload. + */ +#define NFC_NDEF_LE_OOB_RECORD_DESC_DEF(NAME, \ + PAYLOAD_ID, \ + P_BLE_ADVDATA) \ + uint8_t NAME##_ndef_le_oob_record_id = (PAYLOAD_ID); \ + uint8_t NAME##_ndef_le_oob_record_id_length = ((PAYLOAD_ID) != 0) ? 1 : 0; \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF( NAME, \ + TNF_MEDIA_TYPE, \ + &NAME##_ndef_le_oob_record_id, \ + NAME##_ndef_le_oob_record_id_length, \ + (le_oob_rec_type_field), \ + sizeof(le_oob_rec_type_field), \ + nfc_le_oob_payload_constructor, \ + (P_BLE_ADVDATA)) \ + +/** + * @brief Macro for accessing the NFC NDEF Bluetooth Carrier Configuration LE record descriptor + * instance that was created with @ref NFC_NDEF_LE_OOB_RECORD_DESC_DEF. + */ +#define NFC_NDEF_LE_OOB_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_LE_OOB_REC_H__ diff --git a/libraries/nfc/src/ndef/nfc_le_oob_rec_parser.c b/libraries/nfc/src/ndef/nfc_le_oob_rec_parser.c new file mode 100644 index 000000000..cf9a80102 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_le_oob_rec_parser.c @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_LE_OOB_REC_PARSER) +#include "nfc_le_oob_rec_parser.h" +#include "util/sdk_errors.h" + +/** + * @brief Function for parsing LE OOB record payload. + * + * This function parses LE OOB record payload and extracts BLE OOB Advertising data structure. + * + * @param[in] p_buff Pointer to the record payload. + * @param[in] p_len Pointer to the record payload length. + * @param[in,out] p_nfc_ble_oob_pairing_data Pointer to the structure that will be used to hold + * parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval Other An error code that might have been returned by + * @ref nfc_ble_oob_advdata_parse function. + */ +static ret_code_t nfc_le_oob_payload_parse(uint8_t * p_buff, + uint32_t * const p_len, + nfc_ble_oob_pairing_data_t * const p_nfc_ble_oob_pairing_data) +{ + ret_code_t err_code = nfc_ble_oob_advdata_parse(p_buff, + *p_len, + p_nfc_ble_oob_pairing_data); + return err_code; +} + +ret_code_t nfc_le_oob_rec_parse(nfc_ndef_record_desc_t const * const p_rec_desc, + nfc_ble_oob_pairing_data_t * const p_nfc_ble_oob_pairing_data) +{ + ret_code_t err_code; + + if (p_rec_desc->tnf != TNF_MEDIA_TYPE) + { + return NRF_ERROR_INVALID_DATA; + } + + if (p_rec_desc->type_length != sizeof(le_oob_rec_type_field)) + { + return NRF_ERROR_INVALID_DATA; + } + + if (memcmp(p_rec_desc->p_type, le_oob_rec_type_field, sizeof(le_oob_rec_type_field)) != 0) + { + return NRF_ERROR_INVALID_DATA; + } + + if (p_rec_desc->payload_constructor != (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint8_t const * p_payload = ((nfc_ndef_bin_payload_desc_t*)(p_rec_desc->p_payload_descriptor))->p_payload; + uint32_t payload_lenght = ((nfc_ndef_bin_payload_desc_t*)(p_rec_desc->p_payload_descriptor))->payload_length; + + err_code = nfc_le_oob_payload_parse((uint8_t *) p_payload, + &payload_lenght, + p_nfc_ble_oob_pairing_data); + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_LE_OOB_REC_PARSER) diff --git a/libraries/nfc/src/ndef/nfc_le_oob_rec_parser.h b/libraries/nfc/src/ndef/nfc_le_oob_rec_parser.h new file mode 100644 index 000000000..466924eb2 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_le_oob_rec_parser.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nfc_le_oob_rec_parser LE OOB records parser + * @{ + * @ingroup nfc_ble_pair_msg + * @brief Functions for parsing and decoding LE OOB records. + */ + +#ifndef __NFC_LE_OOB_REC_PARSER_H__ +#define __NFC_LE_OOB_REC_PARSER_H__ + +#include "nfc_ndef_record.h" +#include "nfc_ble_oob_advdata_parser.h" +#include "nfc_ble_pair_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for parsing general record description as LE OOB record. + * + * This function checks if record description matches the LE OOB record pattern and extracts BLE + * OOB Advertising data structure. It is required for the record description to use binary payload + * descriptor. + * + * @param[in] p_rec_desc Pointer to the record descriptor. + * @param[in,out] p_nfc_ble_oob_pairing_data Pointer to the structure that will be used to hold + * parsed data. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_INVALID_DATA If the NDEF record type or TNF is incorrect. + * @retval NRF_ERROR_NOT_SUPPORTED If the payload descriptor is not binary. + * @retval Other An error code that might have been returned by + * @ref nfc_ble_oob_advdata_parse function. + */ +ret_code_t nfc_le_oob_rec_parse(nfc_ndef_record_desc_t const * const p_rec_desc, + nfc_ble_oob_pairing_data_t * const p_nfc_ble_oob_pairing_data); + +#ifdef __cplusplus +} +#endif + +#endif // __NFC_LE_OOB_REC_PARSER_H__ + +/** @} */ diff --git a/libraries/nfc/src/ndef/nfc_ndef_msg.c b/libraries/nfc/src/ndef/nfc_ndef_msg.c new file mode 100644 index 000000000..4fc6df89e --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_msg.c @@ -0,0 +1,183 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_MSG) + +#include "util/app_util.h" +#include "nfc_ndef_msg.h" +#include "util/nordic_common.h" +#include "nrf.h" + + +/** + * @brief Resolve the value of record location flags of the NFC NDEF record within an NFC NDEF message. + */ +__STATIC_INLINE nfc_ndef_record_location_t record_location_get(uint32_t index, + uint32_t record_count) +{ + nfc_ndef_record_location_t record_location; + + if (index == 0) + { + if (record_count == 1) + { + record_location = NDEF_LONE_RECORD; + } + else + { + record_location = NDEF_FIRST_RECORD; + } + } + else if (record_count == index + 1) + { + record_location = NDEF_LAST_RECORD; + } + else + { + record_location = NDEF_MIDDLE_RECORD; + } + + return record_location; +} + + +ret_code_t nfc_ndef_msg_encode(nfc_ndef_msg_desc_t const * p_ndef_msg_desc, + uint8_t * p_msg_buffer, + uint32_t * const p_msg_len) +{ + nfc_ndef_record_location_t record_location; + uint32_t temp_len; + uint32_t i; + uint32_t err_code; + + uint32_t sum_of_len = 0; + + if ((p_ndef_msg_desc == NULL) || p_msg_len == NULL) + { + return NRF_ERROR_NULL; + } + + nfc_ndef_record_desc_t * * pp_record_rec_desc = p_ndef_msg_desc->pp_record; + + if (p_ndef_msg_desc->pp_record == NULL) + { + return NRF_ERROR_NULL; + } + +#if NFC_NDEF_MSG_TAG_TYPE == TYPE_4_TAG + uint8_t * p_root_msg_buffer = p_msg_buffer; + + if (p_msg_buffer != NULL) + { + if (*p_msg_len < NLEN_FIELD_SIZE) + { + return NRF_ERROR_NO_MEM; + } + + p_msg_buffer += NLEN_FIELD_SIZE; + } + sum_of_len += NLEN_FIELD_SIZE; +#endif + + for (i = 0; i < p_ndef_msg_desc->record_count; i++) + { + record_location = record_location_get(i, p_ndef_msg_desc->record_count); + + temp_len = *p_msg_len - sum_of_len; + + err_code = nfc_ndef_record_encode(*pp_record_rec_desc, + record_location, + p_msg_buffer, + &temp_len); + + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + sum_of_len += temp_len; + if (p_msg_buffer != NULL) + { + p_msg_buffer += temp_len; + } + + /* next record */ + pp_record_rec_desc++; + } + +#if NFC_NDEF_MSG_TAG_TYPE == TYPE_4_TAG + if (p_msg_buffer != NULL) + { + if (sum_of_len - NLEN_FIELD_SIZE > UINT16_MAX) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + UNUSED_RETURN_VALUE(uint16_big_encode(sum_of_len - NLEN_FIELD_SIZE, p_root_msg_buffer)); + } +#endif + + *p_msg_len = sum_of_len; + + return NRF_SUCCESS; +} + + +void nfc_ndef_msg_clear(nfc_ndef_msg_desc_t * p_msg) +{ + p_msg->record_count = 0; +} + + +ret_code_t nfc_ndef_msg_record_add(nfc_ndef_msg_desc_t * const p_msg, + nfc_ndef_record_desc_t * const p_record) +{ + if (p_msg->record_count >= p_msg->max_record_count) + { + return NRF_ERROR_NO_MEM; + } + + p_msg->pp_record[p_msg->record_count] = p_record; + p_msg->record_count++; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_MSG) diff --git a/libraries/nfc/src/ndef/nfc_ndef_msg.h b/libraries/nfc/src/ndef/nfc_ndef_msg.h new file mode 100644 index 000000000..8850bf387 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_msg.h @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_MSG_H__ +#define NFC_NDEF_MSG_H__ + +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif +/**@file + * + * @defgroup nfc_ndef_msg Custom NDEF messages + * @{ + * @ingroup nfc_modules + * + * @brief Generation of NFC NDEF messages for the NFC tag. + * + */ + +#define TYPE_4_TAG 4U ///< Type 4 Tag identifier. +#define NLEN_FIELD_SIZE 2U ///< Size of NLEN field, used to encode NDEF message for Type 4 Tag. + + /** + * @brief NDEF message descriptor. + */ + typedef struct { + nfc_ndef_record_desc_t ** pp_record; ///< Pointer to an array of pointers to NDEF record descriptors. + uint32_t max_record_count; ///< Number of elements in the allocated pp_record array, which defines the maximum number of records within the NDEF message. + uint32_t record_count; ///< Number of records in the NDEF message. + } nfc_ndef_msg_desc_t; + + /** + * @brief Function for encoding an NDEF message. + * + * This function encodes an NDEF message according to the provided message descriptor. + * + * @note The way of encoding an NDEF message may vary depending on tag's platform, which + * can be chosen with @ref NFC_NDEF_MSG_TAG_TYPE in @c sdk_config.h. + * + * @param[in] p_ndef_msg_desc Pointer to the message descriptor. + * @param[out] p_msg_buffer Pointer to the message destination. If NULL, function will + * calculate the expected size of the message. + * @param[in,out] p_msg_len Size of the available memory for the message as input. Size of + * the generated message as output. + * + * @return Return value from @ref nfc_ndef_record_encode. + */ +ret_code_t nfc_ndef_msg_encode(nfc_ndef_msg_desc_t const * p_ndef_msg_desc, + uint8_t * p_msg_buffer, + uint32_t * const p_msg_len); + +/** + * @brief Function for clearing an NDEF message. + * + * This function clears an NDEF message descriptor, thus empties the NDEF message. + * + * @param[in,out] p_msg Pointer to the message descriptor. + */ +void nfc_ndef_msg_clear( nfc_ndef_msg_desc_t * p_msg); + +/** + * @brief Function for adding a record to an NDEF message. + * + * @param[in] p_record Pointer to the record descriptor. + * @param[in,out] p_msg Pointer to the message descriptor. + * + * @retval NRF_SUCCESS If the record was added successfully. + * @retval NRF_ERROR_NO_MEM If the message already contains the maximum number of records and the operation is not allowed. + */ +ret_code_t nfc_ndef_msg_record_add(nfc_ndef_msg_desc_t * const p_msg, + nfc_ndef_record_desc_t * const p_record); + + +/**@brief Macro for creating and initializing an NFC NDEF message descriptor. + * + * This macro creates and initializes an instance of type @ref nfc_ndef_msg_desc_t + * and an array of pointers to record descriptors (@ref nfc_ndef_record_desc_t) used + * by the message. + * + * Use the macro @ref NFC_NDEF_MSG to access the NDEF message descriptor instance. + * + * @note The message descriptor is declared as automatic variable, which implies that + * the NDEF message encoding must be done in the same variable scope. + * + * @param[in] NAME Name of the related instance. + * @param[in] MAX_RECORD_CNT Maximal count of records in the message. + */ +#define NFC_NDEF_MSG_DEF(NAME, MAX_RECORD_CNT) \ + nfc_ndef_record_desc_t * NAME##_nfc_ndef_p_record_desc_array[MAX_RECORD_CNT]; \ + nfc_ndef_msg_desc_t NAME##_nfc_ndef_msg_desc = \ + { \ + .pp_record = NAME##_nfc_ndef_p_record_desc_array, \ + .max_record_count = MAX_RECORD_CNT, \ + .record_count = 0 \ + } + +/** @brief Macro for accessing the NFC NDEF message descriptor instance + * that you created with @ref NFC_NDEF_MSG_DEF. + */ +#define NFC_NDEF_MSG(NAME) (NAME##_nfc_ndef_msg_desc) + +/** + * @brief Macro for creating and initializing an NFC NDEF record descriptor with an encapsulated NDEF message. + + * This macro creates and initializes a static instance of type + * @ref nfc_ndef_record_desc_t that contains an encapsulated NDEF message as + * payload. @ref nfc_ndef_msg_encode is used as payload constructor to encode + * the message. The encoded message is then used as payload for the record. + * + * Use the macro @ref NFC_NDEF_NESTED_NDEF_MSG_RECORD to access the NDEF record descriptor instance. + * + * @note The message descriptor is declared as automatic variable, which implies that + * the NDEF message encoding must be done in the same variable scope. + * + * @param[in] NAME Name of the created record descriptor instance. + * @param[in] TNF Type Name Format (TNF) value for the record. + * @param[in] P_ID Pointer to the ID string. + * @param[in] ID_LEN Length of the ID string. + * @param[in] P_TYPE Pointer to the type string. + * @param[in] TYPE_LEN Length of the type string. + * @param[in] P_NESTED_MESSAGE Pointer to the message descriptor to encapsulate + * as the record's payload. + */ +#define NFC_NDEF_NESTED_NDEF_MSG_RECORD_DEF( NAME, \ + TNF, \ + P_ID, \ + ID_LEN, \ + P_TYPE, \ + TYPE_LEN, \ + P_NESTED_MESSAGE ) \ + nfc_ndef_record_desc_t NAME##_ndef_record_nested_desc = \ + { \ + .tnf = TNF, \ + \ + .id_length = ID_LEN, \ + .p_id = P_ID, \ + \ + .type_length = TYPE_LEN, \ + .p_type = P_TYPE, \ + \ + .payload_constructor = (p_payload_constructor_t)(nfc_ndef_msg_encode), \ + .p_payload_descriptor = (void*) (P_NESTED_MESSAGE) \ + } + +/** @brief Macro for accessing the NFC NDEF record descriptor instance + * that you created with @ref NFC_NDEF_NESTED_NDEF_MSG_RECORD_DEF. + */ +#define NFC_NDEF_NESTED_NDEF_MSG_RECORD(NAME) (NAME##_ndef_record_nested_desc) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/libraries/nfc/src/ndef/nfc_ndef_msg_parser.c b/libraries/nfc/src/ndef/nfc_ndef_msg_parser.c new file mode 100644 index 000000000..6ce0b6c7f --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_msg_parser.c @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_MSG_PARSER) + +#include "nfc_ndef_msg_parser.h" +#include "nrf_delay.h" + +#define NRF_LOG_MODULE_NAME nfc_ndef_msg_parser +#if NFC_NDEF_MSG_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_NDEF_MSG_PARSER_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_NDEF_MSG_PARSER_INFO_COLOR +#include "util/nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_NDEF_MSG_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "util/nrf_log.h" +#endif // NFC_NDEF_MSG_PARSER_LOG_ENABLED + +ret_code_t ndef_msg_parser(uint8_t * const p_result_buf, + uint32_t * const p_result_buf_len, + uint8_t * const p_nfc_data, + uint32_t * const p_nfc_data_len) +{ + ret_code_t ret_code; + nfc_ndef_parser_memo_desc_t parser_memory_helper; + + ret_code = ndef_parser_memo_resolve(p_result_buf, + p_result_buf_len, + &parser_memory_helper); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + ret_code = internal_ndef_msg_parser(&parser_memory_helper, + p_nfc_data, + p_nfc_data_len); + + return ret_code; +} + + +void ndef_msg_printout(nfc_ndef_msg_desc_t * const p_msg_desc) +{ + uint32_t i; + + NRF_LOG_INFO("NDEF message contains %d record(s)", p_msg_desc->record_count); + + for (i = 0; i < p_msg_desc->record_count; i++) + { + ndef_record_printout(i, p_msg_desc->pp_record[i]); + } +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_MSG_PARSER) diff --git a/libraries/nfc/src/ndef/nfc_ndef_msg_parser.h b/libraries/nfc/src/ndef/nfc_ndef_msg_parser.h new file mode 100644 index 000000000..e3b8c2343 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_msg_parser.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_MSG_PARSER_H__ +#define NFC_NDEF_MSG_PARSER_H__ + +/**@file + * + * @defgroup nfc_ndef_parser NDEF message parser + * @{ + * @ingroup nfc_modules + * + * @brief Parser for NFC NDEF messages and records. + * + * @defgroup nfc_ndef_msg_parser Parser for NDEF messages + * @{ + * @ingroup nfc_ndef_parser + * + * @brief Parser for NFC NDEF messages. + * + */ + +#include +#include "nfc_ndef_msg_parser_local.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Macro for calculating the memory size required for holding the + * description of a message that consists of a certain number of NDEF records. + * + * @param[in] max_count_of_records Maximum number of records to hold. + */ +#define NFC_NDEF_PARSER_REQIRED_MEMO_SIZE_CALC(max_count_of_records) \ + ((uint32_t)(max_count_of_records) <= 1) ? \ + (sizeof(parsed_ndef_msg_1_t) * (uint32_t)(max_count_of_records)) : \ + (sizeof(parsed_ndef_msg_1_t) + ((NFC_PARSER_M_DELTA) *((uint32_t)(max_count_of_records) - 1))) + +/** + * @brief Function for parsing NFC NDEF messages. + * + * This function parses NDEF messages using NDEF binary record descriptors. + * + * @param[out] p_result_buf Pointer to the buffer that will be used to hold + * the NDEF message descriptor. After parsing is completed successfully, the first address + * in the buffer is filled by the NDEF message descriptor + * (@ref nfc_ndef_msg_desc_t), which provides a full description of + * the parsed NDEF message. + * @param[in,out] p_result_buf_len As input: size of the buffer specified by @p p_result_buf. + * As output: size of the reserved (used) part of the buffer specified by + * @p p_result_buf. + * @param[in] p_nfc_data Pointer to the data to be parsed. + * @param[in,out] p_nfc_data_len As input: size of the NFC data in the @p p_nfc_data buffer. As output: size of the parsed message. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NO_MEM If the provided buffer is too small to hold a one-record message or + * the buffer is too small to hold the actual result of the parsing. + * @retval NRF_ERROR_INVALID_LENGTH If the expected message length is bigger than the amount of the provided input data. + * @retval NRF_ERROR_INVALID_DATA If the message is not a valid NDEF message. + */ +ret_code_t ndef_msg_parser(uint8_t * const p_result_buf, + uint32_t * const p_result_buf_len, + uint8_t * const p_nfc_data, + uint32_t * const p_nfc_data_len); + +/** + * @brief Function for printing the parsed contents of an NDEF message. + * + * @param[in] p_msg_desc Pointer to the descriptor of the message that should be printed. + */ +void ndef_msg_printout(nfc_ndef_msg_desc_t * const p_msg_desc); + +/** + * @} + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif // NFC_NDEF_MSG_PARSER_H__ + + diff --git a/libraries/nfc/src/ndef/nfc_ndef_msg_parser_local.c b/libraries/nfc/src/ndef/nfc_ndef_msg_parser_local.c new file mode 100644 index 000000000..e621bca51 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_msg_parser_local.c @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_MSG_PARSER) + +#include "nfc_ndef_msg_parser_local.h" + +ret_code_t internal_ndef_msg_parser(nfc_ndef_parser_memo_desc_t * const p_parser_memo_desc, + uint8_t const * p_nfc_data, + uint32_t * const p_nfc_data_len) +{ + nfc_ndef_record_location_t record_location; + + ret_code_t ret_code; + + uint32_t nfc_data_left = *p_nfc_data_len; + uint32_t temp_nfc_data_len = 0; + + // want to modify -> use local copy + nfc_ndef_bin_payload_desc_t * p_bin_pay_desc = p_parser_memo_desc->p_bin_pay_desc; + nfc_ndef_record_desc_t * p_rec_desc = p_parser_memo_desc->p_rec_desc; + + + while (nfc_data_left > 0) + { + temp_nfc_data_len = nfc_data_left; + + ret_code = ndef_record_parser(p_bin_pay_desc, + p_rec_desc, + &record_location, + p_nfc_data, + &temp_nfc_data_len); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + // verify the records location flags + if (p_parser_memo_desc->p_msg_desc->record_count == 0) + { + if ((record_location != NDEF_FIRST_RECORD) && (record_location != NDEF_LONE_RECORD)) + { + return NRF_ERROR_INVALID_DATA; + } + } + else + { + if ((record_location != NDEF_MIDDLE_RECORD) && (record_location != NDEF_LAST_RECORD)) + { + return NRF_ERROR_INVALID_DATA; + } + } + + ret_code = nfc_ndef_msg_record_add(p_parser_memo_desc->p_msg_desc, p_rec_desc); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + nfc_data_left -= temp_nfc_data_len; + + if ((record_location == NDEF_LAST_RECORD) || (record_location == NDEF_LONE_RECORD)) + { + *p_nfc_data_len = *p_nfc_data_len - nfc_data_left; + return NRF_SUCCESS; + } + else + { + if (p_parser_memo_desc->p_msg_desc->record_count == + p_parser_memo_desc->p_msg_desc->max_record_count) + { + return NRF_ERROR_NO_MEM; + } + + p_nfc_data += temp_nfc_data_len; + p_bin_pay_desc++; + p_rec_desc++; + } + } + + return NRF_ERROR_INVALID_DATA; + +} + + +ret_code_t ndef_parser_memo_resolve(uint8_t * const p_result_buf, + uint32_t * const p_result_buf_len, + nfc_ndef_parser_memo_desc_t * const p_parser_memo_desc) +{ + + uint32_t max_rec_num; + uint32_t memory_last; + uint8_t * p_end; + nfc_ndef_record_desc_t * * pp_record_desc_array; + + if (*p_result_buf_len < sizeof(parsed_ndef_msg_1_t)) + { + return NRF_ERROR_NO_MEM; + } + + memory_last = (*p_result_buf_len) - sizeof(parsed_ndef_msg_1_t); + max_rec_num = (memory_last / (NFC_PARSER_M_DELTA)) + 1; + + p_parser_memo_desc->p_msg_desc = (nfc_ndef_msg_desc_t *) p_result_buf; + pp_record_desc_array = + (nfc_ndef_record_desc_t * *) &p_parser_memo_desc->p_msg_desc[1]; + p_parser_memo_desc->p_bin_pay_desc = + (nfc_ndef_bin_payload_desc_t *) &pp_record_desc_array[max_rec_num]; + p_parser_memo_desc->p_rec_desc = + (nfc_ndef_record_desc_t *) &p_parser_memo_desc->p_bin_pay_desc[max_rec_num]; + + // initialize message description + p_parser_memo_desc->p_msg_desc->pp_record = pp_record_desc_array; + p_parser_memo_desc->p_msg_desc->max_record_count = max_rec_num; + p_parser_memo_desc->p_msg_desc->record_count = 0; + + p_end = (uint8_t *) &p_parser_memo_desc->p_rec_desc[max_rec_num]; + + *p_result_buf_len = p_end - p_result_buf; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_MSG_PARSER) diff --git a/libraries/nfc/src/ndef/nfc_ndef_msg_parser_local.h b/libraries/nfc/src/ndef/nfc_ndef_msg_parser_local.h new file mode 100644 index 000000000..33111b913 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_msg_parser_local.h @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_MSG_PARSER_LOCAL_H__ +#define NFC_NDEF_MSG_PARSER_LOCAL_H__ + +/**@file + * + * @defgroup nfc_ndef_msg_parser_local NDEF message parser (internal) + * @{ + * @ingroup nfc_ndef_msg_parser + * + * @brief Internal part of the parser for NFC NDEF messages. + * + */ + +#include +#include "nfc_ndef_msg.h" +#include "nfc_ndef_record_parser.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type for holding descriptors that are used by the NDEF parser. + */ +typedef struct +{ + nfc_ndef_msg_desc_t * p_msg_desc; ///< Pointer to the message descriptor. + nfc_ndef_bin_payload_desc_t * p_bin_pay_desc; ///< Pointer to the array of binary payload descriptors. + nfc_ndef_record_desc_t * p_rec_desc; ///< Pointer to the array of record descriptors. +} nfc_ndef_parser_memo_desc_t; + +/** + * @brief Memory allocated for a one-record message. + */ +typedef struct +{ + nfc_ndef_msg_desc_t msg_desc; + nfc_ndef_record_desc_t * p_record_desc_array[1]; + nfc_ndef_bin_payload_desc_t bin_pay_desc[1]; + nfc_ndef_record_desc_t rec_desc[1]; +} parsed_ndef_msg_1_t; + +/** + * @brief Memory allocated for a two-record message. + */ +typedef struct +{ + nfc_ndef_msg_desc_t msg_desc; + nfc_ndef_record_desc_t * p_record_desc_array[2]; + nfc_ndef_bin_payload_desc_t bin_pay_desc[2]; + nfc_ndef_record_desc_t rec_desc[2]; +} parsed_ndef_msg_2_t; + +/** + * @brief Amount of memory that is required per record in addition to the memory allocated for the message descriptor. + */ +#define NFC_PARSER_M_DELTA (sizeof(parsed_ndef_msg_2_t) - sizeof(parsed_ndef_msg_1_t)) + + +/** + * @brief Function for resolving data instances in the provided buffer according + * to requirements of the function @ref internal_ndef_msg_parser. + * + * This internal function distributes the provided memory between certain data instances that are required + * by @ref internal_ndef_msg_parser. + * + * This function should not be used directly. + * + * @param[in] p_result_buf Pointer to the buffer that will be used to allocate + * data instances. + * @param[in,out] p_result_buf_len As input: size of the buffer specified by @p p_result_buf. + * As output: size of the reserved (used) part of the buffer specified by + * @p p_result_buf. + * @param[out] p_parser_memo_desc Pointer to the structure for holding descriptors of the allocated data + * instances. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NO_MEM If the provided buffer is too small to hold a one-record message. + */ +ret_code_t ndef_parser_memo_resolve(uint8_t * const p_result_buf, + uint32_t * const p_result_buf_len, + nfc_ndef_parser_memo_desc_t * const p_parser_memo_desc); + + +/** + * @brief Function for parsing NFC NDEF messages. + * + * This internal function parses NDEF messages into certain data instances. + * + * This function should not be used directly. + * + * @param[in,out] p_parser_memo_desc Pointer to the structure that holds descriptors of the allocated data + * instances for the parser. This structure contains the following fields: @n + * .p_msg_desc Pointer to the message descriptor that will + * be filled with parsed data. @n + * .p_bin_pay_desc Pointer to the array of binary payload + * descriptors that will be filled with parsed + * data. @n + * .p_rec_desc Pointer to the array of record descriptors + * that will be filled with parsed data. @n + * The arrays specified by @p .p_bin_pay_desc and @p .p_rec_desc must not + * contain more elements than the message descriptor + * specified by \p .p_msg_desc can hold. + * + * @param[in] p_nfc_data Pointer to the data to be parsed. + * @param[in,out] p_nfc_data_len As input: size of the NFC data in the @p p_nfc_data buffer. + * As output: size of the parsed message. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_INVALID_LENGTH If the expected message length is bigger than the amount of provided input data. + * @retval NRF_ERROR_INVALID_DATA If the message is not a valid NDEF message. + * @retval NRF_ERROR_NO_MEM If the provided memory resources are too small to hold the parsing result. + */ +ret_code_t internal_ndef_msg_parser(nfc_ndef_parser_memo_desc_t * const p_parser_memo_desc, + uint8_t const * p_nfc_data, + uint32_t * const p_nfc_data_len); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif // NFC_NDEF_MSG_PARSER_LOCAL_H__ diff --git a/libraries/nfc/src/ndef/nfc_ndef_record.c b/libraries/nfc/src/ndef/nfc_ndef_record.c new file mode 100644 index 000000000..2c6a54df2 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_record.c @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_config.h" +#include "util/nordic_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_RECORD) + +#include +#include "nfc_ndef_record.h" +#include "util/app_util.h" +#include "nrf.h" + + +/* Sum of sizes of fields: TNF-flags, Type Length, Payload Length in long NDEF record. */ +#define NDEF_RECORD_BASE_LONG_SIZE (2 + NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE) + +__STATIC_INLINE uint32_t record_header_size_calc(nfc_ndef_record_desc_t const * p_ndef_record_desc) +{ + uint32_t len = NDEF_RECORD_BASE_LONG_SIZE; + + len += p_ndef_record_desc->id_length + p_ndef_record_desc->type_length; + + if (p_ndef_record_desc->id_length > 0) + { + len++; + } + + return len; +} + + +ret_code_t nfc_ndef_record_encode(nfc_ndef_record_desc_t const * p_ndef_record_desc, + nfc_ndef_record_location_t record_location, + uint8_t * p_record_buffer, + uint32_t * p_record_len) +{ + uint8_t * p_flags; // use as pointer to TNF + flags field + uint8_t * p_payload_len = NULL; // use as pointer to payload length field + uint32_t record_payload_len; + + if (p_ndef_record_desc == NULL) + { + return NRF_ERROR_NULL; + } + + // count record length without payload + uint32_t record_header_len = record_header_size_calc(p_ndef_record_desc); + uint32_t err_code = NRF_SUCCESS; + + if (p_record_buffer != NULL) + { + /* verify location range */ + if ((record_location & (~NDEF_RECORD_LOCATION_MASK)) != 0x00) + { + return NRF_ERROR_INVALID_PARAM; + } + + /* verify if there is enough available memory */ + if (record_header_len > *p_record_len) + { + return NRF_ERROR_NO_MEM; + } + + p_flags = p_record_buffer; + p_record_buffer++; + + // set location bits and clear other bits in 1st byte. + *p_flags = record_location; + + *p_flags |= p_ndef_record_desc->tnf; + + /* TYPE LENGTH */ + *(p_record_buffer++) = p_ndef_record_desc->type_length; + + // use always long record and remember payload len field memory offset. + p_payload_len = p_record_buffer; + p_record_buffer += NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE; + + /* ID LENGTH - option */ + if (p_ndef_record_desc->id_length > 0) + { + *(p_record_buffer++) = p_ndef_record_desc->id_length; + + /* IL flag */ + *p_flags |= NDEF_RECORD_IL_MASK; + } + + /* TYPE */ + memcpy(p_record_buffer, p_ndef_record_desc->p_type, p_ndef_record_desc->type_length); + p_record_buffer += p_ndef_record_desc->type_length; + + /* ID */ + if (p_ndef_record_desc->id_length > 0) + { + memcpy(p_record_buffer, p_ndef_record_desc->p_id, p_ndef_record_desc->id_length); + p_record_buffer += p_ndef_record_desc->id_length; + } + + // count how much memory is left in record buffer for payload field. + record_payload_len = (*p_record_len - record_header_len); + } + + /* PAYLOAD */ + if (p_ndef_record_desc->payload_constructor != NULL) + { + err_code = + p_ndef_record_desc->payload_constructor(p_ndef_record_desc->p_payload_descriptor, + p_record_buffer, + &record_payload_len); + + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + else + { + return NRF_ERROR_NULL; + } + + if (p_record_buffer != NULL) + { + /* PAYLOAD LENGTH */ + (void) uint32_big_encode(record_payload_len, p_payload_len); + } + + *p_record_len = record_header_len + record_payload_len; + + return NRF_SUCCESS; +} + + +ret_code_t nfc_ndef_bin_payload_memcopy(nfc_ndef_bin_payload_desc_t * p_payload_descriptor, + uint8_t * p_buffer, + uint32_t * p_len) +{ + + if (p_buffer != NULL) + { + if ( *p_len < p_payload_descriptor->payload_length) + { + return NRF_ERROR_NO_MEM; + } + + memcpy(p_buffer, + p_payload_descriptor->p_payload, + p_payload_descriptor->payload_length); + } + + *p_len = p_payload_descriptor->payload_length; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_RECORD) diff --git a/libraries/nfc/src/ndef/nfc_ndef_record.h b/libraries/nfc/src/ndef/nfc_ndef_record.h new file mode 100644 index 000000000..76480c183 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_record.h @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_RECORD_H__ +#define NFC_NDEF_RECORD_H__ + +#include +#include +#include "compiler_abstraction.h" +#include "util/sdk_errors.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nfc_ndef_record Custom NDEF records + * @{ + * @ingroup nfc_ndef_msg + * + * @brief Generation of NFC NDEF records for NFC messages. + * + */ + + +#define NDEF_RECORD_IL_MASK 0x08 ///< Mask of the ID field presence bit in the flags byte of an NDEF record. +#define NDEF_RECORD_TNF_MASK 0x07 ///< Mask of the TNF value field in the first byte of an NDEF record. +#define NDEF_RECORD_SR_MASK 0x10 ///< Mask of the SR flag. If set, this flag indicates that the PAYLOAD_LENGTH field has a size of 1 byte. Otherwise, PAYLOAD_LENGTH has 4 bytes. +#define NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE 4 ///< Size of the Payload Length field in a long NDEF record. +#define NDEF_RECORD_PAYLOAD_LEN_SHORT_SIZE 1 ///< Size of the Payload Length field in a short NDEF record. +#define NDEF_RECORD_ID_LEN_SIZE 1 ///< Size of the ID Length field in an NDEF record. + + +/** + * @brief Payload constructor type. + + * A payload constructor is a function for constructing the payload of an NDEF + * record. + * + * @param[in] p_payload_descriptor Pointer to the input data for the constructor. + * @param[out] p_buffer Pointer to the payload destination. If NULL, function will + * calculate the expected size of the record payload. + * + * @param[in,out] p_len Size of the available memory to write as input. Size of the generated + * record payload as output. The implementation must check if the payload + * will fit in the provided buffer. This must be checked by the caller function. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_xxx If an error occurred. + */ +typedef ret_code_t (* p_payload_constructor_t)(void * p_payload_descriptor, + uint8_t * p_buffer, + uint32_t * p_len); + + +/** + * @brief Type Name Format (TNF) Field Values. + * + * Values to specify the TNF of a record. + */ +typedef enum +{ + TNF_EMPTY = 0x00, ///< The value indicates that there is no type or payload associated with this record. + TNF_WELL_KNOWN = 0x01, ///< NFC Forum well-known type [NFC RTD]. + TNF_MEDIA_TYPE = 0x02, ///< Media-type as defined in RFC 2046 [RFC 2046]. + TNF_ABSOLUTE_URI = 0x03, ///< Absolute URI as defined in RFC 3986 [RFC 3986]. + TNF_EXTERNAL_TYPE = 0x04, ///< NFC Forum external type [NFC RTD]. + TNF_UNKNOWN_TYPE = 0x05, ///< The value indicates that there is no type associated with this record. + TNF_UNCHANGED = 0x06, ///< The value is used for the record chunks used in chunked payload. + TNF_RESERVED = 0x07, ///< The value is reserved for future use. +} nfc_ndef_record_tnf_t; + + +/** + * @brief NDEF record descriptor. + */ +typedef struct +{ + nfc_ndef_record_tnf_t tnf; ///< Value of the Type Name Format (TNF) field. + + uint8_t id_length; ///< Length of the ID field. If 0, a record format without ID field is assumed. + uint8_t const * p_id; ///< Pointer to the ID field data. Not relevant if id_length is 0. + + uint8_t type_length; ///< Length of the type field. + uint8_t const * p_type; ///< Pointer to the type field data. Not relevant if type_length is 0. + + p_payload_constructor_t payload_constructor; ///< Pointer to the payload constructor function. + void * p_payload_descriptor; ///< Pointer to the data for the payload constructor function. + +} nfc_ndef_record_desc_t; + +/** + * @brief Record position within the NDEF message. + * + * Values to specify the location of a record within the NDEF message. + */ +typedef enum +{ + NDEF_FIRST_RECORD = 0x80, ///< First record. + NDEF_MIDDLE_RECORD = 0x00, ///< Middle record. + NDEF_LAST_RECORD = 0x40, ///< Last record. + NDEF_LONE_RECORD = 0xC0 ///< Only one record in the message. +} nfc_ndef_record_location_t; + +#define NDEF_RECORD_LOCATION_MASK (NDEF_LONE_RECORD) ///< Mask of the Record Location bits in the NDEF record's flags byte. + +/** + * @brief Binary data descriptor containing the payload for the record. + */ +typedef struct +{ + uint8_t const * p_payload; ///< Pointer to the buffer with the data. + uint32_t payload_length; ///< Length of data in bytes. +} nfc_ndef_bin_payload_desc_t; + +/** + * @brief Macro for creating and initializing an NFC NDEF record descriptor for a generic record. + * + * This macro creates and initializes an instance of type @ref nfc_ndef_record_desc_t. + * + * Use the macro @ref NFC_NDEF_GENERIC_RECORD_DESC to access the NDEF record descriptor instance. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF record encoding must be done in the same variable scope. + * + * @param[in] NAME Name of the created descriptor instance. + * @param[in] TNF Type Name Format (TNF) value for the record. + * @param[in] P_ID Pointer to the ID string. + * @param[in] ID_LEN Length of the ID string. + * @param[in] P_TYPE Pointer to the type string. + * @param[in] TYPE_LEN Length of the type string. + * @param[in] P_PAYLOAD_CONSTRUCTOR Pointer to the payload constructor function. + * The constructor must be of type @ref p_payload_constructor_t. + * @param[in] P_PAYLOAD_DESCRIPTOR Pointer to the data for the payload constructor. + */ +#define NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME, \ + TNF, \ + P_ID, \ + ID_LEN, \ + P_TYPE, \ + TYPE_LEN, \ + P_PAYLOAD_CONSTRUCTOR, \ + P_PAYLOAD_DESCRIPTOR) \ + nfc_ndef_record_desc_t NAME##_ndef_generic_record_desc = \ + { \ + .tnf = TNF, \ + \ + .id_length = ID_LEN, \ + .p_id = P_ID, \ + \ + .type_length = TYPE_LEN, \ + .p_type = P_TYPE, \ + \ + .payload_constructor = (p_payload_constructor_t)P_PAYLOAD_CONSTRUCTOR, \ + .p_payload_descriptor = (void *) P_PAYLOAD_DESCRIPTOR \ + } + + +/** @brief Macro for accessing the NFC NDEF record descriptor instance + * that you created with @ref NFC_NDEF_GENERIC_RECORD_DESC_DEF. + */ +#define NFC_NDEF_GENERIC_RECORD_DESC(NAME) (NAME##_ndef_generic_record_desc) + +/** + * @brief Macro for creating and initializing an NFC NDEF record descriptor for a record with + * binary payload. + * + * This macro creates and initializes a static instance of type @ref nfc_ndef_record_desc_t and a binary data descriptor containing the payload data. + * + * Use the macro @ref NFC_NDEF_RECORD_BIN_DATA to access the NDEF record descriptor instance. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF record encoding must be done in the same variable scope. + * + * @param[in] NAME Name of the created descriptor instance. + * @param[in] TNF Type Name Format (TNF) value for the record. + * @param[in] P_ID Pointer to the ID string. + * @param[in] ID_LEN Length of the ID string. + * @param[in] P_TYPE Pointer to the type string. + * @param[in] TYPE_LEN Length of the type string. + * @param[in] P_PAYLOAD Pointer to the payload data that will be copied to the payload field. + * @param[in] PAYLOAD_LEN Length of the payload. + */ +#define NFC_NDEF_RECORD_BIN_DATA_DEF(NAME, \ + TNF, \ + P_ID, ID_LEN, \ + P_TYPE, \ + TYPE_LEN, \ + P_PAYLOAD, \ + PAYLOAD_LEN) \ + nfc_ndef_bin_payload_desc_t NAME##_nfc_ndef_bin_payload_desc = \ + { \ + .p_payload = P_PAYLOAD, \ + .payload_length = PAYLOAD_LEN \ + }; \ + \ + nfc_ndef_record_desc_t NAME##_nfc_ndef_bin_record_desc = \ + { \ + .tnf = TNF, \ + \ + .id_length = ID_LEN, \ + .p_id = P_ID, \ + \ + .type_length = TYPE_LEN, \ + .p_type = P_TYPE, \ + \ + .payload_constructor = (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy, \ + .p_payload_descriptor = (void *) &NAME##_nfc_ndef_bin_payload_desc \ + } + + +/** @brief Macro for accessing the NFC NDEF record descriptor instance + * that you created with @ref NFC_NDEF_RECORD_BIN_DATA_DEF. + */ +#define NFC_NDEF_RECORD_BIN_DATA(NAME) (NAME##_nfc_ndef_bin_record_desc) + +/** @brief Macro for accessing the binary data descriptor that contains + * the payload of the record that you created with @ref NFC_NDEF_RECORD_BIN_DATA_DEF. + */ +#define NFC_NDEF_BIN_PAYLOAD_DESC(NAME) (NAME##_nfc_ndef_bin_payload_desc) + +/** + * @brief Function for encoding an NDEF record. + * + * This function encodes an NDEF record according to the provided record descriptor. + * + * @param[in] p_ndef_record_desc Pointer to the record descriptor. + * @param[in] record_location Location of the record within the NDEF message. + * @param[out] p_record_buffer Pointer to the record destination. If NULL, function will + * calculate the expected size of the record. + * @param[in,out] p_record_len Size of the available memory for the record as input. Size of the generated + * record as output. + * + * @retval NRF_SUCCESS If the record was encoded successfully. + * @retval NRF_ERROR_NO_MEM If the predicted record size is bigger than the provided buffer space. + * @retval NRF_ERROR_INVALID_PARAM If the location of the record is erroneous. + * @retval Other Other codes might be returned depending on the NDEF record payload constructor implementation. + */ +ret_code_t nfc_ndef_record_encode(nfc_ndef_record_desc_t const * p_ndef_record_desc, + nfc_ndef_record_location_t record_location, + uint8_t * p_record_buffer, + uint32_t * p_record_len); + +/** + * @brief Function for constructing the payload for an NFC NDEF record from binary data. + * + * This function copies data from a binary buffer to the payload field of the NFC NDEF record. + * + * @param[in] p_payload_descriptor Pointer to the descriptor of the binary data location and size. + * + * @param[out] p_buffer Pointer to the payload destination. If NULL, function will + * calculate the expected size of the record payload. + * @param[in,out] p_len Size of the available memory for the payload as input. Size of the copied payload + * as output. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_NO_MEM If the payload size is bigger than the provided buffer space. + */ +ret_code_t nfc_ndef_bin_payload_memcopy(nfc_ndef_bin_payload_desc_t * p_payload_descriptor, + uint8_t * p_buffer, + uint32_t * p_len); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif // NFC_NDEF_RECORD_H__ + diff --git a/libraries/nfc/src/ndef/nfc_ndef_record_parser.c b/libraries/nfc/src/ndef/nfc_ndef_record_parser.c new file mode 100644 index 000000000..5e47f7248 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_record_parser.c @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_RECORD_PARSER) + +#include +#include +#include "nfc_ndef_record_parser.h" +#include "util/app_util.h" +#include "util/nordic_common.h" +#include "nrf_delay.h" + +#define NRF_LOG_MODULE_NAME nfc_ndef_parser +#if NFC_NDEF_RECORD_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_NDEF_RECORD_PARSER_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_NDEF_RECORD_PARSER_INFO_COLOR +#include "util/nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_NDEF_RECORD_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "util/nrf_log.h" +#endif // NFC_NDEF_RECORD_PARSER_LOG_ENABLED + +/* Sum of sizes of fields: TNF-flags, Type Length, Payload Length in short NDEF record. */ +#define NDEF_RECORD_BASE_LONG_SHORT (2 + NDEF_RECORD_PAYLOAD_LEN_SHORT_SIZE) + + +ret_code_t ndef_record_parser(nfc_ndef_bin_payload_desc_t * p_bin_pay_desc, + nfc_ndef_record_desc_t * p_rec_desc, + nfc_ndef_record_location_t * p_record_location, + uint8_t const * p_nfc_data, + uint32_t * p_nfc_data_len) +{ + uint32_t expected_rec_size = NDEF_RECORD_BASE_LONG_SHORT; + + if (expected_rec_size > *p_nfc_data_len) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_rec_desc->tnf = (nfc_ndef_record_tnf_t) ((*p_nfc_data) & NDEF_RECORD_TNF_MASK); + + /* An NDEF parser that receives an NDEF record with an unknown or unsupported TNF field value + SHOULD treat it as Unknown. See NFCForum-TS-NDEF_1.0 */ + if (p_rec_desc->tnf == TNF_RESERVED) + { + p_rec_desc->tnf = TNF_UNKNOWN_TYPE; + } + + *p_record_location = (nfc_ndef_record_location_t) ((*p_nfc_data) & NDEF_RECORD_LOCATION_MASK); + + uint8_t flags = *(p_nfc_data++); + + p_rec_desc->type_length = *(p_nfc_data++); + + uint32_t payload_lenght; + + if (flags & NDEF_RECORD_SR_MASK) + { + payload_lenght = *(p_nfc_data++); + } + else + { + expected_rec_size += + NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE - NDEF_RECORD_PAYLOAD_LEN_SHORT_SIZE; + + if (expected_rec_size > *p_nfc_data_len) + { + return NRF_ERROR_INVALID_LENGTH; + } + + payload_lenght = uint32_big_decode(p_nfc_data); + p_nfc_data += NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE; + } + + if (flags & NDEF_RECORD_IL_MASK) + { + expected_rec_size += NDEF_RECORD_ID_LEN_SIZE; + + if (expected_rec_size > *p_nfc_data_len) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_rec_desc->id_length = *(p_nfc_data++); + } + else + { + p_rec_desc->id_length = 0; + p_rec_desc->p_id = NULL; + } + + expected_rec_size += p_rec_desc->type_length + p_rec_desc->id_length + payload_lenght; + + if (expected_rec_size > *p_nfc_data_len) + { + return NRF_ERROR_INVALID_LENGTH; + } + + if (p_rec_desc->type_length > 0) + { + p_rec_desc->p_type = p_nfc_data; + + p_nfc_data += p_rec_desc->type_length; + } + else + { + p_rec_desc->p_type = NULL; + } + + if (p_rec_desc->id_length > 0) + { + p_rec_desc->p_id = p_nfc_data; + + p_nfc_data += p_rec_desc->id_length; + } + + if (payload_lenght == 0) + { + p_bin_pay_desc->p_payload = NULL; + } + else + { + p_bin_pay_desc->p_payload = p_nfc_data; + } + + p_bin_pay_desc->payload_length = payload_lenght; + + p_rec_desc->p_payload_descriptor = p_bin_pay_desc; + p_rec_desc->payload_constructor = (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy; + + *p_nfc_data_len = expected_rec_size; + + return NRF_SUCCESS; +} + +char const * const tnf_strings[] = +{ + "Empty", + "NFC Forum well-known type", + "Media-type (RFC 2046)", + "Absolute URI (RFC 3986)", + "NFC Forum external type (NFC RTD)", + "Unknown", + "Unchanged", + "Reserved" +}; + +void ndef_record_printout(uint32_t num, nfc_ndef_record_desc_t * const p_rec_desc) +{ + NRF_LOG_INFO("NDEF record %d content:", num); + NRF_LOG_INFO("TNF: %s",(uint32_t)tnf_strings[p_rec_desc->tnf]); + + if (p_rec_desc->p_id != NULL) + { + NRF_LOG_INFO("ID:"); + NRF_LOG_HEXDUMP_INFO((uint8_t *)p_rec_desc->p_id, p_rec_desc->id_length); + } + + if (p_rec_desc->p_type != NULL) + { + NRF_LOG_INFO("type:"); + NRF_LOG_HEXDUMP_INFO((uint8_t *)p_rec_desc->p_type, p_rec_desc->type_length); + } + + if (p_rec_desc->payload_constructor == (p_payload_constructor_t) nfc_ndef_bin_payload_memcopy) + { + nfc_ndef_bin_payload_desc_t * p_bin_pay_desc = p_rec_desc->p_payload_descriptor; + + if (p_bin_pay_desc->p_payload != NULL) + { + NRF_LOG_INFO("Payload length: %d bytes", p_bin_pay_desc->payload_length); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_bin_pay_desc->p_payload, p_bin_pay_desc->payload_length); + } + else + { + NRF_LOG_INFO("No payload"); + } + } +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_RECORD_PARSER) diff --git a/libraries/nfc/src/ndef/nfc_ndef_record_parser.h b/libraries/nfc/src/ndef/nfc_ndef_record_parser.h new file mode 100644 index 000000000..d67cc84e9 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_ndef_record_parser.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_RECORD_PARSER_H__ +#define NFC_NDEF_RECORD_PARSER_H__ + +#include +#include "util/sdk_errors.h" +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nfc_ndef_record_parser Parser for NDEF records + * @{ + * @ingroup nfc_ndef_parser + * + * @brief Parser for NFC NDEF records. + * + */ + + +/** + * @brief Function for parsing NDEF records. + * + * This parsing implementation uses the binary payload descriptor (@ref nfc_ndef_bin_payload_desc_t) to describe the payload for the record. + * + * @param[out] p_bin_pay_desc Pointer to the binary payload descriptor that will be filled and referenced by the record descriptor. + * @param[out] p_rec_desc Pointer to the record descriptor that will be filled with parsed data. + * @param[out] p_record_location Pointer to the record location. + * @param[in] p_nfc_data Pointer to the raw data to be parsed. + * @param[in,out] p_nfc_data_len As input: size of the NFC data in the @p p_nfc_data buffer. As output: size of the parsed record. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_INVALID_LENGTH If the expected record length is bigger than the provided input data amount. + */ +ret_code_t ndef_record_parser(nfc_ndef_bin_payload_desc_t * p_bin_pay_desc, + nfc_ndef_record_desc_t * p_rec_desc, + nfc_ndef_record_location_t * p_record_location, + uint8_t const * p_nfc_data, + uint32_t * p_nfc_data_len); + +/** + * @brief Function for printing the parsed contents of the NDEF record. + * + * @param[in] num Sequence number of the record within the NDEF message. + * @param[in] p_rec_desc Pointer to the descriptor of the record that should be printed. + * + */ +void ndef_record_printout(uint32_t num, nfc_ndef_record_desc_t * const p_rec_desc); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif // NFC_NDEF_RECORD_PARSER_H__ diff --git a/libraries/nfc/src/ndef/nfc_text_rec.c b/libraries/nfc/src/ndef/nfc_text_rec.c new file mode 100644 index 000000000..d99104209 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_text_rec.c @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_TEXT_RECORD) + +#include +#include "nfc_text_rec.h" +#include "nrf_error.h" + +#define TEXT_REC_STATUS_SIZE 1 ///< Size of the status. +#define TEXT_REC_STATUS_UTF_POS 7 ///< Position of a character encoding type. +#define TEXT_REC_RESERVED_POS 6 ///< Reserved position. + +const uint8_t nfc_text_rec_type_field[] = {'T'}; + + +/** + * @brief Function for calculating payload size. + */ +__STATIC_INLINE uint32_t nfc_text_rec_payload_size_get(nfc_text_rec_payload_desc_t * p_nfc_rec_text_payload_desc) +{ + return (TEXT_REC_STATUS_SIZE + + p_nfc_rec_text_payload_desc->lang_code_len + + p_nfc_rec_text_payload_desc->data_len); +} + +ret_code_t nfc_text_rec_payload_constructor(nfc_text_rec_payload_desc_t * p_nfc_rec_text_payload_desc, + uint8_t * p_buff, + uint32_t * p_len) +{ + if ((p_nfc_rec_text_payload_desc->lang_code_len == 0) + || (p_nfc_rec_text_payload_desc->lang_code_len & (1 << TEXT_REC_RESERVED_POS)) + || (p_nfc_rec_text_payload_desc->lang_code_len & (1 << TEXT_REC_STATUS_UTF_POS)) + || (p_nfc_rec_text_payload_desc->p_lang_code == NULL) + || (p_nfc_rec_text_payload_desc->data_len == 0) + || (p_nfc_rec_text_payload_desc->p_data == NULL) + || (p_len == NULL)) + { + return NRF_ERROR_INVALID_PARAM; + } + + uint32_t payload_size = nfc_text_rec_payload_size_get(p_nfc_rec_text_payload_desc); + + if (p_buff != NULL) + { + if (payload_size > *p_len) + { + return NRF_ERROR_NO_MEM; + } + + *p_buff = (p_nfc_rec_text_payload_desc->lang_code_len + + (p_nfc_rec_text_payload_desc->utf << TEXT_REC_STATUS_UTF_POS)); + p_buff += TEXT_REC_STATUS_SIZE; + + memcpy(p_buff, + p_nfc_rec_text_payload_desc->p_lang_code, + p_nfc_rec_text_payload_desc->lang_code_len); + p_buff += p_nfc_rec_text_payload_desc->lang_code_len; + + memcpy(p_buff, + p_nfc_rec_text_payload_desc->p_data, + p_nfc_rec_text_payload_desc->data_len); + } + + *p_len = payload_size; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_TEXT_RECORD) diff --git a/libraries/nfc/src/ndef/nfc_text_rec.h b/libraries/nfc/src/ndef/nfc_text_rec.h new file mode 100644 index 000000000..50a1e0da8 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_text_rec.h @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_TEXT_REC_H__ +#define NFC_TEXT_REC_H__ + +/**@file + * + * @defgroup nfc_text_rec Text records + * @{ + * @ingroup nfc_ndef_messages + * + * @brief Generation of NFC NDEF Text record descriptions. + * + */ + +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type of the Unicode Transformation Format. + * + * Values to specify the type of UTF for an NFC NDEF Text record. + */ +typedef enum +{ + UTF_8 = 0, ///< Unicode Transformation Format 8. + UTF_16 = 1, ///< Unicode Transformation Format 16. +} nfc_text_rec_utf_type_t; + +/** + * @brief Text record payload descriptor. + */ +typedef struct +{ + nfc_text_rec_utf_type_t utf; ///< Type of the Unicode Transformation Format. + + uint8_t const * p_lang_code; ///< Pointer to the IANA language code. + uint8_t lang_code_len; ///< Length of the IANA language code. + + uint8_t const * p_data; ///< Pointer to the user text. + uint32_t data_len; ///< Length of the user text. +} nfc_text_rec_payload_desc_t; + +/** + * @brief Constructor for an NFC NDEF Text record payload. + * + * @param[in] p_nfc_rec_text_payload_desc Pointer to the Text record description. + * @param[out] p_buff Pointer to the payload destination. If NULL, function will + * calculate the expected size of the Text record payload. + * + * @param[in,out] p_len Size of the available memory to write as input. + * Size of the generated record payload as output. + */ +ret_code_t nfc_text_rec_payload_constructor(nfc_text_rec_payload_desc_t * p_nfc_rec_text_payload_desc, + uint8_t * p_buff, + uint32_t * p_len); + +/** + * @brief External reference to the type field of the Text record, defined in the + * file @c nfc_text_rec.c. It is used in the @ref NFC_NDEF_TEXT_RECORD_DESC_DEF macro. + */ +extern const uint8_t nfc_text_rec_type_field[]; + +/** + * @brief Size of the type field of the Text record, defined in the + * file @c nfc_text_rec.c. It is used in the @ref NFC_NDEF_TEXT_RECORD_DESC_DEF macro. + */ +#define NFC_TEXT_REC_TYPE_LENGTH 1 + +/** + *@brief Macro for creating and initializing an NFC NDEF record descriptor for a Text record. + * + * This macro creates and initializes an instance of type @ref nfc_ndef_record_desc_t and + * an instance of type @ref nfc_text_rec_payload_desc_t, which together constitute + * an instance of a Text record. + * + * Use the macro @ref NFC_NDEF_TEXT_RECORD_DESC to access the NDEF Text record descriptor instance. + * + * @param[in] NAME Name of the created record descriptor instance. + * @param[in] UTF Unicode Transformation Format. + * @param[in] P_LANG_CODE Pointer to the IANA language code. + * @param[in] LANG_CODE_LEN Length of the IANA language code. + * @param[in] P_DATA Pointer to the user text. + * @param[in] DATA_LEN Length of the user text. + */ +#define NFC_NDEF_TEXT_RECORD_DESC_DEF(NAME, \ + UTF, \ + P_LANG_CODE, \ + LANG_CODE_LEN, \ + P_DATA, \ + DATA_LEN) \ + nfc_text_rec_payload_desc_t NAME##_nfc_text_rec_payload_desc = \ + { \ + .utf = UTF, \ + .p_lang_code = P_LANG_CODE, \ + .lang_code_len = LANG_CODE_LEN, \ + .p_data = P_DATA, \ + .data_len = DATA_LEN, \ + }; \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME, \ + TNF_WELL_KNOWN, \ + 0, \ + 0, \ + nfc_text_rec_type_field, \ + NFC_TEXT_REC_TYPE_LENGTH, \ + nfc_text_rec_payload_constructor, \ + &(NAME##_nfc_text_rec_payload_desc)) + +/** + * @brief Macro for accessing the NFC NDEF Text record descriptor + * instance that was created with @ref NFC_NDEF_TEXT_RECORD_DESC_DEF. + */ +#define NFC_NDEF_TEXT_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_TEXT_REC_H__ diff --git a/libraries/nfc/src/ndef/nfc_uri_msg.c b/libraries/nfc/src/ndef/nfc_uri_msg.c new file mode 100644 index 000000000..1602922d0 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_uri_msg.c @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_URI_MSG) + +#include +#include "nfc_uri_msg.h" +#include "util/sdk_macros.h" + +ret_code_t nfc_uri_msg_encode( nfc_uri_id_t uri_id_code, + uint8_t const * const p_uri_data, + uint8_t uri_data_len, + uint8_t * p_buf, + uint32_t * p_len) +{ + ret_code_t err_code; + + /* Create NFC NDEF message description with URI record */ + NFC_NDEF_MSG_DEF(nfc_uri_msg, 1); + NFC_NDEF_URI_RECORD_DESC_DEF(nfc_uri_rec, uri_id_code, p_uri_data, uri_data_len); + + err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_uri_msg), + &NFC_NDEF_URI_RECORD_DESC(nfc_uri_rec)); + VERIFY_SUCCESS(err_code); + VERIFY_PARAM_NOT_NULL(p_uri_data); + + /* Encode whole message into buffer */ + err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_uri_msg), + p_buf, + p_len); + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_URI_MSG) diff --git a/libraries/nfc/src/ndef/nfc_uri_msg.h b/libraries/nfc/src/ndef/nfc_uri_msg.h new file mode 100644 index 000000000..efc5746e0 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_uri_msg.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_URI_MSG_H__ +#define NFC_URI_MSG_H__ + +/**@file + * + * @defgroup nfc_uri_msg URI messages + * @{ + * @ingroup nfc_ndef_messages + * + * @brief Generation of NFC NDEF messages with a URI record. + * + */ + +#include "nfc_ndef_msg.h" +#include "nfc_uri_rec.h" +#include "nrf_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for encoding an NFC NDEF URI message. + * + * This function encodes an NFC NDEF message into a buffer. + * + * @param[in] uri_id_code URI identifier code that defines the protocol field of the URI. + * @param[in] p_uri_data Pointer to the URI string. + * The string should not contain the protocol field if the protocol + * was specified in @p uri_id_code. + * @param[in] uri_data_len Length of the URI string. + * @param[out] p_buf Pointer to the buffer for the message. + * @param[in,out] p_len Size of the available memory for the message as input. + * Size of the generated message as output. + * + * @retval NRF_SUCCESS If the description was successfully created. + * @retval NRF_ERROR_NULL If the URI string was invalid (equal to NULL). + * @retval NRF_ERROR_NO_MEM If the predicted message size is bigger than the provided + * buffer space. + * @retval Other Other codes might be returned depending on + * the function @ref nfc_ndef_msg_encode. + */ +ret_code_t nfc_uri_msg_encode( nfc_uri_id_t uri_id_code, + uint8_t const * const p_uri_data, + uint8_t uri_data_len, + uint8_t * p_buf, + uint32_t * p_len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_URI_MSG_H__ diff --git a/libraries/nfc/src/ndef/nfc_uri_rec.c b/libraries/nfc/src/ndef/nfc_uri_rec.c new file mode 100644 index 000000000..33320ea20 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_uri_rec.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_NDEF_URI_REC) + +#include +#include "nfc_uri_rec.h" +#include "nrf_error.h" + +const uint8_t ndef_uri_record_type = 'U'; ///< URI Record type. + +/** + * @brief Function for constructing the payload for a URI record. + * + * This function encodes the payload according to the URI record definition. It implements an API + * compatible with @ref p_payload_constructor_t. + * + * @param[in] p_input Pointer to the description of the payload. + * @param[out] p_buff Pointer to payload destination. If NULL, function will + * calculate the expected size of the URI record payload. + * + * @param[in,out] p_len Size of available memory to write as input. Size of generated + * payload as output. + * + * @retval NRF_SUCCESS If the payload was encoded successfully. + * @retval NRF_ERROR_NO_MEM If the predicted payload size is bigger than the provided buffer space. + */ +ret_code_t nfc_uri_payload_constructor( uri_payload_desc_t * p_input, + uint8_t * p_buff, + uint32_t * p_len) +{ + if (p_buff != NULL) + { + /* Verify if there is enough available memory */ + if (p_input->uri_data_len >= *p_len) + { + return NRF_ERROR_NO_MEM; + } + + /* Copy descriptor content into the buffer */ + *(p_buff++) = p_input->uri_id_code; + memcpy(p_buff, p_input->p_uri_data, p_input->uri_data_len ); + } + + *p_len = p_input->uri_data_len + 1; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NFC_NDEF_URI_REC) diff --git a/libraries/nfc/src/ndef/nfc_uri_rec.h b/libraries/nfc/src/ndef/nfc_uri_rec.h new file mode 100644 index 000000000..ad744d571 --- /dev/null +++ b/libraries/nfc/src/ndef/nfc_uri_rec.h @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_URI_REC_H__ +#define NFC_URI_REC_H__ + +/**@file + * + * @defgroup nfc_uri_rec URI records + * @{ + * @ingroup nfc_uri_msg + * + * @brief Generation of NFC NDEF URI record descriptions. + * + */ + +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @enum nfc_uri_id_t + * @brief URI identifier codes according to "URI Record Type Definition" + * (denotation "NFCForum-TS-RTD_URI_1.0" published on 2006-07-24) chapter 3.2.2. + */ +typedef enum +{ + NFC_URI_NONE = 0x00, /**< No prepending is done. */ + NFC_URI_HTTP_WWW = 0x01, /**< "http://www." */ + NFC_URI_HTTPS_WWW = 0x02, /**< "https://www." */ + NFC_URI_HTTP = 0x03, /**< "http:" */ + NFC_URI_HTTPS = 0x04, /**< "https:" */ + NFC_URI_TEL = 0x05, /**< "tel:" */ + NFC_URI_MAILTO = 0x06, /**< "mailto:" */ + NFC_URI_FTP_ANONYMOUS = 0x07, /**< "ftp://anonymous:anonymous@" */ + NFC_URI_FTP_FTP = 0x08, /**< "ftp://ftp." */ + NFC_URI_FTPS = 0x09, /**< "ftps://" */ + NFC_URI_SFTP = 0x0A, /**< "sftp://" */ + NFC_URI_SMB = 0x0B, /**< "smb://" */ + NFC_URI_NFS = 0x0C, /**< "nfs://" */ + NFC_URI_FTP = 0x0D, /**< "ftp://" */ + NFC_URI_DAV = 0x0E, /**< "dav://" */ + NFC_URI_NEWS = 0x0F, /**< "news:" */ + NFC_URI_TELNET = 0x10, /**< "telnet://" */ + NFC_URI_IMAP = 0x11, /**< "imap:" */ + NFC_URI_RTSP = 0x12, /**< "rtsp://" */ + NFC_URI_URN = 0x13, /**< "urn:" */ + NFC_URI_POP = 0x14, /**< "pop:" */ + NFC_URI_SIP = 0x15, /**< "sip:" */ + NFC_URI_SIPS = 0x16, /**< "sips:" */ + NFC_URI_TFTP = 0x17, /**< "tftp:" */ + NFC_URI_BTSPP = 0x18, /**< "btspp://" */ + NFC_URI_BTL2CAP = 0x19, /**< "btl2cap://" */ + NFC_URI_BTGOEP = 0x1A, /**< "btgoep://" */ + NFC_URI_TCPOBEX = 0x1B, /**< "tcpobex://" */ + NFC_URI_IRDAOBEX = 0x1C, /**< "irdaobex://" */ + NFC_URI_FILE = 0x1D, /**< "file://" */ + NFC_URI_URN_EPC_ID = 0x1E, /**< "urn:epc:id:" */ + NFC_URI_URN_EPC_TAG = 0x1F, /**< "urn:epc:tag:" */ + NFC_URI_URN_EPC_PAT = 0x20, /**< "urn:epc:pat:" */ + NFC_URI_URN_EPC_RAW = 0x21, /**< "urn:epc:raw:" */ + NFC_URI_URN_EPC = 0x22, /**< "urn:epc:" */ + NFC_URI_URN_NFC = 0x23, /**< "urn:nfc:" */ + NFC_URI_RFU = 0xFF /**< No prepending is done. Reserved for future use. */ +} nfc_uri_id_t; + + +/** + * @brief Type of description of the payload of a URI record. + */ +typedef struct +{ + nfc_uri_id_t uri_id_code; /**< URI identifier code. */ + uint8_t const * p_uri_data; /**< Pointer to a URI string. */ + uint8_t uri_data_len; /**< Length of the URI string. */ +} uri_payload_desc_t; + +/** + * @brief External reference to the type field of the URI record, defined in the + * file @c nfc_uri_rec.c. It is used in the @ref NFC_NDEF_URI_RECORD_DESC_DEF macro. + */ +extern const uint8_t ndef_uri_record_type; + +/** + * @brief Function for constructing the payload for a URI record. + * + * This function encodes the payload according to the URI record definition. It implements an API + * compatible with @ref p_payload_constructor_t. + * + * @param[in] p_input Pointer to the description of the payload. + * @param[out] p_buff Pointer to payload destination. If NULL, function will + * calculate the expected size of the URI record payload. + * + * @param[in,out] p_len Size of available memory to write as input. Size of generated + * payload as output. + * + * @retval NRF_SUCCESS If the payload was encoded successfully. + * @retval NRF_ERROR_NO_MEM If the predicted payload size is bigger than the provided buffer space. + */ +ret_code_t nfc_uri_payload_constructor( uri_payload_desc_t * p_input, + uint8_t * p_buff, + uint32_t * p_len); + +/** @brief Macro for generating a description of a URI record. + * + * This macro initializes an instance of an NFC NDEF record description of a URI record. + * + * @note The record descriptor is declared as automatic variable, which implies that + * the NDEF message encoding (see @ref nfc_uri_msg_encode) must be done + * in the same variable scope. + * + * @param[in] NAME Name for accessing record descriptor. + * @param[in] URI_ID_CODE URI identifier code that defines the protocol field of the URI. + * @param[in] P_URI_DATA Pointer to the URI string. + * The string should not contain the protocol field if the protocol + * was specified in @p uri_id_code. + * @param[in] URI_DATA_LEN Length of the URI string. + */ +#define NFC_NDEF_URI_RECORD_DESC_DEF(NAME, \ + URI_ID_CODE, \ + P_URI_DATA, \ + URI_DATA_LEN) \ + uri_payload_desc_t NAME##_ndef_uri_record_payload_desc = \ + { \ + .uri_id_code = (URI_ID_CODE), \ + .p_uri_data = (P_URI_DATA), \ + .uri_data_len = (URI_DATA_LEN) \ + }; \ + \ + NFC_NDEF_GENERIC_RECORD_DESC_DEF( NAME, \ + TNF_WELL_KNOWN, \ + NULL, \ + 0, \ + &ndef_uri_record_type, \ + sizeof(ndef_uri_record_type), \ + nfc_uri_payload_constructor, \ + &NAME##_ndef_uri_record_payload_desc) \ + +/** + * @brief Macro for accessing the NFC NDEF URI record descriptor instance that + * was created with @ref NFC_NDEF_URI_RECORD_DESC_DEF. + */ +#define NFC_NDEF_URI_RECORD_DESC(NAME) NFC_NDEF_GENERIC_RECORD_DESC(NAME) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NFC_URI_REC_H__ diff --git a/libraries/nfc/src/ndef/parser/record/nfc_ndef_record_parser.h b/libraries/nfc/src/ndef/parser/record/nfc_ndef_record_parser.h new file mode 100644 index 000000000..d67cc84e9 --- /dev/null +++ b/libraries/nfc/src/ndef/parser/record/nfc_ndef_record_parser.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_NDEF_RECORD_PARSER_H__ +#define NFC_NDEF_RECORD_PARSER_H__ + +#include +#include "util/sdk_errors.h" +#include "nfc_ndef_record.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nfc_ndef_record_parser Parser for NDEF records + * @{ + * @ingroup nfc_ndef_parser + * + * @brief Parser for NFC NDEF records. + * + */ + + +/** + * @brief Function for parsing NDEF records. + * + * This parsing implementation uses the binary payload descriptor (@ref nfc_ndef_bin_payload_desc_t) to describe the payload for the record. + * + * @param[out] p_bin_pay_desc Pointer to the binary payload descriptor that will be filled and referenced by the record descriptor. + * @param[out] p_rec_desc Pointer to the record descriptor that will be filled with parsed data. + * @param[out] p_record_location Pointer to the record location. + * @param[in] p_nfc_data Pointer to the raw data to be parsed. + * @param[in,out] p_nfc_data_len As input: size of the NFC data in the @p p_nfc_data buffer. As output: size of the parsed record. + * + * @retval NRF_SUCCESS If the function completed successfully. + * @retval NRF_ERROR_INVALID_LENGTH If the expected record length is bigger than the provided input data amount. + */ +ret_code_t ndef_record_parser(nfc_ndef_bin_payload_desc_t * p_bin_pay_desc, + nfc_ndef_record_desc_t * p_rec_desc, + nfc_ndef_record_location_t * p_record_location, + uint8_t const * p_nfc_data, + uint32_t * p_nfc_data_len); + +/** + * @brief Function for printing the parsed contents of the NDEF record. + * + * @param[in] num Sequence number of the record within the NDEF message. + * @param[in] p_rec_desc Pointer to the descriptor of the record that should be printed. + * + */ +void ndef_record_printout(uint32_t num, nfc_ndef_record_desc_t * const p_rec_desc); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif // NFC_NDEF_RECORD_PARSER_H__ diff --git a/libraries/nfc/src/t2t_parser/nfc_t2t_parser.c b/libraries/nfc/src/t2t_parser/nfc_t2t_parser.c new file mode 100644 index 000000000..654bb044f --- /dev/null +++ b/libraries/nfc/src/t2t_parser/nfc_t2t_parser.c @@ -0,0 +1,679 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/sdk_common.h" +#if NRF_MODULE_ENABLED(NFC_T2T_PARSER) + +#include +#include +#include "nrf_delay.h" +#include "nfc_t2t_parser.h" + +#define NRF_LOG_MODULE_NAME nfc_t2t_parser +#if NFC_T2T_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_T2T_PARSER_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_T2T_PARSER_INFO_COLOR +#include "util/nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_T2T_PARSER_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "util/nrf_log.h" +#endif // NFC_T2T_PARSER_LOG_ENABLED + +/// Gets least significant nibble (a 4-bit value) from a byte. +#define LSN_GET(val) (val & 0x0F) + +/// Gets most significant nibble (a 4-bit value) from a byte. +#define MSN_GET(val) ((val >> 4) & 0x0F) + +/** + * @brief Function for inserting the TLV block into a @ref type_2_tag_t structure. + * + * The content of a TLV block structure pointed by the p_tlv_block is copied into a TLV block + * array within the structure pointed by the p_type_2_tag. + * + * @param[in,out] p_type_2_tag Pointer to the structure that contains the TLV blocks array. + * @param[in] p_tlv_block Pointer to the TLV block to insert. + * + * @retval NRF_SUCCESS If the block was inserted successfully. + * @retval NRF_ERROR_NO_MEM If there is already maximum number of blocks stored in the array. + * + */ +static ret_code_t type_2_tag_tlv_block_insert(type_2_tag_t * p_type_2_tag, + tlv_block_t * p_tlv_block) +{ + if (p_type_2_tag->tlv_count == p_type_2_tag->max_tlv_blocks) + { + return NRF_ERROR_NO_MEM; + } + + // Copy contents of the source block. + p_type_2_tag->p_tlv_block_array[p_type_2_tag->tlv_count] = *p_tlv_block; + p_type_2_tag->tlv_count++; + + return NRF_SUCCESS; +} + + +/** + * @brief Function for checking if the TLV block length is correct. + * + * Some TLV block has predefined length: + * TLV_NULL and TLV_TERMINATOR always have a length of 1 byte. + * TLV_LOCK_CONTROL and TLV_MEMORY_CONTROL always have a length of 3 bytes. + * + * @param[in] p_block_to_check Pointer to the structure that contains the TLV block length. + * + * @retval TRUE If the length is correct. + * @retval FALSE Otherwise. + * + */ +static bool tlv_block_is_data_length_correct(tlv_block_t * p_block_to_check) +{ + switch (p_block_to_check->tag) + { + case TLV_NULL: + case TLV_TERMINATOR: + if (p_block_to_check->length != TLV_NULL_TERMINATOR_LEN) + { + return false; + } + break; + + case TLV_LOCK_CONTROL: + case TLV_MEMORY_CONTROL: + if (p_block_to_check->length != TLV_LOCK_MEMORY_CTRL_LEN) + { + return false; + } + break; + + case TLV_NDEF_MESSAGE: + case TLV_PROPRIETARY: + default: + // Any length will do. + break; + } + + return true; +} + +/** + * @brief Function for checking if the end of the tag data area was reached. + * + * @param[in] p_type_2_tag Pointer to the structure that contains the data area size. + * @param[in] offset Current byte offset. + * + * @retval TRUE If the offset indicates the end of the data area. + * @retval FALSE Otherwise. + * + */ +static bool type_2_tag_is_end_reached(type_2_tag_t * p_type_2_tag, uint16_t offset) +{ + return offset == (p_type_2_tag->cc.data_area_size + T2T_FIRST_DATA_BLOCK_OFFSET); +} + + +/** + * @brief Function for checking if version of Type 2 Tag specification read from a tag is supported. + * + * @param[in] p_type_2_tag Pointer to the structure that contains the tag version. + * + * @retval TRUE If the version is supported and tag data can be parsed. + * @retval FALSE Otherwise. + * + */ +static bool type_2_tag_is_version_supported(type_2_tag_t * p_type_2_tag) +{ + // Simple check atm, as only 1 major version has been issued so far, so no backward compatibility + // is needed, tags with newer version implemented shall be rejected according to the doc. + return p_type_2_tag->cc.major_version == T2T_SUPPORTED_MAJOR_VERSION; +} + + +/** + * @brief Function for checking if the field fits into the data area specified in + * the Capability Container. + * + * @param[in] p_type_2_tag Pointer to the structure that contains the data area size. + * @param[in] offset As Offset of the field to check. + * @param[in] field_length Length of the field to check. + * + * @retval TRUE If the field fits into the data area. + * @retval FALSE If the field exceeds the data area. + * + */ +static bool type_2_tag_is_field_within_data_range(type_2_tag_t * p_type_2_tag, + uint16_t offset, + uint16_t field_length) +{ + // Invalid argument, return false. + if (field_length == 0) + { + return false; + } + return ( (offset + field_length - 1) < + (p_type_2_tag->cc.data_area_size + T2T_FIRST_DATA_BLOCK_OFFSET) ) + && ( offset >= T2T_FIRST_DATA_BLOCK_OFFSET ); +} + + +/** + * @brief Function for reading the tag field of a TLV block from the p_raw_data buffer. + * + * This function reads the tag field containing a TLV block type and inserts its value into + * a structure pointed by the p_tlv_buf pointer. + * + * @param[in] p_type_2_tag Pointer to the structure that contains Type 2 Tag data parsed so far. + * @param[in] p_raw_data Pointer to the buffer with a raw data from the tag. + * @param[in,out] p_t_offset As input: offset of the tag field to read. As output: offset of + * the first byte after the tag field. + * @param[out] p_tlv_buf Pointer to a @ref tlv_block_t structure where the tag type will be + * inserted. + * + * @retval NRF_SUCCESS If the tag field at specified offset is correct. + * @retval NRF_ERROR_INVALID_DATA If the tag field at specified offset exceeds the data + * area specified in the Capability Container. + * + */ +static ret_code_t type_2_tag_type_extract(type_2_tag_t * p_type_2_tag, + uint8_t * p_raw_data, + uint16_t * p_t_offset, + tlv_block_t * p_tlv_buf) +{ + if (!type_2_tag_is_field_within_data_range(p_type_2_tag, *p_t_offset, TLV_T_LENGTH)) + { + return NRF_ERROR_INVALID_DATA; + } + + p_tlv_buf->tag = p_raw_data[*p_t_offset]; + *p_t_offset += TLV_T_LENGTH; + + return NRF_SUCCESS; +} + + +/** + * @brief Function for reading the length field of a TLV block from the p_raw_data buffer. + * + * This function reads the length field of a TLV block and inserts its value into a structure + * pointed by the p_tlv_buf pointer. + * + * @param[in] p_type_2_tag Pointer to the structure that contains Type 2 Tag data parsed so far. + * @param[in] p_raw_data Pointer to the buffer with a raw data from the tag. + * @param[in,out] p_l_offset As input: offset of the length field to read. As output: offset of + * the first byte after the length field. + * @param[out] p_tlv_buf Pointer to a @ref tlv_block_t structure where the length will be + * inserted. + * + * @retval NRF_SUCCESS If the length field at specified offset is correct. + * @retval NRF_ERROR_INVALID_DATA If the length field at specified offset exceeds the data + * area specified in the Capability Container or has + * incorrect format. + * + */ +static ret_code_t type_2_tag_length_extract(type_2_tag_t * p_type_2_tag, + uint8_t * p_raw_data, + uint16_t * p_l_offset, + tlv_block_t * p_tlv_buf) +{ + uint16_t length; + + if (!type_2_tag_is_field_within_data_range(p_type_2_tag, *p_l_offset, TLV_L_SHORT_LENGTH)) + { + return NRF_ERROR_INVALID_DATA; + } + + length = p_raw_data[*p_l_offset]; + + if (length == TLV_L_FORMAT_FLAG) + { + // Check another two bytes. + if (!type_2_tag_is_field_within_data_range(p_type_2_tag, *p_l_offset, TLV_L_LONG_LENGTH)) + { + return NRF_ERROR_INVALID_DATA; + } + + length = uint16_big_decode(&p_raw_data[*p_l_offset + 1]); + + // Long length value cannot be lower than 0xFF. + if (length < 0xFF) + { + return NRF_ERROR_INVALID_DATA; + } + + p_tlv_buf->length = length; + *p_l_offset += TLV_L_LONG_LENGTH; + + } + else + { + p_tlv_buf->length = length; + *p_l_offset += TLV_L_SHORT_LENGTH; + } + + return NRF_SUCCESS; +} + + +/** + * @brief Function for reading a pointer to the value field of a TLV block from the p_raw_data buffer. + * + * This function reads a pointer to the value field of a TLV block and inserts it into + * a structure pointed by the p_tlv_buf pointer. If there is no value field present in the + * TLV block, NULL is inserted. + * + * @param[in] p_type_2_tag Pointer to the structure that contains Type 2 Tag data parsed so far. + * @param[in] p_raw_data Pointer to the buffer with a raw data from the tag. + * @param[in,out] p_v_offset As input: offset of the value field to read. As output: offset of + * the first byte after the value field. + * @param[in,out] p_tlv_buf Pointer to a @ref tlv_block_t structure where the value field + * pointer will be inserted. + * + * @retval NRF_SUCCESS If the value field at specified offset is correct. + * @retval NRF_ERROR_INVALID_DATA If the value field at specified offset exceeds the data + * area specified in the Capability Container. + * + */ +static ret_code_t type_2_tag_value_ptr_extract(type_2_tag_t * p_type_2_tag, + uint8_t * p_raw_data, + uint16_t * p_v_offset, + tlv_block_t * p_tlv_buf) +{ + if (p_tlv_buf->length == 0) + { + // Clear the value pointer, don't touch the offset. + p_tlv_buf->p_value = NULL; + } + else + { + if (!type_2_tag_is_field_within_data_range(p_type_2_tag, *p_v_offset, p_tlv_buf->length)) + { + return NRF_ERROR_INVALID_DATA; + } + + p_tlv_buf->p_value = p_raw_data + *p_v_offset; + *p_v_offset += p_tlv_buf->length; + } + + return NRF_SUCCESS; +} + + +/** + * @brief Function for reading a single TLV block from the p_raw_data buffer. + * + * This function reads a single TLV block from the p_raw_data buffer and stores its contents in a + * structure pointed by the p_tlv_buf. + * + * @param[in] p_type_2_tag Pointer to the structure that contains Type 2 Tag data parsed so far. + * @param[in] p_raw_data Pointer to the buffer with a raw data from the tag. + * @param[in,out] p_tlv_offset As input: offset of the TLV block to read. As output: offset of the + * next TLV block, 0 if it was the last block. + * @param[out] p_tlv_buf Pointer to a @ref tlv_block_t structure that will be filled with + * the data read. + * + * @retval NRF_SUCCESS If the parsing operation of the block succeeded. Otherwise, an error + * code is returned. + * + */ +static ret_code_t type_2_tag_tlv_block_extract(type_2_tag_t * p_type_2_tag, + uint8_t * p_raw_data, + uint16_t * p_offset, + tlv_block_t * p_tlv_buf) +{ + ret_code_t err_code; + memset(p_tlv_buf, 0, sizeof(tlv_block_t)); + + // TLV Tag field. + err_code = type_2_tag_type_extract(p_type_2_tag, p_raw_data, p_offset, p_tlv_buf); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Further processing depends on tag field value. + switch (p_tlv_buf->tag) + { + case TLV_NULL: + // Simply ignore NULL blocks, leave the incremented offset. + break; + + case TLV_TERMINATOR: + // Write 0 to the offset variable, indicating that last TLV block was found. + *p_offset = 0; + break; + + case TLV_LOCK_CONTROL: + case TLV_MEMORY_CONTROL: + case TLV_NDEF_MESSAGE: + case TLV_PROPRIETARY: + default: + // Unknown blocks should also be extracted. + err_code = type_2_tag_length_extract(p_type_2_tag, p_raw_data, p_offset, p_tlv_buf); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + if (p_tlv_buf->length > 0) + { + err_code = type_2_tag_value_ptr_extract(p_type_2_tag, p_raw_data, p_offset, p_tlv_buf); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + break; + } + + return NRF_SUCCESS; +} + + +/** + * @brief Function for checking the checksum bytes of the UID stored in internal area. + * + * This function calculates the block check character (BCC) bytes based on the parsed serial number + * and compares them with bytes read from the Type 2 Tag. + * + * @param[in] p_sn Pointer to the @ref type_2_tag_serial_number_t structure to check. + * + * @retval TRUE If the calculated BCC matched the BCC from the tag. + * @retval FALSE Otherwise. + * + */ +static bool type_2_tag_is_bcc_correct(type_2_tag_serial_number_t * p_sn) +{ + uint8_t bcc1 = (uint8_t)T2T_UID_BCC_CASCADE_BYTE ^ + (uint8_t)p_sn->manufacturer_id ^ + (uint8_t)((p_sn->serial_number_part_1 >> 8) & 0xFF) ^ + (uint8_t)(p_sn->serial_number_part_1 & 0xFF); + + uint8_t bcc2 = (uint8_t)((p_sn->serial_number_part_2 >> 24) & 0xFF) ^ + (uint8_t)((p_sn->serial_number_part_2 >> 16) & 0xFF) ^ + (uint8_t)((p_sn->serial_number_part_2 >> 8) & 0xFF) ^ + (uint8_t)( p_sn->serial_number_part_2 & 0xFF); + + return (bcc1 == p_sn->check_byte_0) && (bcc2 == p_sn->check_byte_1); +} + + +/** + * @brief Function for parsing an internal area of a Type 2 Tag. + * + * This function reads data from an internal area in the raw data buffer and fills the + * @ref type_2_tag_serial_number_t structure within @ref type_2_tag_t. + * + * @param[in,out] p_type_2_tag Pointer to the structure that will be filled with parsed data. + * @param[in] p_raw_data Pointer to the buffer with raw data from the tag. + * + * @retval NRF_SUCCESS If the parsing operation of the internal area succeeded. + * Otherwise, an error code is returned. + * + */ +static ret_code_t type_2_tag_internal_parse(type_2_tag_t * p_type_2_tag, uint8_t * p_raw_data) +{ + p_type_2_tag->sn.manufacturer_id = p_raw_data[0]; + p_type_2_tag->sn.serial_number_part_1 = uint16_big_decode(&p_raw_data[1]); + p_type_2_tag->sn.check_byte_0 = p_raw_data[3]; + p_type_2_tag->sn.serial_number_part_2 = uint32_big_decode(&p_raw_data[4]); + p_type_2_tag->sn.check_byte_1 = p_raw_data[8]; + p_type_2_tag->sn.internal = p_raw_data[9]; + + p_type_2_tag->lock_bytes = uint16_big_decode(&p_raw_data[10]); + + if (!type_2_tag_is_bcc_correct(&p_type_2_tag->sn)) + { + NRF_LOG_WARNING("Warning! BCC of the serial number is not correct!"); + } + + return NRF_SUCCESS; +} + + +/** + * @brief Function for parsing a Capabiliy Container area of a Type 2 Tag. + * + * This function reads data from a Capability Container area in the raw data buffer and fills the + * @ref type_2_tag_capability_container_t structure within @ref type_2_tag_t. + * + * @param[in,out] p_type_2_tag Pointer to the structure that will be filled with parsed data. + * @param[in] p_raw_data Pointer to the buffer with raw data from the tag. + * + * @retval NRF_SUCCESS If the parsing operation of the Capability Container succeeded. + * Otherwise, an error code is returned. + * + */ +static ret_code_t type_2_tag_cc_parse(type_2_tag_t * p_type_2_tag, uint8_t * p_raw_data) +{ + uint8_t * p_cc_block = p_raw_data + T2T_CC_BLOCK_OFFSET; + + if (p_cc_block[0] != T2T_NFC_FORUM_DEFINED_DATA) + { + return NRF_ERROR_INVALID_DATA; + } + + p_type_2_tag->cc.major_version = MSN_GET(p_cc_block[1]); + p_type_2_tag->cc.minor_version = LSN_GET(p_cc_block[1]); + p_type_2_tag->cc.data_area_size = p_cc_block[2] * 8; + p_type_2_tag->cc.read_access = MSN_GET(p_cc_block[3]); + p_type_2_tag->cc.write_access = LSN_GET(p_cc_block[3]); + + return NRF_SUCCESS; +} + + +/** + * @brief Function for parsing a single TLV block. + * + * This function reads a single TLV block from the raw data buffer, from the position indicated by + * the p_tlv_offset, and adds it to the @ref type_2_tag_t structure. + * + * @param[in,out] p_type_2_tag Pointer to the structure that will be filled with parsed data. + * @param[in] p_raw_data Pointer to the buffer with raw data from the tag. + * @param[in,out] p_tlv_offset As input: offset of the TLV block to parse. As output: offset of the + * next TLV block, 0 if it was the last block. + * + * @retval NRF_SUCCESS If the parsing operation of the block succeeded. Otherwise, an error + * code is returned. + * + */ +static ret_code_t type_2_tag_tlv_parse(type_2_tag_t * p_type_2_tag, + uint8_t * p_raw_data, + uint16_t * p_tlv_offset) +{ + ret_code_t err_code; + tlv_block_t new_block; + + // Get tag field. + err_code = type_2_tag_tlv_block_extract(p_type_2_tag, p_raw_data, p_tlv_offset, &new_block); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + if (!tlv_block_is_data_length_correct(&new_block)) + { + return NRF_ERROR_INVALID_DATA; + } + + // Further action depends on tag type. + switch (new_block.tag) + { + case TLV_NULL: + case TLV_TERMINATOR: + // Ignore them. + break; + + case TLV_LOCK_CONTROL: + case TLV_MEMORY_CONTROL: + case TLV_NDEF_MESSAGE: + case TLV_PROPRIETARY: + default: + // Unknown tag types are also added. + err_code = type_2_tag_tlv_block_insert(p_type_2_tag, &new_block); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("Warning! Not enough memory to insert all of the blocks!"); + return err_code; + } + break; + } + + return NRF_SUCCESS; +} + + +void type_2_tag_clear(type_2_tag_t * p_type_2_tag) +{ + p_type_2_tag->tlv_count = 0; + memset(&p_type_2_tag->cc, 0, sizeof(p_type_2_tag->cc)); + memset(&p_type_2_tag->sn, 0, sizeof(p_type_2_tag->sn)); +} + + +ret_code_t type_2_tag_parse(type_2_tag_t * p_type_2_tag, uint8_t * p_raw_data) +{ + ret_code_t err_code; + + type_2_tag_clear(p_type_2_tag); + + err_code = type_2_tag_internal_parse(p_type_2_tag, p_raw_data); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = type_2_tag_cc_parse(p_type_2_tag, p_raw_data); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + if (!type_2_tag_is_version_supported(p_type_2_tag)) + { + return NRF_ERROR_NOT_SUPPORTED; + } + + uint16_t offset = T2T_FIRST_DATA_BLOCK_OFFSET; + + while (offset > 0) + { + // Check if end of tag is reached (no terminator block was present). + if (type_2_tag_is_end_reached(p_type_2_tag, offset)) + { + NRF_LOG_DEBUG("No terminator block was found in the tag!"); + break; + } + + err_code = type_2_tag_tlv_parse(p_type_2_tag, p_raw_data, &offset); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + return NRF_SUCCESS; +} + + +void type_2_tag_printout(type_2_tag_t * p_type_2_tag) +{ + uint32_t i; + NRF_LOG_INFO("Type 2 Tag contents:"); + NRF_LOG_INFO("Number of TLV blocks: %d", p_type_2_tag->tlv_count); + + NRF_LOG_DEBUG("Internal data:"); + NRF_LOG_DEBUG(" Manufacturer ID: 0x%02x", p_type_2_tag->sn.manufacturer_id); + NRF_LOG_DEBUG(" Serial number part 1: 0x%04x", p_type_2_tag->sn.serial_number_part_1); + NRF_LOG_DEBUG(" Check byte 0: 0x%02x", p_type_2_tag->sn.check_byte_0); + NRF_LOG_DEBUG(" Serial number part 2: 0x%08lx", p_type_2_tag->sn.serial_number_part_2); + NRF_LOG_DEBUG(" Check byte 1: 0x%02x", p_type_2_tag->sn.check_byte_1); + NRF_LOG_DEBUG(" Internal byte: 0x%02x", p_type_2_tag->sn.internal); + NRF_LOG_DEBUG(" Lock bytes: 0x%04x", p_type_2_tag->lock_bytes); + + NRF_LOG_DEBUG("Capability Container data:"); + NRF_LOG_DEBUG(" Major version number: %d", p_type_2_tag->cc.major_version); + NRF_LOG_DEBUG(" Minor version number: %d", p_type_2_tag->cc.minor_version); + NRF_LOG_DEBUG(" Data area size: %d", p_type_2_tag->cc.data_area_size); + NRF_LOG_DEBUG(" Read access: 0x%02X", p_type_2_tag->cc.read_access); + NRF_LOG_DEBUG(" Write access: 0x%02X", p_type_2_tag->cc.write_access); + + for (i = 0; i < p_type_2_tag->tlv_count; i++) + { + NRF_LOG_INFO("TLV block 0x%02X: ", p_type_2_tag->p_tlv_block_array[i].tag); + switch (p_type_2_tag->p_tlv_block_array[i].tag) + { + case TLV_LOCK_CONTROL: + NRF_LOG_INFO("Lock Control"); + break; + case TLV_MEMORY_CONTROL: + NRF_LOG_INFO("Memory Control"); + break; + case TLV_NDEF_MESSAGE: + NRF_LOG_INFO("NDEF Message"); + break; + case TLV_PROPRIETARY: + NRF_LOG_INFO("Proprietary"); + break; + case TLV_NULL: + NRF_LOG_INFO("Null\r\n"); + break; + case TLV_TERMINATOR: + NRF_LOG_INFO("Terminator"); + break; + default: + NRF_LOG_INFO("Unknown"); + break; + } + + NRF_LOG_INFO(" Data length: %d", p_type_2_tag->p_tlv_block_array[i].length); + + if (p_type_2_tag->p_tlv_block_array[i].length > 0) + { + NRF_LOG_DEBUG(" Data:"); + NRF_LOG_HEXDUMP_DEBUG(p_type_2_tag->p_tlv_block_array[i].p_value, + p_type_2_tag->p_tlv_block_array[i].length); + } + } +} + +#endif // NRF_MODULE_ENABLED(NFC_T2T_PARSER) diff --git a/libraries/nfc/src/t2t_parser/nfc_t2t_parser.h b/libraries/nfc/src/t2t_parser/nfc_t2t_parser.h new file mode 100644 index 000000000..2a6f58cc1 --- /dev/null +++ b/libraries/nfc/src/t2t_parser/nfc_t2t_parser.h @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_TYPE_2_TAG_PARSER_H__ +#define NFC_TYPE_2_TAG_PARSER_H__ + +#include +#include "nfc_tlv_block.h" +#include "util/sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nfc_type_2_tag Type 2 Tag + * @{ + * @ingroup nfc_type_2_tag_parser + * + * @brief Descriptor for a Type 2 Tag. + * + */ + +/** + * @brief Descriptor for the internal bytes of a Type 2 Tag. + */ +typedef struct +{ + uint8_t manufacturer_id; ///< Manufacturer ID (the most significant byte of the UID/serial number). + uint16_t serial_number_part_1; ///< Bytes 5-4 of the tag UID. + uint8_t check_byte_0; ///< First block check character byte (XOR of the cascade tag byte, manufacturer ID byte, and the serial_number_part_1 bytes). + uint32_t serial_number_part_2; ///< Bytes 3-0 of the tag UID. + uint8_t check_byte_1; ///< Second block check character byte (XOR of the serial_number_part_2 bytes). + uint8_t internal; ///< Tag internal bytes. +} type_2_tag_serial_number_t; + +/** + * @brief Descriptor for the Capability Container (CC) bytes of a Type 2 Tag. + */ +typedef struct +{ + uint8_t major_version; ///< Major version of the supported Type 2 Tag specification. + uint8_t minor_version; ///< Minor version of the supported Type 2 Tag specification. + uint16_t data_area_size; ///< Size of the data area in bytes. + uint8_t read_access; ///< Read access for the data area. + uint8_t write_access; ///< Write access for the data area. +} type_2_tag_capability_container_t; + +/** + * @brief Type 2 Tag descriptor. + */ +typedef struct +{ + type_2_tag_serial_number_t sn; ///< Values within the serial number area of the tag. + uint16_t lock_bytes; ///< Value of the lock bytes. + type_2_tag_capability_container_t cc; ///< Values within the Capability Container area of the tag. + + uint16_t const max_tlv_blocks; ///< Maximum number of TLV blocks that can be stored. + tlv_block_t * p_tlv_block_array; ///< Pointer to the array for TLV blocks. + uint16_t tlv_count; ///< Number of TLV blocks stored in the Type 2 Tag. + +} type_2_tag_t; + +/** + * @brief Macro for creating and initializing a Type 2 Tag descriptor. + * + * This macro creates and initializes a static instance of a @ref type_2_tag_t structure and + * an array of @ref tlv_block_t descriptors. + * + * Use the macro @ref NFC_TYPE_2_TAG_DESC to access the Type 2 Tag descriptor instance. + * + * @param[in] NAME Name of the created descriptor instance. + * @param[in] MAX_BLOCKS Maximum number of @ref tlv_block_t descriptors that can be stored in the array. + * + */ +#define NFC_TYPE_2_TAG_DESC_DEF(NAME, MAX_BLOCKS) \ + static tlv_block_t NAME##_tlv_block_array[MAX_BLOCKS]; \ + static type_2_tag_t NAME##_type_2_tag = \ + { \ + .max_tlv_blocks = MAX_BLOCKS, \ + .p_tlv_block_array = NAME##_tlv_block_array, \ + .tlv_count = 0 \ + } + +/** + * @brief Macro for accessing the @ref type_2_tag_t instance that was created + * with @ref NFC_TYPE_2_TAG_DESC_DEF. + */ +#define NFC_TYPE_2_TAG_DESC(NAME) (NAME##_type_2_tag) + + +#define T2T_NFC_FORUM_DEFINED_DATA 0xE1 ///< Value indicating that the Type 2 Tag contains NFC Forum defined data. +#define T2T_UID_BCC_CASCADE_BYTE 0x88 ///< Value used for calculating the first BCC byte of a Type 2 Tag serial number. + +#define T2T_SUPPORTED_MAJOR_VERSION 1 ///< Supported major version of the Type 2 Tag specification. +#define T2T_SUPPORTED_MINOR_VERSION 2 ///< Supported minor version of the Type 2 Tag specification. + +#define T2T_BLOCK_SIZE 4 ///< Type 2 Tag block size in bytes. + +#define T2T_CC_BLOCK_OFFSET 12 ///< Offset of the Capability Container area in the Type 2 Tag. +#define T2T_FIRST_DATA_BLOCK_OFFSET 16 ///< Offset of the data area in the Type 2 Tag. + +/** + * @} + */ + + +/** + * @defgroup nfc_type_2_tag_parser NFC Type 2 Tag parser + * @{ + * @ingroup nfc_t2t + * + * @brief Parser for Type 2 Tag data. + * + */ + +/** + * @brief Function for clearing the @ref type_2_tag_t structure. + * + * @param[in,out] p_type_2_tag Pointer to the structure that should be cleared. + * + */ +void type_2_tag_clear(type_2_tag_t * p_type_2_tag); + +/** + * @brief Function for parsing raw data read from a Type 2 Tag. + * + * This function parses the header and the following TLV blocks of a Type 2 Tag. The data is read + * from a buffer and stored in a @ref type_2_tag_t structure. + * + * @param[out] p_type_2_tag Pointer to the structure that will be filled with parsed data. + * @param[in] p_raw_data Pointer to the buffer with raw data from the tag (should + * point at the first byte of the first block of the tag). + * + * @retval NRF_SUCCESS If the data was parsed successfully. + * @retval NRF_ERROR_NO_MEM If there is not enough memory to store all of the TLV blocks. + * @retval Other If an error occurred during the parsing operation. + * + */ +ret_code_t type_2_tag_parse(type_2_tag_t * p_type_2_tag, uint8_t * p_raw_data); + +/** + * @brief Function for printing parsed contents of the Type 2 Tag. + * + * @param[in] p_type_2_tag Pointer to the structure that should be printed. + * + */ +void type_2_tag_printout(type_2_tag_t * p_type_2_tag); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_TYPE_2_TAG_PARSER_H__ */ diff --git a/libraries/nfc/src/t2t_parser/nfc_tlv_block.h b/libraries/nfc/src/t2t_parser/nfc_tlv_block.h new file mode 100644 index 000000000..3fcfdf4e5 --- /dev/null +++ b/libraries/nfc/src/t2t_parser/nfc_tlv_block.h @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_TLV_BLOCK_H__ +#define NFC_TLV_BLOCK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nfc_type_2_tag_tlv_block Type 2 Tag TLV blocks + * @{ + * @ingroup nfc_type_2_tag_parser + * + * @brief Descriptor for a Type 2 Tag TLV block. + * + */ + +/** + * @brief Tag field values. + * + * Possible values for the tag field in a TLV block. + */ +typedef enum +{ + TLV_NULL = 0x00, ///< Might be used for padding of memory areas. + TLV_LOCK_CONTROL = 0x01, ///< Defines details of the lock bits. + TLV_MEMORY_CONTROL = 0x02, ///< Identifies reserved memory areas. + TLV_NDEF_MESSAGE = 0x03, ///< Contains an NDEF message. + TLV_PROPRIETARY = 0xFD, ///< Tag proprietary information. + TLV_TERMINATOR = 0xFE ///< Last TLV block in the data area. +} tlv_block_types_t; + +/** + * @brief TLV block descriptor. + */ +typedef struct +{ + uint8_t tag; ///< Type of the TLV block. + uint16_t length; ///< Length of the value field. + uint8_t * p_value; ///< Pointer to the value field (NULL if no value field is present in the block). +} tlv_block_t; + +#define TLV_T_LENGTH 1 ///< Length of a tag field. + +#define TLV_L_SHORT_LENGTH 1 ///< Length of a short length field. +#define TLV_L_LONG_LENGTH 3 ///< Length of an extended length field. +#define TLV_L_FORMAT_FLAG 0xFF ///< Value indicating the use of an extended length field. + +#define TLV_NULL_TERMINATOR_LEN 0 ///< Predefined length of the NULL and TERMINATOR TLV blocks. +#define TLV_LOCK_MEMORY_CTRL_LEN 3 ///< Predefined length of the LOCK CONTROL and MEMORY CONTROL blocks. + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_TLV_BLOCK_H__ */ diff --git a/libraries/nfc/src/util/app_error.c b/libraries/nfc/src/util/app_error.c new file mode 100644 index 000000000..73a1234af --- /dev/null +++ b/libraries/nfc/src/util/app_error.c @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +#include "nrf.h" +#include +#include "app_error.h" +#include "nordic_common.h" +#include "sdk_errors.h" + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @warning This handler is an example only and does not fit a final product. You need to analyze + * how your product is supposed to react in case of error. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler_bare(ret_code_t error_code) +{ + error_info_t error_info = + { + .line_num = 0, + .p_file_name = NULL, + .err_code = error_code, + }; + + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} + +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info) +{ + /* static error variables - in order to prevent removal by optimizers */ + static volatile struct + { + uint32_t fault_id; + uint32_t pc; + uint32_t error_info; + assert_info_t * p_assert_info; + error_info_t * p_error_info; + ret_code_t err_code; + uint32_t line_num; + const uint8_t * p_file_name; + } m_error_data = {0}; + + // The following variable helps Keil keep the call stack visible, in addition, it can be set to + // 0 in the debugger to continue executing code after the error check. + volatile bool loop = true; + UNUSED_VARIABLE(loop); + + m_error_data.fault_id = id; + m_error_data.pc = pc; + m_error_data.error_info = info; + + switch (id) + { + case NRF_FAULT_ID_SDK_ASSERT: + m_error_data.p_assert_info = (assert_info_t *)info; + m_error_data.line_num = m_error_data.p_assert_info->line_num; + m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name; + break; + + case NRF_FAULT_ID_SDK_ERROR: + m_error_data.p_error_info = (error_info_t *)info; + m_error_data.err_code = m_error_data.p_error_info->err_code; + m_error_data.line_num = m_error_data.p_error_info->line_num; + m_error_data.p_file_name = m_error_data.p_error_info->p_file_name; + break; + } + + UNUSED_VARIABLE(m_error_data); + + // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger. + __disable_irq(); + while (loop); + + __enable_irq(); +} diff --git a/libraries/nfc/src/util/app_error.h b/libraries/nfc/src/util/app_error.h new file mode 100644 index 000000000..1da0c01c2 --- /dev/null +++ b/libraries/nfc/src/util/app_error.h @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler and macros for utilizing a common error handler. + */ + +#ifndef APP_ERROR_H__ +#define APP_ERROR_H__ + + +#include +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "nordic_common.h" +#include "app_error_weak.h" +#ifdef ANT_STACK_SUPPORT_REQD +#include "ant_error.h" +#endif // ANT_STACK_SUPPORT_REQD + + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_FAULT_ID_SDK_RANGE_START (0x00004000) /**< The start of the range of error IDs defined in the SDK. */ + +/**@defgroup APP_ERROR_FAULT_IDS Fault ID types + * @{ */ +#define NRF_FAULT_ID_SDK_ERROR (NRF_FAULT_ID_SDK_RANGE_START + 1) /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */ +#define NRF_FAULT_ID_SDK_ASSERT (NRF_FAULT_ID_SDK_RANGE_START + 2) /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */ +/**@} */ + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR. + */ +typedef struct +{ + uint32_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ + uint32_t err_code; /**< The error code representing the error that occurred. */ +} error_info_t; + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT. + */ +typedef struct +{ + uint32_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ +} assert_info_t; + +/**@brief Defines required by app_error_handler assembler intructions. + */ +#define APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM (offsetof(error_info_t, line_num)) +#define APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME (offsetof(error_info_t, p_file_name)) +#define APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE (offsetof(error_info_t, err_code)) +#define APP_ERROR_ERROR_INFO_SIZE (sizeof(error_info_t)) +#define APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE \ + ALIGN_NUM(APP_ERROR_ERROR_INFO_SIZE, sizeof(uint64_t)) + + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name); + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + */ +void app_error_handler_bare(ret_code_t error_code); + +/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info); + +/**@brief Function for logging details of error and flushing logs. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_log_handle(uint32_t id, uint32_t pc, uint32_t info); + + +/**@brief Macro for calling error handler function. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#ifdef DEBUG +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \ + } while (0) +#else +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler_bare((ERR_CODE)); \ + } while (0) +#endif +/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#define APP_ERROR_CHECK(ERR_CODE) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != NRF_SUCCESS) \ + { \ + APP_ERROR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) + +/**@brief Macro for calling error handler function if supplied boolean value is false. + * + * @param[in] BOOLEAN_VALUE Boolean value to be evaluated. + */ +#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \ + do \ + { \ + const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \ + if (!LOCAL_BOOLEAN_VALUE) \ + { \ + APP_ERROR_HANDLER(0); \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_H__ + +/** @} */ diff --git a/libraries/nfc/src/util/app_error_handler_gcc.c b/libraries/nfc/src/util/app_error_handler_gcc.c new file mode 100644 index 000000000..51a971e58 --- /dev/null +++ b/libraries/nfc/src/util/app_error_handler_gcc.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#include "compiler_abstraction.h" +#include "app_error.h" + +#if defined (__CORTEX_M) && (__CORTEX_M == 0x04) +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) __attribute__(( naked )); + +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + __ASM volatile( + + "push {lr} \n" + + /* reserve space on stack for error_info_t struct - preserve 8byte stack aligment */ + "sub sp, sp, %0 \n" + + /* prepare error_info_t struct */ + "str r0, [sp, %1] \n" + "str r1, [sp, %3] \n" + "str r2, [sp, %2] \n" + + /* prepare arguments and call function: app_error_fault_handler */ + "ldr r0, =%4 \n" + "mov r1, lr \n" + "mov r2, sp \n" + "bl %5 \n" + + /* release stack */ + "add sp, sp, %0 \n" + + "pop {pc} \n" + ".ltorg \n" + + : /* Outputs */ + : /* Inputs */ + "I" (APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE), + "I" (APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE), + "I" (APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME), + "I" (APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM), + "X" (NRF_FAULT_ID_SDK_ERROR), + "X" (app_error_fault_handler) + : /* Clobbers */ + "r0", "r1", "r2" + ); +} +#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00) +/* NRF51 implementation is currently not supporting PC readout */ +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + error_info_t error_info = { + .line_num = line_num, + .p_file_name = p_file_name, + .err_code = error_code, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} +#else +#error Architecture not supported +#endif + diff --git a/libraries/nfc/src/util/app_error_weak.c b/libraries/nfc/src/util/app_error_weak.c new file mode 100644 index 000000000..9a5ecdd27 --- /dev/null +++ b/libraries/nfc/src/util/app_error_weak.c @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "app_error.h" + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "app_util_platform.h" +#include "nrf_strerror.h" + +// #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT +// #include "nrf_sdm.h" +// #endif + +/*lint -save -e14 */ +/** + * Function is implemented as weak so that it can be overwritten by custom application error handler + * when needed. + */ +__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) +{ + __disable_irq(); + NRF_LOG_FINAL_FLUSH(); + +#ifndef DEBUG + NRF_LOG_ERROR("Fatal error"); +#else + switch (id) + { +// #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT +// case NRF_FAULT_ID_SD_ASSERT: +// NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED"); +// break; +// case NRF_FAULT_ID_APP_MEMACC: +// NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS"); +// break; +// #endif + case NRF_FAULT_ID_SDK_ASSERT: + { + assert_info_t * p_info = (assert_info_t *)info; + NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", + p_info->p_file_name, + p_info->line_num); + break; + } + case NRF_FAULT_ID_SDK_ERROR: + { + error_info_t * p_info = (error_info_t *)info; + NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x", + p_info->err_code, + nrf_strerror_get(p_info->err_code), + p_info->p_file_name, + p_info->line_num, + pc); + NRF_LOG_ERROR("End of error report"); + break; + } + default: + NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc); + break; + } +#endif + + NRF_BREAKPOINT_COND; + // On assert, the system can only recover with a reset. + +#ifndef DEBUG + NRF_LOG_WARNING("System reset"); + NVIC_SystemReset(); +#else + app_error_save_and_stop(id, pc, info); +#endif // DEBUG +} +/*lint -restore */ diff --git a/libraries/nfc/src/util/app_error_weak.h b/libraries/nfc/src/util/app_error_weak.h new file mode 100644 index 000000000..f52f64405 --- /dev/null +++ b/libraries/nfc/src/util/app_error_weak.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 APP_ERROR_WEAK_H__ +#define APP_ERROR_WEAK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +/**@brief Callback function for errors, asserts, and faults. + * + * @details This function is called every time an error is raised in app_error, nrf_assert, or + * in the SoftDevice. Information about the error can be found in the @p info + * parameter. + * + * See also @ref nrf_fault_handler_t for more details. + * + * @note The function is implemented as weak so that it can be redefined by a custom error + * handler when needed. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. The value of the @p id + * parameter dictates how to interpret this parameter. Refer to the documentation + * for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for + * details about interpreting @p info. + */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_WEAK_H__ diff --git a/libraries/nfc/src/util/app_util.h b/libraries/nfc/src/util/app_util.h new file mode 100644 index 000000000..5de3b2e98 --- /dev/null +++ b/libraries/nfc/src/util/app_util.h @@ -0,0 +1,1326 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_H__ +#define APP_UTIL_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "nordic_common.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @cond (NODOX) + */ +/*lint -save -e27 -e10 -e19 */ +#if defined (__LINT__) +#define STACK_BASE 0x1F000 // Arbitrary value. +#define STACK_TOP 0x20000 // Arbitrary value. + +#elif defined ( __CC_ARM ) +extern char STACK$$Base; +extern char STACK$$Length; +#define STACK_BASE &STACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&STACK$$Length)) + +#elif defined ( __ICCARM__ ) +extern char CSTACK$$Base; +extern char CSTACK$$Length; +#define STACK_BASE &CSTACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&CSTACK$$Length)) + +#elif defined ( __GNUC__ ) +extern uint32_t __StackTop; +extern uint32_t __StackLimit; +#define STACK_BASE &__StackLimit +#define STACK_TOP &__StackTop +#endif + +/* These macros are valid only when absolute placement is used for the application + * image. The macros are not compile time symbols. They cannot be used as a + * constant expression, for example, inside a static assert or linker script + * at-placement. */ +#if defined (__LINT__) +#define CODE_START (0) // Arbitrary value. +#define CODE_END (0x1000) // Arbitrary value. +#define CODE_SIZE (0x1000) // Arbitrary value. + +#elif defined ( __CC_ARM ) +extern char Load$$LR$$LR_IROM1$$Base; +extern char Load$$LR$$LR_IROM1$$Length; +extern char Load$$LR$$LR_IROM1$$Limit; +#define CODE_START ((uint32_t)&Load$$LR$$LR_IROM1$$Base) +#define CODE_END ((uint32_t)&Load$$LR$$LR_IROM1$$Limit) +#define CODE_SIZE ((uint32_t)&Load$$LR$$LR_IROM1$$Length) + +#elif defined ( __ICCARM__ ) +extern void * __vector_table; +extern char RO_END$$Base; +#define CODE_START ((uint32_t)&__vector_table) +#define CODE_END ((uint32_t)&RO_END$$Base) +#define CODE_SIZE (CODE_END - CODE_START) + +#elif defined(__SES_ARM) +extern uint32_t * _vectors; +extern uint32_t __FLASH_segment_used_end__; +#define CODE_START ((uint32_t)&_vectors) +#define CODE_END ((uint32_t)&__FLASH_segment_used_end__) +#define CODE_SIZE (CODE_END - CODE_START) + +#elif defined ( __GNUC__ ) +extern uint32_t __isr_vector; +extern uint32_t __etext; +#define CODE_START ((uint32_t)&__isr_vector) +#define CODE_END ((uint32_t)&__etext) +#define CODE_SIZE (CODE_END - CODE_START) +#endif +/** @} + * @endcond + */ +/* lint -restore */ + +#if defined(MBR_PRESENT) //|| defined(SOFTDEVICE_PRESENT) +#include "nrf_mbr.h" +#define BOOTLOADER_ADDRESS ((*(uint32_t *)MBR_BOOTLOADER_ADDR) == 0xFFFFFFFF ? *MBR_UICR_BOOTLOADER_ADDR : *(uint32_t *)MBR_BOOTLOADER_ADDR) /**< The currently configured start address of the bootloader. If 0xFFFFFFFF, no bootloader start address is configured. */ +#define MBR_PARAMS_PAGE_ADDRESS ((*(uint32_t *)MBR_PARAM_PAGE_ADDR) == 0xFFFFFFFF ? *MBR_UICR_PARAM_PAGE_ADDR : *(uint32_t *)MBR_PARAM_PAGE_ADDR) /**< The currently configured address of the MBR params page. If 0xFFFFFFFF, no MBR params page address is configured. */ +#else +#define BOOTLOADER_ADDRESS (NRF_UICR->NRFFW[0]) /**< Check UICR, just in case. */ +#define MBR_PARAMS_PAGE_ADDRESS (NRF_UICR->NRFFW[1]) /**< Check UICR, just in case. */ +#endif + +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + +/** + * @brief Counts number of bits required for the given value + * + * The macro technically searches for the highest bit set. + * For value 0 it returns 0. + * + * @param val Value to be processed + * + * @return Number of bits required for the given value + */ +//lint -emacro(572,VBITS) +#define VBITS(val) VBITS_32(val) + +/** + * @def VBITS_1 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_2 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_4 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_8 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_16 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_32 + * @brief Internal macro used by @ref VBITS */ +#define VBITS_1( v) ((((v) & (0x0001U << 0)) != 0) ? 1U : 0U) +#define VBITS_2( v) ((((v) & (0x0001U << 1)) != 0) ? VBITS_1 ((v) >> 1) + 1 : VBITS_1 (v)) +#define VBITS_4( v) ((((v) & (0x0003U << 2)) != 0) ? VBITS_2 ((v) >> 2) + 2 : VBITS_2 (v)) +#define VBITS_8( v) ((((v) & (0x000fU << 4)) != 0) ? VBITS_4 ((v) >> 4) + 4 : VBITS_4 (v)) +#define VBITS_16(v) ((((v) & (0x00ffU << 8)) != 0) ? VBITS_8 ((v) >> 8) + 8 : VBITS_8 (v)) +#define VBITS_32(v) ((((v) & (0xffffU << 16)) != 0) ? VBITS_16((v) >> 16) + 16 : VBITS_16(v)) + + +/*Segger embedded studio originally has offsetof macro which cannot be used in macros (like STATIC_ASSERT). + This redefinition is to allow using that. */ +#if defined(__SES_ARM) && defined(__GNUC__) +#undef offsetof +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#endif + +/**@brief Implementation specific macro for delayed macro expansion used in string concatenation +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs + + +/**@brief Macro used to concatenate string using delayed macro expansion +* +* @note This macro will delay concatenation until the expressions have been resolved +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) + + +#ifndef __LINT__ + +#ifdef __GNUC__ +#ifdef __cplusplus +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#else +#define STATIC_ASSERT_SIMPLE(EXPR) _Static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) _Static_assert(EXPR, MSG) +#endif +#endif + +#ifdef __CC_ARM +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#endif + +#ifdef __ICCARM__ +#define STATIC_ASSERT_SIMPLE(EXPR) static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) static_assert(EXPR, MSG) +#endif + +#else // __LINT__ + +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_ignore(void)) +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_ignore(void)) + +#endif + + +#define _SELECT_ASSERT_FUNC(x, EXPR, MSG, ASSERT_MACRO, ...) ASSERT_MACRO + +/** + * @brief Static (i.e. compile time) assert macro. + * + * @note The output of STATIC_ASSERT can be different across compilers. + * + * Usage: + * STATIC_ASSERT(expression); + * STATIC_ASSERT(expression, message); + * + * @hideinitializer + */ +//lint -save -esym(???, STATIC_ASSERT) +#define STATIC_ASSERT(...) \ + _SELECT_ASSERT_FUNC(x, ##__VA_ARGS__, \ + STATIC_ASSERT_MSG(__VA_ARGS__), \ + STATIC_ASSERT_SIMPLE(__VA_ARGS__)) +//lint -restore + + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_IMPL( \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + + +/**@brief Macro to get the number of arguments in a call variadic macro call + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_LESS_1_IMPL( \ + _ignored, \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + +/**@brief Macro to get the number of arguments in a call variadic macro call. + * First argument is not counted. + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS_LESS_1(...) NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) + + +/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ +typedef uint8_t uint16_le_t[2]; + +/**@brief Type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ +typedef uint8_t uint32_le_t[4]; + +/**@brief Byte array type. */ +typedef struct +{ + uint16_t size; /**< Number of array entries. */ + uint8_t * p_data; /**< Pointer to array entries. */ +} uint8_array_t; + + +/**@brief Macro for performing rounded integer division (as opposed to truncating the result). + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Rounded (integer) result of dividing A by B. + */ +#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) + + +/**@brief Macro for checking if an integer is a power of two. + * + * @param[in] A Number to be tested. + * + * @return true if value is power of two. + * @return false if value not power of two. + */ +#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) + + +/**@brief Macro for converting milliseconds to ticks. + * + * @param[in] TIME Number of milliseconds to convert. + * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. + */ +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) + + +/**@brief Macro for performing integer division, making sure the result is rounded up. + * + * @details One typical use for this is to compute the number of objects with size B is needed to + * hold A number of bytes. + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Integer result of dividing A by B, rounded up. + */ +#define CEIL_DIV(A, B) \ + (((A) + (B) - 1) / (B)) + + +/**@brief Macro for creating a buffer aligned to 4 bytes. + * + * @param[in] NAME Name of the buffor. + * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). + */ +#define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] + + +/**@brief Macro for calculating the number of words that are needed to hold a number of bytes. + * + * @details Adds 3 and divides by 4. + * + * @param[in] n_bytes The number of bytes. + * + * @return The number of words that @p n_bytes take up (rounded up). + */ +#define BYTES_TO_WORDS(n_bytes) (((n_bytes) + 3) >> 2) + + +/**@brief The number of bytes in a word. + */ +#define BYTES_PER_WORD (4) + + +/**@brief Macro for increasing a number to the nearest (larger) multiple of another number. + * + * @param[in] alignment The number to align to. + * @param[in] number The number to align (increase). + * + * @return The aligned (increased) @p number. + */ +#define ALIGN_NUM(alignment, number) (((number) - 1) + (alignment) - (((number) - 1) % (alignment))) + +/**@brief Macro for getting first of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_1(a1, a2) a1 + +/**@brief Macro for getting second of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_2(a1, a2) a2 + + +/**@brief Container of macro (borrowed from Linux kernel). + * + * This macro returns parent structure address basing on child member address. + * + * @param ptr Address of child type. + * @param type Type of parent structure. + * @param member Name of child field in parent structure. + * + * @return Parent structure address. + * */ +#define CONTAINER_OF(ptr, type, member) \ + (type *)((char *)ptr - offsetof(type, member)) + + +/** + * @brief Define Bit-field mask + * + * Macro that defined the mask with selected number of bits set, starting from + * provided bit number. + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + */ +#define BF_MASK(bcnt, boff) ( ((1U << (bcnt)) - 1U) << (boff) ) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value + * + * @param[in] val Value from which selected bit-field would be extracted + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return Value of the selected bits + */ +#define BF_GET(val, bcnt, boff) ( ( (val) & BF_MASK((bcnt), (boff)) ) >> (boff) ) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field + * + * @param[in] val Value to set on bit-field + * @param[in] bcnt Number of bits for bit-field + * @param[in] boff Offset of bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_VAL(val, bcnt, boff) ( (((uint32_t)(val)) << (boff)) & BF_MASK(bcnt, boff) ) + +/** + * @name Configuration of complex bit-field + * + * @sa BF_CX + * @{ + */ +/** @brief Position of bit count in complex bit-field value */ +#define BF_CX_BCNT_POS 0U +/** @brief Mask of bit count in complex bit-field value */ +#define BF_CX_BCNT_MASK (0xffU << BF_CX_BCNT_POS) +/** @brief Position of bit position in complex bit-field value */ +#define BF_CX_BOFF_POS 8U +/** @brief Mask of bit position in complex bit-field value */ +#define BF_CX_BOFF_MASK (0xffU << BF_CX_BOFF_POS) +/** @} */ + +/** + * @brief Define complex bit-field + * + * Complex bit-field would contain its position and size in one number. + * @sa BF_CX_MASK + * @sa BF_CX_POS + * @sa BF_CX_GET + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return The single number that describes the bit-field completely. + */ +#define BF_CX(bcnt, boff) ( ((((uint32_t)(bcnt)) << BF_CX_BCNT_POS) & BF_CX_BCNT_MASK) | ((((uint32_t)(boff)) << BF_CX_BOFF_POS) & BF_CX_BOFF_MASK) ) + +/** + * @brief Get number of bits in bit-field + * + * @sa BF_CX + * + * @param bf_cx Complex bit-field + * + * @return Number of bits in given bit-field + */ +#define BF_CX_BCNT(bf_cx) ( ((bf_cx) & BF_CX_BCNT_MASK) >> BF_CX_BCNT_POS ) + +/** + * @brief Get lowest bit number in the field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Lowest bit number in given bit-field + */ +#define BF_CX_BOFF(bf_cx) ( ((bf_cx) & BF_CX_BOFF_MASK) >> BF_CX_BOFF_POS ) + +/** + * @brief Get bit mask of the selected field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Mask of given bit-field + */ +#define BF_CX_MASK(bf_cx) BF_MASK(BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value. + * Bit-field is given as a complex value. + * + * @sa BF_CX + * @sa BF_GET + * + * @param[in] val Value from which selected bit-field would be extracted + * @param[in] bf_cx Complex bit-field + * + * @return Value of the selected bits. + */ +#define BF_CX_GET(val, bf_cx) BF_GET(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field. + * + * @param[in] val Value to set on bit-field + * @param[in] bf_cx Complex bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_CX_VAL(val, bf_cx) BF_VAL(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Extracting data from the brackets + * + * This macro get rid of brackets around the argument. + * It can be used to pass multiple arguments in logical one argument to a macro. + * Call it with arguments inside brackets: + * @code + * #define ARGUMENTS (a, b, c) + * BRACKET_EXTRACT(ARGUMENTS) + * @endcode + * It would produce: + * @code + * a, b, c + * @endcode + * + * @param a Argument with anything inside brackets + * @return Anything that appears inside the brackets of the argument + * + * @note + * The argument of the macro have to be inside brackets. + * In other case the compilation would fail. + */ +#define BRACKET_EXTRACT(a) BRACKET_EXTRACT_(a) +#define BRACKET_EXTRACT_(a) BRACKET_EXTRACT__ a +#define BRACKET_EXTRACT__(...) __VA_ARGS__ + + +/** + * @brief Check if number of parameters is more than 1 + * + * @param ... Arguments to count + * + * @return 0 If argument count is <= 1 + * @return 1 If argument count is > 1 + * + * @sa NUM_VA_ARGS + * @sa NUM_IS_MORE_THAN_1 + */ +#define NUM_VA_ARGS_IS_MORE_THAN_1(...) NUM_IS_MORE_THAN_1(NUM_VA_ARGS(__VA_ARGS__)) + +/** + * @brief Check if given numeric value is bigger than 1 + * + * This macro accepts numeric value, that may be the result of argument expansion. + * This numeric value is then converted to 0 if it is lover than 1 or to 1 if + * its value is higher than 1. + * The generated result can be used to glue it into other macro mnemonic name. + * + * @param N Numeric value to check + * + * @return 0 If argument is <= 1 + * @return 1 If argument is > 1 + * + * @note Any existing definition of a form NUM_IS_MORE_THAN_1_PROBE_[N] can + * broke the result of this macro + */ +#define NUM_IS_MORE_THAN_1(N) NUM_IS_MORE_THAN_1_(N) +#define NUM_IS_MORE_THAN_1_(N) NUM_IS_MORE_THAN_1_PROBE_(NUM_IS_MORE_THAN_1_PROBE_ ## N, 1) +#define NUM_IS_MORE_THAN_1_PROBE_(...) GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)) +#define NUM_IS_MORE_THAN_1_PROBE_0 ~, 0 +#define NUM_IS_MORE_THAN_1_PROBE_1 ~, 0 + +/** + * @brief Get the first argument + * + * @param ... Arguments to select + * + * @return First argument or empty if no arguments are provided + */ +#define GET_VA_ARG_1(...) GET_VA_ARG_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_VA_ARG_1_(a1, ...) a1 + +/** + * @brief Get all the arguments but the first one + * + * @param ... Arguments to select + * + * @return All arguments after the first one or empty if less than 2 arguments are provided + */ +#define GET_ARGS_AFTER_1(...) GET_ARGS_AFTER_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_ARGS_AFTER_1_(a1, ...) __VA_ARGS__ + +/** + * @brief Size of a field in declared structure + * + * Macro that returns the size of the structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. It can be even field inside field (field.somethingelse.and_another). + * + * @return Size of the field + */ +#define FIELD_SIZE(struct_type, field) sizeof(((struct struct_type*)NULL)->field) + +/** + * @brief Number of elements in field array in declared structure + * + * Macro that returns number of elementy in structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. + * + * @return Number of elements in field array + * + * @sa FIELD_SIZE + */ +#define FIELD_ARRAY_SIZE(struct_type, field) (FIELD_SIZE(struct_type, field) / FIELD_SIZE(struct_type, field[0])) + +/** + * @brief Mapping macro + * + * Macro that process all arguments using given macro + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) +#define MACRO_MAP_(...) MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total + +/** + * @brief Mapping macro, recursive version + * + * Can be used in @ref MACRO_MAP macro + */ +#define MACRO_MAP_REC(...) MACRO_MAP_REC_(__VA_ARGS__) +#define MACRO_MAP_REC_(...) MACRO_MAP_REC_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total +/** + * @brief Mapping N arguments macro + * + * Macro similar to @ref MACRO_MAP but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) +#define MACRO_MAP_N_(N, ...) CONCAT_2(MACRO_MAP_, N)(__VA_ARGS__, ) + +/** + * @brief Mapping N arguments macro, recursive version + * + * Can be used in @ref MACRO_MAP_N macro + */ +#define MACRO_MAP_REC_N(N, ...) MACRO_MAP_REC_N_(N, __VA_ARGS__) +#define MACRO_MAP_REC_N_(N, ...) CONCAT_2(MACRO_MAP_REC_, N)(__VA_ARGS__, ) + +#define MACRO_MAP_0( ...) +#define MACRO_MAP_1( macro, a, ...) macro(a) +#define MACRO_MAP_2( macro, a, ...) macro(a) MACRO_MAP_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_3( macro, a, ...) macro(a) MACRO_MAP_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_4( macro, a, ...) macro(a) MACRO_MAP_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_5( macro, a, ...) macro(a) MACRO_MAP_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_6( macro, a, ...) macro(a) MACRO_MAP_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_7( macro, a, ...) macro(a) MACRO_MAP_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_8( macro, a, ...) macro(a) MACRO_MAP_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_9( macro, a, ...) macro(a) MACRO_MAP_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_10(macro, a, ...) macro(a) MACRO_MAP_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_11(macro, a, ...) macro(a) MACRO_MAP_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_12(macro, a, ...) macro(a) MACRO_MAP_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_13(macro, a, ...) macro(a) MACRO_MAP_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_14(macro, a, ...) macro(a) MACRO_MAP_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_15(macro, a, ...) macro(a) MACRO_MAP_14(macro, __VA_ARGS__, ) +#define MACRO_MAP_16(macro, a, ...) macro(a) MACRO_MAP_15(macro, __VA_ARGS__, ) +#define MACRO_MAP_17(macro, a, ...) macro(a) MACRO_MAP_16(macro, __VA_ARGS__, ) +#define MACRO_MAP_18(macro, a, ...) macro(a) MACRO_MAP_17(macro, __VA_ARGS__, ) +#define MACRO_MAP_19(macro, a, ...) macro(a) MACRO_MAP_18(macro, __VA_ARGS__, ) +#define MACRO_MAP_20(macro, a, ...) macro(a) MACRO_MAP_19(macro, __VA_ARGS__, ) +#define MACRO_MAP_21(macro, a, ...) macro(a) MACRO_MAP_20(macro, __VA_ARGS__, ) +#define MACRO_MAP_22(macro, a, ...) macro(a) MACRO_MAP_21(macro, __VA_ARGS__, ) +#define MACRO_MAP_23(macro, a, ...) macro(a) MACRO_MAP_22(macro, __VA_ARGS__, ) +#define MACRO_MAP_24(macro, a, ...) macro(a) MACRO_MAP_23(macro, __VA_ARGS__, ) +#define MACRO_MAP_25(macro, a, ...) macro(a) MACRO_MAP_24(macro, __VA_ARGS__, ) +#define MACRO_MAP_26(macro, a, ...) macro(a) MACRO_MAP_25(macro, __VA_ARGS__, ) +#define MACRO_MAP_27(macro, a, ...) macro(a) MACRO_MAP_26(macro, __VA_ARGS__, ) +#define MACRO_MAP_28(macro, a, ...) macro(a) MACRO_MAP_27(macro, __VA_ARGS__, ) +#define MACRO_MAP_29(macro, a, ...) macro(a) MACRO_MAP_28(macro, __VA_ARGS__, ) +#define MACRO_MAP_30(macro, a, ...) macro(a) MACRO_MAP_29(macro, __VA_ARGS__, ) +#define MACRO_MAP_31(macro, a, ...) macro(a) MACRO_MAP_30(macro, __VA_ARGS__, ) +#define MACRO_MAP_32(macro, a, ...) macro(a) MACRO_MAP_31(macro, __VA_ARGS__, ) + + +#define MACRO_MAP_REC_0( ...) +#define MACRO_MAP_REC_1( macro, a, ...) macro(a) +#define MACRO_MAP_REC_2( macro, a, ...) macro(a) MACRO_MAP_REC_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_3( macro, a, ...) macro(a) MACRO_MAP_REC_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_4( macro, a, ...) macro(a) MACRO_MAP_REC_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_5( macro, a, ...) macro(a) MACRO_MAP_REC_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_6( macro, a, ...) macro(a) MACRO_MAP_REC_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_7( macro, a, ...) macro(a) MACRO_MAP_REC_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_8( macro, a, ...) macro(a) MACRO_MAP_REC_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_9( macro, a, ...) macro(a) MACRO_MAP_REC_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_10(macro, a, ...) macro(a) MACRO_MAP_REC_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_11(macro, a, ...) macro(a) MACRO_MAP_REC_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_12(macro, a, ...) macro(a) MACRO_MAP_REC_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_13(macro, a, ...) macro(a) MACRO_MAP_REC_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_14(macro, a, ...) macro(a) MACRO_MAP_REC_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_15(macro, a, ...) macro(a) MACRO_MAP_REC_14(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_16(macro, a, ...) macro(a) MACRO_MAP_REC_15(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_17(macro, a, ...) macro(a) MACRO_MAP_REC_16(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_18(macro, a, ...) macro(a) MACRO_MAP_REC_17(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_19(macro, a, ...) macro(a) MACRO_MAP_REC_18(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_20(macro, a, ...) macro(a) MACRO_MAP_REC_19(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_21(macro, a, ...) macro(a) MACRO_MAP_REC_20(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_22(macro, a, ...) macro(a) MACRO_MAP_REC_21(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_23(macro, a, ...) macro(a) MACRO_MAP_REC_22(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_24(macro, a, ...) macro(a) MACRO_MAP_REC_23(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_25(macro, a, ...) macro(a) MACRO_MAP_REC_24(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_26(macro, a, ...) macro(a) MACRO_MAP_REC_25(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_27(macro, a, ...) macro(a) MACRO_MAP_REC_26(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_28(macro, a, ...) macro(a) MACRO_MAP_REC_27(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_29(macro, a, ...) macro(a) MACRO_MAP_REC_28(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_30(macro, a, ...) macro(a) MACRO_MAP_REC_29(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_31(macro, a, ...) macro(a) MACRO_MAP_REC_30(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_32(macro, a, ...) macro(a) MACRO_MAP_REC_31(macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index + * + * Basically macro similar to @ref MACRO_MAP, but the processing function would get an argument + * and current argument index (beginning from 0). + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR(...) MACRO_MAP_FOR_(__VA_ARGS__) +#define MACRO_MAP_FOR_N_LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, \ + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +#define MACRO_MAP_FOR_(...) MACRO_MAP_FOR_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with current index + * + * Macro is similar to @ref MACRO_MAP_FOR but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_FOR_N(N, ...) MACRO_MAP_FOR_N_(N, __VA_ARGS__) +#define MACRO_MAP_FOR_N_(N, ...) CONCAT_2(MACRO_MAP_FOR_, N)((MACRO_MAP_FOR_N_LIST), __VA_ARGS__, ) + +#define MACRO_MAP_FOR_0( n_list, ...) +#define MACRO_MAP_FOR_1( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) +#define MACRO_MAP_FOR_2( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_3( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_4( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_5( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_6( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_7( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_8( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_9( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_10(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_11(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_12(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_13(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_14(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_15(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_16(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_17(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_18(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_19(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_20(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_21(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_22(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_23(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_24(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_25(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_26(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_27(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_28(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_29(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_30(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_31(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_32(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index and parameter + * + * Version of @ref MACRO_MAP_FOR that passes also the same parameter to all macros. + * + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM(param, ...) MACRO_MAP_FOR_PARAM_(param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_(param, ...) MACRO_MAP_FOR_PARAM_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), param, __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with with current index and parameter + * + * @param N Number of arguments to map + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM_N(N, param, ...) MACRO_MAP_FOR_PARAM_N_(N, param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_N_(N, param, ...) CONCAT_2(MACRO_MAP_FOR_PARAM_, N)((MACRO_MAP_FOR_N_LIST), param, __VA_ARGS__, ) + + +#define MACRO_MAP_FOR_PARAM_0( n_list, param, ...) +#define MACRO_MAP_FOR_PARAM_1( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) +#define MACRO_MAP_FOR_PARAM_2( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_3( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_4( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_5( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_6( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_7( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_8( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_9( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_10(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_11(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_12(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_13(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_14(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_15(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_16(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_17(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_18(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_19(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_20(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_21(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_22(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_23(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_24(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_25(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_26(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_27(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_28(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_29(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_30(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_31(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_32(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) + + + +/** + * @brief Repeating macro. + * + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT(count, macro, ...) MACRO_REPEAT_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_(count, macro, ...) CONCAT_2(MACRO_REPEAT_, count)(macro, __VA_ARGS__) + +#define MACRO_REPEAT_0(macro, ...) +#define MACRO_REPEAT_1(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_0(macro, __VA_ARGS__) +#define MACRO_REPEAT_2(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_1(macro, __VA_ARGS__) +#define MACRO_REPEAT_3(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_2(macro, __VA_ARGS__) +#define MACRO_REPEAT_4(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_3(macro, __VA_ARGS__) +#define MACRO_REPEAT_5(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_4(macro, __VA_ARGS__) +#define MACRO_REPEAT_6(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_5(macro, __VA_ARGS__) +#define MACRO_REPEAT_7(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_6(macro, __VA_ARGS__) +#define MACRO_REPEAT_8(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_7(macro, __VA_ARGS__) +#define MACRO_REPEAT_9(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_8(macro, __VA_ARGS__) +#define MACRO_REPEAT_10(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_9(macro, __VA_ARGS__) +#define MACRO_REPEAT_11(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_10(macro, __VA_ARGS__) +#define MACRO_REPEAT_12(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_11(macro, __VA_ARGS__) +#define MACRO_REPEAT_13(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_12(macro, __VA_ARGS__) +#define MACRO_REPEAT_14(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_13(macro, __VA_ARGS__) +#define MACRO_REPEAT_15(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_14(macro, __VA_ARGS__) +#define MACRO_REPEAT_16(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_15(macro, __VA_ARGS__) +#define MACRO_REPEAT_17(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_16(macro, __VA_ARGS__) +#define MACRO_REPEAT_18(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_17(macro, __VA_ARGS__) +#define MACRO_REPEAT_19(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_18(macro, __VA_ARGS__) +#define MACRO_REPEAT_20(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_19(macro, __VA_ARGS__) +#define MACRO_REPEAT_21(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_20(macro, __VA_ARGS__) +#define MACRO_REPEAT_22(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_21(macro, __VA_ARGS__) +#define MACRO_REPEAT_23(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_22(macro, __VA_ARGS__) +#define MACRO_REPEAT_24(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_23(macro, __VA_ARGS__) +#define MACRO_REPEAT_25(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_24(macro, __VA_ARGS__) +#define MACRO_REPEAT_26(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_25(macro, __VA_ARGS__) +#define MACRO_REPEAT_27(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_26(macro, __VA_ARGS__) +#define MACRO_REPEAT_28(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_27(macro, __VA_ARGS__) +#define MACRO_REPEAT_29(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_28(macro, __VA_ARGS__) +#define MACRO_REPEAT_30(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_29(macro, __VA_ARGS__) +#define MACRO_REPEAT_31(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_30(macro, __VA_ARGS__) +#define MACRO_REPEAT_32(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_31(macro, __VA_ARGS__) + + +/** + * @brief Repeating macro with current index. + * + * Macro similar to @ref MACRO_REPEAT but the processing function gets the arguments + * and the current argument index (beginning from 0). + + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(index, arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT_FOR(count, macro, ...) MACRO_REPEAT_FOR_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_(count, macro, ...) CONCAT_2(MACRO_REPEAT_FOR_, count)((MACRO_MAP_FOR_N_LIST), macro, __VA_ARGS__) + +#define MACRO_REPEAT_FOR_0(n_list, macro, ...) +#define MACRO_REPEAT_FOR_1(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_0((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_2(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_1((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_3(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_2((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_4(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_3((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_5(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_4((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_6(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_5((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_7(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_6((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_8(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_7((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_9(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_8((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_10(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_9((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_11(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_12(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_13(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_14(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_15(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_16(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_17(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_18(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_19(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_20(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_21(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_22(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_23(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_24(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_25(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_26(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_27(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_28(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_29(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_30(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_31(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_32(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) + + +/**@brief Adding curly brace to the macro parameter. + * + * Useful in array of structures initialization. + * + * @param p Parameter to put into the curly brace. */ +#define PARAM_CBRACE(p) { p }, + + +/**@brief Function for changing the value unit. + * + * @param[in] value Value to be rescaled. + * @param[in] old_unit_reversal Reversal of the incoming unit. + * @param[in] new_unit_reversal Reversal of the desired unit. + * + * @return Number of bytes written. + */ +static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) +{ + return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); +} + +/**@brief Function for encoding a uint16 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +/**@brief Function for encoding a three-byte value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + return 3; +} + +/**@brief Function for encoding a uint32 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + +/**@brief Function for encoding a uint40 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint40_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x0000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x00FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0xFF00000000) >> 32); + return 5; +} + +/**@brief Function for encoding a uint48 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint48_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x0000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x00000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x0000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0x00FF00000000) >> 32); + p_encoded_data[5] = (uint8_t) ((value & 0xFF0000000000) >> 40); + return 6; +} + +/**@brief Function for decoding a uint16 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); +} + +/**@brief Function for decoding a uint16 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0]) << 8 ) | + (((uint16_t)((uint8_t *)p_encoded_data)[1])) ); +} + +/**@brief Function for decoding a three-byte value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value (uint32_t). + */ +static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); +} + +/**@brief Function for decoding a uint32 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); +} + +/**@brief Function for decoding a uint32 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 24) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 0) ); +} + +/** + * @brief Function for encoding an uint16 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_big_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) (value >> 8); + p_encoded_data[1] = (uint8_t) (value & 0xFF); + + return sizeof(uint16_t); +} + +/*lint -esym(526, __rev) */ +/*lint -esym(628, __rev) */ +/**@brief Function for encoding a uint32 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * The address pointed to must be word alligned. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_big_encode(uint32_t value, uint8_t * p_encoded_data) +{ + *(uint32_t *)p_encoded_data = __REV(value); + return sizeof(uint32_t); +} + +/**@brief Function for decoding a uint40 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint40_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 )); +} + +/**@brief Function for decoding a uint48 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint48_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32) | + (((uint64_t)((uint8_t *)p_encoded_data)[5]) << 40 )); +} + +/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. + * + * @details The calculation is based on a linearized version of the battery's discharge + * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and + * is considered to be the lower boundary. + * + * The discharge curve for CR2032 is non-linear. In this model it is split into + * 4 linear sections: + * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) + * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) + * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) + * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) + * + * These numbers are by no means accurate. Temperature and + * load in the actual application is not accounted for! + * + * @param[in] mvolts The voltage in mV + * + * @return Battery level in percent. +*/ +static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) +{ + uint8_t battery_level; + + if (mvolts >= 3000) + { + battery_level = 100; + } + else if (mvolts > 2900) + { + battery_level = 100 - ((3000 - mvolts) * 58) / 100; + } + else if (mvolts > 2740) + { + battery_level = 42 - ((2900 - mvolts) * 24) / 160; + } + else if (mvolts > 2440) + { + battery_level = 18 - ((2740 - mvolts) * 12) / 300; + } + else if (mvolts > 2100) + { + battery_level = 6 - ((2440 - mvolts) * 6) / 340; + } + else + { + battery_level = 0; + } + + return battery_level; +} + +/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. + * + * @param[in] p Pointer value to be checked. + * + * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. + */ +static __INLINE bool is_word_aligned(void const* p) +{ + return (((uintptr_t)p & 0x03) == 0); +} + +/*lint -e{568, 685} */ +/** + * @brief Function for checking if provided address is located in stack space. + * + * @param[in] ptr Pointer to be checked. + * + * @return true if address is in stack space, false otherwise. + */ +static __INLINE bool is_address_from_stack(void * ptr) +{ + if (((uint32_t)ptr >= (uint32_t)STACK_BASE) && + ((uint32_t)ptr < (uint32_t)STACK_TOP) ) + { + return true; + } + else + { + return false; + } +} + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_H__ + +/** @} */ diff --git a/libraries/nfc/src/util/app_util_bds.h b/libraries/nfc/src/util/app_util_bds.h new file mode 100644 index 000000000..4d1aeb030 --- /dev/null +++ b/libraries/nfc/src/util/app_util_bds.h @@ -0,0 +1,449 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_BDS_H__ +#define APP_UTIL_BDS_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "app_util.h" +#include "ble_srv_common.h" +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t nibble_t; +typedef uint32_t uint24_t; +typedef uint64_t uint40_t; + +/**@brief IEEE 11073-20601 Regulatory Certification Data List Structure */ +typedef struct +{ + uint8_t * p_list; /**< Pointer the byte array containing the encoded opaque structure based on IEEE 11073-20601 specification. */ + uint8_t list_len; /**< Length of the byte array. */ +} regcertdatalist_t; + +/**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, meaning 4 bits for exponent (base 10) and 12 bits mantissa) */ +typedef struct +{ + int8_t exponent; /**< Base 10 exponent, should be using only 4 bits */ + int16_t mantissa; /**< Mantissa, should be using only 12 bits */ +} sfloat_t; + +/**@brief Date and Time structure. */ +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} ble_date_time_t; + + +/**@brief Function for encoding a uint16 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint16_encode(const uint16_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +static __INLINE uint8_t bds_int16_encode(const int16_t * p_value, uint8_t * p_encoded_data) +{ + uint16_t tmp = *p_value; + return bds_uint16_encode(&tmp, p_encoded_data); +} + +/**@brief Function for encoding a uint24 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint24_encode(const uint32_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16); + return (3); +} + + +/**@brief Function for encoding a uint32 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint32_encode(const uint32_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((*p_value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + + +/**@brief Function for encoding a uint40 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint40_encode(const uint64_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x00000000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x000000000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x0000000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((*p_value & 0x00000000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((*p_value & 0x000000FF00000000) >> 32); + return 5; +} + +/**@brief Function for encoding a sfloat value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_sfloat_encode(const sfloat_t * p_value, uint8_t * p_encoded_data) +{ + uint16_t encoded_val; + + encoded_val = ((p_value->exponent << 12) & 0xF000) | + ((p_value->mantissa << 0) & 0x0FFF); + + return(bds_uint16_encode(&encoded_val, p_encoded_data)); +} + + +/**@brief Function for encoding a uint8_array value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + */ +static __INLINE uint8_t bds_uint8_array_encode(const uint8_array_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_data, p_value->size); + return p_value->size; +} + + +/**@brief Function for encoding a utf8_str value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + + */ +static __INLINE uint8_t bds_ble_srv_utf8_str_encode(const ble_srv_utf8_str_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_str, p_value->length); + return p_value->length; +} + +/**@brief Function for encoding a regcertdatalist value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + + */ +static __INLINE uint8_t bds_regcertdatalist_encode(const regcertdatalist_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_list, p_value->list_len); + return p_value->list_len; +} + + +/**@brief Function for decoding a date_time value. + * + * @param[in] p_date_time pointer to the date_time structure to encode. + * @param[in] p_encoded_data pointer to the encoded data + * @return length of the encoded field. + */ +static __INLINE uint8_t bds_ble_date_time_encode(const ble_date_time_t * p_date_time, + uint8_t * p_encoded_data) +{ + uint8_t len = bds_uint16_encode(&p_date_time->year, &p_encoded_data[0]); + + p_encoded_data[len++] = p_date_time->month; + p_encoded_data[len++] = p_date_time->day; + p_encoded_data[len++] = p_date_time->hours; + p_encoded_data[len++] = p_date_time->minutes; + p_encoded_data[len++] = p_date_time->seconds; + + return len; +} + + +/**@brief Function for decoding a uint16 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint16_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint16_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 ); + return (sizeof(uint16_t)); +} + + +/**@brief Function for decoding a int16 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_int16_decode(const uint8_t len, + const uint8_t * p_encoded_data, + int16_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + uint16_t tmp = 0; + uint8_t retval = bds_uint16_decode(len, p_encoded_data, &tmp); + *p_decoded_val = (int16_t)tmp; + return retval; +} + + +/**@brief Function for decoding a uint24 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint24_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint32_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16); + return (3); +} + + +/**@brief Function for decoding a uint32 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint32_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint32_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 ); + return (sizeof(uint32_t)); +} + + +/**@brief Function for decoding a uint40 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint40_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint64_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24 )| + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 ); + return (40); +} + + +/**@brief Function for decoding a sfloat value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + + */ +static __INLINE uint8_t bds_sfloat_decode(const uint8_t len, + const uint8_t * p_encoded_data, + sfloat_t * p_decoded_val) +{ + + p_decoded_val->exponent = 0; + bds_uint16_decode(len, p_encoded_data, (uint16_t*)&p_decoded_val->mantissa); + p_decoded_val->exponent = (uint8_t)((p_decoded_val->mantissa & 0xF000) >> 12); + p_decoded_val->mantissa &= 0x0FFF; + return len; +} + + +/**@brief Function for decoding a uint8_array value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint8_array_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint8_array_t * p_decoded_val) +{ + memcpy(p_decoded_val->p_data, p_encoded_data, len); + p_decoded_val->size = len; + return p_decoded_val->size; +} + + +/**@brief Function for decoding a utf8_str value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_ble_srv_utf8_str_decode(const uint8_t len, + const uint8_t * p_encoded_data, + ble_srv_utf8_str_t * p_decoded_val) +{ + p_decoded_val->p_str = (uint8_t*)p_encoded_data; + p_decoded_val->length = len; + return p_decoded_val->length; +} + + +/**@brief Function for decoding a regcertdatalist value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_regcertdatalist_decode(const uint8_t len, + const uint8_t * p_encoded_data, + regcertdatalist_t * p_decoded_val) +{ + memcpy(p_decoded_val->p_list, p_encoded_data, len); + p_decoded_val->list_len = len; + return p_decoded_val->list_len; +} + + +/**@brief Function for decoding a date_time value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_date_time pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_ble_date_time_decode(const uint8_t len, + const uint8_t * p_encoded_data, + ble_date_time_t * p_date_time) +{ + UNUSED_VARIABLE(len); + uint8_t pos = bds_uint16_decode(len, &p_encoded_data[0], &p_date_time->year); + p_date_time->month = p_encoded_data[pos++]; + p_date_time->day = p_encoded_data[pos++]; + p_date_time->hours = p_encoded_data[pos++]; + p_date_time->minutes = p_encoded_data[pos++]; + p_date_time->seconds = p_encoded_data[pos++]; + + return pos; +} + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_BDS_H__ + +/** @} */ diff --git a/libraries/nfc/src/util/app_util_platform.c b/libraries/nfc/src/util/app_util_platform.c new file mode 100644 index 000000000..8e29efcf4 --- /dev/null +++ b/libraries/nfc/src/util/app_util_platform.c @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "app_util_platform.h" + +// #ifdef SOFTDEVICE_PRESENT +// /* Global nvic state instance, required by nrf_nvic.h */ +// extern nrf_nvic_state_t nrf_nvic_state; +// #endif + +static uint32_t m_in_critical_region = 0; + +void app_util_disable_irq(void) +{ + __disable_irq(); + m_in_critical_region++; +} + +void app_util_enable_irq(void) +{ + m_in_critical_region--; + if (m_in_critical_region == 0) + { + __enable_irq(); + } +} + +void app_util_critical_region_enter(uint8_t *p_nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +// #if defined(SOFTDEVICE_PRESENT) +// /* return value can be safely ignored */ +// (void) sd_nvic_critical_region_enter(p_nested); +// #else + app_util_disable_irq(); +//#endif +} + +void app_util_critical_region_exit(uint8_t nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +// #if defined(SOFTDEVICE_PRESENT) +// /* return value can be safely ignored */ +// (void) sd_nvic_critical_region_exit(nested); +// #else + app_util_enable_irq(); +//#endif +} + + +uint8_t privilege_level_get(void) +{ +#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__) + /* the Cortex-M0 has no concept of privilege */ + return APP_LEVEL_PRIVILEGED; +#elif __CORTEX_M >= (0x04U) + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (0 == isr_vector_num) + { + /* Thread Mode, check nPRIV */ + int32_t control = __get_CONTROL(); + return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED; + } + else + { + /* Handler Mode, always privileged */ + return APP_LEVEL_PRIVILEGED; + } +#endif +} + + +uint8_t current_int_priority_get(void) +{ + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (isr_vector_num > 0) + { + int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); + return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); + } + else + { + return APP_IRQ_PRIORITY_THREAD; + } +} diff --git a/libraries/nfc/src/util/app_util_platform.h b/libraries/nfc/src/util/app_util_platform.h new file mode 100644 index 000000000..4bbc9a977 --- /dev/null +++ b/libraries/nfc/src/util/app_util_platform.h @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup app_util_platform Utility Functions and Definitions (Platform) + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications when using SoftDevice. + */ + +#ifndef APP_UTIL_PLATFORM_H__ +#define APP_UTIL_PLATFORM_H__ + +#include +#include "compiler_abstraction.h" +#include "nrf.h" +// #ifdef SOFTDEVICE_PRESENT +// #include "nrf_soc.h" +// #include "nrf_nvic.h" +// #endif +#include "nrf_assert.h" +#include "app_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if __CORTEX_M == (0x00U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_APP_HIGH 1 +#define _PRIO_APP_MID 1 +#define _PRIO_SD_LOW 2 +#define _PRIO_APP_LOW_MID 3 +#define _PRIO_APP_LOW 3 +#define _PRIO_APP_LOWEST 3 +#define _PRIO_THREAD 4 +#elif __CORTEX_M >= (0x04U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_SD_MID 1 +#define _PRIO_APP_HIGH 2 +#define _PRIO_APP_MID 3 +#define _PRIO_SD_LOW 4 +#define _PRIO_APP_LOW_MID 5 +#define _PRIO_APP_LOW 6 +#define _PRIO_APP_LOWEST 7 +#define _PRIO_THREAD 15 +#else + #error "No platform defined" +#endif + + +//lint -save -e113 -e452 +/**@brief The interrupt priorities available to the application while the SoftDevice is active. */ +typedef enum +{ +// #ifndef SOFTDEVICE_PRESENT +// APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH, /**< Running in Application Highest interrupt level. */ +// #else + APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH, /**< Running in Application Highest interrupt level. */ +//#endif + APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH, /**< Running in Application High interrupt level. */ +// #ifndef SOFTDEVICE_PRESENT +// APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW, /**< Running in Application Middle interrupt level. */ +// #else + APP_IRQ_PRIORITY_MID = _PRIO_APP_MID, /**< Running in Application Middle interrupt level. */ +//#endif + APP_IRQ_PRIORITY_LOW_MID = _PRIO_APP_LOW_MID, /**< Running in Application Middle Low interrupt level. */ + APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW, /**< Running in Application Low interrupt level. */ + APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST, /**< Running in Application Lowest interrupt level. */ + APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< Running in Thread Mode. */ +} app_irq_priority_t; +//lint -restore + + +/*@brief The privilege levels available to applications in Thread Mode */ +typedef enum +{ + APP_LEVEL_UNPRIVILEGED, + APP_LEVEL_PRIVILEGED +} app_level_t; + +/**@cond NO_DOXYGEN */ +#define EXTERNAL_INT_VECTOR_OFFSET 16 +/**@endcond */ + +/**@brief Macro for setting a breakpoint. + */ +#if defined(__GNUC__) +#define NRF_BREAKPOINT __asm__("BKPT 0"); +#else +#define NRF_BREAKPOINT __BKPT(0) +#endif + +/** @brief Macro for setting a breakpoint. + * + * If it is possible to detect debugger presence then it is set only in that case. + * + */ +#if __CORTEX_M == 0x04 +#define NRF_BREAKPOINT_COND do { \ + /* C_DEBUGEN == 1 -> Debugger Connected */ \ + if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ + { \ + /* Generate breakpoint if debugger is connected */ \ + NRF_BREAKPOINT; \ + } \ + }while (0) +#else +#define NRF_BREAKPOINT_COND NRF_BREAKPOINT +#endif // __CORTEX_M == 0x04 + +#if defined ( __CC_ARM ) +#define PACKED(TYPE) __packed TYPE +#define PACKED_STRUCT PACKED(struct) +#elif defined ( __GNUC__ ) +#define PACKED __attribute__((packed)) +#define PACKED_STRUCT struct PACKED +#elif defined (__ICCARM__) +#define PACKED_STRUCT __packed struct +#endif + +#if defined ( __CC_ARM ) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("push") \ + _Pragma ("O3") +#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("pop") +#elif defined ( __GNUC__ ) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma("GCC push_options") \ + _Pragma ("GCC optimize (\"Os\")") +#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("GCC pop_options") +#elif defined (__ICCARM__) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("optimize=high z") +#define PRAGMA_OPTIMIZATION_FORCE_END +#endif + + +void app_util_critical_region_enter (uint8_t *p_nested); +void app_util_critical_region_exit (uint8_t nested); + +/**@brief Macro for entering a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +// #ifdef SOFTDEVICE_PRESENT +// #define CRITICAL_REGION_ENTER() \ +// { \ +// uint8_t __CR_NESTED = 0; \ +// app_util_critical_region_enter(&__CR_NESTED); +// #else +#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL) +//#endif + +/**@brief Macro for leaving a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +// #ifdef SOFTDEVICE_PRESENT +// #define CRITICAL_REGION_EXIT() \ +// app_util_critical_region_exit(__CR_NESTED); \ +// } +// #else +#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0) +//#endif + +/* Workaround for Keil 4 */ +#ifndef IPSR_ISR_Msk +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ +#endif + + + +/**@brief Macro to enable anonymous unions from a certain point in the code. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_ENABLE _Pragma("push") \ + _Pragma("anon_unions") \ + struct semicolon_swallower +#elif defined(__ICCARM__) + #define ANON_UNIONS_ENABLE _Pragma("language=extended") \ + struct semicolon_swallower +#else + #define ANON_UNIONS_ENABLE struct semicolon_swallower + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro to disable anonymous unions from a certain point in the code. + * @note Call only after first calling @ref ANON_UNIONS_ENABLE. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_DISABLE _Pragma("pop") \ + struct semicolon_swallower +#elif defined(__ICCARM__) + #define ANON_UNIONS_DISABLE struct semicolon_swallower + // for IAR leave anonymous unions enabled +#else + #define ANON_UNIONS_DISABLE struct semicolon_swallower + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro for adding pragma directive only for GCC. + */ +#ifdef __GNUC__ +#define GCC_PRAGMA(v) _Pragma(v) +#else +#define GCC_PRAGMA(v) +#endif + +/* Workaround for Keil 4 */ +#ifndef CONTROL_nPRIV_Msk +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ +#endif + +/**@brief Function for finding the current interrupt level. + * + * @return Current interrupt level. See @ref app_irq_priority_t for values. + */ +uint8_t current_int_priority_get(void); + + +/**@brief Function for finding out the current privilege level. + * + * @return Current privilege level. + * @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level. + * @retval APP_LEVEL_PRIVILEGED We are running in privileged level. + */ +uint8_t privilege_level_get(void); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_PLATFORM_H__ + +/** @} */ diff --git a/libraries/nfc/src/util/ble_advdata.c b/libraries/nfc/src/util/ble_advdata.c new file mode 100644 index 000000000..f4a7ca624 --- /dev/null +++ b/libraries/nfc/src/util/ble_advdata.c @@ -0,0 +1,838 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/ble_advdata.h" +#include "ble_gap.h" +#include "ble_srv_common.h" +#include "util/sdk_common.h" + +// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data. + + +// Types of LE Bluetooth Device Address AD type +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL + +#define UUID16_SIZE 2 /**< Size of 16 bit UUID. */ +#define UUID32_SIZE 4 /**< Size of 32 bit UUID. */ +#define UUID128_SIZE 16 /**< Size of 128 bit UUID. */ + +#define N_AD_TYPES 2 /**< The number of Advertising data types to search for at a time. */ + + +static ret_code_t ble_device_addr_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + ble_gap_addr_t device_addr; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get BLE address. + err_code = sd_ble_gap_addr_get(&device_addr); + VERIFY_SUCCESS(err_code); + + // Encode LE Bluetooth Device Address. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS; + *p_offset += AD_TYPE_FIELD_SIZE; + memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN); + *p_offset += BLE_GAP_ADDR_LEN; + if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type) + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC; + } + else + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM; + } + *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE; + + return NRF_SUCCESS; +} + +static ret_code_t name_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + uint16_t rem_adv_data_len; + uint16_t actual_length; + uint8_t adv_data_format; + + + // Validate parameters + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len)) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check for buffer overflow. + if ( (((*p_offset) + AD_DATA_OFFSET) > max_size) || + ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (((*p_offset) + AD_DATA_OFFSET + p_advdata->short_name_len) > max_size))) + { + return NRF_ERROR_DATA_SIZE; + } + + rem_adv_data_len = max_size - (*p_offset) - AD_DATA_OFFSET; + actual_length = rem_adv_data_len; + + // Get GAP device name and length + err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + AD_DATA_OFFSET], + &actual_length); + VERIFY_SUCCESS(err_code); + + // Check if device intend to use short name and it can fit available data size. + // If the name is shorter than the preferred short name length then it is no longer + // a short name and is in fact the complete name of the device. + if (((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) || + (actual_length <= p_advdata->short_name_len)) && + (actual_length <= rem_adv_data_len)) + { + // Complete device name can fit, setting Complete Name in Adv Data. + adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; + } + else + { + // Else short name needs to be used. Or application has requested use of short name. + adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; + + // If application has set a preference on the short name size, it needs to be considered, + // else fit what can be fit. + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (p_advdata->short_name_len <= rem_adv_data_len)) + { + // Short name fits available size. + actual_length = p_advdata->short_name_len; + } + // Else whatever can fit the data buffer will be packed. + else + { + actual_length = rem_adv_data_len; + } + } + + // There is only 1 byte intended to encode length which is (actual_length + AD_TYPE_FIELD_SIZE) + if (actual_length > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Complete name field in encoded data. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + actual_length); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_data_format; + *p_offset += AD_TYPE_FIELD_SIZE; + *p_offset += actual_length; + + return NRF_SUCCESS; +} + + +static ret_code_t appearance_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + uint16_t appearance; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get GAP appearance field. + err_code = sd_ble_gap_appearance_get(&appearance); + VERIFY_SUCCESS(err_code); + + // Encode Length, AD Type and Appearance. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE; + *p_offset += AD_TYPE_FIELD_SIZE; + *p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + +static ret_code_t flags_encode(int8_t flags, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode flags. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = flags; + *p_offset += AD_TYPE_FLAGS_DATA_SIZE; + + return NRF_SUCCESS; +} + +static ret_code_t tx_power_level_encode(int8_t tx_power_level, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode TX Power Level. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = tx_power_level; + *p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE; + + return NRF_SUCCESS; +} + + +static ret_code_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type, + uint8_t uuid_size, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + int i; + bool is_heading_written = false; + uint16_t start_pos = *p_offset; + uint16_t length; + + for (i = 0; i < p_uuid_list->uuid_cnt; i++) + { + ret_code_t err_code; + uint8_t encoded_size; + ble_uuid_t uuid = p_uuid_list->p_uuids[i]; + + // Find encoded uuid size. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); + VERIFY_SUCCESS(err_code); + + // Check size. + if (encoded_size == uuid_size) + { + uint8_t heading_bytes = (is_heading_written) ? 0 : AD_DATA_OFFSET; + + // Check for buffer overflow + if (((*p_offset) + encoded_size + heading_bytes) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + if (!is_heading_written) + { + // Write AD structure heading. + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_type; + *p_offset += AD_TYPE_FIELD_SIZE; + is_heading_written = true; + } + + // Write UUID. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); + VERIFY_SUCCESS(err_code); + *p_offset += encoded_size; + } + } + + if (is_heading_written) + { + // Write length. + length = (*p_offset) - (start_pos + AD_LENGTH_FIELD_SIZE); + // There is only 1 byte intended to encode length + if (length > 0x00FF) + { + return NRF_ERROR_DATA_SIZE; + } + p_encoded_data[start_pos] = (uint8_t)length; + } + + return NRF_SUCCESS; +} + + +static ret_code_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type_16, + uint8_t adv_type_128, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + + // Encode 16 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_16, + sizeof(uint16_le_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + // Encode 128 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_128, + sizeof(ble_uuid128_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +static ret_code_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) +{ + // Check Minimum Connection Interval. + if ((p_conn_int->min_conn_interval < 0x0006) || + ( + (p_conn_int->min_conn_interval > 0x0c80) && + (p_conn_int->min_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check Maximum Connection Interval. + if ((p_conn_int->max_conn_interval < 0x0006) || + ( + (p_conn_int->max_conn_interval > 0x0c80) && + (p_conn_int->max_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. + if ((p_conn_int->min_conn_interval != 0xffff) && + (p_conn_int->max_conn_interval != 0xffff) && + (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +static ret_code_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Check parameters. + err_code = conn_int_check(p_conn_int); + VERIFY_SUCCESS(err_code); + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode Minimum and Maximum Connection Intervals. + *p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]); + *p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + + +static ret_code_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size; + + // Check for buffer overflow. + if (((*p_offset) + AD_DATA_OFFSET + data_size) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode Company Identifier. + *p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]); + + // Encode additional manufacturer specific data. + if (p_manuf_sp_data->data.size > 0) + { + if (p_manuf_sp_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); + *p_offset += p_manuf_sp_data->data.size; + } + + return NRF_SUCCESS; +} + +// Implemented only for 16-bit UUIDs +static ret_code_t service_data_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint8_t i; + + // Check parameter consistency. + if (p_advdata->p_service_data_array == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + for (i = 0; i < p_advdata->service_data_count; i++) + { + ble_advdata_service_data_t * p_service_data; + uint32_t data_size; + + p_service_data = &p_advdata->p_service_data_array[i]; + // For now implemented only for 16-bit UUIDs + data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size; + + // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode service 16-bit UUID. + *p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]); + + // Encode additional service data. + if (p_service_data->data.size > 0) + { + if (p_service_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size); + *p_offset += p_service_data->data.size; + } + } + + return NRF_SUCCESS; +} + +ret_code_t ble_advdata_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t max_size = *p_len; + *p_len = 0; + + // Encode LE Bluetooth Device Address + if (p_advdata->include_ble_device_addr) + { + err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode appearance. + if (p_advdata->include_appearance) + { + err_code = appearance_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + //Encode Flags + if (p_advdata->flags != 0 ) + { + err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode TX power level. + if (p_advdata->p_tx_power_level != NULL) + { + err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'more available' uuid list. + if (p_advdata->uuids_more_available.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_more_available, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'complete' uuid list. + if (p_advdata->uuids_complete.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_complete, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'solicited service' uuid list. + if (p_advdata->uuids_solicited.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_solicited, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Slave Connection Interval Range. + if (p_advdata->p_slave_conn_int != NULL) + { + err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Manufacturer Specific Data. + if (p_advdata->p_manuf_specific_data != NULL) + { + err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Service Data. + if (p_advdata->service_data_count > 0) + { + err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode name. WARNING: it is encoded last on purpose since too long device name is truncated. + if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) + { + err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + return err_code; +} + + +uint16_t ble_advdata_search(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t * p_offset, + uint8_t ad_type) +{ + if ((p_encoded_data == NULL) || (p_offset == NULL)) + { + return 0; + } + + uint16_t i = 0; + + while ((i + 1 < data_len) && ((i < *p_offset) || (p_encoded_data[i + 1] != ad_type))) + { + // Jump to next data. + i += (p_encoded_data[i] + 1); + } + + if (i >= data_len) + { + return 0; + } + else + { + uint16_t offset = i + 2; + uint16_t len = p_encoded_data[i] ? (p_encoded_data[i] - 1) : 0; + if (!len || ((offset + len) > data_len)) + { + // Malformed. Zero length or extends beyond provided data. + return 0; + } + *p_offset = offset; + return len; + } +} + + +uint8_t * ble_advdata_parse(uint8_t * p_encoded_data, + uint16_t data_len, + uint8_t ad_type) +{ + uint16_t offset = 0; + uint16_t len = ble_advdata_search(p_encoded_data, data_len, &offset, ad_type); + + if (len == 0) + { + return NULL; + } + else + { + return &p_encoded_data[offset]; + } +} + + +bool ble_advdata_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name) +{ + uint16_t parsed_name_len; + uint8_t const * p_parsed_name; + uint16_t data_offset = 0; + + if (p_target_name == NULL) + { + return false; + } + + + parsed_name_len = ble_advdata_search(p_encoded_data, + data_len, + &data_offset, + BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME); + + p_parsed_name = &p_encoded_data[data_offset]; + + if ( (data_offset != 0) + && (parsed_name_len != 0) + && (strlen(p_target_name) == parsed_name_len) + && (memcmp(p_target_name, p_parsed_name, parsed_name_len) == 0)) + { + return true; + } + + return false; +} + + +bool ble_advdata_short_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name, + uint8_t const short_name_min_len) +{ + uint16_t parsed_name_len; + uint8_t const * p_parsed_name; + uint16_t data_offset = 0; + + if (p_target_name == NULL) + { + return false; + } + + parsed_name_len = ble_advdata_search(p_encoded_data, + data_len, + &data_offset, + BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); + + p_parsed_name = &p_encoded_data[data_offset]; + + if ( (data_offset != 0) + && (parsed_name_len != 0) + && (parsed_name_len >= short_name_min_len) + && (parsed_name_len < strlen(p_target_name)) + && (memcmp(p_target_name, p_parsed_name, parsed_name_len) == 0)) + { + return true; + } + + return false; +} + + +bool ble_advdata_uuid_find(uint8_t const * p_encoded_data, + uint16_t data_len, + ble_uuid_t const * p_target_uuid) +{ + + ret_code_t err_code; + uint16_t data_offset = 0; + uint8_t raw_uuid_len = UUID128_SIZE; + uint8_t const * p_parsed_uuid; + uint16_t parsed_uuid_len = data_len; + uint8_t raw_uuid[UUID128_SIZE]; + uint8_t ad_types[N_AD_TYPES]; + + err_code = sd_ble_uuid_encode(p_target_uuid, &raw_uuid_len, raw_uuid); + + if ((p_encoded_data == NULL) || (err_code != NRF_SUCCESS)) + { + // Invalid p_encoded_data or p_target_uuid. + return false; + } + + switch (raw_uuid_len) + { + case UUID16_SIZE: + ad_types[0] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE; + ad_types[1] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE; + break; + + case UUID32_SIZE: + // Not currently supported by sd_ble_uuid_encode(). + ad_types[0] = BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE; + ad_types[1] = BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE; + break; + + case UUID128_SIZE: + ad_types[0] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE; + ad_types[1] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE; + break; + + default: + return false; + } + + for (uint8_t i = 0; (i < N_AD_TYPES) && (data_offset == 0); i++) + { + parsed_uuid_len = ble_advdata_search(p_encoded_data, data_len, &data_offset, ad_types[i]); + } + + if (data_offset == 0) + { + // Could not find any relevant UUIDs in the encoded data. + return false; + } + + p_parsed_uuid = &p_encoded_data[data_offset]; + + // Verify if any UUID matches the given UUID. + for (uint16_t list_offset = 0; list_offset < parsed_uuid_len; list_offset += raw_uuid_len) + { + if (memcmp(&p_parsed_uuid[list_offset], raw_uuid, raw_uuid_len) == 0) + { + return true; + } + } + + // Could not find the UUID among the encoded data. + return false; +} + + +bool ble_advdata_appearance_find(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t const * p_target_appearance) +{ + uint16_t data_offset = 0; + uint8_t appearance_len; + uint16_t decoded_appearance; + + appearance_len = ble_advdata_search(p_encoded_data, data_len, &data_offset, BLE_GAP_AD_TYPE_APPEARANCE); + + if ( (data_offset == 0) + || (p_target_appearance == NULL) + || (appearance_len == 0)) + { + // Could not find any Appearance in the encoded data, or invalid p_target_appearance. + return false; + } + + decoded_appearance = uint16_decode(&p_encoded_data[data_offset]); + + if (decoded_appearance == *p_target_appearance) + { + return true; + } + + // Could not find the appearance among the encoded data. + return false; +} diff --git a/libraries/nfc/src/util/ble_advdata.h b/libraries/nfc/src/util/ble_advdata.h new file mode 100644 index 000000000..52f99fd98 --- /dev/null +++ b/libraries/nfc/src/util/ble_advdata.h @@ -0,0 +1,326 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup ble_sdk_lib_advdata Advertising and Scan Response Data Encoder + * @{ + * @ingroup ble_sdk_lib + * @brief Functions for encoding data in the Advertising and Scan Response Data format, + * and for passing the data to the stack. + */ + +#ifndef BLE_ADVDATA_H__ +#define BLE_ADVDATA_H__ + +#include +#include +#include +#include "ble.h" +#include "util/sdk_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ +#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ +#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ + +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ + AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ +#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ +#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ +#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ +#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ + +#define BLE_ADV_DATA_MATCH_FULL_NAME 0xff + + +/**@brief Security Manager TK value. */ +typedef struct +{ + uint8_t tk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing TK value in little-endian format. */ +} ble_advdata_tk_value_t; + +/**@brief Advertising data LE Role types. This enumeration contains the options available for the LE role inside + * the advertising data. */ +typedef enum +{ + BLE_ADVDATA_ROLE_NOT_PRESENT = 0, /**< LE Role AD structure not present. */ + BLE_ADVDATA_ROLE_ONLY_PERIPH, /**< Only Peripheral Role supported. */ + BLE_ADVDATA_ROLE_ONLY_CENTRAL, /**< Only Central Role supported. */ + BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */ + BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */ +} ble_advdata_le_role_t; + +/**@brief Advertising data name type. This enumeration contains the options available for the device name inside + * the advertising data. */ +typedef enum +{ + BLE_ADVDATA_NO_NAME, /**< Include no device name in advertising data. */ + BLE_ADVDATA_SHORT_NAME, /**< Include short device name in advertising data. */ + BLE_ADVDATA_FULL_NAME /**< Include full device name in advertising data. */ +} ble_advdata_name_type_t; + +/**@brief UUID list type. */ +typedef struct +{ + uint16_t uuid_cnt; /**< Number of UUID entries. */ + ble_uuid_t * p_uuids; /**< Pointer to UUID array entries. */ +} ble_advdata_uuid_list_t; + +/**@brief Connection interval range structure. */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). */ + uint16_t max_conn_interval; /**< Maximum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). The value 0xFFFF indicates no specific maximum. */ +} ble_advdata_conn_int_t; + +/**@brief Manufacturer specific data structure. */ +typedef struct +{ + uint16_t company_identifier; /**< Company identifier code. */ + uint8_array_t data; /**< Additional manufacturer specific data. */ +} ble_advdata_manuf_data_t; + +/**@brief Service data structure. */ +typedef struct +{ + uint16_t service_uuid; /**< Service UUID. */ + uint8_array_t data; /**< Additional service data. */ +} ble_advdata_service_data_t; + +/**@brief Advertising data structure. This structure contains all options and data needed for encoding and + * setting the advertising data. */ +typedef struct +{ + ble_advdata_name_type_t name_type; /**< Type of device name. */ + uint8_t short_name_len; /**< Length of short device name (if short type is specified). */ + bool include_appearance; /**< Determines if Appearance shall be included. */ + uint8_t flags; /**< Advertising data Flags field. */ + int8_t * p_tx_power_level; /**< TX Power Level field. */ + ble_advdata_uuid_list_t uuids_more_available; /**< List of UUIDs in the 'More Available' list. */ + ble_advdata_uuid_list_t uuids_complete; /**< List of UUIDs in the 'Complete' list. */ + ble_advdata_uuid_list_t uuids_solicited; /**< List of solicited UUIDs. */ + ble_advdata_conn_int_t * p_slave_conn_int; /**< Slave Connection Interval Range. */ + ble_advdata_manuf_data_t * p_manuf_specific_data; /**< Manufacturer specific data. */ + ble_advdata_service_data_t * p_service_data_array; /**< Array of Service data structures. */ + uint8_t service_data_count; /**< Number of Service data structures. */ + bool include_ble_device_addr; /**< Determines if LE Bluetooth Device Address shall be included. */ + ble_advdata_le_role_t le_role; /**< LE Role field. Included when different from @ref BLE_ADVDATA_ROLE_NOT_PRESENT. @warning This field can be used only for NFC. For BLE advertising, set it to NULL. */ + ble_advdata_tk_value_t * p_tk_value; /**< Security Manager TK value field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ + uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ + ble_gap_lesc_oob_data_t * p_lesc_data; /**< LE Secure Connections OOB data. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ +} ble_advdata_t; + +/**@brief Function for encoding data in the Advertising and Scan Response data format (AD structures). + * + * @details This function encodes data into the Advertising and Scan Response data format + * (AD structures) based on the fields in the supplied structures. This function can be + * used to create a payload of Advertising packet or Scan Response packet, or a payload of + * NFC message intended for initiating the Out-of-Band pairing. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. + * \c out: Length of encoded data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in + * \p p_advdata. + * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could + * fit into the provided buffer or some encoded AD structure is too + * long and its length cannot be encoded with one octet. + * + * @warning This API may override the application's request to use the long name and use a short name + * instead. This truncation will occur in case the long name does not fit the provided buffer size. + * The application can specify a preferred short name length if truncation is required. + * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name + * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni + * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. + * However, it should be noted that this is just a preference that the application can specify, and + * if the preference is too large to fit in the provided buffer, the name can be truncated further. + */ +ret_code_t ble_advdata_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len); + + +/**@brief Function for searching encoded Advertising or Scan Response data for specific data types. + * + * @details This function searches through encoded data e.g. the data produced by + * @ref ble_advdata_encode, or the data found in Advertising reports + * (@ref BLE_GAP_EVT_ADV_REPORT), and gives the offset of the data within the data buffer. + * The data with type \p ad_type can be found at p_encoded_data[*p_offset] after calling + * the function. This function can iterate through multiple instances of data of one + * type by calling it again with the offset provided by the previous call. + * + * Example code for finding multiple instances of one type of data: + * offset = 0; + * ble_advdata_search(&data, len, &offset, AD_TYPE); + * first_instance_of_data = data[offset]; + * ble_advdata_search(&data, len, &offset, AD_TYPE); + * second_instance_of_data = data[offset]; + * + * @param[in] p_encoded_data The data buffer containing the encoded Advertising data. + * @param[in] data_len The length of the data buffer \p p_encoded_data. + * @param[inout] p_offset \c in: The offset to start searching from. + * \c out: The offset the data type can be found at. + * This value is not changed if the call returns 0. + * @param[in] ad_type The type of data to search for. + * + * @return The length of the found data, or 0 if no data was found with the the type \p ad_type, + * or if \p p_encoded_data or \p p_offset were NULL. + */ +uint16_t ble_advdata_search(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t * p_offset, + uint8_t ad_type); + +/**@brief Function for getting specific data from encoded Advertising or Scan Response data. + * + * @details This function searches through encoded data e.g. the data produced by + * @ref ble_advdata_encode, or the data found in Advertising reports + * (@ref BLE_GAP_EVT_ADV_REPORT), and returns a pointer directly to the data within the + * data buffer. + * + * Example code: + * ad_type_data = ble_advdata_parse(&data, len, AD_TYPE); + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] ad_type Type of data to search for. + * + * @return Pointer to the found data, or NULL if no data was found with the type \p ad_type, + * or if \p p_encoded_data or \p p_data_len were NULL. + */ +uint8_t * ble_advdata_parse(uint8_t * p_encoded_data, + uint16_t data_len, + uint8_t ad_type); + + +/**@brief Function for searching through encoded Advertising data for a complete local name. + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_name Name to search for. + * + * @retval true If \p p_target_name was found among \p p_encoded_data, as a complete local name. + * @retval false If \p p_target_name was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_name was NULL. + */ +bool ble_advdata_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name); + + +/**@brief Function for searching through encoded Advertising data for a device shortened name. + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_name Name to search for. + * @param[in] short_name_min_len Minimum length of the shortened name. + * For example, if the advertising data has a shortened name 'No' and this parameter is + * set to 4 with a target_name set to Nordic_XXX it will return false, but if + * the shortened name in the advertising data is 'Nord', it will return true. + * @note: If the shortened name in the Advertising data has the same length as the target name, + * this function will return false, since this means that the complete name is actually + * longer, thus different than the target name. + * + * @retval true If \p p_target_name was found among \p p_encoded_data, as short local name. + * @retval false If \p p_target_name was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_name was NULL. + */ +bool ble_advdata_short_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name, + uint8_t const short_name_min_len); + +/**@brief Function for searching through encoded Advertising data for a UUID (16-bit or 128-bit). + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_uuid UUID to search for. + * + * @retval true If \p p_target_uuid was found among \p p_encoded_data. + * @retval false If \p p_target_uuid was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_uuid was NULL. + */ +bool ble_advdata_uuid_find(uint8_t const * p_encoded_data, + uint16_t data_len, + ble_uuid_t const * p_target_uuid); + + +/**@brief Function for searching through encoded Advertising data for an appearance. + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_appearance Appearance to search for. + * + * @retval true If \p p_target_appearance was found among \p p_encoded_data. + * @retval false If \p p_target_appearance was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_appearance was NULL. + */ +bool ble_advdata_appearance_find(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t const * p_target_appearance); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_ADVDATA_H__ + +/** @} */ diff --git a/libraries/nfc/src/util/ble_srv_common.c b/libraries/nfc/src/util/ble_srv_common.c new file mode 100644 index 000000000..bb5553d18 --- /dev/null +++ b/libraries/nfc/src/util/ble_srv_common.c @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/* Attention! + * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile + * qualification listings, this section of source code must not be modified. + */ + +#include "ble_srv_common.h" +#include +#include "nordic_common.h" +#include "util/app_error.h" +#include "ble.h" + +bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data) +{ + uint16_t cccd_value = uint16_decode(p_encoded_data); + return ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0); +} + +bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data) +{ + uint16_t cccd_value = uint16_decode(p_encoded_data); + return ((cccd_value & BLE_GATT_HVX_INDICATION) != 0); +} + +uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, + const ble_srv_report_ref_t * p_report_ref) +{ + uint8_t len = 0; + + p_encoded_buffer[len++] = p_report_ref->report_id; + p_encoded_buffer[len++] = p_report_ref->report_type; + + APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN); + return len; +} + + +void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii) +{ + p_utf8->length = (uint16_t)strlen(p_ascii); + p_utf8->p_str = (uint8_t *)p_ascii; +} + + +/**@brief Function for setting security requirements of a characteristic. + * + * @param[in] level required security level. + * @param[out] p_perm Characteristic security requirements. + * + * @return encoded security level and security mode. + */ +static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm) +{ + + + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); + switch (level) + { + case SEC_NO_ACCESS: + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); + break; + case SEC_OPEN: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm); + break; + case SEC_JUST_WORKS: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm); + break; + case SEC_MITM: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm); + break; + case SEC_SIGNED: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm); + break; + case SEC_SIGNED_MITM: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm); + break; + } + return; +} + + +uint32_t characteristic_add(uint16_t service_handle, + ble_add_char_params_t * p_char_props, + ble_gatts_char_handles_t * p_char_handle) +{ + ble_gatts_char_md_t char_md; + ble_gatts_attr_t attr_char_value; + ble_uuid_t char_uuid; + ble_gatts_attr_md_t attr_md; + ble_gatts_attr_md_t user_descr_attr_md; + ble_gatts_attr_md_t cccd_md; + + if (p_char_props->uuid_type == 0) + { + char_uuid.type = BLE_UUID_TYPE_BLE; + } + else + { + char_uuid.type = p_char_props->uuid_type; + } + char_uuid.uuid = p_char_props->uuid; + + memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t)); + set_security_req(p_char_props->read_access, &attr_md.read_perm); + set_security_req(p_char_props->write_access, & attr_md.write_perm); + attr_md.rd_auth = (p_char_props->is_defered_read ? 1 : 0); + attr_md.wr_auth = (p_char_props->is_defered_write ? 1 : 0); + attr_md.vlen = (p_char_props->is_var_len ? 1 : 0); + attr_md.vloc = (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + + + memset(&char_md, 0, sizeof(ble_gatts_char_md_t)); + if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1)) + { + + memset(&cccd_md, 0, sizeof(cccd_md)); + set_security_req(p_char_props->cccd_write_access, &cccd_md.write_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); + + cccd_md.vloc = BLE_GATTS_VLOC_STACK; + + char_md.p_cccd_md = &cccd_md; + } + char_md.char_props = p_char_props->char_props; + char_md.char_ext_props = p_char_props->char_ext_props; + + memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t)); + attr_char_value.p_uuid = &char_uuid; + attr_char_value.p_attr_md = &attr_md; + attr_char_value.max_len = p_char_props->max_len; + if (p_char_props->p_init_value != NULL) + { + attr_char_value.init_len = p_char_props->init_len; + attr_char_value.p_value = p_char_props->p_init_value; + } + if (p_char_props->p_user_descr != NULL) + { + memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t)); + char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size; + char_md.char_user_desc_size = p_char_props->p_user_descr->size; + char_md.p_char_user_desc = p_char_props->p_user_descr->p_char_user_desc; + + char_md.p_user_desc_md = &user_descr_attr_md; + + set_security_req(p_char_props->p_user_descr->read_access, &user_descr_attr_md.read_perm); + set_security_req(p_char_props->p_user_descr->write_access, &user_descr_attr_md.write_perm); + + user_descr_attr_md.rd_auth = (p_char_props->p_user_descr->is_defered_read ? 1 : 0); + user_descr_attr_md.wr_auth = (p_char_props->p_user_descr->is_defered_write ? 1 : 0); + user_descr_attr_md.vlen = (p_char_props->p_user_descr->is_var_len ? 1 : 0); + user_descr_attr_md.vloc = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + } + if (p_char_props->p_presentation_format != NULL) + { + char_md.p_char_pf = p_char_props->p_presentation_format; + } + return sd_ble_gatts_characteristic_add(service_handle, + &char_md, + &attr_char_value, + p_char_handle); +} + + +uint32_t descriptor_add(uint16_t char_handle, + ble_add_descr_params_t * p_descr_props, + uint16_t * p_descr_handle) +{ + ble_gatts_attr_t descr_params; + ble_uuid_t desc_uuid; + ble_gatts_attr_md_t attr_md; + + memset(&descr_params, 0, sizeof(descr_params)); + if (p_descr_props->uuid_type == 0) + { + desc_uuid.type = BLE_UUID_TYPE_BLE; + } + else + { + desc_uuid.type = p_descr_props->uuid_type; + } + desc_uuid.uuid = p_descr_props->uuid; + descr_params.p_uuid = &desc_uuid; + + set_security_req(p_descr_props->read_access, &attr_md.read_perm); + set_security_req(p_descr_props->write_access,&attr_md.write_perm); + + attr_md.rd_auth = (p_descr_props->is_defered_read ? 1 : 0); + attr_md.wr_auth = (p_descr_props->is_defered_write ? 1 : 0); + attr_md.vlen = (p_descr_props->is_var_len ? 1 : 0); + attr_md.vloc = (p_descr_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + descr_params.p_attr_md = &attr_md; + + descr_params.init_len = p_descr_props->init_len; + descr_params.init_offs = p_descr_props->init_offs; + descr_params.max_len = p_descr_props->max_len; + descr_params.p_value = p_descr_props->p_value; + + return sd_ble_gatts_descriptor_add(char_handle, &descr_params, p_descr_handle); +} diff --git a/libraries/nfc/src/util/ble_srv_common.h b/libraries/nfc/src/util/ble_srv_common.h new file mode 100644 index 000000000..b6771e557 --- /dev/null +++ b/libraries/nfc/src/util/ble_srv_common.h @@ -0,0 +1,409 @@ +/** + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup ble_sdk_srv_common Common service definitions + * @{ + * @ingroup ble_sdk_srv + * @brief Constants, type definitions, and functions that are common to all services. + */ + +#ifndef BLE_SRV_COMMON_H__ +#define BLE_SRV_COMMON_H__ + +#include +#include +#include "ble_types.h" +#include "app_util.h" +#include "ble.h" +#include "ble_gap.h" +#include "ble_gatt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup UUID_SERVICES Service UUID definitions + * @{ */ +#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ +#define BLE_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ +#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ +#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ +#define BLE_UUID_LOCATION_AND_NAVIGATION_SERVICE 0x1819 /**< Location and Navigation service UUID. */ +#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ +#define BLE_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ +#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ +#define BLE_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ +#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ +#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ +#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ +#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ +#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ +#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ +#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ +#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ +#define BLE_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ +#define BLE_UUID_IPSP_SERVICE 0x1820 /**< Internet Protocol Support service UUID. */ +#define BLE_UUID_BMS_SERVICE 0x181E /**< BOND MANAGEMENT service UUID*/ +#define BLE_UUID_CGM_SERVICE 0x181F /**< Continuous Glucose Monitoring service UUID*/ +#define BLE_UUID_PLX_SERVICE 0x1822 /**< Pulse Oximeter Service UUID*/ +#define BLE_UUID_OTS_SERVICE 0x1825 /**< Object Transfer Service UUID*/ + +/** @} */ + +/** @defgroup UUID_CHARACTERISTICS Characteristic UUID definitions + * @{ */ +#define BLE_UUID_REMOVABLE_CHAR 0x2A3A /**< Removable characteristic UUID. */ +#define BLE_UUID_SERVICE_REQUIRED_CHAR 0x2A3B /**< Service Required characteristic UUID. */ +#define BLE_UUID_ALERT_CATEGORY_ID_CHAR 0x2A43 /**< Alert Category Id characteristic UUID. */ +#define BLE_UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR 0x2A42 /**< Alert Category Id Bit Mask characteristic UUID. */ +#define BLE_UUID_ALERT_LEVEL_CHAR 0x2A06 /**< Alert Level characteristic UUID. */ +#define BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR 0x2A44 /**< Alert Notification Control Point characteristic UUID. */ +#define BLE_UUID_ALERT_STATUS_CHAR 0x2A3F /**< Alert Status characteristic UUID. */ +#define BLE_UUID_BATTERY_LEVEL_CHAR 0x2A19 /**< Battery Level characteristic UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_FEATURE_CHAR 0x2A49 /**< Blood Pressure Feature characteristic UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR 0x2A35 /**< Blood Pressure Measurement characteristic UUID. */ +#define BLE_UUID_BODY_SENSOR_LOCATION_CHAR 0x2A38 /**< Body Sensor Location characteristic UUID. */ +#define BLE_UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR 0x2A22 /**< Boot Keyboard Input Report characteristic UUID. */ +#define BLE_UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR 0x2A32 /**< Boot Keyboard Output Report characteristic UUID. */ +#define BLE_UUID_BOOT_MOUSE_INPUT_REPORT_CHAR 0x2A33 /**< Boot Mouse Input Report characteristic UUID. */ +#define BLE_UUID_CURRENT_TIME_CHAR 0x2A2B /**< Current Time characteristic UUID. */ +#define BLE_UUID_DATE_TIME_CHAR 0x2A08 /**< Date Time characteristic UUID. */ +#define BLE_UUID_DAY_DATE_TIME_CHAR 0x2A0A /**< Day Date Time characteristic UUID. */ +#define BLE_UUID_DAY_OF_WEEK_CHAR 0x2A09 /**< Day Of Week characteristic UUID. */ +#define BLE_UUID_DST_OFFSET_CHAR 0x2A0D /**< Dst Offset characteristic UUID. */ +#define BLE_UUID_EXACT_TIME_256_CHAR 0x2A0C /**< Exact Time 256 characteristic UUID. */ +#define BLE_UUID_FIRMWARE_REVISION_STRING_CHAR 0x2A26 /**< Firmware Revision String characteristic UUID. */ +#define BLE_UUID_GLUCOSE_FEATURE_CHAR 0x2A51 /**< Glucose Feature characteristic UUID. */ +#define BLE_UUID_GLUCOSE_MEASUREMENT_CHAR 0x2A18 /**< Glucose Measurement characteristic UUID. */ +#define BLE_UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR 0x2A34 /**< Glucose Measurement Context characteristic UUID. */ +#define BLE_UUID_HARDWARE_REVISION_STRING_CHAR 0x2A27 /**< Hardware Revision String characteristic UUID. */ +#define BLE_UUID_HEART_RATE_CONTROL_POINT_CHAR 0x2A39 /**< Heart Rate Control Point characteristic UUID. */ +#define BLE_UUID_HEART_RATE_MEASUREMENT_CHAR 0x2A37 /**< Heart Rate Measurement characteristic UUID. */ +#define BLE_UUID_HID_CONTROL_POINT_CHAR 0x2A4C /**< Hid Control Point characteristic UUID. */ +#define BLE_UUID_HID_INFORMATION_CHAR 0x2A4A /**< Hid Information characteristic UUID. */ +#define BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR 0x2A2A /**< IEEE Regulatory Certification Data List characteristic UUID. */ +#define BLE_UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR 0x2A36 /**< Intermediate Cuff Pressure characteristic UUID. */ +#define BLE_UUID_INTERMEDIATE_TEMPERATURE_CHAR 0x2A1E /**< Intermediate Temperature characteristic UUID. */ +#define BLE_UUID_LOCAL_TIME_INFORMATION_CHAR 0x2A0F /**< Local Time Information characteristic UUID. */ +#define BLE_UUID_MANUFACTURER_NAME_STRING_CHAR 0x2A29 /**< Manufacturer Name String characteristic UUID. */ +#define BLE_UUID_MEASUREMENT_INTERVAL_CHAR 0x2A21 /**< Measurement Interval characteristic UUID. */ +#define BLE_UUID_MODEL_NUMBER_STRING_CHAR 0x2A24 /**< Model Number String characteristic UUID. */ +#define BLE_UUID_UNREAD_ALERT_CHAR 0x2A45 /**< Unread Alert characteristic UUID. */ +#define BLE_UUID_NEW_ALERT_CHAR 0x2A46 /**< New Alert characteristic UUID. */ +#define BLE_UUID_PNP_ID_CHAR 0x2A50 /**< PNP Id characteristic UUID. */ +#define BLE_UUID_PROTOCOL_MODE_CHAR 0x2A4E /**< Protocol Mode characteristic UUID. */ +#define BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR 0x2A52 /**< Record Access Control Point characteristic UUID. */ +#define BLE_UUID_REFERENCE_TIME_INFORMATION_CHAR 0x2A14 /**< Reference Time Information characteristic UUID. */ +#define BLE_UUID_REPORT_CHAR 0x2A4D /**< Report characteristic UUID. */ +#define BLE_UUID_REPORT_MAP_CHAR 0x2A4B /**< Report Map characteristic UUID. */ +#define BLE_UUID_RINGER_CONTROL_POINT_CHAR 0x2A40 /**< Ringer Control Point characteristic UUID. */ +#define BLE_UUID_RINGER_SETTING_CHAR 0x2A41 /**< Ringer Setting characteristic UUID. */ +#define BLE_UUID_SCAN_INTERVAL_WINDOW_CHAR 0x2A4F /**< Scan Interval Window characteristic UUID. */ +#define BLE_UUID_SCAN_REFRESH_CHAR 0x2A31 /**< Scan Refresh characteristic UUID. */ +#define BLE_UUID_SERIAL_NUMBER_STRING_CHAR 0x2A25 /**< Serial Number String characteristic UUID. */ +#define BLE_UUID_SOFTWARE_REVISION_STRING_CHAR 0x2A28 /**< Software Revision String characteristic UUID. */ +#define BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR 0x2A47 /**< Supported New Alert Category characteristic UUID. */ +#define BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR 0x2A48 /**< Supported Unread Alert Category characteristic UUID. */ +#define BLE_UUID_SYSTEM_ID_CHAR 0x2A23 /**< System Id characteristic UUID. */ +#define BLE_UUID_TEMPERATURE_MEASUREMENT_CHAR 0x2A1C /**< Temperature Measurement characteristic UUID. */ +#define BLE_UUID_TEMPERATURE_TYPE_CHAR 0x2A1D /**< Temperature Type characteristic UUID. */ +#define BLE_UUID_TIME_ACCURACY_CHAR 0x2A12 /**< Time Accuracy characteristic UUID. */ +#define BLE_UUID_TIME_SOURCE_CHAR 0x2A13 /**< Time Source characteristic UUID. */ +#define BLE_UUID_TIME_UPDATE_CONTROL_POINT_CHAR 0x2A16 /**< Time Update Control Point characteristic UUID. */ +#define BLE_UUID_TIME_UPDATE_STATE_CHAR 0x2A17 /**< Time Update State characteristic UUID. */ +#define BLE_UUID_TIME_WITH_DST_CHAR 0x2A11 /**< Time With Dst characteristic UUID. */ +#define BLE_UUID_TIME_ZONE_CHAR 0x2A0E /**< Time Zone characteristic UUID. */ +#define BLE_UUID_TX_POWER_LEVEL_CHAR 0x2A07 /**< TX Power Level characteristic UUID. */ +#define BLE_UUID_CSC_FEATURE_CHAR 0x2A5C /**< Cycling Speed and Cadence Feature characteristic UUID. */ +#define BLE_UUID_CSC_MEASUREMENT_CHAR 0x2A5B /**< Cycling Speed and Cadence Measurement characteristic UUID. */ +#define BLE_UUID_RSC_FEATURE_CHAR 0x2A54 /**< Running Speed and Cadence Feature characteristic UUID. */ +#define BLE_UUID_SC_CTRLPT_CHAR 0x2A55 /**< Speed and Cadence Control Point UUID. */ +#define BLE_UUID_RSC_MEASUREMENT_CHAR 0x2A53 /**< Running Speed and Cadence Measurement characteristic UUID. */ +#define BLE_UUID_SENSOR_LOCATION_CHAR 0x2A5D /**< Sensor Location characteristic UUID. */ +#define BLE_UUID_EXTERNAL_REPORT_REF_DESCR 0x2907 /**< External Report Reference descriptor UUID. */ +#define BLE_UUID_REPORT_REF_DESCR 0x2908 /**< Report Reference descriptor UUID. */ +#define BLE_UUID_LN_FEATURE_CHAR 0x2A6A /**< Location Navigation Service, Feature characteristic UUID. */ +#define BLE_UUID_LN_POSITION_QUALITY_CHAR 0x2A69 /**< Location Navigation Service, Position quality UUID. */ +#define BLE_UUID_LN_LOCATION_AND_SPEED_CHAR 0x2A67 /**< Location Navigation Service, Location and Speed characteristic UUID. */ +#define BLE_UUID_LN_NAVIGATION_CHAR 0x2A68 /**< Location Navigation Service, Navigation characteristic UUID. */ +#define BLE_UUID_LN_CONTROL_POINT_CHAR 0x2A6B /**< Location Navigation Service, Control point characteristic UUID. */ +#define BLE_UUID_BMS_CTRLPT 0x2AA4 /**< BMS Control Point characteristic UUID. */ +#define BLE_UUID_BMS_FEATURE 0x2AA5 /**< BMS Feature characteristic UUID. */ +#define BLE_UUID_CGM_MEASUREMENT 0x2AA7 /**< CGM Service, Measurement characteristic UUID*/ +#define BLE_UUID_CGM_FEATURE 0x2AA8 /**< CGM Service, Feature characteristic UUID*/ +#define BLE_UUID_CGM_STATUS 0x2AA9 /**< CGM Service, Status characteristic UUID*/ +#define BLE_UUID_CGM_SESSION_START_TIME 0x2AAA /**< CGM Service, session start time characteristic UUID*/ +#define BLE_UUID_CGM_SESSION_RUN_TIME 0x2AAB /**< CGM Service, session run time characteristic UUID*/ +#define BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT 0x2AAC /**< CGM Service, specific ops ctrlpt characteristic UUID*/ +#define BLE_UUID_PLX_SPOT_CHECK_MEAS 0x2A5E /**< PLX Service, spot check measurement characteristic UUID*/ +#define BLE_UUID_PLX_CONTINUOUS_MEAS 0x2A5F /**< PLX Service, continuous measurement characteristic UUID*/ +#define BLE_UUID_PLX_FEATURES 0x2A60 /**< PLX Service, feature characteristic UUID*/ +#define BLE_UUID_OTS_FEATURES 0x2ABD /**< OTS Service, feature characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_NAME 0x2ABE /**< OTS Service, Object Name characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_TYPE 0x2ABF /**< OTS Service, Object Type characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_SIZE 0x2AC0 /**< OTS Service, Object Size characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_FIRST_CREATED 0x2AC1 /**< OTS Service, Object First Created characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_LAST_MODIFIED 0x2AC2 /**< OTS Service, Object Last Modified characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_ID 0x2AC3 /**< OTS Service, Object ID characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_PROPERTIES 0x2AC4 /**< OTS Service, Object Properties characteristic UUID*/ +#define BLE_UUID_OTS_OACP 0x2AC5 /**< OTS Service, Object Action Control Point characteristic UUID*/ +#define BLE_UUID_OTS_OLCP 0x2AC6 /**< OTS Service, Object List Control Point characteristic UUID*/ +#define BLE_UUID_OTS_LF 0x2AC7 /**< OTS Service, Object List Filter characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_CHANGED 0x2AC8 /**< OTS Service, Object Changed characteristic UUID*/ + + + + +/** @} */ + +/** @defgroup ALERT_LEVEL_VALUES Definitions for the Alert Level characteristic values + * @{ */ +#define BLE_CHAR_ALERT_LEVEL_NO_ALERT 0x00 /**< No Alert. */ +#define BLE_CHAR_ALERT_LEVEL_MILD_ALERT 0x01 /**< Mild Alert. */ +#define BLE_CHAR_ALERT_LEVEL_HIGH_ALERT 0x02 /**< High Alert. */ +/** @} */ + +#define BLE_SRV_ENCODED_REPORT_REF_LEN 2 /**< The length of an encoded Report Reference Descriptor. */ +#define BLE_CCCD_VALUE_LEN 2 /**< The length of a CCCD value. */ + +/**@brief Type definition for error handler function that will be called in case of an error in + * a service or a service library module. */ +typedef void (*ble_srv_error_handler_t) (uint32_t nrf_error); + + + +/**@brief Value of a Report Reference descriptor. + * + * @details This is mapping information that maps the parent characteristic to the Report ID(s) and + * Report Type(s) defined within a Report Map characteristic. + */ +typedef struct +{ + uint8_t report_id; /**< Non-zero value if there is more than one instance of the same Report Type */ + uint8_t report_type; /**< Type of Report characteristic (see @ref BLE_HIDS_REPORT_TYPE) */ +} ble_srv_report_ref_t; + +/**@brief UTF-8 string data type. + * + * @note The type can only hold a pointer to the string data (i.e. not the actual data). + */ +typedef struct +{ + uint16_t length; /**< String length. */ + uint8_t * p_str; /**< String data. */ +} ble_srv_utf8_str_t; + + +/**@brief Security settings structure. + * @details This structure contains the security options needed during initialization of the + * service. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ +} ble_srv_security_mode_t; + +/**@brief Security settings structure. + * @details This structure contains the security options needed during initialization of the + * service. It can be used when the characteristics contains a CCCD. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t cccd_write_perm; /**< Write permissions for Client Characteristic Configuration Descriptor. */ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ +} ble_srv_cccd_security_mode_t; + +/**@brief Function for decoding a CCCD value, and then testing if notification is + * enabled. + * + * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. + * + * @retval TRUE If notification is enabled. + * @retval FALSE Otherwise. + */ +bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data); + + +/**@brief Function for decoding a CCCD value, and then testing if indication is + * enabled. + * + * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. + * + * @retval TRUE If indication is enabled. + * @retval FALSE Otherwise. + */ +bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data); + + +/**@brief Function for encoding a Report Reference Descriptor. + * + * @param[in] p_encoded_buffer The buffer of the encoded data. + * @param[in] p_report_ref Report Reference value to be encoded. + * + * @return Length of the encoded data. + */ +uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, + const ble_srv_report_ref_t * p_report_ref); + +/**@brief Function for making a UTF-8 structure refer to an ASCII string. + * + * @param[out] p_utf8 UTF-8 structure to be set. + * @param[in] p_ascii ASCII string to be referred to. + */ +void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii); + + +/**@brief Security Access enumeration. + * @details This enumeration gives the possible requirements for accessing a characteristic value. + */ +typedef enum +{ + SEC_NO_ACCESS = 0, /**< Not possible to access. */ + SEC_OPEN = 1, /**< Access open. */ + SEC_JUST_WORKS = 2, /**< Access possible with 'Just Works' security at least. */ + SEC_MITM = 3, /**< Access possible with 'MITM' security at least. */ + SEC_SIGNED = 4, /**< Access possible with 'signed' security at least. */ + SEC_SIGNED_MITM = 5 /**< Access possible with 'signed and MITM' security at least. */ +}security_req_t; + + +/**@brief Characteristic User Descriptor parameters. + * @details This structure contains the parameters for User Descriptor. + */ +typedef struct +{ + uint16_t max_size; /**< Maximum size of the user descriptor*/ + uint16_t size; /**< Size of the user descriptor*/ + uint8_t *p_char_user_desc; /**< User descriptor content, pointer to a UTF-8 encoded string (non-NULL terminated)*/ + bool is_var_len; /**< Indicates if the user descriptor has variable length.*/ + ble_gatt_char_props_t char_props; /**< user descriptor properties.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + security_req_t read_access; /**< Security requirement for reading the user descriptor.*/ + security_req_t write_access; /**< Security requirement for writing the user descriptor.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ +}ble_add_char_user_desc_t; + + +/**@brief Add characteristic parameters structure. + * @details This structure contains the parameters needed to use the @ref characteristic_add function. + */ +typedef struct +{ + uint16_t uuid; /**< Characteristic UUID (16 bits UUIDs).*/ + uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ + uint16_t max_len; /**< Maximum length of the characteristic value.*/ + uint16_t init_len; /**< Initial length of the characteristic value.*/ + uint8_t * p_init_value; /**< Initial encoded value of the characteristic.*/ + bool is_var_len; /**< Indicates if the characteristic value has variable length.*/ + ble_gatt_char_props_t char_props; /**< Characteristic properties.*/ + ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic extended properties.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + security_req_t read_access; /**< Security requirement for reading the characteristic value.*/ + security_req_t write_access; /**< Security requirement for writing the characteristic value.*/ + security_req_t cccd_write_access; /**< Security requirement for writing the characteristic's CCCD.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ + ble_add_char_user_desc_t *p_user_descr; /**< Pointer to user descriptor if needed*/ + ble_gatts_char_pf_t *p_presentation_format; /**< Pointer to characteristic format if needed*/ +} ble_add_char_params_t; + + +/**@brief Add descriptor parameters structure. + * @details This structure contains the parameters needed to use the @ref descriptor_add function. + */ +typedef struct +{ + uint16_t uuid; /**< descriptor UUID (16 bits UUIDs).*/ + uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + bool is_var_len; /**< Indicates if the descriptor value has variable length.*/ + security_req_t read_access; /**< Security requirement for reading the descriptor value.*/ + security_req_t write_access; /**< Security requirement for writing the descriptor value.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ + uint16_t init_len; /**< Initial descriptor value length in bytes. */ + uint16_t init_offs; /**< Initial descriptor value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */ + uint16_t max_len; /**< Maximum descriptor value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ + uint8_t* p_value; /**< Pointer to the value of the descriptor*/ +} ble_add_descr_params_t; + + +/**@brief Function for adding a characteristic to a given service. + * + * If no pointer is given for the initial value, + * the initial length parameter will be ignored and the initial length will be 0. + * + * @param[in] service_handle Handle of the service to which the characteristic is to be added. + * @param[in] p_char_props Information needed to add the characteristic. + * @param[out] p_char_handle Handle of the added characteristic. + * + * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. + */ +uint32_t characteristic_add(uint16_t service_handle, + ble_add_char_params_t * p_char_props, + ble_gatts_char_handles_t * p_char_handle); + + +/**@brief Function for adding a characteristic's descriptor to a given characteristic. + * + * @param[in] char_handle Handle of the characteristic to which the descriptor is to be added, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. + * @param[in] p_descr_props Information needed to add the descriptor. + * @param[out] p_descr_handle Handle of the added descriptor. + * + * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. + */ +uint32_t descriptor_add(uint16_t char_handle, + ble_add_descr_params_t * p_descr_props, + uint16_t * p_descr_handle); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_SRV_COMMON_H__ + +/** @} */ diff --git a/libraries/nfc/src/util/nfc_platform.c b/libraries/nfc/src/util/nfc_platform.c new file mode 100644 index 000000000..38edf268a --- /dev/null +++ b/libraries/nfc/src/util/nfc_platform.c @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#include "nrf_drv_clock.h" +//#if NRF_MODULE_ENABLED(NFC_PLATFORM) + +#include "nfc_platform.h" +#define NRF_LOG_MODULE_NAME nfc_platform +#if NFC_PLATFORM_LOG_ENABLED +#define NRF_LOG_LEVEL NFC_PLATFORM_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NFC_PLATFORM_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR NFC_PLATFORM_DEBUG_COLOR +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#else // NFC_PLATFORM_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#include "nrf_log.h" +#endif // NFC_PLATFORM_LOG_ENABLED + +/* Static data */ +static nrf_drv_clock_handler_item_t m_clock_handler_item; /**< Clock event handler item structure. */ + +/**@brief Function for handling events from the Clock module. + * + * @param[in] event Clock event. + * + */ +static inline void clock_event_handler(nrf_drv_clock_evt_type_t event) +{ + switch(event) + { + case NRF_DRV_CLOCK_EVT_HFCLK_STARTED: + /* Activate NFCT only when HFXO is running */ + nrfx_nfct_state_force(NRFX_NFCT_STATE_ACTIVATED); + break; + + default: + /* No implementation required */ + break; + } +} + + +nrfx_err_t nfc_platform_setup(void) +{ + nrfx_err_t err_code; + + /* Initialize the Clock module for handling high precision clock requests */ + m_clock_handler_item.event_handler = clock_event_handler; + m_clock_handler_item.p_next = NULL; + + err_code = nrf_drv_clock_init(); + if (err_code == NRF_ERROR_MODULE_ALREADY_INITIALIZED) + { + err_code = NRFX_SUCCESS; + } + else if (err_code != NRF_SUCCESS) + { + return NRFX_ERROR_INTERNAL; + } + + NRF_LOG_DEBUG("Utils init"); + return err_code; +} + + +void nfc_platform_event_handler(nrfx_nfct_evt_t const * p_event) +{ + switch (p_event->evt_id) + { + case NRFX_NFCT_EVT_FIELD_DETECTED: + NRF_LOG_DEBUG("Field detected"); + nrf_drv_clock_hfclk_request(&m_clock_handler_item); + break; + + case NRFX_NFCT_EVT_FIELD_LOST: + NRF_LOG_DEBUG("Field lost"); + nrf_drv_clock_hfclk_release(); + break; + + default: + /* No implementation required */ + break; + } +} + +//#endif // NRF_MODULE_ENABLED(NFC_PLATFORM) diff --git a/libraries/nfc/src/util/nfc_platform.h b/libraries/nfc/src/util/nfc_platform.h new file mode 100644 index 000000000..a1279af63 --- /dev/null +++ b/libraries/nfc/src/util/nfc_platform.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NFC_PLATFORM_H__ +#define NFC_PLATFORM_H__ + +/** @file + * + * @addtogroup nfc_api + * + * @defgroup nfc_platform Platform-specific module for NFC + * @{ + * @ingroup nfc_api + * @brief @tagAPI52 Platform-specific module for Near Field Communication Tag (NFCT). + * + * This module is used to set up platform-specific components that are required for NFC, and to + * activate NFCT peripheral when all necessary conditions are fulfilled. + * + * @note Before the NFCT peripheral enters the ACTIVATED state, the HFXO must be running. To fulfill + * this requirement, this module uses the clock management module. + * + */ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for initializing platform-specific modules required by NFC. + * + * This function sets up clock managing interface and other platform specific components + * that are required for NFC. + * + * @retval NRFX_SUCCESS If the NFC module is initialized successfully. If one + * of the arguments is invalid, an error code is returned. + */ +nrfx_err_t nfc_platform_setup(void); + + +/** + * @brief Function for handling NFCT events that require platform-specific actions. + * + * This function is used by the NFC platform module to observe NFC events. This event flow is + * necessary to track in order to determine when HFXO must be running and when the NFCT peripheral must + * be activated. + * + * @param[in] p_event NFCT driver event. + */ +void nfc_platform_event_handler(nrfx_nfct_evt_t const * p_event); + + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* NFC_PLATFORM_H__ */ + diff --git a/libraries/nfc/src/util/nordic_common.h b/libraries/nfc/src/util/nordic_common.h new file mode 100644 index 000000000..def79949b --- /dev/null +++ b/libraries/nfc/src/util/nordic_common.h @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2008 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Common defines and macros for firmware developed by Nordic Semiconductor. + */ + +#ifndef NORDIC_COMMON_H__ +#define NORDIC_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Check if selected module is enabled + * + * This is save function for driver enable checking. + * Correct from Lint point of view (not using default of undefined value). + * + * Usage: + * @code + #if NRF_MODULE_ENABLED(UART) + ... + #endif + * @endcode + * + * @param module The module name. + * + * @retval 1 The macro _ENABLE is defined and is non-zero. + * @retval 0 The macro _ENABLE is not defined or it equals zero. + * + * @note + * This macro intentionally does not implement second expansion level. + * The name of the module to be checked has to be given directly as a parameter. + * And given parameter would be connected with @c _ENABLED postfix directly + * without evaluating its value. + */ +//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator" +#ifdef NRF_MODULE_ENABLE_ALL +#warning "Do not use NRF_MODULE_ENABLE_ALL for real builds." +#define NRF_MODULE_ENABLED(module) 1 +#else +#define NRF_MODULE_ENABLED(module) \ + ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0) +#endif +/** The upper 8 bits of a 32 bit value */ +//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value" +#define MSB_32(a) (((a) & 0xFF000000) >> 24) +/** The lower 8 bits (of a 32 bit value) */ +#define LSB_32(a) ((a) & 0x000000FF) + +/** The upper 8 bits of a 16 bit value */ +//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value" +#define MSB_16(a) (((a) & 0xFF00) >> 8) +/** The lower 8 bits (of a 16 bit value) */ +#define LSB_16(a) ((a) & 0x00FF) + +/** Leaves the minimum of the two 32-bit arguments */ +/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/** Leaves the maximum of the two 32-bit arguments */ +/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +/**@brief Concatenates two parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * + * @return Two parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_3 + */ +#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2) +/** Auxiliary macro used by @ref CONCAT_2 */ +#define CONCAT_2_(p1, p2) p1##p2 + +/**@brief Concatenates three parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * @param p3 Third parameter to concatenating + * + * @return Three parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_2 + */ +#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3) +/** Auxiliary macro used by @ref CONCAT_3 */ +#define CONCAT_3_(p1, p2, p3) p1##p2##p3 + +#define STRINGIFY_(val) #val +/** Converts a macro argument into a character constant. + */ +#define STRINGIFY(val) STRINGIFY_(val) + +/** Counts number of elements inside the array + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/**@brief Set a bit in the uint32 word. + * + * @param[in] W Word whose bit is being set. + * @param[in] B Bit number in the word to be set. + */ +#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B))) + + +/**@brief Clears a bit in the uint32 word. + * + * @param[in] W Word whose bit is to be cleared. + * @param[in] B Bit number in the word to be cleared. + */ +#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B)))) + + +/**@brief Checks if a bit is set. + * + * @param[in] W Word whose bit is to be checked. + * @param[in] B Bit number in the word to be checked. + * + * @retval 1 if bit is set. + * @retval 0 if bit is not set. + */ +#define IS_SET(W, B) (((W) >> (B)) & 1) + +#define BIT_0 0x01 /**< The value of bit 0 */ +#define BIT_1 0x02 /**< The value of bit 1 */ +#define BIT_2 0x04 /**< The value of bit 2 */ +#define BIT_3 0x08 /**< The value of bit 3 */ +#define BIT_4 0x10 /**< The value of bit 4 */ +#define BIT_5 0x20 /**< The value of bit 5 */ +#define BIT_6 0x40 /**< The value of bit 6 */ +#define BIT_7 0x80 /**< The value of bit 7 */ +#define BIT_8 0x0100 /**< The value of bit 8 */ +#define BIT_9 0x0200 /**< The value of bit 9 */ +#define BIT_10 0x0400 /**< The value of bit 10 */ +#define BIT_11 0x0800 /**< The value of bit 11 */ +#define BIT_12 0x1000 /**< The value of bit 12 */ +#define BIT_13 0x2000 /**< The value of bit 13 */ +#define BIT_14 0x4000 /**< The value of bit 14 */ +#define BIT_15 0x8000 /**< The value of bit 15 */ +#define BIT_16 0x00010000 /**< The value of bit 16 */ +#define BIT_17 0x00020000 /**< The value of bit 17 */ +#define BIT_18 0x00040000 /**< The value of bit 18 */ +#define BIT_19 0x00080000 /**< The value of bit 19 */ +#define BIT_20 0x00100000 /**< The value of bit 20 */ +#define BIT_21 0x00200000 /**< The value of bit 21 */ +#define BIT_22 0x00400000 /**< The value of bit 22 */ +#define BIT_23 0x00800000 /**< The value of bit 23 */ +#define BIT_24 0x01000000 /**< The value of bit 24 */ +#define BIT_25 0x02000000 /**< The value of bit 25 */ +#define BIT_26 0x04000000 /**< The value of bit 26 */ +#define BIT_27 0x08000000 /**< The value of bit 27 */ +#define BIT_28 0x10000000 /**< The value of bit 28 */ +#define BIT_29 0x20000000 /**< The value of bit 29 */ +#define BIT_30 0x40000000 /**< The value of bit 30 */ +#define BIT_31 0x80000000 /**< The value of bit 31 */ + +#define UNUSED_VARIABLE(X) ((void)(X)) +#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X) +#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X) + +#ifdef __cplusplus +} +#endif + +#endif // NORDIC_COMMON_H__ diff --git a/libraries/nfc/src/util/nrf_assert.c b/libraries/nfc/src/util/nrf_assert.c new file mode 100644 index 000000000..162465763 --- /dev/null +++ b/libraries/nfc/src/util/nrf_assert.c @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2006 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_assert.h" +#include "app_error.h" +#include "nordic_common.h" + +__WEAK void assert_nrf_callback(uint16_t line_num, const uint8_t * file_name) +{ + assert_info_t assert_info = + { + .line_num = line_num, + .p_file_name = file_name, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ASSERT, 0, (uint32_t)(&assert_info)); + + UNUSED_VARIABLE(assert_info); +} diff --git a/libraries/nfc/src/util/nrf_assert.h b/libraries/nfc/src/util/nrf_assert.h new file mode 100644 index 000000000..08771e125 --- /dev/null +++ b/libraries/nfc/src/util/nrf_assert.h @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2006 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Utilities for verifying program logic + */ + +#ifndef NRF_ASSERT_H_ +#define NRF_ASSERT_H_ + +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for handling assertions. + * + * + * @note + * This function is called when an assertion has triggered. + * + * @note + * This function is deprecated and will be removed in future releases. + * Use app_error_fault_handler instead. + * + * + * @post + * All hardware is put into an idle non-emitting state (in particular the radio is highly + * important to switch off since the radio might be in a state that makes it send + * packets continiously while a typical final infinit ASSERT loop is executing). + * + * + * @param line_num The line number where the assertion is called + * @param file_name Pointer to the file name + */ +//lint -save -esym(14, assert_nrf_callback) +void assert_nrf_callback(uint16_t line_num, const uint8_t *file_name); +//lint -restore + +#if (defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)) +#define NRF_ASSERT_PRESENT 1 +#else +#define NRF_ASSERT_PRESENT 0 +#endif + +//#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + +/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */ +/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \ + +/** @brief Function for checking intended for production code. + * + * Check passes if "expr" evaluates to true. */ + +#ifdef _lint +#define ASSERT(expr) \ +if (expr) \ +{ \ +} \ +else \ +{ \ + while (1); \ +} +#else //_lint +#define ASSERT(expr) \ +if (NRF_ASSERT_PRESENT) \ +{ \ + if (expr) \ + { \ + } \ + else \ + { \ + assert_nrf_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \ + } \ +} + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ASSERT_H_ */ diff --git a/libraries/nfc/src/util/nrf_atomic.c b/libraries/nfc/src/util/nrf_atomic.c new file mode 100644 index 000000000..7303254e4 --- /dev/null +++ b/libraries/nfc/src/util/nrf_atomic.c @@ -0,0 +1,449 @@ +/** + * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_atomic.h" + +#ifndef NRF_ATOMIC_USE_BUILD_IN +#if (defined(__GNUC__) && defined(WIN32)) + #define NRF_ATOMIC_USE_BUILD_IN 1 +#else + #define NRF_ATOMIC_USE_BUILD_IN 0 +#endif +#endif // NRF_ATOMIC_USE_BUILD_IN + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) +#define STREX_LDREX_PRESENT +#else +#include "app_util_platform.h" +#endif + + +#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) +#include "nrf_atomic_internal.h" +#endif + +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); + +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data = value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); + return value; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data = value; + CRITICAL_REGION_EXIT(); + return value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data |= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data |= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data &= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data &= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data ^= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data ^= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data += value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data += value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_compare_exchange(p_data, + p_expected, + &desired, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + return nrf_atomic_internal_cmp_exch(p_data, p_expected, desired); +#else + bool ret; + CRITICAL_REGION_ENTER(); + if (*p_data == *p_expected) + { + *p_data = desired; + ret = true; + } + else + { + *p_expected = *p_data; + ret = false; + } + CRITICAL_REGION_EXIT(); + return ret; +#endif +} + +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return expected; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return new_val; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_and(p_data, 0); +} + +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_and(p_data, 0); +} + diff --git a/libraries/nfc/src/util/nrf_atomic.h b/libraries/nfc/src/util/nrf_atomic.h new file mode 100644 index 000000000..7bb7e8e0e --- /dev/null +++ b/libraries/nfc/src/util/nrf_atomic.h @@ -0,0 +1,274 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nrf_atomic Atomic operations API + * @ingroup app_common + * @{ + * + * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. + At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). + * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. + */ + +#ifndef NRF_ATOMIC_H__ +#define NRF_ATOMIC_H__ + +#include "sdk_common.h" + +/** + * @brief Atomic 32 bit unsigned type + * */ +typedef volatile uint32_t nrf_atomic_u32_t; + +/** + * @brief Atomic 1 bit flag type (technically 32 bit) + * */ +typedef volatile uint32_t nrf_atomic_flag_t; + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief If value at pointer is equal to expected value, changes value at pointer to desired + * + * Atomically compares the value pointed to by p_data with the value pointed to by p_expected, + * and if those are equal, replaces the former with desired. Otherwise, loads the actual value + * pointed to by p_data into *p_expected. + * + * @param p_data Atomic memory pointer to test and modify. + * @param p_expected Pointer to test value. + * @param desired Value to be stored to atomic memory. + * + * @retval true *p_data was equal to *p_expected + * @retval false *p_data was not equal to *p_expected + */ +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/**************************************************************************************************/ + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_H__ */ + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_atomic_internal.h b/libraries/nfc/src/util/nrf_atomic_internal.h new file mode 100644 index 000000000..a773d3377 --- /dev/null +++ b/libraries/nfc/src/util/nrf_atomic_internal.h @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_ATOMIC_INTERNAL_H__ +#define NRF_ATOMIC_INTERNAL_H__ + +#include "sdk_common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nrf_atomic_internal Atomic operations internals + * @ingroup nrf_atomic + * @{ + * + */ + +/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error "Unsupported core version" +#endif + +#if defined ( __CC_ARM ) +static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. + * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are + * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. + * */ + push {r4, r5} + mov r4, r0 + +loop_mov + ldrex r0, [r4] + mov r5, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_mov + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_orr + ldrex r0, [r4] + orr r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_orr + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_and + ldrex r0, [r4] + and r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_and + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_eor + ldrex r0, [r4] + eor r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_eor + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_add + ldrex r0, [r4] + add r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_add + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub + ldrex r0, [r4] + sub r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ +#define RET_REG r0 +#define P_EXPC r1 +#define VALUE r2 +#define STR_RES r3 +#define P_DATA r4 +#define EXPC_VAL r5 +#define ACT_VAL r6 + + push {r4-r6} + mov P_DATA, r0 + mov RET_REG, #0 + +loop_cmp_exch + ldrex ACT_VAL, [P_DATA] + ldr EXPC_VAL, [P_EXPC] + cmp ACT_VAL, EXPC_VAL + ittee eq + strexeq STR_RES, VALUE, [P_DATA] + moveq RET_REG, #1 + strexne STR_RES, ACT_VAL, [P_DATA] + strne ACT_VAL, [P_EXPC] + cmp STR_RES, #0 + itt ne + movne RET_REG, #0 + bne loop_cmp_exch + + pop {r4-r6} + bx lr + +#undef RET_REG +#undef P_EXPC +#undef VALUE +#undef STR_RES +#undef P_DATA +#undef EXPC_VAL +#undef ACT_VAL +} + +static __asm uint32_t nrf_atomic_internal_sub_hs(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub_ge + ldrex r0, [r4] + cmp r0, r1 + ite hs + subhs r5, r0, r1 + movlo r5, r0 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub_ge + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ + old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +/** + * @brief Atomic operation generic macro + * @param[in] asm_op operation: mov, orr, and, eor, add, sub + * @param[out] old_val atomic object output (uint32_t), value before operation + * @param[out] new_val atomic object output (uint32_t), value after operation + * @param[in] value atomic operation operand + * */ +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ +{ \ + uint32_t str_res; \ + __ASM volatile( \ + "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ + NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ + " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ + " teq %[str_res], #0\n" \ + " bne.n 1b" \ + : \ + [old_val]"=&r" (old_val), \ + [new_val]"=&r" (new_val), \ + [str_res]"=&r" (str_res) \ + : \ + [ptr]"r" (ptr), \ + [value]"r" (value) \ + : "cc"); \ + UNUSED_PARAMETER(str_res); \ +} + +#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub_hs(new_val, old_val, value) \ + "cmp %["#old_val"], %["#value"]\n " \ + "ite hs\n" \ + "subhs %["#new_val"], %["#old_val"], %["#value"]\n" \ + "movlo %["#new_val"], %["#old_val"]\n" + +static inline bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ + bool res = false; + uint32_t str_res = 0; + uint32_t act_val = 0; + uint32_t exp_val = 0; + UNUSED_VARIABLE(str_res); + UNUSED_VARIABLE(act_val); + UNUSED_VARIABLE(exp_val); + __ASM volatile( + "1: ldrex %[act_val], [%[ptr]]\n" + " ldr %[exp_val], [%[expc]]\n" + " cmp %[act_val], %[exp_val]\n" + " ittee eq\n" + " strexeq %[str_res], %[value], [%[ptr]]\n" + " moveq %[res], #1\n" + " strexne %[str_res], %[act_val], [%[ptr]]\n" + " strne %[act_val], [%[expc]]\n" + " cmp %[str_res], #0\n" + " itt ne\n" + " movne %[res], #0\n" + " bne.n 1b" + : + [res] "=&r" (res), + [exp_val] "=&r" (exp_val), + [act_val] "=&r" (act_val), + [str_res] "=&r" (str_res) + : + "0" (res), + "1" (exp_val), + "2" (act_val), + [expc] "r" (p_expected), + [ptr] "r" (p_data), + [value] "r" (value) + : "cc"); + return res; +} + +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_INTERNAL_H__ */ + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_atomic_sanity_check.h b/libraries/nfc/src/util/nrf_atomic_sanity_check.h new file mode 100644 index 000000000..82b751025 --- /dev/null +++ b/libraries/nfc/src/util/nrf_atomic_sanity_check.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_ATOMIC_SANITY_CHECK_H__ +#define NRF_ATOMIC_SANITY_CHECK_H__ + +#include "nrf_atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Quick sanity check of nrf_atomic API + * */ +static inline void nrf_atomic_sanity_check(void) +{ +#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + nrf_atomic_u32_t val; + nrf_atomic_u32_t flag; + + /*Fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store_fetch(&val, 10) == 0); + ASSERT(nrf_atomic_u32_store_fetch(&val, 0) == 10); + + val = 0; + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 16) == 0); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == (0xFFFFFFFF)); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 16)) == 0xFFFFFFFF); + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 5)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0xFFFFFFFF) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16)) == 0); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 5)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16) | (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 0); + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add_fetch(&val, 1 << 24) == 200); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0xFFFFFFFF) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 1000); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0xFFFFFFFF) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 0); + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 0); + + /*No fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store(&val, 10) == 10); + ASSERT(nrf_atomic_u32_store(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_or(&val, 1 << 16) == 1 << 16); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0xFFFFFFFF) == 0xFFFFFFFF); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 16)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 5)) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16) | (1 << 5)) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_add(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add(&val, 100) == 200); + ASSERT(nrf_atomic_u32_add(&val, 1 << 24) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0xFFFFFFFF) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub(&val, 100) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0xFFFFFFFF) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_SANITY_CHECK_H__ */ diff --git a/libraries/nfc/src/util/nrf_balloc.c b/libraries/nfc/src/util/nrf_balloc.c new file mode 100644 index 000000000..380d469e1 --- /dev/null +++ b/libraries/nfc/src/util/nrf_balloc.c @@ -0,0 +1,399 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" + #if NRF_MODULE_ENABLED(NRF_BALLOC) + +#include "nrf_section.h" +#include "nrf_balloc.h" +#include "app_util_platform.h" + + +#if NRF_BALLOC_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_BALLOC_CONFIG_LOG_LEVEL + #define NRF_LOG_INITIAL_LEVEL NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_BALLOC_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_BALLOC_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_BALLOC_CONFIG_LOG_ENABLED +#include "nrf_log.h" + +#define HEAD_GUARD_FILL 0xBAADF00D /**< Magic number used to mark head guard.*/ +#define TAIL_GUARD_FILL 0xBAADCAFE /**< Magic number used to mark tail guard.*/ +#define FREE_MEM_FILL 0xBAADBAAD /**< Magic number used to mark free memory.*/ + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define POOL_ID(_p_pool) _p_pool->p_name +#define POOL_MARKER "%s" +#else +#define POOL_ID(_p_pool) _p_pool +#define POOL_MARKER "0x%08X" +#endif + +NRF_SECTION_DEF(nrf_balloc, nrf_balloc_t); + +#if NRF_BALLOC_CLI_CMDS && NRF_CLI_ENABLED +#include "nrf_cli.h" + +static void nrf_balloc_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + if (argc > 1) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad argument count"); + return; + } + + uint32_t num_of_instances = NRF_SECTION_ITEM_COUNT(nrf_balloc, nrf_balloc_t); + uint32_t i; + + for (i = 0; i < num_of_instances; i++) + { + const nrf_balloc_t * p_instance = NRF_SECTION_ITEM_GET(nrf_balloc, nrf_balloc_t, i); + + uint32_t element_size = NRF_BALLOC_ELEMENT_SIZE(p_instance); + uint32_t dbg_addon = p_instance->block_size - element_size; + uint32_t pool_size = p_instance->p_stack_limit - p_instance->p_stack_base; + uint32_t max_util = nrf_balloc_max_utilization_get(p_instance); + uint32_t util = nrf_balloc_utilization_get(p_instance); + const char * p_name = p_instance->p_name; + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n\t- Element size:\t%d + %d bytes of debug information\r\n" + "\t- Usage:\t%u%% (%u out of %u elements)\r\n" + "\t- Maximum:\t%u%% (%u out of %u elements)\r\n\r\n", + p_name, element_size, dbg_addon, + 100ul * util/pool_size, util,pool_size, + 100ul * max_util/pool_size, max_util,pool_size); + + } +} +// Register "balloc" command and its subcommands in CLI. +NRF_CLI_CREATE_STATIC_SUBCMD_SET(nrf_balloc_commands) +{ + NRF_CLI_CMD(status, NULL, "Print status of balloc instances.", nrf_balloc_status), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(balloc, &nrf_balloc_commands, "Commands for BALLOC management", nrf_balloc_status); +#endif //NRF_BALLOC_CLI_CMDS + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +/**@brief Validate block memory, prepare block guards, and calculate pointer to the element. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_head Pointer to the beginning of the block. + * + * @return Pointer to the element. + */ +__STATIC_INLINE void * nrf_balloc_block_unwrap(nrf_balloc_t const * p_pool, void * p_head) +{ + ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0)); + ASSERT((p_head != NULL) && (((uint32_t)(p_head) % sizeof(uint32_t)) == 0)); + + uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags); + uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags); + + uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size); + uint32_t * p_element = (uint32_t *)p_head + head_words; + + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_head; ptr < p_tail; ptr++) + { + if (*ptr != FREE_MEM_FILL) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Detected free memory corruption at 0x%08X (0x%08X != 0x%08X)", + ptr, *ptr, FREE_MEM_FILL); + APP_ERROR_CHECK_BOOL(false); + } + } + } + + for (uint32_t * ptr = p_head; ptr < p_element; ptr++) + { + *ptr = HEAD_GUARD_FILL; + } + + for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++) + { + *ptr = TAIL_GUARD_FILL; + } + + return p_element; +} + +/**@brief Calculate pointer to the block, validate block guards, and mark block memory as free. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_element Pointer to the element. + * + * @return Pointer to the beginning of the block. + */ +__STATIC_INLINE void * nrf_balloc_element_wrap(nrf_balloc_t const * p_pool, void * p_element) +{ + ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0)); + ASSERT((p_element != NULL) && (((uint32_t)(p_element) % sizeof(uint32_t)) == 0)); + + uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags); + uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags); + + uint32_t * p_head = (uint32_t *)p_element - head_words; + uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size); + + for (uint32_t * ptr = p_head; ptr < (uint32_t *)p_element; ptr++) + { + if (*ptr != HEAD_GUARD_FILL) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Detected Head Guard corruption at 0x%08X (0x%08X != 0x%08X)", + ptr, *ptr, HEAD_GUARD_FILL); + APP_ERROR_CHECK_BOOL(false); + } + } + + for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++) + { + if (*ptr != TAIL_GUARD_FILL) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Detected Tail Guard corruption at 0x%08X (0x%08X != 0x%08X)", + ptr, *ptr, TAIL_GUARD_FILL); + APP_ERROR_CHECK_BOOL(false); + } + } + + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_head; ptr < p_tail; ptr++) + { + *ptr = FREE_MEM_FILL; + } + } + + return p_head; +} + +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Convert block index to a pointer. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] idx Index of the block. + * + * @return Pointer to the beginning of the block. + */ +static void * nrf_balloc_idx2block(nrf_balloc_t const * p_pool, uint8_t idx) +{ + ASSERT(p_pool != NULL); + return (uint8_t *)(p_pool->p_memory_begin) + ((size_t)(idx) * p_pool->block_size); +} + +/**@brief Convert block pointer to index. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_block Pointer to the beginning of the block. + * + * @return Index of the block. + */ +static uint8_t nrf_balloc_block2idx(nrf_balloc_t const * p_pool, void const * p_block) +{ + ASSERT(p_pool != NULL); + return ((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) / p_pool->block_size; +} + +ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool) +{ + uint8_t pool_size; + + VERIFY_PARAM_NOT_NULL(p_pool); + + ASSERT(p_pool->p_cb); + ASSERT(p_pool->p_stack_base); + ASSERT(p_pool->p_stack_limit); + ASSERT(p_pool->p_memory_begin); + ASSERT(p_pool->block_size); + + pool_size = p_pool->p_stack_limit - p_pool->p_stack_base; + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size); + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_pool->p_memory_begin; ptr < (uint32_t *)(p_memory_end); ptr++) + { + *ptr = FREE_MEM_FILL; + } + } +#endif + + NRF_LOG_INST_INFO(p_pool->p_log, "Initialized (size: %u x %u = %u bytes)", + pool_size, + p_pool->block_size, + pool_size * p_pool->block_size); + + p_pool->p_cb->p_stack_pointer = p_pool->p_stack_base; + while (pool_size--) + { + *(p_pool->p_cb->p_stack_pointer)++ = pool_size; + } + + p_pool->p_cb->max_utilization = 0; + + return NRF_SUCCESS; +} + +void * nrf_balloc_alloc(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + + void * p_block = NULL; + + CRITICAL_REGION_ENTER(); + + if (p_pool->p_cb->p_stack_pointer > p_pool->p_stack_base) + { + // Allocate block. + p_block = nrf_balloc_idx2block(p_pool, *--(p_pool->p_cb->p_stack_pointer)); + + // Update utilization statistics. + uint8_t utilization = p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer; + if (p_pool->p_cb->max_utilization < utilization) + { + p_pool->p_cb->max_utilization = utilization; + } + } + + CRITICAL_REGION_EXIT(); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + if (p_block != NULL) + { + p_block = nrf_balloc_block_unwrap(p_pool, p_block); + } +#endif + + NRF_LOG_INST_DEBUG(p_pool->p_log, "Allocating element: 0x%08X", p_block); + + return p_block; +} + +void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element) +{ + ASSERT(p_pool != NULL); + ASSERT(p_element != NULL) + + NRF_LOG_INST_DEBUG(p_pool->p_log, "Freeing element: 0x%08X", p_element); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + void * p_block = nrf_balloc_element_wrap(p_pool, p_element); + + // These checks could be done outside critical region as they use only pool configuration data. + if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags)) + { + uint8_t pool_size = p_pool->p_stack_limit - p_pool->p_stack_base; + void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size); + + // Check if the element belongs to this pool. + if ((p_block < p_pool->p_memory_begin) || (p_block >= p_memory_end)) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Attempted to free element (0x%08X) that does not belong to the pool.", + p_element); + APP_ERROR_CHECK_BOOL(false); + } + + // Check if the pointer is valid. + if ((((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) % p_pool->block_size) != 0) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Attempted to free corrupted element address (0x%08X).", p_element); + APP_ERROR_CHECK_BOOL(false); + } + } +#else + void * p_block = p_element; +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + CRITICAL_REGION_ENTER(); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + // These checks have to be done in critical region as they use p_pool->p_stack_pointer. + if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags)) + { + // Check for allocated/free ballance. + if (p_pool->p_cb->p_stack_pointer >= p_pool->p_stack_limit) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Attempted to free an element (0x%08X) while the pool is full.", + p_element); + APP_ERROR_CHECK_BOOL(false); + } + } + + if (NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(p_pool->debug_flags)) + { + // Check for double free. + for (uint8_t * p_idx = p_pool->p_stack_base; p_idx < p_pool->p_cb->p_stack_pointer; p_idx++) + { + if (nrf_balloc_idx2block(p_pool, *p_idx) == p_block) + { + NRF_LOG_INST_ERROR(p_pool->p_log, "Attempted to double-free an element (0x%08X).", + p_element); + APP_ERROR_CHECK_BOOL(false); + } + } + } +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + // Free the element. + *(p_pool->p_cb->p_stack_pointer)++ = nrf_balloc_block2idx(p_pool, p_block); + + CRITICAL_REGION_EXIT(); +} + +#endif // NRF_MODULE_ENABLED(NRF_BALLOC) diff --git a/libraries/nfc/src/util/nrf_balloc.h b/libraries/nfc/src/util/nrf_balloc.h new file mode 100644 index 000000000..0e6059f46 --- /dev/null +++ b/libraries/nfc/src/util/nrf_balloc.h @@ -0,0 +1,351 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/** + * @defgroup nrf_balloc Block memory allocator + * @{ + * @ingroup app_common + * @brief This module handles block memory allocator features. + */ + + +#ifndef NRF_BALLOC_H__ +#define NRF_BALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdk_errors.h" +#include "sdk_config.h" +#include "app_util_platform.h" +#include "app_util.h" +#include "nrf_log_instance.h" +#include "nrf_section.h" + +/** @brief Name of the module used for logger messaging. + */ +#define NRF_BALLOC_LOG_NAME balloc + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED || NRF_BALLOC_CLI_CMDS +#define NRF_BALLOC_HAS_NAME 1 +#else +#define NRF_BALLOC_HAS_NAME 0 +#endif + +/**@defgroup NRF_BALLOC_DEBUG Macros for preparing debug flags for block allocator module. + * @{ */ +#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(words) (((words) & 0xFF) << 0) +#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(flags) (((flags) >> 0) & 0xFF) +#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(words) (((words) & 0xFF) << 8) +#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(flags) (((flags) >> 8) & 0xFF) + +#define NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(enable) (!!(enable) << 16) +#define NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(flags) (flags & (1 << 16)) +#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(enable) (!!(enable) << 17) +#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(flags) (flags & (1 << 17)) +#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(enable) (!!(enable) << 18) +#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(flags) (flags & (1 << 18)) +/**@} */ + +/**@brief Default debug flags for @ref nrf_balloc. This is used by the @ref NRF_BALLOC_DEF macro. + * Flags can be changed in @ref sdk_config. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + #define NRF_BALLOC_DEFAULT_DEBUG_FLAGS \ + ( \ + NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS) | \ + NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS) | \ + NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED) | \ + NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED) | \ + NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED) \ + ) +#else + #define NRF_BALLOC_DEFAULT_DEBUG_FLAGS 0 +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Block memory allocator control block.*/ +typedef struct +{ + uint8_t * p_stack_pointer; //!< Current allocation stack pointer. + uint8_t max_utilization; //!< Maximum utilization of the memory pool. +} nrf_balloc_cb_t; + +/**@brief Block memory allocator pool instance. The pool is made of elements of the same size. */ +typedef struct +{ + nrf_balloc_cb_t * p_cb; //!< Pointer to the instance control block. + uint8_t * p_stack_base; //!< Base of the allocation stack. + /**< + * Stack is used to store handlers to not allocated elements. + */ + uint8_t * p_stack_limit; //!< Maximum possible value of the allocation stack pointer. + void * p_memory_begin; //!< Pointer to the start of the memory pool. + /**< + * Memory is used as a heap for blocks. + */ + NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled). +#if NRF_BALLOC_HAS_NAME + const char * p_name; //!< Pointer to string with pool name. +#endif +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + uint32_t debug_flags; //!< Debugging settings. + /**< + * Debug flag should be created by @ref NRF_BALLOC_DEBUG. + */ +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + uint16_t block_size; //!< Size of the allocated block (including debug overhead). + /**< + * Single block contains user element with header and tail + * words. + */ +} nrf_balloc_t; + +/**@brief Get total memory consumed by single block (element size with overhead caused by debug + * flags). + * + * @param[in] _element_size Size of an element. + * @param[in] _debug_flags Debug flags. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + #define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \ + ( \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(_debug_flags)) + \ + ALIGN_NUM(sizeof(uint32_t), (_element_size)) + \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(_debug_flags)) \ + ) +#else + #define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \ + ALIGN_NUM(sizeof(uint32_t), (_element_size)) +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + +/**@brief Get element size ( excluding debugging overhead is present) + * flags). + * + * @param[in] _p_balloc Pointer to balloc instance. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \ + (ALIGN_NUM(sizeof(uint32_t), (_p_balloc)->block_size) - \ + ((sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET((_p_balloc)->debug_flags)) + \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET((_p_balloc)->debug_flags)))) +#else +#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \ + (_p_balloc)->block_size +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) .debug_flags = (_debug_flags), +#else +#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) +#endif + +#if NRF_BALLOC_HAS_NAME +#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) .p_name = STRINGIFY(_name), +#else +#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) +#endif + + +/**@brief Create a block allocator instance with custom debug flags. + * + * @note This macro reserves memory for the given block allocator instance. + * + * @param[in] _name Name of the allocator. + * @param[in] _element_size Size of one element. + * @param[in] _pool_size Size of the pool. + * @param[in] _debug_flags Debug flags (@ref NRF_BALLOC_DEBUG). + */ +#define NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, _debug_flags) \ + STATIC_ASSERT((_pool_size) <= UINT8_MAX); \ + static uint8_t CONCAT_2(_name, _nrf_balloc_pool_stack)[(_pool_size)]; \ + static uint32_t CONCAT_2(_name,_nrf_balloc_pool_mem) \ + [NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) * (_pool_size) / sizeof(uint32_t)]; \ + static nrf_balloc_cb_t CONCAT_2(_name,_nrf_balloc_cb); \ + NRF_LOG_INSTANCE_REGISTER(NRF_BALLOC_LOG_NAME, _name, \ + NRF_BALLOC_CONFIG_INFO_COLOR, \ + NRF_BALLOC_CONFIG_DEBUG_COLOR, \ + NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL, \ + NRF_BALLOC_CONFIG_LOG_ENABLED ? \ + NRF_BALLOC_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ + NRF_SECTION_ITEM_REGISTER(nrf_balloc, const nrf_balloc_t _name) = \ + { \ + .p_cb = &CONCAT_2(_name,_nrf_balloc_cb), \ + .p_stack_base = CONCAT_2(_name,_nrf_balloc_pool_stack), \ + .p_stack_limit = CONCAT_2(_name,_nrf_balloc_pool_stack) + (_pool_size), \ + .p_memory_begin = CONCAT_2(_name,_nrf_balloc_pool_mem), \ + .block_size = NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags), \ + \ + NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_BALLOC_LOG_NAME, _name) \ + __NRF_BALLOC_ASSIGN_POOL_NAME(_name) \ + __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) \ + } + +/**@brief Create a block allocator instance. + * + * @note This macro reserves memory for the given block allocator instance. + * + * @param[in] _name Name of the allocator. + * @param[in] _element_size Size of one element. + * @param[in] _pool_size Size of the pool. + */ +#define NRF_BALLOC_DEF(_name, _element_size, _pool_size) \ + NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, NRF_BALLOC_DEFAULT_DEBUG_FLAGS) + +/**@brief Create a block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + */ +#define NRF_BALLOC_INTERFACE_DEC(_type, _name) \ + _type * CONCAT_2(_name,_alloc)(void); \ + void CONCAT_2(_name,_free)(_type * p_element) + +/**@brief Define a custom block allocator interface. + * + * @param[in] _attr Function attribute that will be added to allocator function definition. + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_CUSTOM_DEF(_attr, _type, _name, _p_pool) \ + _attr _type * CONCAT_2(_name,_alloc)(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_pool) != NULL); \ + ASSERT((_p_pool)->block_size >= \ + NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return (_type *)(nrf_balloc_alloc(_p_pool)); \ + } \ + \ + _attr void CONCAT_2(_name,_free)(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_pool) != NULL); \ + ASSERT((_p_pool)->block_size >= \ + NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + nrf_balloc_free((_p_pool), p_element); \ + } + +/**@brief Define block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_DEF(_type, _name, _p_pool) \ + NRF_BALLOC_INTERFACE_CUSTOM_DEF(/* empty */, _type, _name, _p_pool) + +/**@brief Define a local block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_LOCAL_DEF(_type, _name, _p_pool) \ + NRF_BALLOC_INTERFACE_CUSTOM_DEF(static, _type, _name, _p_pool) + +/**@brief Function for initializing a block memory allocator pool. + * + * @param[out] p_pool Pointer to the pool that is to be initialized. + * + * @return NRF_SUCCESS on success, otherwise error code. + */ +ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool); + +/**@brief Function for allocating an element from the pool. + * + * @note This module guarantees that the returned memory is aligned to 4. + * + * @param[in] p_pool Pointer to the memory pool from which the element will be allocated. + * + * @return Allocated element or NULL if the specified pool is empty. + */ +void * nrf_balloc_alloc(nrf_balloc_t const * p_pool); + +/**@brief Function for freeing an element back to the pool. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_element Element to be freed. + */ +void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element); + +/**@brief Function for getting maximum memory pool utilization. + * + * @param[in] p_pool Pointer to the memory pool instance. + * + * @return Maximum number of elements allocated from the pool. + */ +__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + return p_pool->p_cb->max_utilization; +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +/**@brief Function for getting current memory pool utilization. + * + * @param[in] p_pool Pointer to the memory pool instance. + * + * @return Maximum number of elements allocated from the pool. + */ +__STATIC_INLINE uint8_t nrf_balloc_utilization_get(nrf_balloc_t const * p_pool); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint8_t nrf_balloc_utilization_get(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + return (p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BALLOC_H__ +/** @} */ diff --git a/libraries/nfc/src/util/nrf_bitmask.h b/libraries/nfc/src/util/nrf_bitmask.h new file mode 100644 index 000000000..e5c924ee7 --- /dev/null +++ b/libraries/nfc/src/util/nrf_bitmask.h @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2006 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_BITMASK_H +#define NRF_BITMASK_H + +#include "compiler_abstraction.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITMASK_BYTE_GET(abs_bit) ((abs_bit)/8) +#define BITMASK_RELBIT_GET(abs_bit) ((abs_bit) & 0x00000007) + +/** + * Function for checking if bit in the multi-byte bit mask is set. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + * + * @return 0 if bit is not set, positive value otherwise. + */ +__STATIC_INLINE uint32_t nrf_bitmask_bit_is_set(uint32_t bit, void const * p_mask) +{ + uint8_t const * p_mask8 = (uint8_t const *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + return (1 << bit) & p_mask8[byte_idx]; +} + +/** + * Function for setting a bit in the multi-byte bit mask. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + */ +__STATIC_INLINE void nrf_bitmask_bit_set(uint32_t bit, void * p_mask) +{ + uint8_t * p_mask8 = (uint8_t *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + p_mask8[byte_idx] |= (1 << bit); +} + +/** + * Function for clearing a bit in the multi-byte bit mask. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + */ +__STATIC_INLINE void nrf_bitmask_bit_clear(uint32_t bit, void * p_mask) +{ + uint8_t * p_mask8 = (uint8_t *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + p_mask8[byte_idx] &= ~(1 << bit); +} + +/** + * Function for performing bitwise OR operation on two multi-byte bit masks. + * + * @param p_mask1 A pointer to the first bit mask. + * @param p_mask2 A pointer to the second bit mask. + * @param p_mask_out A pointer to the output bit mask. + * @param length Length of output mask in bytes. + */ +__STATIC_INLINE void nrf_bitmask_masks_or(void const * p_mask1, + void const * p_mask2, + void * p_out_mask, + uint32_t length) +{ + uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1; + uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2; + uint8_t * p_mask8_out = (uint8_t *)p_out_mask; + uint32_t i; + for (i = 0; i < length; i++) + { + p_mask8_out[i] = p_mask8_1[i] | p_mask8_2[i]; + } +} + +/** + * Function for performing bitwise AND operation on two multi-byte bit masks. + * + * @param p_mask1 A pointer to the first bit mask. + * @param p_mask2 A pointer to the second bit mask. + * @param p_mask_out A pointer to the output bit mask. + * @param length Length of output mask in bytes. + */ +__STATIC_INLINE void nrf_bitmask_masks_and(void const * p_mask1, + void const * p_mask2, + void * p_out_mask, + uint32_t length) +{ + uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1; + uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2; + uint8_t * p_mask8_out = (uint8_t *)p_out_mask; + uint32_t i; + for (i = 0; i < length; i++) + { + p_mask8_out[i] = p_mask8_1[i] & p_mask8_2[i]; + } +} + +#ifdef __cplusplus +} +#endif + +#endif //NRF_BITMASK_H diff --git a/libraries/nfc/src/util/nrf_drv_clock.c b/libraries/nfc/src/util/nrf_drv_clock.c new file mode 100644 index 000000000..f747e89ea --- /dev/null +++ b/libraries/nfc/src/util/nrf_drv_clock.c @@ -0,0 +1,618 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "util/nordic_common.h" +#include "nrf_drv_clock.h" +#include "app_util_platform.h" +//#if NRF_MODULE_ENABLED(NRF_CLOCK) + +// #ifdef SOFTDEVICE_PRESENT +// #include "nrf_sdh.h" +// #include "nrf_sdh_soc.h" +// #endif + +#include + +#define NRF_LOG_MODULE_NAME clock +#if CLOCK_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR +#else //CLOCK_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL 0 +#endif //CLOCK_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define EVT_TO_STR(event) \ + (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ + (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \ + "UNKNOWN EVENT")))) + + +/*lint -save -e652 */ +#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC +#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal +#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth +/*lint -restore */ + +#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC)// && !defined(SOFTDEVICE_PRESENT) +#define CALIBRATION_SUPPORT 1 +#else +#define CALIBRATION_SUPPORT 0 +#endif +typedef enum +{ + CAL_STATE_IDLE, + CAL_STATE_CT, + CAL_STATE_HFCLK_REQ, + CAL_STATE_CAL, + CAL_STATE_ABORT, +} nrf_drv_clock_cal_state_t; + +/**@brief CLOCK control block. */ +typedef struct +{ + bool module_initialized; /*< Indicate the state of module */ + volatile bool hfclk_on; /*< High-frequency clock state. */ + volatile bool lfclk_on; /*< Low-frequency clock state. */ + volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_hf_head; + volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_lf_head; +#if CALIBRATION_SUPPORT + nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item; + nrf_drv_clock_event_handler_t cal_done_handler; + volatile nrf_drv_clock_cal_state_t cal_state; +#endif // CALIBRATION_SUPPORT +} nrf_drv_clock_cb_t; + +static nrf_drv_clock_cb_t m_clock_cb; + +static void clock_irq_handler(nrfx_clock_evt_type_t evt); + +static void lfclk_stop(void) +{ +#if CALIBRATION_SUPPORT + nrfx_clock_calibration_timer_stop(); +#endif + +// #ifdef SOFTDEVICE_PRESENT +// // If LFCLK is requested to stop while SD is still enabled, +// // it indicates an error in the application. +// // Enabling SD should increment the LFCLK request. +// ASSERT(!nrf_sdh_is_enabled()); +// #endif // SOFTDEVICE_PRESENT + + // LFCLK can be started independently by the watchdog and cannot be stopped + // by the CLOCK peripheral. This code handles this situation and prevents LFCLK to be stopped. + // Otherwise driver can stuck when waiting for the operation to complete. + if (!nrf_wdt_started(NRF_WDT)) + { + nrfx_clock_lfclk_stop(); + m_clock_cb.lfclk_on = false; + } +} + +static void hfclk_start(void) +{ +// #ifdef SOFTDEVICE_PRESENT +// if (nrf_sdh_is_enabled()) +// { +// (void)sd_clock_hfclk_request(); +// return; +// } +// #endif // SOFTDEVICE_PRESENT + + nrfx_clock_hfclk_start(); +} + +static void hfclk_stop(void) +{ +// #ifdef SOFTDEVICE_PRESENT +// if (nrf_sdh_is_enabled()) +// { +// (void)sd_clock_hfclk_release(); +// m_clock_cb.hfclk_on = false; +// return; +// } +// #endif // SOFTDEVICE_PRESENT + + nrfx_clock_hfclk_stop(); + m_clock_cb.hfclk_on = false; +} + +bool nrf_drv_clock_init_check(void) +{ + return m_clock_cb.module_initialized; +} + +ret_code_t nrf_drv_clock_init(void) +{ + ret_code_t err_code = NRF_SUCCESS; + if (m_clock_cb.module_initialized) + { + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + else + { + m_clock_cb.p_hf_head = NULL; + m_clock_cb.hfclk_requests = 0; + m_clock_cb.p_lf_head = NULL; + m_clock_cb.lfclk_requests = 0; + err_code = nrfx_clock_init(clock_irq_handler); +// #ifdef SOFTDEVICE_PRESENT +// if (!nrf_sdh_is_enabled()) +// #endif + { + nrfx_clock_enable(); + } + +#if CALIBRATION_SUPPORT + m_clock_cb.cal_state = CAL_STATE_IDLE; +#endif + + m_clock_cb.module_initialized = true; + } + + if (nrf_wdt_started(NRF_WDT)) + { + m_clock_cb.lfclk_on = true; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_clock_uninit(void) +{ + ASSERT(m_clock_cb.module_initialized); + nrfx_clock_disable(); + nrfx_clock_uninit(); + + m_clock_cb.module_initialized = false; +} + +static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head, + nrf_drv_clock_handler_item_t * p_item) +{ + nrf_drv_clock_handler_item_t * p_next = *p_head; + while (p_next) + { + if (p_next == p_item) + { + return; + } + p_next = p_next->p_next; + } + + p_item->p_next = (*p_head ? *p_head : NULL); + *p_head = p_item; +} + +static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head) +{ + nrf_drv_clock_handler_item_t * p_item = *p_head; + if (p_item) + { + *p_head = p_item->p_next; + } + return p_item; +} + +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.lfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, + p_handler_item); + } + if (m_clock_cb.lfclk_requests == 0) + { + nrfx_clock_lfclk_start(); + } + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.lfclk_requests > 0); +} + +void nrf_drv_clock_lfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.lfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.lfclk_requests); + if (m_clock_cb.lfclk_requests == 0) + { + lfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_lfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +// #ifdef SOFTDEVICE_PRESENT +// if (nrf_sdh_is_enabled()) +// { +// return true; +// } +// #endif // SOFTDEVICE_PRESENT + + return nrfx_clock_lfclk_is_running(); +} + +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.hfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, + p_handler_item); + } + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_start(); + } + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.hfclk_requests > 0); +} + +void nrf_drv_clock_hfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.hfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.hfclk_requests); + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_hfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +// #ifdef SOFTDEVICE_PRESENT +// if (nrf_sdh_is_enabled()) +// { +// uint32_t is_running; +// UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running)); +// return (is_running ? true : false); +// } +// #endif // SOFTDEVICE_PRESENT + + return nrfx_clock_hfclk_is_running(); +} + +#if CALIBRATION_SUPPORT +static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event) +{ + if (m_clock_cb.cal_state == CAL_STATE_ABORT) + { + nrf_drv_clock_hfclk_release(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + } + else + { + ASSERT(event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + if (nrfx_clock_calibration_start() != NRFX_SUCCESS) + { + ASSERT(false); + } + } +} +#endif // CALIBRATION_SUPPORT + +ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE); + if (m_clock_cb.lfclk_on == false) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (m_clock_cb.cal_state == CAL_STATE_IDLE) + { + m_clock_cb.cal_done_handler = handler; + m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started; + if (interval == 0) + { + m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ; + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + else + { + m_clock_cb.cal_state = CAL_STATE_CT; + nrfx_clock_calibration_timer_start(interval); + } + } + else + { + err_code = NRF_ERROR_BUSY; + } + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + UNUSED_PARAMETER(interval); + UNUSED_PARAMETER(handler); + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_calibration_abort(void) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + CRITICAL_REGION_ENTER(); + switch (m_clock_cb.cal_state) + { + case CAL_STATE_CT: + nrfx_clock_calibration_timer_stop(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + break; + case CAL_STATE_HFCLK_REQ: + /* fall through. */ + case CAL_STATE_CAL: + m_clock_cb.cal_state = CAL_STATE_ABORT; + break; + default: + break; + } + CRITICAL_REGION_EXIT(); + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.module_initialized); + *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE); + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + UNUSED_PARAMETER(p_is_calibrating); + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +__STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type) +{ + nrf_drv_clock_handler_item_t **p_head; + if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head; + } + else + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head; + } + + while (1) + { + nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head); + if (!p_item) + { + break; + } + + p_item->event_handler(evt_type); + } +} + +static void clock_irq_handler(nrfx_clock_evt_type_t evt) +{ + if (evt == NRFX_CLOCK_EVT_HFCLK_STARTED) + { + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + if (evt == NRFX_CLOCK_EVT_LFCLK_STARTED) + { + m_clock_cb.lfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } +#if CALIBRATION_SUPPORT + if (evt == NRFX_CLOCK_EVT_CTTO) + { + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + + if (evt == NRFX_CLOCK_EVT_CAL_DONE) + { + nrf_drv_clock_hfclk_release(); + bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(aborted ? + NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE); + } + } +#endif // CALIBRATION_SUPPORT +} + +// #ifdef SOFTDEVICE_PRESENT +// /** +// * @brief SoftDevice SoC event handler. +// * +// * @param[in] evt_id SoC event. +// * @param[in] p_context Context. +// */ +// static void soc_evt_handler(uint32_t evt_id, void * p_context) +// { +// if (evt_id == NRF_EVT_HFCLKSTARTED) +// { +// m_clock_cb.hfclk_on = true; +// clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); +// } +// } +// NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); + +// /** +// * @brief SoftDevice enable/disable state handler. +// * +// * @param[in] state State. +// * @param[in] p_context Context. +// */ +// static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +// { +// switch (state) +// { +// case NRF_SDH_EVT_STATE_ENABLE_PREPARE: +// NVIC_DisableIRQ(POWER_CLOCK_IRQn); +// break; + +// case NRF_SDH_EVT_STATE_ENABLED: +// CRITICAL_REGION_ENTER(); +// /* Make sure that nrf_drv_clock module is initialized */ +// if (!m_clock_cb.module_initialized) +// { +// (void)nrf_drv_clock_init(); +// } +// /* SD is one of the LFCLK requesters, but it will enable it by itself. */ +// ++(m_clock_cb.lfclk_requests); +// m_clock_cb.lfclk_on = true; +// CRITICAL_REGION_EXIT(); +// break; + +// case NRF_SDH_EVT_STATE_DISABLED: +// /* Reinit interrupts */ +// ASSERT(m_clock_cb.module_initialized); +// nrfx_clock_enable(); + +// /* SD leaves LFCLK enabled - disable it if it is no longer required. */ +// nrf_drv_clock_lfclk_release(); +// break; + +// default: +// break; +// } +// } + +// NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) = +// { +// .handler = sd_state_evt_handler, +// .p_context = NULL, +// }; + +// #endif // SOFTDEVICE_PRESENT + +#undef NRF_CLOCK_LFCLK_RC +#undef NRF_CLOCK_LFCLK_Xtal +#undef NRF_CLOCK_LFCLK_Synth + +//#endif // NRF_MODULE_ENABLED(NRF_CLOCK) diff --git a/libraries/nfc/src/util/nrf_drv_clock.h b/libraries/nfc/src/util/nrf_drv_clock.h new file mode 100644 index 000000000..a88a0e42d --- /dev/null +++ b/libraries/nfc/src/util/nrf_drv_clock.h @@ -0,0 +1,298 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_CLOCK_H__ +#define NRF_DRV_CLOCK_H__ + +// #include +#include "nrfx_clock.h" +#include "sdk_errors.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_clock Clock driver - legacy layer + * @{ + * @ingroup nrf_clock + * + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief Clock events. + */ +typedef enum +{ + NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. + NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. + NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done. + NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted. +} nrf_drv_clock_evt_type_t; + +/** + * @brief Clock event handler. + * + * @param[in] event Event. + */ +typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event); + +// Forward declaration of the nrf_drv_clock_handler_item_t type. +typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t; + +struct nrf_drv_clock_handler_item_s +{ + nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started. + nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started. +}; + +/** + * @brief Function for checking if driver is already initialized + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + */ +bool nrf_drv_clock_init_check(void); + +/** + * @brief Function for initializing the nrf_drv_clock module. + * + * After initialization, the module is in power off state (clocks are not requested). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized. + */ +ret_code_t nrf_drv_clock_init(void); + +/** + * @brief Function for uninitializing the clock module. + * + */ +void nrf_drv_clock_uninit(void); + +/** + * @brief Function for requesting the LFCLK. + * + * The low-frequency clock can be requested by different modules + * or contexts. The driver ensures that the clock will be started only when it is requested + * the first time. If the clock is not ready but it was already started, the handler item that is + * provided as an input parameter is added to the list of handlers that will be notified + * when the clock is started. If the clock is already enabled, user callback is called from the + * current context. + * + * The first request will start the selected LFCLK source. If an event handler is + * provided, it will be called once the LFCLK is started. If the LFCLK was already started at this + * time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_lfclk_is_running function can be polled to check if the clock has started. + * + * @note When a SoftDevice is enabled, the LFCLK is always running and the driver cannot control it. + * + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the LFCLK. + * + * If there are no more requests, the LFCLK source will be stopped. + * + * @note When a SoftDevice is enabled, the LFCLK is always running. + */ +void nrf_drv_clock_lfclk_release(void); + +/** + * @brief Function for checking the LFCLK state. + * + * @retval true If the LFCLK is running. + * @retval false If the LFCLK is not running. + */ +bool nrf_drv_clock_lfclk_is_running(void); + +/** + * @brief Function for requesting the high-accuracy source HFCLK. + * + * The high-accuracy source + * can be requested by different modules or contexts. The driver ensures that the high-accuracy + * clock will be started only when it is requested the first time. If the clock is not ready + * but it was already started, the handler item that is provided as an input parameter is added + * to the list of handlers that will be notified when the clock is started. + * + * If an event handler is provided, it will be called once the clock is started. If the clock was already + * started at this time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_hfclk_is_running function can be polled to check if the clock has started. + * + * @note If a SoftDevice is running, the clock is managed by the SoftDevice and all requests are handled by + * the SoftDevice. This function cannot be called from all interrupt priority levels in that case. + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the high-accuracy source HFCLK. + * + * If there are no more requests, the high-accuracy source will be released. + */ +void nrf_drv_clock_hfclk_release(void); + +/** + * @brief Function for checking the HFCLK state. + * + * @retval true If the HFCLK is running (for \nRFXX XTAL source). + * @retval false If the HFCLK is not running. + */ +bool nrf_drv_clock_hfclk_is_running(void); + +/** + * @brief Function for starting a single calibration process. + * + * This function can also delay the start of calibration by a user-specified value. The delay will use + * a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to + * check if calibration is still in progress. If a handler is provided, the user can be notified when + * calibration is completed. The ext calibration can be started from the handler context. + * + * The calibration process consists of three phases: + * - Delay (optional) + * - Requesting the high-accuracy HFCLK + * - Hardware-supported calibration + * + * @param[in] delay Time after which the calibration will be started (in 0.25 s units). + * @param[in] handler NULL or user function to be called when calibration is completed or aborted. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + * @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off. + * @retval NRF_ERROR_BUSY If calibration is in progress. + */ +ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler); + +/** + * @brief Function for aborting calibration. + * + * This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler + * was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once + * aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check + * if the system is calibrating. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_calibration_abort(void); + +/** + * @brief Function for checking if calibration is in progress. + * + * This function indicates that the system is + * in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start). + * + * @param[out] p_is_calibrating True if calibration is in progress, false if not. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating); + +/**@brief Function for returning a requested task address for the clock driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task); + +/**@brief Function for returning a requested event address for the clock driver module. + * + * @param[in] event One of the peripheral events. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event); + + +// #ifdef SOFTDEVICE_PRESENT +// /** +// * @brief Function called by the SoftDevice handler if an @ref NRF_SOC_EVTS event is received from the SoftDevice. +// * +// * @param[in] evt_id One of NRF_SOC_EVTS values. +// */ +// void nrf_drv_clock_on_soc_event(uint32_t evt_id); + +// /** +// * @brief Function called by the SoftDevice handler when the SoftDevice has been enabled. +// * +// * This function is called just after the SoftDevice has been properly enabled. +// * Its main purpose is to mark that LFCLK has been requested by SD. +// */ +// void nrf_drv_clock_on_sd_enable(void); + +// /** +// * @brief Function called by the SoftDevice handler when the SoftDevice has been disabled. +// * +// * This function is called just after the SoftDevice has been properly disabled. +// * It has two purposes: +// * 1. Releases the LFCLK from the SD. +// * 2. Reinitializes an interrupt after the SD releases POWER_CLOCK_IRQ. +// */ +// void nrf_drv_clock_on_sd_disable(void); + +// #endif +/** + *@} + **/ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task) +{ + return nrf_clock_task_address_get(NRF_CLOCK,task); +} + +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event) +{ + return nrf_clock_event_address_get(NRF_CLOCK,event); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_CLOCK_H__ diff --git a/libraries/nfc/src/util/nrf_drv_uart.c b/libraries/nfc/src/util/nrf_drv_uart.c new file mode 100644 index 000000000..5e50454ad --- /dev/null +++ b/libraries/nfc/src/util/nrf_drv_uart.c @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_drv_uart.h" + +#ifdef UARTE_PRESENT +#define INSTANCE_COUNT UARTE_COUNT +#else +#define INSTANCE_COUNT UART_COUNT +#endif + +static nrf_uart_event_handler_t m_handlers[INSTANCE_COUNT]; +static void * m_contexts[INSTANCE_COUNT]; + +#if defined(UARTE_PRESENT) && defined(UART_PRESENT) +uint8_t nrf_drv_uart_use_easy_dma[INSTANCE_COUNT]; +#endif + +#if defined(NRF_DRV_UART_WITH_UARTE) +static void uarte_evt_handler(nrfx_uarte_event_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_uart_event_t event = + { + .type = (nrf_drv_uart_evt_type_t)p_event->type, + .data = + { + .error = + { + .rxtx = + { + .p_data = p_event->data.error.rxtx.p_data, + .bytes = p_event->data.error.rxtx.bytes, + }, + .error_mask = p_event->data.error.error_mask, + } + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // defined(NRF_DRV_UART_WITH_UARTE) + +#if defined(NRF_DRV_UART_WITH_UART) +static void uart_evt_handler(nrfx_uart_event_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_uart_event_t event = + { + .type = (nrf_drv_uart_evt_type_t)p_event->type, + .data = + { + .error = + { + .rxtx = + { + .p_data = p_event->data.error.rxtx.p_data, + .bytes = p_event->data.error.rxtx.bytes, + }, + .error_mask = p_event->data.error.error_mask, + } + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // defined(NRF_DRV_UART_WITH_UART) + +ret_code_t nrf_drv_uart_init(nrf_drv_uart_t const * p_instance, + nrf_drv_uart_config_t const * p_config, + nrf_uart_event_handler_t event_handler) +{ + uint32_t inst_idx = p_instance->inst_idx; + m_handlers[inst_idx] = event_handler; + m_contexts[inst_idx] = p_config->p_context; + +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) +#ifdef NRF52840_XXAA + if (inst_idx == 1) + { + ASSERT(p_config->use_easy_dma); + } +#endif + nrf_drv_uart_use_easy_dma[inst_idx] = p_config->use_easy_dma; +#endif + + nrf_drv_uart_config_t config = *p_config; + config.p_context = (void *)inst_idx; + + ret_code_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_init(&p_instance->uarte, + (nrfx_uarte_config_t const *)&config, + event_handler ? uarte_evt_handler : NULL); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_init(&p_instance->uart, + (nrfx_uart_config_t const *)&config, + event_handler ? uart_evt_handler : NULL); + } + return result; +} diff --git a/libraries/nfc/src/util/nrf_drv_uart.h b/libraries/nfc/src/util/nrf_drv_uart.h new file mode 100644 index 000000000..e8978fdc3 --- /dev/null +++ b/libraries/nfc/src/util/nrf_drv_uart.h @@ -0,0 +1,661 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_UART_H__ +#define NRF_DRV_UART_H__ + +#include +#include "nrf_uarte.h" +#include "sdk_errors.h" +#if defined(UARTE_PRESENT) && NRFX_CHECK(NRFX_UARTE_ENABLED) + #define NRF_DRV_UART_WITH_UARTE +#endif +#if defined(UART_PRESENT) && NRFX_CHECK(NRFX_UART_ENABLED) + #define NRF_DRV_UART_WITH_UART +#endif + +#if defined(NRF_DRV_UART_WITH_UARTE) + #include + #define NRF_DRV_UART_CREATE_UARTE(id) \ + .uarte = NRFX_UARTE_INSTANCE(id), +#else + // Compilers (at least the smart ones) will remove the UARTE related code + // (blocks starting with "if (NRF_DRV_UART_USE_UARTE)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_uarte_init(...) 0 + #define nrfx_uarte_uninit(...) + #define nrfx_uarte_task_address_get(...) 0 + #define nrfx_uarte_event_address_get(...) 0 + #define nrfx_uarte_tx(...) 0 + #define nrfx_uarte_tx_in_progress(...) 0 + #define nrfx_uarte_tx_abort(...) + #define nrfx_uarte_rx(...) 0 + #define nrfx_uarte_rx_ready(...) 0 + #define nrfx_uarte_rx_abort(...) + #define nrfx_uarte_errorsrc_get(...) 0 + #define NRF_DRV_UART_CREATE_UARTE(id) +#endif + +#if defined(NRF_DRV_UART_WITH_UART) + #include + + #define NRF_DRV_UART_CREATE_UART(id) _NRF_DRV_UART_CREATE_UART(id) + #define _NRF_DRV_UART_CREATE_UART(id) NRF_DRV_UART_CREATE_UART_##id + #define NRF_DRV_UART_CREATE_UART_0 \ + .uart = NRFX_UART_INSTANCE(0), + #define NRF_DRV_UART_CREATE_UART_1 \ + .uart = { .p_reg = NULL }, + +#else + // Compilers (at least the smart ones) will remove the UART related code + // (blocks starting with "if (NRF_DRV_UART_USE_UART)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_uart_init(...) 0 + #define nrfx_uart_uninit(...) + #define nrfx_uart_task_address_get(...) 0 + #define nrfx_uart_event_address_get(...) 0 + #define nrfx_uart_tx(...) 0 + #define nrfx_uart_tx_in_progress(...) 0 + #define nrfx_uart_tx_abort(...) + #define nrfx_uart_rx(...) 0 + #define nrfx_uart_rx_enable(...) + #define nrfx_uart_rx_disable(...) + #define nrfx_uart_rx_ready(...) 0 + #define nrfx_uart_rx_abort(...) + #define nrfx_uart_errorsrc_get(...) 0 + #define NRF_DRV_UART_CREATE_UART(id) + + // This part is for old modules that use directly UART HAL definitions + // (to make them compilable for chips that have only UARTE). + #define NRF_UART_BAUDRATE_1200 NRF_UARTE_BAUDRATE_1200 + #define NRF_UART_BAUDRATE_2400 NRF_UARTE_BAUDRATE_2400 + #define NRF_UART_BAUDRATE_4800 NRF_UARTE_BAUDRATE_4800 + #define NRF_UART_BAUDRATE_9600 NRF_UARTE_BAUDRATE_9600 + #define NRF_UART_BAUDRATE_14400 NRF_UARTE_BAUDRATE_14400 + #define NRF_UART_BAUDRATE_19200 NRF_UARTE_BAUDRATE_19200 + #define NRF_UART_BAUDRATE_28800 NRF_UARTE_BAUDRATE_28800 + #define NRF_UART_BAUDRATE_38400 NRF_UARTE_BAUDRATE_38400 + #define NRF_UART_BAUDRATE_57600 NRF_UARTE_BAUDRATE_57600 + #define NRF_UART_BAUDRATE_76800 NRF_UARTE_BAUDRATE_76800 + #define NRF_UART_BAUDRATE_115200 NRF_UARTE_BAUDRATE_115200 + #define NRF_UART_BAUDRATE_230400 NRF_UARTE_BAUDRATE_230400 + #define NRF_UART_BAUDRATE_250000 NRF_UARTE_BAUDRATE_250000 + #define NRF_UART_BAUDRATE_460800 NRF_UARTE_BAUDRATE_460800 + #define NRF_UART_BAUDRATE_921600 NRF_UARTE_BAUDRATE_921600 + #define NRF_UART_BAUDRATE_1000000 NRF_UARTE_BAUDRATE_1000000 + typedef nrf_uarte_baudrate_t nrf_uart_baudrate_t; + #define NRF_UART_ERROR_OVERRUN_MASK NRF_UARTE_ERROR_OVERRUN_MASK + #define NRF_UART_ERROR_PARITY_MASK NRF_UARTE_ERROR_PARITY_MASK + #define NRF_UART_ERROR_FRAMING_MASK NRF_UARTE_ERROR_PARITY_MASK + #define NRF_UART_ERROR_BREAK_MASK NRF_UARTE_ERROR_BREAK_MASK + typedef nrf_uarte_error_mask_t nrf_uart_error_mask_t; + #define NRF_UART_HWFC_DISABLED NRF_UARTE_HWFC_DISABLED + #define NRF_UART_HWFC_ENABLED NRF_UARTE_HWFC_ENABLED + typedef nrf_uarte_hwfc_t nrf_uart_hwfc_t; + #define NRF_UART_PARITY_EXCLUDED NRF_UARTE_PARITY_EXCLUDED + #define NRF_UART_PARITY_INCLUDED NRF_UARTE_PARITY_INCLUDED + typedef nrf_uarte_parity_t nrf_uart_parity_t; + typedef nrf_uarte_task_t nrf_uart_task_t; + typedef nrf_uarte_event_t nrf_uart_event_t; + #define NRF_UART_PSEL_DISCONNECTED NRF_UARTE_PSEL_DISCONNECTED + #define nrf_uart_event_clear(...) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_uart UART driver - legacy layer + * @{ + * @ingroup nrf_uart + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief Structure for the UART driver instance. + */ +typedef struct +{ + uint8_t inst_idx; +#if defined(NRF_DRV_UART_WITH_UARTE) + nrfx_uarte_t uarte; +#endif +#if defined(NRF_DRV_UART_WITH_UART) + nrfx_uart_t uart; +#endif +} nrf_drv_uart_t; + +/** + * @brief Macro for creating an UART driver instance. + */ +#define NRF_DRV_UART_INSTANCE(id) \ +{ \ + .inst_idx = id, \ + NRF_DRV_UART_CREATE_UARTE(id) \ + NRF_DRV_UART_CREATE_UART(id) \ +} + +/** + * @brief Types of UART driver events. + */ +typedef enum +{ + NRF_DRV_UART_EVT_TX_DONE, ///< Requested TX transfer completed. + NRF_DRV_UART_EVT_RX_DONE, ///< Requested RX transfer completed. + NRF_DRV_UART_EVT_ERROR, ///< Error reported by UART peripheral. +} nrf_drv_uart_evt_type_t; + +/**@brief Structure for UART configuration. */ +typedef struct +{ + uint32_t pseltxd; ///< TXD pin number. + uint32_t pselrxd; ///< RXD pin number. + uint32_t pselcts; ///< CTS pin number. + uint32_t pselrts; ///< RTS pin number. + void * p_context; ///< Context passed to interrupt handler. + nrf_uart_hwfc_t hwfc; ///< Flow control configuration. + nrf_uart_parity_t parity; ///< Parity configuration. + nrf_uart_baudrate_t baudrate; ///< Baudrate. + uint8_t interrupt_priority; ///< Interrupt priority. +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) + bool use_easy_dma; +#endif +} nrf_drv_uart_config_t; + +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) +extern uint8_t nrf_drv_uart_use_easy_dma[]; +#define NRF_DRV_UART_DEFAULT_CONFIG_USE_EASY_DMA .use_easy_dma = true, +#else +#define NRF_DRV_UART_DEFAULT_CONFIG_USE_EASY_DMA +#endif + +/**@brief UART default configuration. */ +#define NRF_DRV_UART_DEFAULT_CONFIG \ +{ \ + .pseltxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselrxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselcts = NRF_UART_PSEL_DISCONNECTED, \ + .pselrts = NRF_UART_PSEL_DISCONNECTED, \ + .p_context = NULL, \ + .hwfc = (nrf_uart_hwfc_t)UART_DEFAULT_CONFIG_HWFC, \ + .parity = (nrf_uart_parity_t)UART_DEFAULT_CONFIG_PARITY, \ + .baudrate = (nrf_uart_baudrate_t)UART_DEFAULT_CONFIG_BAUDRATE, \ + .interrupt_priority = UART_DEFAULT_CONFIG_IRQ_PRIORITY, \ + NRF_DRV_UART_DEFAULT_CONFIG_USE_EASY_DMA \ +} + +/**@brief Structure for UART transfer completion event. */ +typedef struct +{ + uint8_t * p_data; ///< Pointer to memory used for transfer. + uint8_t bytes; ///< Number of bytes transfered. +} nrf_drv_uart_xfer_evt_t; + +/**@brief Structure for UART error event. */ +typedef struct +{ + nrf_drv_uart_xfer_evt_t rxtx; ///< Transfer details includes number of bytes transfered. + uint32_t error_mask;///< Mask of error flags that generated the event. +} nrf_drv_uart_error_evt_t; + +/**@brief Structure for UART event. */ +typedef struct +{ + nrf_drv_uart_evt_type_t type; ///< Event type. + union + { + nrf_drv_uart_xfer_evt_t rxtx; ///< Data provided for transfer completion events. + nrf_drv_uart_error_evt_t error;///< Data provided for error event. + } data; +} nrf_drv_uart_event_t; + +/** + * @brief UART interrupt event handler. + * + * @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available + * only within the context of the event handler. + * @param[in] p_context Context passed to interrupt handler, set on initialization. + */ +typedef void (*nrf_uart_event_handler_t)(nrf_drv_uart_event_t * p_event, void * p_context); + +/** + * @brief Function for initializing the UART driver. + * + * This function configures and enables UART. After this function GPIO pins are controlled by UART. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. + * @param[in] event_handler Event handler provided by the user. If not provided driver works in + * blocking mode. + * + * @retval NRFX_SUCCESS If initialization was successful. + * @retval NRFX_ERROR_INVALID_STATE If driver is already initialized. + */ +ret_code_t nrf_drv_uart_init(nrf_drv_uart_t const * p_instance, + nrf_drv_uart_config_t const * p_config, + nrf_uart_event_handler_t event_handler); + +/** + * @brief Function for uninitializing the UART driver. + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_uninit(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for getting the address of a specific UART task. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] task Task. + * + * @return Task address. + */ +__STATIC_INLINE +uint32_t nrf_drv_uart_task_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_task_t task); + +/** + * @brief Function for getting the address of a specific UART event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] event Event. + * + * @return Event address. + */ +__STATIC_INLINE +uint32_t nrf_drv_uart_event_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_event_t event); + +/** + * @brief Function for sending data over UART. + * + * If an event handler was provided in nrf_drv_uart_init() call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, i.e. this function + * returns when the transfer is finished. Blocking mode is not using interrupt so + * there is no context switching inside the function. + * + * @note Peripherals using EasyDMA (i.e. UARTE) require that the transfer buffers + * are placed in the Data RAM region. If they are not and UARTE instance is + * used, this function will fail with error code NRFX_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_data Pointer to data. + * @param[in] length Number of bytes to send. + * + * @retval NRFX_SUCCESS If initialization was successful. + * @retval NRFX_ERROR_BUSY If driver is already transferring. + * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context + * (blocking mode only, also see @ref nrf_drv_uart_rx_disable). + * @retval NRFX_ERROR_INVALID_ADDR If p_data does not point to RAM buffer (UARTE only). + */ +__STATIC_INLINE +ret_code_t nrf_drv_uart_tx(nrf_drv_uart_t const * p_instance, + uint8_t const * const p_data, + uint8_t length); + +/** + * @brief Function for checking if UART is currently transmitting. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If UART is transmitting. + * @retval false If UART is not transmitting. + */ +__STATIC_INLINE +bool nrf_drv_uart_tx_in_progress(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for aborting any ongoing transmission. + * @note @ref NRF_DRV_UART_EVT_TX_DONE event will be generated in non-blocking mode. Event will + * contain number of bytes sent until abort was called. If Easy DMA is not used event will be + * called from the function context. If Easy DMA is used it will be called from UART interrupt + * context. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_tx_abort(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for receiving data over UART. + * + * If an event handler was provided in the nrf_drv_uart_init() call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, i.e. this function + * returns when the transfer is finished. Blocking mode is not using interrupt so + * there is no context switching inside the function. + * The receive buffer pointer is double buffered in non-blocking mode. The secondary + * buffer can be set immediately after starting the transfer and will be filled + * when the primary buffer is full. The double buffering feature allows + * receiving data continuously. + * + * @note Peripherals using EasyDMA (i.e. UARTE) require that the transfer buffers + * are placed in the Data RAM region. If they are not and UARTE driver instance + * is used, this function will fail with error code NRFX_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_data Pointer to data. + * @param[in] length Number of bytes to receive. + * + * @retval NRFX_SUCCESS If initialization was successful. + * @retval NRFX_ERROR_BUSY If the driver is already receiving + * (and the secondary buffer has already been set + * in non-blocking mode). + * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context + * (blocking mode only, also see @ref nrf_drv_uart_rx_disable). + * @retval NRFX_ERROR_INTERNAL If UART peripheral reported an error. + * @retval NRFX_ERROR_INVALID_ADDR If p_data does not point to RAM buffer (UARTE only). + */ +__STATIC_INLINE +ret_code_t nrf_drv_uart_rx(nrf_drv_uart_t const * p_instance, + uint8_t * p_data, + uint8_t length); + + + +/** + * @brief Function for testing the receiver state in blocking mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If the receiver has at least one byte of data to get. + * @retval false If the receiver is empty. + */ +__STATIC_INLINE +bool nrf_drv_uart_rx_ready(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for enabling the receiver. + * + * UART has a 6-byte-long RX FIFO and it is used to store incoming data. If a user does not call the + * UART receive function before the FIFO is filled, an overrun error will appear. Enabling the receiver + * without specifying an RX buffer is supported only in UART mode (without Easy DMA). The receiver must be + * explicitly closed by the user @sa nrf_drv_uart_rx_disable. This function asserts if the mode is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_rx_enable(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for disabling the receiver. + * + * This function must be called to close the receiver after it has been explicitly enabled by + * @sa nrf_drv_uart_rx_enable. The feature is supported only in UART mode (without Easy DMA). The function + * asserts if mode is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_rx_disable(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for aborting any ongoing reception. + * @note @ref NRF_DRV_UART_EVT_RX_DONE event will be generated in non-blocking mode. The event will + * contain the number of bytes received until abort was called. The event is called from UART interrupt + * context. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_rx_abort(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for reading error source mask. Mask contains values from @ref nrf_uart_error_mask_t. + * @note Function should be used in blocking mode only. In case of non-blocking mode, an error event is + * generated. Function clears error sources after reading. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval Mask of reported errors. + */ +__STATIC_INLINE +uint32_t nrf_drv_uart_errorsrc_get(nrf_drv_uart_t const * p_instance); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) + #define NRF_DRV_UART_USE_UARTE (nrf_drv_uart_use_easy_dma[p_instance->inst_idx]) +#elif defined(NRF_DRV_UART_WITH_UARTE) + #define NRF_DRV_UART_USE_UARTE true +#else + #define NRF_DRV_UART_USE_UARTE false +#endif +#define NRF_DRV_UART_USE_UART (!NRF_DRV_UART_USE_UARTE) + +__STATIC_INLINE +void nrf_drv_uart_uninit(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + nrfx_uarte_uninit(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_uninit(&p_instance->uart); + } +} + +__STATIC_INLINE +uint32_t nrf_drv_uart_task_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_task_t task) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_task_address_get(&p_instance->uarte, + (nrf_uarte_task_t)task); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_task_address_get(&p_instance->uart, task); + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_uart_event_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_event_t event) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_event_address_get(&p_instance->uarte, + (nrf_uarte_event_t)event); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_event_address_get(&p_instance->uart, event); + } + return result; +} + +__STATIC_INLINE +ret_code_t nrf_drv_uart_tx(nrf_drv_uart_t const * p_instance, + uint8_t const * p_data, + uint8_t length) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_tx(&p_instance->uarte, + p_data, + length); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_tx(&p_instance->uart, + p_data, + length); + } + return result; +} + +__STATIC_INLINE +bool nrf_drv_uart_tx_in_progress(nrf_drv_uart_t const * p_instance) +{ + bool result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_tx_in_progress(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_tx_in_progress(&p_instance->uart); + } + return result; +} + +__STATIC_INLINE +void nrf_drv_uart_tx_abort(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + nrfx_uarte_tx_abort(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_tx_abort(&p_instance->uart); + } +} + +__STATIC_INLINE +ret_code_t nrf_drv_uart_rx(nrf_drv_uart_t const * p_instance, + uint8_t * p_data, + uint8_t length) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_rx(&p_instance->uarte, + p_data, + length); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_rx(&p_instance->uart, + p_data, + length); + } + return result; +} + +__STATIC_INLINE +bool nrf_drv_uart_rx_ready(nrf_drv_uart_t const * p_instance) +{ + bool result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_rx_ready(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_rx_ready(&p_instance->uart); + } + return result; +} + +__STATIC_INLINE +void nrf_drv_uart_rx_enable(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + NRFX_ASSERT(false); // not supported + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_rx_enable(&p_instance->uart); + } +} + +__STATIC_INLINE +void nrf_drv_uart_rx_disable(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + NRFX_ASSERT(false); // not supported + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_rx_disable(&p_instance->uart); + } +} + +__STATIC_INLINE +void nrf_drv_uart_rx_abort(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + nrfx_uarte_rx_abort(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_rx_abort(&p_instance->uart); + } +} + +__STATIC_INLINE +uint32_t nrf_drv_uart_errorsrc_get(nrf_drv_uart_t const * p_instance) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_errorsrc_get(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrf_uart_event_clear(p_instance->uart.p_reg, NRF_UART_EVENT_ERROR); + result = nrfx_uart_errorsrc_get(&p_instance->uart); + } + return result; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_UART_H__ diff --git a/libraries/nfc/src/util/nrf_fprintf.c b/libraries/nfc/src/util/nrf_fprintf.c new file mode 100644 index 000000000..0aeddf276 --- /dev/null +++ b/libraries/nfc/src/util/nrf_fprintf.c @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_FPRINTF) +#include + +#include "nrf_assert.h" +#include "nrf_fprintf_format.h" + +void nrf_fprintf_buffer_flush(nrf_fprintf_ctx_t * const p_ctx) +{ + ASSERT(p_ctx != NULL); + + if (p_ctx->io_buffer_cnt == 0) + { + return; + } + + p_ctx->fwrite(p_ctx->p_user_ctx, + p_ctx->p_io_buffer, + p_ctx->io_buffer_cnt); + p_ctx->io_buffer_cnt = 0; +} + +void nrf_fprintf(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + ...) +{ + ASSERT(p_ctx != NULL); + ASSERT(p_ctx->fwrite != NULL); + ASSERT(p_ctx->p_io_buffer != NULL); + ASSERT(p_ctx->io_buffer_size > 0); + + if (p_fmt == NULL) + { + return; + } + + va_list args = {0}; + va_start(args, p_fmt); + + nrf_fprintf_fmt(p_ctx, p_fmt, &args); + + va_end(args); +} + +#endif // NRF_MODULE_ENABLED(NRF_FPRINTF) + diff --git a/libraries/nfc/src/util/nrf_fprintf.h b/libraries/nfc/src/util/nrf_fprintf.h new file mode 100644 index 000000000..b585d339a --- /dev/null +++ b/libraries/nfc/src/util/nrf_fprintf.h @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_FPRINTF_H__ +#define NRF_FPRINTF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (* nrf_fprintf_fwrite)(void const * p_user_ctx, char const * p_str, size_t length); + +/** + * @brief fprintf context + */ +typedef struct nrf_fprintf_ctx +{ + char * const p_io_buffer; ///< Pointer to IO buffer. + size_t const io_buffer_size; ///< IO buffer size. + size_t io_buffer_cnt; ///< IO buffer usage. + bool auto_flush; ///< Auto flush configurator. + + void const * const p_user_ctx; ///< Pointer to user data to be passed to the fwrite funciton. + + nrf_fprintf_fwrite fwrite; ///< Pointer to function sending data stream. +} nrf_fprintf_ctx_t; + + +/** + * @brief Macro for defining nrf_fprintf instance. + * + * @param name Instance name. + * @param _p_user_ctx Pointer to user data. + * @param _p_io_buffer Pointer to IO buffer + * @param _io_buffer_size Size of IO buffer. + * @param _auto_flush Indicator if IO buffer shall be automatically flush. + * @param _fwrite Pointer to function sending data stream. + * */ +#define NRF_FPRINTF_DEF(name, _p_user_ctx, _p_io_buffer, _io_buffer_size, _auto_flush, _fwrite) \ + static nrf_fprintf_ctx_t name = \ + { \ + .p_io_buffer = _p_io_buffer, \ + .io_buffer_size = _io_buffer_size, \ + .io_buffer_cnt = 0, \ + .auto_flush = _auto_flush, \ + .p_user_ctx = _p_user_ctx, \ + .fwrite = _fwrite \ + } + +/** + * @brief fprintf like function which send formated data stream to output specified by user + * @ref nrf_fprintf_ctx_t + * + * @param p_ctx fprintf context. + * @param p_fmt Format string. + * @param ... List of parameters to print. + * */ +void nrf_fprintf(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + ...); + +/** + * @brief function flushing data stored in io_buffer @ref nrf_fprintf_ctx_t + * + * @param p_ctx fprintf context + */ +void nrf_fprintf_buffer_flush(nrf_fprintf_ctx_t * const p_ctx); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FPRINTF_H__ */ + diff --git a/libraries/nfc/src/util/nrf_fprintf_format.c b/libraries/nfc/src/util/nrf_fprintf_format.c new file mode 100644 index 000000000..05b4e7878 --- /dev/null +++ b/libraries/nfc/src/util/nrf_fprintf_format.c @@ -0,0 +1,810 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o 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. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +* * +* RTT version: 6.14d * +* * +*********************************************************************/ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_FPRINTF) + +#include + +#include "nrf_assert.h" +#include "nrf_fprintf.h" +#include "nrf_fprintf_format.h" + +#define NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define NRF_CLI_FORMAT_FLAG_PAD_ZERO (1u << 1) +#define NRF_CLI_FORMAT_FLAG_PRINT_SIGN (1u << 2) + +#define NRF_CLI_FORMAT_DOUBLE_DEF_PRECISION 6 + +#define NRF_CLI_FORMAT_DOUBLE_SIGN_POSITION 63U +#define NRF_CLI_FORMAT_DOUBLE_SIGN_MASK 1ULL +#define NRF_CLI_FORMAT_DOUBLE_SIGN (NRF_CLI_FORMAT_DOUBLE_SIGN_MASK << NRF_CLI_FORMAT_DOUBLE_SIGN_POSITION) +#define NRF_CLI_FORMAT_DOUBLE_EXP_POSITION 52U +#define NRF_CLI_FORMAT_DOUBLE_EXP_MASK 0x7FFULL +#define NRF_CLI_FORMAT_DOUBLE_EXP (NRF_CLI_FORMAT_DOUBLE_EXP_MASK << NRF_CLI_FORMAT_DOUBLE_EXP_POSITION) +#define NRF_CLI_FORMAT_DOUBLE_MANT_POSITION 0U +#define NRF_CLI_FORMAT_DOUBLE_MANT_MASK 0xFFFFFFFFFFFFF +#define NRF_CLI_FORMAT_DOUBLE_MANT (NRF_CLI_FORMAT_DOUBLE_MANT_MASK << NRF_CLI_FORMAT_DOUBLE_MANT_POSITION) + +#define NRF_CLI_FORMAT_DOUBLE_SIGN_GET(v) (!!((v) & NRF_CLI_FORMAT_DOUBLE_SIGN)) +#define NRF_CLI_FORMAT_DOUBLE_EXP_GET(v) (((v) & NRF_CLI_FORMAT_DOUBLE_EXP) >> NRF_CLI_FORMAT_DOUBLE_EXP_POSITION) +#define NRF_CLI_FORMAT_DOUBLE_MANT_GET(v) (((v) & NRF_CLI_FORMAT_DOUBLE_MANT) >> NRF_CLI_FORMAT_DOUBLE_MANT_POSITION) +#define NRF_CLI_FORMAT_REQ_SIGN_SPACE(s, f) ((s) | (!!((f) & NRF_CLI_FORMAT_FLAG_PRINT_SIGN))) + +#define HIGH_32(v) ((v) >> 32) +#define LOW_32(v) (((1ULL << 32) - 1) & v) + + +static void buffer_add(nrf_fprintf_ctx_t * const p_ctx, char c) +{ +#if NRF_MODULE_ENABLED(NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF) + if (c == '\n') + { + buffer_add(p_ctx, '\r'); + } +#endif + p_ctx->p_io_buffer[p_ctx->io_buffer_cnt++] = c; + + if (p_ctx->io_buffer_cnt >= p_ctx->io_buffer_size) + { + nrf_fprintf_buffer_flush(p_ctx); + } +} + +static void string_print(nrf_fprintf_ctx_t * const p_ctx, + char const * p_str, + uint32_t FieldWidth, + uint32_t FormatFlags) +{ + uint32_t Width = 0; + char c; + + if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) + { + while ((c = *p_str) != '\0') + { + p_str++; + Width++; + buffer_add(p_ctx, c); + } + + while ((FieldWidth > Width) && (FieldWidth > 0)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + } + else + { + if (p_str != 0) + { + Width = strlen(p_str); + } + + while ((FieldWidth > Width) && (FieldWidth > 0)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + + while ((c = *p_str) != '\0') + { + p_str++; + Width++; + buffer_add(p_ctx, c); + } + } +} + +static void unsigned_print(nrf_fprintf_ctx_t * const p_ctx, + uint32_t v, + uint32_t Base, + uint32_t NumDigits, + uint32_t FieldWidth, + uint32_t FormatFlags) +{ + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' }; + uint32_t Div; + uint32_t Value; + uint32_t Width; + char c; + + Value = v; + // + // Get actual field width + // + Width = 1u; + while (Value >= Base) + { + Value = (Value / Base); + Width++; + } + if (NumDigits > Width) + { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u) + { + if (FieldWidth != 0u) + { + if (((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == NRF_CLI_FORMAT_FLAG_PAD_ZERO) && + (NumDigits == 0u)) + { + c = '0'; + } + else + { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, c); + } + } + } + + Value = 1; + /* + * Compute Digit. + * Loop until Digit has the value of the highest digit required. + * Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + */ + while (1) + { + /* User specified a min number of digits to print? => Make sure we loop at least that + * often, before checking anything else (> 1 check avoids problems with NumDigits + * being signed / unsigned) + */ + if (NumDigits > 1u) + { + NumDigits--; + } + else + { + Div = v / Value; + // Is our divider big enough to extract the highest digit from value? => Done + if (Div < Base) + { + break; + } + } + Value *= Base; + } + // + // Output digits + // + do + { + Div = v / Value; + v -= Div * Value; + buffer_add(p_ctx, _aV2C[Div]); + Value /= Base; + } while (Value); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) + { + if (FieldWidth != 0u) + { + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + } + } +} + +static void int_print(nrf_fprintf_ctx_t * const p_ctx, + int32_t v, + uint32_t Base, + uint32_t NumDigits, + uint32_t FieldWidth, + uint32_t FormatFlags) +{ + uint32_t Width; + int32_t Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int32_t)Base) + { + Number = (Number / (int32_t)Base); + Width++; + } + if (NumDigits > Width) + { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || + ((FormatFlags & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) == NRF_CLI_FORMAT_FLAG_PRINT_SIGN))) + { + FieldWidth--; + } + // + // Print leading spaces if necessary + // + if ((((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && + ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) + { + if (FieldWidth != 0u) + { + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + } + } + // + // Print sign if necessary + // + if (v < 0) + { + v = -v; + buffer_add(p_ctx, '-'); + } + else if ((FormatFlags & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) == NRF_CLI_FORMAT_FLAG_PRINT_SIGN) + { + buffer_add(p_ctx, '+'); + } + else + { + /* do nothing */ + } + // + // Print leading zeros if necessary + // + if (((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == NRF_CLI_FORMAT_FLAG_PAD_ZERO) && + ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) + { + if (FieldWidth != 0u) + { + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, '0'); + } + } + } + // + // Print number without sign + // + unsigned_print(p_ctx, (uint32_t)v, Base, NumDigits, FieldWidth, FormatFlags); +} + +#if NRF_MODULE_ENABLED(NRF_FPRINTF_DOUBLE) + +static void fill_space(nrf_fprintf_ctx_t * const p_ctx, + uint8_t len, + bool zeros) +{ + for (; len > 0; len--) + { + if (zeros) + { + buffer_add(p_ctx, '0'); + } + else + { + buffer_add(p_ctx, ' '); + } + } +} + +static void float_print(nrf_fprintf_ctx_t * const p_ctx, + double v, + uint32_t digits, + uint32_t width, + uint32_t format, + bool uppercase) +{ + bool sign, transform = false; + uint64_t num, mant, lead, low, base, res, carry, x, s0, s1, s2, s3, fr; + int32_t exp; + uint8_t highest, offset, lead_len = 0, skipped = 0; + uint8_t precision = digits ? digits + 1 : NRF_CLI_FORMAT_DOUBLE_DEF_PRECISION + 1; + /* Default digits should be -1, because 0 could be a requirement, not the default. + * This should be changed for the whole library. + */ + + if ((v > 0.0) && (v < 1.0)) + { + v += 1.0; + transform = true; + } + else if ((v > -1.0) && (v < 0.0)) + { + v -= 1.0; + transform = true; + } + + memcpy(&num, &v, sizeof(num)); + sign = NRF_CLI_FORMAT_DOUBLE_SIGN_GET(num); + exp = NRF_CLI_FORMAT_DOUBLE_EXP_GET(num); + mant = NRF_CLI_FORMAT_DOUBLE_MANT_GET(num); + + /* Special cases */ + if (exp == NRF_CLI_FORMAT_DOUBLE_EXP_MASK) + { + if (width && (!(format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY))) + { + fill_space(p_ctx, width - 3 - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format), false); + } + + if (sign) + { + buffer_add(p_ctx, '-'); + } + else if (format & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) + { + buffer_add(p_ctx, '+'); + } + + if (mant != 0) + { + if(uppercase) + { + buffer_add(p_ctx, 'N'); + buffer_add(p_ctx, 'A'); + buffer_add(p_ctx, 'N'); + } + else + { + buffer_add(p_ctx, 'n'); + buffer_add(p_ctx, 'a'); + buffer_add(p_ctx, 'n'); + } + } + else + { + if(uppercase) + { + buffer_add(p_ctx, 'I'); + buffer_add(p_ctx, 'N'); + buffer_add(p_ctx, 'F'); + } + else + { + buffer_add(p_ctx, 'i'); + buffer_add(p_ctx, 'n'); + buffer_add(p_ctx, 'f'); + } + } + return; + } + + /* Add leading 1 to mantissa (except 0.0) */ + if ((mant != 0) || (exp != 0)) + { + mant |= (1ULL << 52); + } + + /* Convert the exponent */ + exp = exp - 1023; + + /* Whole numbers */ + offset = 52 - exp; + + if (offset > 64) + { + /* Float fraction offset overflow */ + return; + } + + lead = (mant >> (offset)); + + /* Fraction */ + low = mant & (~(lead << offset)); + + while (((low & 0x1) == 0) && low > 0) + { + low = low >> 1U; + skipped++; + } + + highest = (offset - skipped); + base = 1; + + for(uint8_t i = 0; i < precision; i++) + { + base *= 10; + } + + /* Handle multiplication with possible overflow */ + x = LOW_32(low) * LOW_32(base); + s0 = LOW_32(x); + + x = HIGH_32(low) * LOW_32(base) + HIGH_32(x); + s1 = LOW_32(x); + s2 = HIGH_32(x); + + x = s1 + LOW_32(low) * HIGH_32(base); + s1 = LOW_32(x); + + x = s2 + HIGH_32(low) * HIGH_32(base) + HIGH_32(x); + s2 = LOW_32(x); + s3 = HIGH_32(x); + + res = s1 << 32 | s0; + carry = s3 << 32 | s2; + + /* Divide and combine */ + carry = carry << (64 - highest); + res = res >> highest; + fr = res | carry; + + /* Roundup */ + if (fr%10 >= 5) + { + fr /= 10; + fr++; + } + else + { + fr /= 10; + } + precision--; + + if (transform && (lead == 1)) + { + lead = 0; + } + + /* Maximum precision handled by int_print() is 10 */ + if (precision > 10) + { + for (uint8_t delta = precision - 10; delta > 0; delta--) + { + fr /= 10; + } + precision = 10; + } + + res = lead; + while (res > 0) + { + res /= 10; + lead_len++; + } + + if ((lead == 0) && (fr == 0)) + { + lead_len = 1; + } + + if(lead_len == 0) + { + lead_len = 1; + } + + if (width && (!(format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY))) + { + int32_t space = width - lead_len - precision - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format) - 1; + if (space > 0) + { + fill_space(p_ctx, space, format & NRF_CLI_FORMAT_FLAG_PAD_ZERO); + } + } + + if (sign) + { + buffer_add(p_ctx, '-'); + } + else if (format & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) + { + buffer_add(p_ctx, '+'); + } + + int_print(p_ctx, + lead, + 10u, + 0, + 0, + 0); + buffer_add(p_ctx, '.'); + int_print(p_ctx, + fr, + 10u, + precision, + 0, + 0); + + if (width && (format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY)) + { + int32_t space = width - lead_len - precision - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format) - 1; + if (space > 0) + { + fill_space(p_ctx, space, false); + } + } +} + +#endif + +void nrf_fprintf_fmt(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + va_list * p_args) +{ + ASSERT(p_ctx != NULL); + + ASSERT(p_ctx->fwrite != NULL); + ASSERT(p_ctx->p_io_buffer != NULL); + ASSERT(p_ctx->io_buffer_size > 0); + + if (p_fmt == NULL) + { + return; + } + + char c; + int32_t v; + uint32_t NumDigits; + uint32_t FormatFlags; + uint32_t FieldWidth; + + do + { + c = *p_fmt; + p_fmt++; + + if (c == 0u) + { + break; + } + if (c == '%') + { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + + do + { + c = *p_fmt; + switch (c) + { + case '-': + FormatFlags |= NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY; + p_fmt++; + break; + case '0': + FormatFlags |= NRF_CLI_FORMAT_FLAG_PAD_ZERO; + p_fmt++; + break; + case '+': + FormatFlags |= NRF_CLI_FORMAT_FLAG_PRINT_SIGN; + p_fmt++; + break; + default: + v = 0; + break; + } + } while (v); + + // + // filter out field width + // + FieldWidth = 0u; + do + { + if (c == '*') + { + /*lint -save -e64 -e56*/ + FieldWidth += va_arg(*p_args, unsigned); + /*lint -restore*/ + p_fmt++; + break; + } + c = *p_fmt; + if ((c < '0') || (c > '9')) + { + break; + } + p_fmt++; + FieldWidth = (FieldWidth * 10u) + (c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *p_fmt; + if (c == '.') + { + p_fmt++; + do + { + c = *p_fmt; + if ((c < '0') || (c > '9')) + { + break; + } + p_fmt++; + NumDigits = NumDigits * 10u + (c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *p_fmt; + do + { + if ((c == 'l') || (c == 'h')) + { + p_fmt++; + c = *p_fmt; + } + else + { + break; + } + } while (1); + // + // Handle specifiers + // + /*lint -save -e64*/ + switch (c) + { + case 'c': + { + char c0; + v = va_arg(*p_args, int32_t); + c0 = (char)v; + buffer_add(p_ctx, c0); + break; + } + case 'd': + case 'i': + v = va_arg(*p_args, int32_t); + int_print(p_ctx, + v, + 10u, + NumDigits, + FieldWidth, + FormatFlags); + break; + case 'u': + v = va_arg(*p_args, int32_t); + unsigned_print(p_ctx, + (uint32_t)v, + 10u, + NumDigits, + FieldWidth, + FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*p_args, int32_t); + unsigned_print(p_ctx, + (uint32_t)v, + 16u, + NumDigits, + FieldWidth, + FormatFlags); + break; + case 's': + { + char const * p_s = va_arg(*p_args, const char *); + string_print(p_ctx, p_s, FieldWidth, FormatFlags); + break; + } + case 'p': + v = va_arg(*p_args, int32_t); + buffer_add(p_ctx, '0'); + buffer_add(p_ctx, 'x'); + unsigned_print(p_ctx, (uint32_t)v, 16u, 8u, 8u, 0); + break; + case '%': + buffer_add(p_ctx, '%'); + break; +#if NRF_MODULE_ENABLED(NRF_FPRINTF_DOUBLE) + case 'f': + { + double dbl = va_arg(*p_args, double); + float_print(p_ctx, + dbl, + NumDigits, + FieldWidth, + FormatFlags, + false); + break; + } + case 'F': + { + double dbl = va_arg(*p_args, double); + float_print(p_ctx, + dbl, + NumDigits, + FieldWidth, + FormatFlags, + true); + break; + } +#endif + default: + break; + } + /*lint -restore*/ + p_fmt++; + } + else + { + buffer_add(p_ctx, c); + } + } while (*p_fmt != '\0'); + + if (p_ctx->auto_flush) + { + nrf_fprintf_buffer_flush(p_ctx); + } +} + +#endif // NRF_MODULE_ENABLED(NRF_FPRINTF) + diff --git a/libraries/nfc/src/util/nrf_fprintf_format.h b/libraries/nfc/src/util/nrf_fprintf_format.h new file mode 100644 index 000000000..920e68598 --- /dev/null +++ b/libraries/nfc/src/util/nrf_fprintf_format.h @@ -0,0 +1,86 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o 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. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +* * +* RTT version: 6.14d * +* * +*********************************************************************/ + +#ifndef NRF_FPRINTF_FORMAT_H__ +#define NRF_FPRINTF_FORMAT_H__ + +#include +#include "nrf_fprintf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Printf like function which sends formated data stream to output. + * + * @param nrf_fprintf_ctx_t Print context. + * @param p_fmt Format string. + * @param p_args List of parameters to print. + * */ +void nrf_fprintf_fmt(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + va_list * p_args); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FPRINTF_FORMAT_H__ */ + diff --git a/libraries/nfc/src/util/nrf_log.h b/libraries/nfc/src/util/nrf_log.h new file mode 100644 index 000000000..cafcd60b1 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log.h @@ -0,0 +1,296 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nrf_log Logger module + * @{ + * @ingroup app_common + * + * @brief The nrf_log module interface. + */ + +#ifndef NRF_LOG_H_ +#define NRF_LOG_H_ + +#include "sdk_common.h" +#include "nrf_section.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_strerror.h" +#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code) +#else +#define NRF_LOG_ERROR_STRING_GET(code) "" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Severity level for the module. + * + * The severity level can be defined in a module to override the default. + */ +#ifndef NRF_LOG_LEVEL + #define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL +#endif + +/** @brief Initial severity if filtering is enabled. + */ +#ifndef NRF_LOG_INITIAL_LEVEL + #define NRF_LOG_INITIAL_LEVEL NRF_LOG_LEVEL +#endif + + +#include "nrf_log_internal.h" + +/** @def NRF_LOG_ERROR + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_WARNING + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + */ + +/** @def NRF_LOG_INFO + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + */ + +/** @def NRF_LOG_DEBUG + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + */ + +#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__) +#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +/** @def NRF_LOG_INST_ERROR + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_WARNING + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_INFO + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_DEBUG + * @brief Macro for logging error messages for given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ +#define NRF_LOG_INST_ERROR(p_inst,...) NRF_LOG_INTERNAL_INST_ERROR(p_inst,__VA_ARGS__) +#define NRF_LOG_INST_WARNING(p_inst,...) NRF_LOG_INTERNAL_INST_WARNING(p_inst,__VA_ARGS__) +#define NRF_LOG_INST_INFO(p_inst,...) NRF_LOG_INTERNAL_INST_INFO(p_inst, __VA_ARGS__) +#define NRF_LOG_INST_DEBUG(p_inst,...) NRF_LOG_INTERNAL_INST_DEBUG(p_inst, __VA_ARGS__) + +/** + * @brief Macro for logging a formatted string without any prefix or timestamp. + */ +#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__) + +/** @def NRF_LOG_HEXDUMP_ERROR + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_WARNING + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INFO + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_DEBUG + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) +#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) +#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) +#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) + +/** @def NRF_LOG_HEXDUMP_INST_ERROR + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_WARNING + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_INFO + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_DEBUG + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_INST_ERROR(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_WARNING(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_INFO(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_DEBUG(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) + +/** + * @brief Macro for logging hexdump without any prefix or timestamp. + */ +#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) + + +/** + * @brief Macro for copying a string to internal logger buffer if logs are deferred. + * + * @param _str String. + */ +#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str) + +/** + * @brief Function for copying a string to the internal logger buffer if logs are deferred. + * + * Use this function to store a string that is volatile (for example allocated + * on stack) or that may change before the deferred logs are processed. Such string is copied + * into the internal logger buffer (see @ref NRF_LOG_STR_PUSH_BUFFER_SIZE). + * + * @note String storing is not reliable. It means that string is copied to the buffer but there is + * no indication when it was used and could be freed. String may be overwritten by another + * @ref nrf_log_push call before being processed. For reliable data dumping use + * hexdump macros (e.g. @ref NRF_LOG_HEXDUMP_INFO). + * + * @note If the logs are not deferred, then this function returns the input parameter. + * + * @param p_str Pointer to the user string. + * + * @return Address to the location where the string is stored in the internal logger buffer. + */ +char const * nrf_log_push(char * const p_str); + +/** + * @brief Macro to be used in a formatted string to a pass float number to the log. + * + * Use this macro in a formatted string instead of the %f specifier together with + * @ref NRF_LOG_FLOAT macro. + * Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f))) + */ +#define NRF_LOG_FLOAT_MARKER "%s%d.%02d" + +/** + * @brief Macro for dissecting a float number into two numbers (integer and residuum). + */ +#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \ + (int32_t)(val), \ + (int32_t)((((val) > 0) ? (val) - (int32_t)(val) \ + : (int32_t)(val) - (val))*100) + + +/** + * @brief Macro for registering an independent module. + * + * Registration creates set of dynamic (RAM) and constant variables associated with the module. + */ +#define NRF_LOG_MODULE_REGISTER() NRF_LOG_INTERNAL_MODULE_REGISTER() + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_H_ + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_backend_flash.c b/libraries/nfc/src/util/nrf_log_backend_flash.c new file mode 100644 index 000000000..1f5424763 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_flash.c @@ -0,0 +1,740 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH) +#include "nrf_log_backend_flash.h" +#include "nrf_log_str_formatter.h" +#include "nrf_fstorage_nvmc.h" +#include "nrf_log.h" +#include "nrf_atomic.h" +#include "nrf_queue.h" +#include "app_error.h" +#include + +#if (NRF_LOG_BACKEND_FLASHLOG_ENABLED == 0) && (NRF_LOG_BACKEND_CRASHLOG_ENABLED == 0) +#error "No flash backend enabled." +#endif + +/** @brief Maximum logger message payload (arguments or data in hexdump) which can be stored. */ +#define FLASH_LOG_MAX_PAYLOAD_SIZE (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE - sizeof(nrf_log_header_t)) + +/** @brief Size of serialization buffer in words. */ +#define FLASH_LOG_SER_BUFFER_WORDS (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE/sizeof(uint32_t)) + +/** @brief Length of logger header. */ +#define LOG_HEADER_LEN (sizeof(nrf_log_header_t)) + +/** @brief Length of logger header given in 32 bit words. */ +#define LOG_HEADER_LEN_WORDS (LOG_HEADER_LEN/sizeof(uint32_t)) + +/** @brief Maximum possible length of standard log message. */ +#define STD_LOG_MSG_MAX_LEN (LOG_HEADER_LEN + NRF_LOG_MAX_NUM_OF_ARGS*sizeof(uint32_t)) + +/* Buffer must be multiple of 4. */ +STATIC_ASSERT((NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE % sizeof(uint32_t)) == 0); + +/* Buffer must fit standard log message. */ +STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE >= STD_LOG_MSG_MAX_LEN); + +/** @brief Flash page size in bytes. */ +#define CODE_PAGE_SIZE 4096 + +/** @brief Start address of the area dedicated for flash log. */ +#define FLASH_LOG_START_ADDR (NRF_LOG_BACKEND_FLASH_START_PAGE * CODE_PAGE_SIZE) + +/** @brief End address of the area dedicated for flash log. */ +#define FLASH_LOG_END_ADDR (FLASH_LOG_START_ADDR + (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE) - 1) + +/** @brief Size of the area dedicated for flash log. */ +#define FLASH_LOG_SIZE (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE) + +/** @brief Start address determined in runtime. + * + * If configuration indicates that flash log should be placed after application. + * */ +#if defined ( __CC_ARM ) +#define RUNTIME_START_ADDR \ + _Pragma("diag_suppress 170") \ + ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \ + (CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR) \ + _Pragma("diag_default 170") +#else +#define RUNTIME_START_ADDR ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \ + (CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR) +#endif +static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt); + +/** @brief Message queue for run time flash log. */ +#if NRF_LOG_BACKEND_FLASHLOG_ENABLED +NRF_QUEUE_DEF(nrf_log_entry_t *, + m_flashlog_queue, + NRF_LOG_BACKEND_FLASHLOG_QUEUE_SIZE, + NRF_QUEUE_MODE_NO_OVERFLOW); +static const nrf_queue_t * mp_flashlog_queue = &m_flashlog_queue; +#else +static const nrf_queue_t * mp_flashlog_queue = NULL; +#endif + + +/** @brief Message FIFO for crash log. */ +#if NRF_LOG_BACKEND_CRASHLOG_ENABLED +NRF_QUEUE_DEF(nrf_log_entry_t *, + m_crashlog_queue, + NRF_LOG_BACKEND_CRASHLOG_FIFO_SIZE, + NRF_QUEUE_MODE_NO_OVERFLOW); +static const nrf_queue_t * mp_crashlog_queue = &m_crashlog_queue; +#else +static const nrf_queue_t * mp_crashlog_queue = NULL; +#endif + + +/** @brief Fstorage instance used for flash log. */ +NRF_FSTORAGE_DEF(nrf_fstorage_t m_log_flash_fstorage) = +{ + /* Set a handler for fstorage events. */ + .evt_handler = fstorage_evt_handler, + .start_addr = FLASH_LOG_START_ADDR, + .end_addr = FLASH_LOG_END_ADDR, +}; + +/** @brief Flash log state. */ +typedef enum +{ + LOG_BACKEND_FLASH_ACTIVE, /**< Flash backend is active. */ + LOG_BACKEND_FLASH_INACTIVE, /**< Flash backend is inactive. All incoming requests are skipped. */ + LOG_BACKEND_FLASH_IN_PANIC, /**< Flash backend is in panic mode. Incoming messages are written to flash in synchronous mode. */ +} log_backend_flash_state_t; + +static log_backend_flash_state_t m_state; /**< Flash logger backend state. */ +static nrf_atomic_flag_t m_busy_flag; /**< Flag indicating if module performs flash writing. */ +static uint32_t m_flash_buf[FLASH_LOG_SER_BUFFER_WORDS]; /**< Buffer used for serializing messages. */ +static uint32_t m_curr_addr; /**< Address of free spot in the storage area. */ +static size_t m_curr_len; /**< Length of current message being written. */ +static uint32_t m_dropped; /**< Number of dropped messages. */ + +/** @brief Log message string injected when entering panic mode. */ +static const char crashlog_str[] = "-----------CRASHLOG------------\r\n"; + +/** @brief Function saturates input to maximum possible length and rounds up value to be multiple + * of word size. + * + * @param length Length value. + * + * @return Modified input length. + */ +static uint32_t saturate_align_length(uint32_t length) +{ + length = (length > FLASH_LOG_MAX_PAYLOAD_SIZE) ? FLASH_LOG_MAX_PAYLOAD_SIZE : length; //saturate + length = CEIL_DIV(length, sizeof(uint32_t))*sizeof(uint32_t); + return length; +} + + +/** + * @brief Function for copying logger message to the buffer. + * + * @param[in] p_msg Logger message. + * @param[out] p_buf Output buffer where serialized message is placed. + * @param[in,out] p_len Buffer size as input, length of prepared data as output. + * + * @return True if message fits into the buffer, false otherwise + */ +static bool msg_to_buf(nrf_log_entry_t * p_msg, uint8_t * p_buf, size_t * p_len) +{ + uint32_t data_len; + nrf_log_header_t header = {0}; + size_t memobj_offset = HEADER_SIZE*sizeof(uint32_t); + + nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), 0); + + memcpy(p_buf, &header, sizeof(nrf_log_header_t)); + p_buf += sizeof(nrf_log_header_t); + + switch (header.base.generic.type) + { + case HEADER_TYPE_STD: + { + data_len = header.base.std.nargs * sizeof(uint32_t); + break; + } + case HEADER_TYPE_HEXDUMP: + { + data_len = saturate_align_length(header.base.hexdump.len); + break; + } + default: + *p_len = 0; + return false; + } + nrf_memobj_read(p_msg, p_buf, data_len, memobj_offset); + + if (*p_len >= sizeof(nrf_log_header_t) + data_len) + { + *p_len = sizeof(nrf_log_header_t) + data_len; + return true; + } + else + { + return false; + } +} + +/** + * @brief Function for getting logger message stored in flash. + * + * @param[in] p_buf Pointer to the location where message is stored. + * @param[out] pp_header Pointer to the log message header. + * @param[out] pp_data Pointer to the log message data (arguments or data in case of hexdump). + * + * @return True if message was successfully fetched, false otherwise. + */ +static bool msg_from_buf(uint32_t * p_buf, + nrf_log_header_t * * pp_header, + uint8_t * * pp_data, + uint32_t * p_len) +{ + *pp_header = (nrf_log_header_t *)p_buf; + *pp_data = (uint8_t *)&p_buf[LOG_HEADER_LEN_WORDS]; + + uint32_t data_len; + + switch ((*pp_header)->base.generic.type) + { + case HEADER_TYPE_STD: + { + data_len = ((*pp_header)->base.std.nargs)*sizeof(uint32_t); + break; + } + case HEADER_TYPE_HEXDUMP: + { + + data_len = saturate_align_length((*pp_header)->base.hexdump.len); + break; + } + default: + return false; + } + + *p_len = LOG_HEADER_LEN + data_len; + return true; +} + +/** + * @brief Function for processing log message queue. + * + * If writing to flash is synchronous then function drains the queue and writes all messages to flash. + * If writing to flash is asynchronous then function starts single write operation. In asynchronous mode + * function is called when new message is put into the queue from from flash operation callback. + * + * Function detects the situation that flash module reports attempt to write outside dedicated area. + * In that case flash backend stops writing any new messages. + * + * @param p_queue Queue will log messages + * @param fstorage_blocking If true it indicates that flash operations are blocking, event handler is not used. + */ +static void log_msg_queue_process(nrf_queue_t const * p_queue, bool fstorage_blocking) +{ + nrf_log_entry_t * p_msg; + bool busy = false; + while (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS) + { + ret_code_t err_code; + + m_curr_len = sizeof(m_flash_buf); + if (!msg_to_buf(p_msg, (uint8_t *)m_flash_buf, &m_curr_len)) + { + nrf_memobj_put(p_msg); + continue; + } + + err_code = nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, m_curr_len, p_msg); + + if (err_code == NRF_SUCCESS) + { + if (fstorage_blocking) + { + m_curr_addr += m_curr_len; + + nrf_memobj_put(p_msg); + } + else + { + busy = true; + break; + } + } + else if (!fstorage_blocking && (err_code == NRF_ERROR_NO_MEM)) + { + // fstorage queue got full. Drop entry. + nrf_memobj_put(p_msg); + m_dropped++; + break; + } + else if (err_code == NRF_ERROR_INVALID_ADDR) + { + // Trying to write outside the area, flash log is full. Skip any new writes. + nrf_memobj_put(p_msg); + m_state = LOG_BACKEND_FLASH_INACTIVE; + } + else + { + ASSERT(false); + } + } + + if (!busy) + { + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&m_busy_flag)); + } +} + +static void queue_element_drop(nrf_queue_t const * p_queue) +{ + nrf_log_entry_t * p_msg; + if (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS) + { + m_dropped++; + nrf_memobj_put(p_msg); + } +} + +static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt) +{ + if (m_state == LOG_BACKEND_FLASH_ACTIVE) + { + switch (p_evt->id) + { + case NRF_FSTORAGE_EVT_WRITE_RESULT: + { + if (p_evt->result == NRF_SUCCESS) + { + m_curr_addr += m_curr_len; + m_curr_len = 0; + log_msg_queue_process(mp_flashlog_queue, false); + } + else + { + m_dropped++; + } + + if (p_evt->p_param) + { + nrf_memobj_put((nrf_log_entry_t *)p_evt->p_param); + } + break; + } + default: + break; + } + } + else if ((m_state == LOG_BACKEND_FLASH_INACTIVE) && + (p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT) && + (p_evt->addr == RUNTIME_START_ADDR)) + { + m_state = LOG_BACKEND_FLASH_ACTIVE; + } +} + +/** + * @brief Function for enqueueing new message. + * + * If queue is full then the oldest message is freed. + * + * @param p_queue Queue. + * @param p_msg Message. + * + * @return Number of dropped messages + */ +static uint32_t message_enqueue(nrf_queue_t const * p_queue, nrf_log_entry_t * p_msg) +{ + uint32_t dropped = 0; + + //flag was set, busy so enqueue message + while (nrf_queue_push(p_queue, &p_msg) != NRF_SUCCESS) + { + + nrf_log_entry_t * p_old_msg; + if (nrf_queue_pop(p_queue, &p_old_msg) == NRF_SUCCESS) + { + nrf_memobj_put(p_old_msg); + dropped++; + } + } + + return dropped; +} + + +void nrf_log_backend_flashlog_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + if (m_state == LOG_BACKEND_FLASH_ACTIVE) + { + nrf_memobj_get(p_msg); + + m_dropped += message_enqueue(mp_flashlog_queue, p_msg); + + if (nrf_atomic_flag_set_fetch(&m_busy_flag) == 0) + { + log_msg_queue_process(mp_flashlog_queue, false); + } + } +} + + +void nrf_log_backend_crashlog_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + if (m_state != LOG_BACKEND_FLASH_INACTIVE) + { + nrf_memobj_get(p_msg); + + UNUSED_RETURN_VALUE(message_enqueue(mp_crashlog_queue, p_msg)); + } + + if (m_state == LOG_BACKEND_FLASH_IN_PANIC) + { + log_msg_queue_process(mp_crashlog_queue, true); + } +} + +void nrf_log_backend_flashlog_flush(nrf_log_backend_t const * p_backend) +{ + queue_element_drop(mp_flashlog_queue); +} + +void nrf_log_backend_crashlog_flush(nrf_log_backend_t const * p_backend) +{ + queue_element_drop(mp_crashlog_queue); +} + +void nrf_log_backend_flashlog_panic_set(nrf_log_backend_t const * p_backend) +{ + /* Empty */ +} + +/** + * @brief Function for injecting log message which will indicate start of crash log. + */ +static void crashlog_marker_inject(void) +{ + nrf_log_header_t crashlog_marker_hdr = { + .base = { + .std = { + .type = HEADER_TYPE_STD, + .severity = NRF_LOG_SEVERITY_INFO_RAW, + .nargs = 0, + .addr = (uint32_t)crashlog_str & STD_ADDR_MASK + } + }, + .module_id = 0, + .timestamp = 0, + }; + m_flash_buf[0] = crashlog_marker_hdr.base.raw; + m_flash_buf[1] = crashlog_marker_hdr.module_id; + m_flash_buf[2] = crashlog_marker_hdr.timestamp; + (void)nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, LOG_HEADER_LEN, NULL); + m_curr_addr += LOG_HEADER_LEN; +} + + +void nrf_log_backend_crashlog_panic_set(nrf_log_backend_t const * p_backend) +{ + if (nrf_fstorage_init(&m_log_flash_fstorage, &nrf_fstorage_nvmc, NULL) == NRF_SUCCESS) + { + m_state = LOG_BACKEND_FLASH_IN_PANIC; + + /* In case of Softdevice MWU may protect access to NVMC. */ + NVIC_DisableIRQ(MWU_IRQn); + + log_msg_queue_process(mp_flashlog_queue, true); + + crashlog_marker_inject(); + + log_msg_queue_process(mp_crashlog_queue, true); + } + else + { + m_state = LOG_BACKEND_FLASH_INACTIVE; + } +} + +/** + * @brief Function for determining first empty location in area dedicated for flash logger backend. + */ +static uint32_t empty_addr_get(void) +{ + uint32_t token = 0; + nrf_log_header_t * p_dummy_header; + uint8_t * p_dummy_data; + + while(nrf_log_backend_flash_next_entry_get(&token, &p_dummy_header, &p_dummy_data) == NRF_SUCCESS) + { + + } + + return token; +} + + +ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api) +{ + ret_code_t err_code; + + + uint32_t start_addr = RUNTIME_START_ADDR; + uint32_t end_addr = start_addr + FLASH_LOG_SIZE - 1; + + m_log_flash_fstorage.start_addr = start_addr; + m_log_flash_fstorage.end_addr = end_addr; + + err_code = nrf_fstorage_init(&m_log_flash_fstorage, p_fs_api, NULL); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + m_curr_addr = empty_addr_get(); + m_state = LOG_BACKEND_FLASH_ACTIVE; + + return err_code; +} + + +ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token, + nrf_log_header_t * * pp_header, + uint8_t * * pp_data) +{ + uint32_t * p_addr = p_token; + uint32_t len; + + *p_addr = (*p_addr == 0) ? RUNTIME_START_ADDR : *p_addr; + + if (nrf_fstorage_rmap(&m_log_flash_fstorage, *p_addr) == NULL) + { + //Supports only memories which can be mapped for reading. + return NRF_ERROR_NOT_SUPPORTED; + } + + if (msg_from_buf((uint32_t *)*p_addr, pp_header, pp_data, &len)) + { + *p_addr += len; + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NOT_FOUND; + } +} + + +ret_code_t nrf_log_backend_flash_erase(void) +{ + ret_code_t err_code; + + m_state = LOG_BACKEND_FLASH_INACTIVE; + err_code = nrf_fstorage_erase(&m_log_flash_fstorage, RUNTIME_START_ADDR, NRF_LOG_BACKEND_PAGES, NULL); + + m_curr_addr = RUNTIME_START_ADDR; + + return err_code; +} + +#if NRF_LOG_BACKEND_FLASHLOG_ENABLED +const nrf_log_backend_api_t nrf_log_backend_flashlog_api = { + .put = nrf_log_backend_flashlog_put, + .flush = nrf_log_backend_flashlog_flush, + .panic_set = nrf_log_backend_flashlog_panic_set, +}; +#endif + +#if NRF_LOG_BACKEND_CRASHLOG_ENABLED +const nrf_log_backend_api_t nrf_log_backend_crashlog_api = { + .put = nrf_log_backend_crashlog_put, + .flush = nrf_log_backend_crashlog_flush, + .panic_set = nrf_log_backend_crashlog_panic_set, +}; +#endif + +#if NRF_LOG_BACKEND_FLASH_CLI_CMDS +#include "nrf_cli.h" + +static uint8_t m_buffer[64]; +static nrf_cli_t const * mp_cli; + +static void cli_tx(void const * p_context, char const * p_buffer, size_t len); + +static nrf_fprintf_ctx_t m_fprintf_ctx = +{ + .p_io_buffer = (char *)m_buffer, + .io_buffer_size = sizeof(m_buffer)-1, + .io_buffer_cnt = 0, + .auto_flush = true, + .p_user_ctx = &mp_cli, + .fwrite = cli_tx +}; + + +static void flashlog_clear_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + } + + UNUSED_RETURN_VALUE(nrf_log_backend_flash_erase()); +} + +#include "nrf_delay.h" +static void cli_tx(void const * p_context, char const * p_buffer, size_t len) +{ + nrf_cli_t * * pp_cli = (nrf_cli_t * *)p_context; + char * p_strbuf = (char *)&p_buffer[len]; + *p_strbuf = '\0'; + nrf_cli_fprintf((nrf_cli_t const *)*pp_cli, NRF_CLI_DEFAULT, p_buffer); + // nrf_delay_ms(10); +} + + +static void entry_process(nrf_cli_t const * p_cli, nrf_log_header_t * p_header, uint8_t * p_data) +{ + mp_cli = p_cli; + + nrf_log_str_formatter_entry_params_t params = + { + .timestamp = p_header->timestamp, + .module_id = p_header->module_id, + .use_colors = 0, + }; + + switch (p_header->base.generic.type) + { + case HEADER_TYPE_STD: + { + params.severity = (nrf_log_severity_t)p_header->base.std.severity; + nrf_log_std_entry_process((const char *)((uint32_t)p_header->base.std.addr), + (uint32_t *)p_data, + p_header->base.std.nargs, + ¶ms, + &m_fprintf_ctx); + break; + } + case HEADER_TYPE_HEXDUMP: + { + params.severity = (nrf_log_severity_t)p_header->base.hexdump.severity; + + nrf_log_hexdump_entry_process(p_data, + p_header->base.hexdump.len, + ¶ms, + &m_fprintf_ctx); + break; + } + default: + ASSERT(0); + } + +} + + +static void flashlog_read_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + } + + uint32_t token = 0; + uint8_t * p_data = NULL; + bool empty = true; + nrf_log_header_t * p_header; + + while (1) + { + if (nrf_log_backend_flash_next_entry_get(&token, &p_header, &p_data) == NRF_SUCCESS) + { + entry_process(p_cli, p_header, p_data); + empty = false; + } + else + { + break; + } + } + + if (empty) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Flash log empty\r\n"); + } +} + + +static void flashlog_status_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + } + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Flash log status:\r\n"); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Location (address: 0x%08X, length: %d)\r\n", + RUNTIME_START_ADDR, FLASH_LOG_SIZE); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Current usage:%d%% (%d of %d bytes used)\r\n", + 100ul * (m_curr_addr - RUNTIME_START_ADDR)/FLASH_LOG_SIZE, + m_curr_addr - RUNTIME_START_ADDR, + FLASH_LOG_SIZE); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Dropped logs: %d\r\n", m_dropped); + + +} + + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_flashlog_cmd) +{ + NRF_CLI_CMD(clear, NULL, "Remove logs", flashlog_clear_cmd), + NRF_CLI_CMD(read, NULL, "Read stored logs", flashlog_read_cmd), + NRF_CLI_CMD(status, NULL, "Flash log status", flashlog_status_cmd), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(flashlog, &m_flashlog_cmd, "Commands for reading logs stored in non-volatile memory", NULL); + +#endif //NRF_LOG_BACKEND_FLASH_CLI_CMDS + +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH) diff --git a/libraries/nfc/src/util/nrf_log_backend_flash.h b/libraries/nfc/src/util/nrf_log_backend_flash.h new file mode 100644 index 000000000..a2704c361 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_flash.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nrf_log_backend_flash Flash logger backend + * @{ + * @ingroup nrf_log + * @brief Flash logger backend. + */ + +#ifndef NRF_LOG_BACKEND_FLASH_H +#define NRF_LOG_BACKEND_FLASH_H + +#include "nrf_log_backend_interface.h" +#include "nrf_fstorage.h" +#include "nrf_log_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Flashlog logger backend API. */ +extern const nrf_log_backend_api_t nrf_log_backend_flashlog_api; + +/** @brief Crashlog logger backend API. */ +extern const nrf_log_backend_api_t nrf_log_backend_crashlog_api; + +/** @brief Flashlog logger backend structure. */ +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_flashlog_t; + +/** @brief Crashlog logger backend structure. */ +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_crashlog_t; + +/** @brief Macro for creating an instance of the flashlog logger backend. */ +#define NRF_LOG_BACKEND_FLASHLOG_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_flashlog_api, NULL) + +/** @brief Macro for creating an instance of the crashlog logger backend. */ +#define NRF_LOG_BACKEND_CRASHLOG_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_crashlog_api, NULL) + +/** + * @brief Function for initializing the flash logger backend. + * + * Flash logger backend consists of two logical backends: flashlog and crashlog. Since both + * backends write to the same flash area, the initialization is common. + * + * @param p_fs_api fstorage API to be used. + * + * @return NRF_SUCCESS or error code returned by @ref nrf_fstorage_init. + */ +ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api); + +/** + * @brief Function for getting a log entry stored in flash. + * + * Log messages stored in flash can be read one by one starting from the oldest one. + * + * @param[in, out] p_token Token reused between consecutive readings of log entries. + * Token must be set to 0 to read the first entry. + * @param[out] pp_header Pointer to the entry header. + * @param[out] pp_data Pointer to the data part of the entry (arguments or data in case of hexdump). + * + * @retval NRF_SUCCESS Entry was successfully read. + * @retval NRF_ERROR_NOT_SUPPORTED fstorage API does not support direct reading. + * @retval NRF_ERROR_NOT_FOUND Entry not found. Last entry was already reached or area is empty. + */ +ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token, + nrf_log_header_t * * pp_header, + uint8_t * * pp_data); + +/** + * @brief Function for erasing flash area dedicated for the flash logger backend. + */ +ret_code_t nrf_log_backend_flash_erase(void); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_UART_H + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_backend_interface.h b/libraries/nfc/src/util/nrf_log_backend_interface.h new file mode 100644 index 000000000..843a4c7e4 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_interface.h @@ -0,0 +1,271 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_BACKEND_INTERFACE_H +#define NRF_LOG_BACKEND_INTERFACE_H + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_backend_interface Logger backend interface + * @{ + * @ingroup nrf_log + * @brief The nrf_log backend interface. + */ + +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_memobj.h" +#endif + +#include "nrf_section.h" +#include "nordic_common.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief nrf_log entry. + */ +#if NRF_LOG_ENABLED +typedef nrf_memobj_t nrf_log_entry_t; +#else +typedef void nrf_log_entry_t; +#endif + +/* Forward declaration of the nrf_log_backend_t type. */ +typedef struct nrf_log_backend_s nrf_log_backend_t; + +/** + * @brief Logger backend API. + */ +typedef struct +{ + /** + * @brief @ref nrf_log_backend_put + */ + void (*put)(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_entry); + + /** + * @brief @ref nrf_log_backend_panic_set + */ + void (*panic_set)(nrf_log_backend_t const * p_backend); + + /** + * @brief @ref nrf_log_backend_flush + */ + void (*flush)(nrf_log_backend_t const * p_backend); +} nrf_log_backend_api_t; + +/** + * @brief Logger backend control block. + */ +typedef struct +{ + nrf_log_backend_t const * p_next; //!< Pointer to the next backend in the logger. + uint8_t id; //!< ID of the backend. + bool enabled; //!< Enable flag. +} nrf_log_backend_cb_t; + +/** + * @brief Logger backend structure. + */ +struct nrf_log_backend_s +{ + nrf_log_backend_api_t const * p_api; //!< Pointer to interface. + void * p_ctx; //!< User context. + char * p_name; //!< Name of the backend. + nrf_log_backend_cb_t * p_cb; //!< Pointer to the backend control block. +}; + + +#define NRF_LOG_BACKEND_SECTION_NAME log_backends + +#define NRF_LOG_BACKEND_SUBSECTION_NAME(_name) NRF_LOG_BACKEND_SECTION_NAME + +/** @brief Invalid ID value indicating that logger backend is not attached to the logger frontend.*/ +#define NRF_LOG_BACKEND_INVALID_ID 0xFF + +/** @brief Memory section where backends are located. */ +NRF_SECTION_DEF(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); + +/** + * @brief Macro for creating a logger backend instance. + * + * @param _name Name of the backend instance. + * @param _api Logger backend API. + * @param _p_ctx Pointer to the user context. + */ +#define NRF_LOG_BACKEND_DEF(_name, _api, _p_ctx) \ + static nrf_log_backend_cb_t CONCAT_2(log_backend_cb_, _name) = { \ + .enabled = false, \ + .id = NRF_LOG_BACKEND_INVALID_ID, \ + .p_next = NULL \ + }; \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_BACKEND_SUBSECTION_NAME(_name), \ + static const nrf_log_backend_t _name) = { \ + .p_api = &_api, \ + .p_ctx = _p_ctx, \ + .p_cb = &CONCAT_2(log_backend_cb_, _name), \ + .p_name = (char *)STRINGIFY(_name) \ + } + + +/** + * @brief Function for putting message with log entry to the backend. + * + * @param[in] p_backend Pointer to the backend instance. + * @param[in] p_msg Pointer to message with log entry. + */ +__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * const p_backend, + nrf_log_entry_t * p_msg); + +/** + * @brief Function for reconfiguring backend to panic mode. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for flushing backend. + * + * On flushing request backend should release log message(s). + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * const p_backend); + + +/** + * @brief Function for setting backend id. + * + * @note It is used internally by the logger. + * + * @param[in] p_backend Pointer to the backend instance. + * @param[in] id Id. + */ +__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t const * const p_backend, uint8_t id); + +/** + * @brief Function for getting backend id. + * + * @note It is used internally by the logger. + * + * @param[in] p_backend Pointer to the backend instance. + * @return Id. + */ +__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for enabling backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for disabling backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for checking state of the backend. + * + * @param[in] p_backend Pointer to the backend instance. + * + * @return True if backend is enabled, false otherwise. + */ +__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * const p_backend); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * const p_backend, + nrf_log_entry_t * p_msg) +{ + p_backend->p_api->put(p_backend, p_msg); +} + +__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_api->panic_set(p_backend); +} + +__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_api->flush(p_backend); +} + +__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t const * const p_backend, uint8_t id) +{ + p_backend->p_cb->id = id; +} + +__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * const p_backend) +{ + return p_backend->p_cb->id; +} + +__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_cb->enabled = true; +} + +__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_cb->enabled = false; +} + +__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * const p_backend) +{ + return p_backend->p_cb->enabled; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_INTERFACE_H + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_backend_rtt.c b/libraries/nfc/src/util/nrf_log_backend_rtt.c new file mode 100644 index 000000000..8120cd8e5 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_rtt.c @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) +#include "nrf_log_backend_rtt.h" +#include "nrf_log_backend_serial.h" +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#include "nrf_delay.h" +#include +#include + +static bool m_host_present; + +static uint8_t m_string_buff[NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE]; + +void nrf_log_backend_rtt_init(void) +{ + SEGGER_RTT_Init(); +} + +static void serial_tx(void const * p_context, char const * buffer, size_t len) +{ + if (len) + { + uint32_t idx = 0; + uint32_t processed; + uint32_t watchdog_counter = NRF_LOG_BACKEND_RTT_TX_RETRY_CNT; + do + { + processed = SEGGER_RTT_WriteNoLock(0, &buffer[idx], len); + idx += processed; + len -= processed; + if (processed == 0) + { + /* There are two possible reasons for not writing any data to RTT: + * - The host is not connected and not reading the data. + * - The buffer got full and will be read by the host. + * These two situations are distinguished using the following algorithm. + * At the begining, the module assumes that the host is active, + * so when no data is read, it busy waits and retries. + * If, after retrying, the host reads the data, the module assumes that the host is active. + * If it fails, the module assumes that the host is inactive and stores that information. On next + * call, only one attempt takes place. The host is marked as active if the attempt is successful. + */ + if (!m_host_present) + { + break; + } + else + { + nrf_delay_ms(NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS); + watchdog_counter--; + if (watchdog_counter == 0) + { + m_host_present = false; + break; + } + } + } + m_host_present = true; + } while (len); + } +} +static void nrf_log_backend_rtt_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE, serial_tx); +} + +static void nrf_log_backend_rtt_flush(nrf_log_backend_t const * p_backend) +{ + +} + +static void nrf_log_backend_rtt_panic_set(nrf_log_backend_t const * p_backend) +{ + +} + +const nrf_log_backend_api_t nrf_log_backend_rtt_api = { + .put = nrf_log_backend_rtt_put, + .flush = nrf_log_backend_rtt_flush, + .panic_set = nrf_log_backend_rtt_panic_set, +}; +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) diff --git a/libraries/nfc/src/util/nrf_log_backend_rtt.h b/libraries/nfc/src/util/nrf_log_backend_rtt.h new file mode 100644 index 000000000..9f549cf22 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_rtt.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nrf_log_backend_rtt Log RTT backend + * @{ + * @ingroup nrf_log + * @brief Log RTT backend. + */ + +#ifndef NRF_LOG_BACKEND_RTT_H +#define NRF_LOG_BACKEND_RTT_H + +#include "nrf_log_backend_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const nrf_log_backend_api_t nrf_log_backend_rtt_api; + +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_rtt_t; + +/** + * @brief RTT backend definition + * + * @param _name Name of the instance. + */ +#define NRF_LOG_BACKEND_RTT_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_rtt_api, NULL) + +void nrf_log_backend_rtt_init(void); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_RTT_H + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_backend_serial.c b/libraries/nfc/src/util/nrf_log_backend_serial.c new file mode 100644 index 000000000..c5849d01a --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_serial.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_log_backend_serial.h" +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" + +void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg, + uint8_t * p_buffer, + uint32_t length, + nrf_fprintf_fwrite tx_func) +{ + nrf_memobj_get(p_msg); + + nrf_fprintf_ctx_t fprintf_ctx = { + .p_io_buffer = (char *)p_buffer, + .io_buffer_size = length, + .io_buffer_cnt = 0, + .auto_flush = false, + .p_user_ctx = NULL, + .fwrite = tx_func + }; + + nrf_log_str_formatter_entry_params_t params; + + nrf_log_header_t header; + size_t memobj_offset = 0; + + nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset = HEADER_SIZE*sizeof(uint32_t); + + params.timestamp = header.timestamp; + params.module_id = header.module_id; + params.dropped = header.dropped; + params.use_colors = NRF_LOG_USES_COLORS; + + /*lint -save -e438*/ + if (header.base.generic.type == HEADER_TYPE_STD) + { + char const * p_log_str = (char const *)((uint32_t)header.base.std.addr); + params.severity = (nrf_log_severity_t)header.base.std.severity; + uint32_t nargs = header.base.std.nargs; + uint32_t args[NRF_LOG_MAX_NUM_OF_ARGS]; + + nrf_memobj_read(p_msg, args, nargs*sizeof(uint32_t), memobj_offset); + memobj_offset += (nargs*sizeof(uint32_t)); + + nrf_log_std_entry_process(p_log_str, + args, + nargs, + ¶ms, + &fprintf_ctx); + + } + else if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t data_len = header.base.hexdump.len; + params.severity = (nrf_log_severity_t)header.base.hexdump.severity; + uint8_t data_buf[8]; + uint32_t chunk_len; + do + { + chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf); + nrf_memobj_read(p_msg, data_buf, chunk_len, memobj_offset); + memobj_offset += chunk_len; + data_len -= chunk_len; + + nrf_log_hexdump_entry_process(data_buf, + chunk_len, + ¶ms, + &fprintf_ctx); + } while (data_len > 0); + } + nrf_memobj_put(p_msg); + /*lint -restore*/ +} +#endif //NRF_LOG_ENABLED diff --git a/libraries/nfc/src/util/nrf_log_backend_serial.h b/libraries/nfc/src/util/nrf_log_backend_serial.h new file mode 100644 index 000000000..0b2874ac3 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_serial.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_BACKEND_SERIAL_H +#define NRF_LOG_BACKEND_SERIAL_H +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_backend_serial Common part of serial backends + * @{ + * @ingroup nrf_log + * @brief The nrf_log serial backend common put function. + */ + + +#include "nrf_log_backend_interface.h" +#include "nrf_fprintf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief A function for processing logger entry with simple serial interface as output. + * + * + */ +void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg, + uint8_t * p_buffer, + uint32_t length, + nrf_fprintf_fwrite tx_func); + +#endif //NRF_LOG_BACKEND_SERIAL_H + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_backend_uart.c b/libraries/nfc/src/util/nrf_log_backend_uart.c new file mode 100644 index 000000000..db374cb30 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_uart.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART) +#include "nrf_log_backend_uart.h" +#include "nrf_log_backend_serial.h" +#include "nrf_log_internal.h" +#include "util/nrf_drv_uart.h" +#include "app_error.h" + +nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0); + +static uint8_t m_string_buff[NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE]; +static volatile bool m_xfer_done; +static bool m_async_mode; +static void uart_evt_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + m_xfer_done = true; +} + +static void uart_init(bool async_mode) +{ + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + config.pseltxd = NRF_LOG_BACKEND_UART_TX_PIN; + config.pselrxd = NRF_UART_PSEL_DISCONNECTED; + config.pselcts = NRF_UART_PSEL_DISCONNECTED; + config.pselrts = NRF_UART_PSEL_DISCONNECTED; + config.baudrate = (nrf_uart_baudrate_t)NRF_LOG_BACKEND_UART_BAUDRATE; + ret_code_t err_code = nrf_drv_uart_init(&m_uart, &config, async_mode ? uart_evt_handler : NULL); + APP_ERROR_CHECK(err_code); + + m_async_mode = async_mode; +} + +void nrf_log_backend_uart_init(void) +{ + bool async_mode = NRF_LOG_DEFERRED ? true : false; + uart_init(async_mode); +} + +static void serial_tx(void const * p_context, char const * p_buffer, size_t len) +{ + uint8_t len8 = (uint8_t)(len & 0x000000FF); + m_xfer_done = false; + ret_code_t err_code = nrf_drv_uart_tx(&m_uart, (uint8_t *)p_buffer, len8); + APP_ERROR_CHECK(err_code); + /* wait for completion since buffer is reused*/ + while (m_async_mode && (m_xfer_done == false)) + { + + } + +} + +static void nrf_log_backend_uart_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, + NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE, serial_tx); +} + +static void nrf_log_backend_uart_flush(nrf_log_backend_t const * p_backend) +{ + +} + +static void nrf_log_backend_uart_panic_set(nrf_log_backend_t const * p_backend) +{ + nrf_drv_uart_uninit(&m_uart); + + uart_init(false); +} + +const nrf_log_backend_api_t nrf_log_backend_uart_api = { + .put = nrf_log_backend_uart_put, + .flush = nrf_log_backend_uart_flush, + .panic_set = nrf_log_backend_uart_panic_set, +}; +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART) diff --git a/libraries/nfc/src/util/nrf_log_backend_uart.h b/libraries/nfc/src/util/nrf_log_backend_uart.h new file mode 100644 index 000000000..20efa33bf --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_backend_uart.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nrf_log_backend_uart Log UART backend + * @{ + * @ingroup nrf_log + * @brief Log UART backend. + */ + +#ifndef NRF_LOG_BACKEND_UART_H +#define NRF_LOG_BACKEND_UART_H + +#include "nrf_log_backend_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const nrf_log_backend_api_t nrf_log_backend_uart_api; + +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_uart_t; + +#define NRF_LOG_BACKEND_UART_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_uart_api, NULL) + +void nrf_log_backend_uart_init(void); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_UART_H + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_ctrl.h b/libraries/nfc/src/util/nrf_log_ctrl.h new file mode 100644 index 000000000..1ff117ca9 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_ctrl.h @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_CTRL_H +#define NRF_LOG_CTRL_H + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_ctrl Functions for controlling nrf_log + * @{ + * @ingroup nrf_log + * @brief The nrf_log control interface. + */ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include +#include +#include "nrf_log_types.h" +#include "nrf_log_ctrl_internal.h" +#include "nrf_log_backend_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Timestamp function prototype. + * + * @return Timestamp value. + */ +typedef uint32_t (*nrf_log_timestamp_func_t)(void); + + +/**@brief Macro for initializing the logs. + * + * Macro has one or two parameters. First parameter (obligatory) is the timestamp function (@ref nrf_log_timestamp_func_t). + * Additionally, as the second parameter timestamp frequency in Hz can be provided. If not provided then default + * frequency is used (@ref NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY). Frequency is used to format timestamp prefix if + * @ref NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED is set. + * + * @return NRF_SUCCESS after successful initialization, otherwise an error code. + */ +#define NRF_LOG_INIT(...) NRF_LOG_INTERNAL_INIT(__VA_ARGS__) + + +/**@brief Macro for processing a single log entry from a queue of deferred logs. + * + * You can call this macro from the main context or from the error handler to process + * log entries one by one. + * + * @note If logs are not deferred, this call has no use and is defined as 'false'. + * + * @retval true There are more logs to process in the buffer. + * @retval false No more logs in the buffer. + */ +#define NRF_LOG_PROCESS() NRF_LOG_INTERNAL_PROCESS() + +/** @brief Macro for processing all log entries from the buffer. + * It blocks until all buffered entries are processed by the backend. + * + * @note If logs are not deferred, this call has no use and is empty. + */ +#define NRF_LOG_FLUSH() NRF_LOG_INTERNAL_FLUSH() + +/** @brief Macro for flushing log data before reset. + * + * @note If logs are not deferred, this call has no use and is empty. + * + * @note If RTT is used, then a breakpoint is hit once flushed. + */ +#define NRF_LOG_FINAL_FLUSH() NRF_LOG_INTERNAL_FINAL_FLUSH() + +/** + * @brief Function for initializing the frontend and the default backend. + * + * @ref NRF_LOG_INIT calls this function to initialize the frontend and the backend. + * If custom backend is used, then @ref NRF_LOG_INIT should not be called. + * Instead, frontend and user backend should be verbosely initialized. + * + * @param timestamp_func Function for getting a 32-bit timestamp. + * @param timestamp_freq Frequency of the timestamp. + * + * @return Error status. + * + */ +ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func, uint32_t timestamp_freq); + +/** + * @brief Function for adding new backend interface to the logger. + * + * @param p_backend Pointer to the backend interface. + * @param severity Initial value of severity level for each module forwarded to the backend. This + * option is only applicable if @ref NRF_LOG_FILTERS_ENABLED is set. + * @return -1 if backend cannot be added or positive number (backend ID). + */ +int32_t nrf_log_backend_add(nrf_log_backend_t const * p_backend, nrf_log_severity_t severity); + +/** + * @brief Function for removing backend from the logger. + * + * @param p_backend Pointer to the backend interface. + * + */ +void nrf_log_backend_remove(nrf_log_backend_t const * p_backend); + +/** + * @brief Function for setting logger backends into panic mode. + * + * When this function is called all attached backends are informed about panic state of the system. + * It is up to the backend to react properly (hold or process logs in blocking mode, etc.) + */ +void nrf_log_panic(void); + +/** + * @brief Function for handling a single log entry. + * + * Use this function only if the logs are buffered. It takes a single entry from the + * buffer and attempts to process it. + * + * @retval true If there are more entries to process. + * @retval false If there are no more entries to process. + */ +bool nrf_log_frontend_dequeue(void); + +/** + * @brief Function for getting number of independent log modules registered into the logger. + * + * @return Number of registered modules. + */ +uint32_t nrf_log_module_cnt_get(void); + +/** + * @brief Function for getting module name. + * + * @param module_id Module ID. + * @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules. + * @return Pointer to string with module name. + */ +const char * nrf_log_module_name_get(uint32_t module_id, bool is_ordered_idx); + +/** + * @brief Function for getting coloring of specific logs. + * + * @param module_id Module ID. + * @param severity Log severity. + * + * @return ID of the color. + */ +uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity); + +/** + * @brief Function for configuring filtering ofs logs in the module. + * + * Filtering of logs in modules is independent for each backend. + * + * @param backend_id Backend ID which want to chenge its configuration. + * @param module_id Module ID which logs will be reconfigured. + * @param severity New severity filter. + */ +void nrf_log_module_filter_set(uint32_t backend_id, + uint32_t module_id, + nrf_log_severity_t severity); + +/** + * @brief Function for getting module severity level. + * + * @param backend_id Backend ID. + * @param module_id Module ID. + * @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules. + * @param dynamic It true current filter for given backend is returned. If false then + * compiled-in level is returned (maximum available). If this parameter is + * false then backend_id parameter is not used. + * + * @return Severity. + */ +nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id, + uint32_t module_id, + bool is_ordered_idx, + bool dynamic); + +/** + * @brief Function stores current filtering configuration into non-volatile memory using @ref fds module. + * + * @return NRF_SUCCESS or @ref fds error code. + */ +ret_code_t nrf_log_config_store(void); + +/** + * @brief Function loads configuration from non-volatile memory using @ref fds module. + * + * @retval NRF_SUCCESS On successful loading. + * @retval NRF_ERROR_NOT_FOUND Configuration file not found. + * @retval NRF_ERROR_INTERNAL Other @ref fds error on reading configuration file. + */ +ret_code_t nrf_log_config_load(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_CTRL_H + +/** + *@} + **/ diff --git a/libraries/nfc/src/util/nrf_log_ctrl_internal.h b/libraries/nfc/src/util/nrf_log_ctrl_internal.h new file mode 100644 index 000000000..90c4cd18b --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_ctrl_internal.h @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_CTRL_INTERNAL_H +#define NRF_LOG_CTRL_INTERNAL_H +/** + * @cond (NODOX) + * @defgroup nrf_log_ctrl_internal Auxiliary internal types declarations + * @{ + * @internal + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) + +#define NRF_LOG_LFCLK_FREQ 32768 + +#ifdef APP_TIMER_CONFIG_RTC_FREQUENCY +#define LOG_TIMESTAMP_DEFAULT_FREQUENCY ((NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY == 0) ? \ + (NRF_LOG_LFCLK_FREQ/(APP_TIMER_CONFIG_RTC_FREQUENCY + 1)) : \ + NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY) +#else +#define LOG_TIMESTAMP_DEFAULT_FREQUENCY NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY +#endif + +#define NRF_LOG_INTERNAL_INIT(...) \ + nrf_log_init(GET_VA_ARG_1(__VA_ARGS__), \ + GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__, LOG_TIMESTAMP_DEFAULT_FREQUENCY))) + +#define NRF_LOG_INTERNAL_PROCESS() nrf_log_frontend_dequeue() +#define NRF_LOG_INTERNAL_FLUSH() \ + do { \ + while (NRF_LOG_INTERNAL_PROCESS()); \ + } while (0) + +#define NRF_LOG_INTERNAL_FINAL_FLUSH() \ + do { \ + nrf_log_panic(); \ + NRF_LOG_INTERNAL_FLUSH(); \ + } while (0) + + +#else // NRF_MODULE_ENABLED(NRF_LOG) +#define NRF_LOG_INTERNAL_PROCESS() false +#define NRF_LOG_INTERNAL_FLUSH() +#define NRF_LOG_INTERNAL_INIT(...) NRF_SUCCESS +#define NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler) \ + UNUSED_PARAMETER(default_handler); UNUSED_PARAMETER(bytes_handler) +#define NRF_LOG_INTERNAL_FINAL_FLUSH() +#endif // NRF_MODULE_ENABLED(NRF_LOG) + +/** @} + * @endcond + */ +#endif // NRF_LOG_CTRL_INTERNAL_H diff --git a/libraries/nfc/src/util/nrf_log_default_backends.c b/libraries/nfc/src/util/nrf_log_default_backends.c new file mode 100644 index 000000000..a5634b503 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_default_backends.c @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_log_default_backends.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_internal.h" +#include "nrf_assert.h" + +#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED +#include "nrf_log_backend_rtt.h" +NRF_LOG_BACKEND_RTT_DEF(rtt_log_backend); +#endif + +#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED +#include "nrf_log_backend_uart.h" +NRF_LOG_BACKEND_UART_DEF(uart_log_backend); +#endif + +void nrf_log_default_backends_init(void) +{ + int32_t backend_id = -1; + (void)backend_id; +#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED + nrf_log_backend_rtt_init(); + backend_id = nrf_log_backend_add(&rtt_log_backend, NRF_LOG_SEVERITY_DEBUG); + ASSERT(backend_id >= 0); + nrf_log_backend_enable(&rtt_log_backend); +#endif + +#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED + nrf_log_backend_uart_init(); + backend_id = nrf_log_backend_add(&uart_log_backend, NRF_LOG_SEVERITY_DEBUG); + ASSERT(backend_id >= 0); + nrf_log_backend_enable(&uart_log_backend); +#endif +} +#endif diff --git a/libraries/nfc/src/util/nrf_log_default_backends.h b/libraries/nfc/src/util/nrf_log_default_backends.h new file mode 100644 index 000000000..055205f1f --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_default_backends.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_DEFAULT_BACKENDS_H__ +#define NRF_LOG_DEFAULT_BACKENDS_H__ + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_default_backends Functions for initializing and adding default backends + * @{ + * @ingroup nrf_log + * @brief The nrf_log default backends. + */ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def NRF_LOG_DEFAULT_BACKENDS_INIT + * @brief Macro for initializing default backends. + * + * Each backend enabled in configuration is initialized and added as a backend to the logger. + */ +#if NRF_LOG_ENABLED +#define NRF_LOG_DEFAULT_BACKENDS_INIT() nrf_log_default_backends_init() +#else +#define NRF_LOG_DEFAULT_BACKENDS_INIT() +#endif + +void nrf_log_default_backends_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_LOG_DEFAULT_BACKENDS_H__ diff --git a/libraries/nfc/src/util/nrf_log_frontend.c b/libraries/nfc/src/util/nrf_log_frontend.c new file mode 100644 index 000000000..698bb5db3 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_frontend.c @@ -0,0 +1,1583 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "app_util.h" +#include "app_util_platform.h" +#include "nrf_log.h" +#include "nrf_log_internal.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_backend_interface.h" +#include "nrf_log_str_formatter.h" +#include "nrf_section.h" +#include "nrf_ringbuf.h" +#include "nrf_memobj.h" +#include "nrf_atomic.h" +#include + +STATIC_ASSERT((NRF_LOG_BUFSIZE % 4) == 0); +STATIC_ASSERT(IS_POWER_OF_TWO(NRF_LOG_BUFSIZE)); + +#define NRF_LOG_BUF_WORDS (NRF_LOG_BUFSIZE/4) + +#if NRF_MODULE_ENABLED(FDS) && NRF_LOG_FILTERS_ENABLED +#define LOG_CONFIG_LOAD_STORE_ENABLED 1 +#else +#define LOG_CONFIG_LOAD_STORE_ENABLED 0 +#endif + +#if NRF_LOG_BUF_WORDS < 32 +#warning "NRF_LOG_BUFSIZE too small, significant number of logs may be lost." +#endif + +NRF_MEMOBJ_POOL_DEF(log_mempool, NRF_LOG_MSGPOOL_ELEMENT_SIZE, NRF_LOG_MSGPOOL_ELEMENT_COUNT); +NRF_RINGBUF_DEF(m_log_push_ringbuf, NRF_LOG_STR_PUSH_BUFFER_SIZE); + +#define NRF_LOG_BACKENDS_FULL 0xFF +#define NRF_LOG_FILTER_BITS_PER_BACKEND 3 +#define NRF_LOG_MAX_BACKENDS (32/NRF_LOG_FILTER_BITS_PER_BACKEND) +#define NRF_LOG_MAX_HEXDUMP (NRF_LOG_MSGPOOL_ELEMENT_SIZE*NRF_LOG_MSGPOOL_ELEMENT_COUNT/2) +#define NRF_LOG_INVALID_BACKEND_U32 0xFFFFFFFF + +/* Mask is extracted from the structure log_data_t to allow compile time initialization which + * is needed to allow usage of the logger (logging) before logger is initialized. + * It cannot be part of the log_data_t because some compilers would put whole log_data_t structure + * into flash (including buffer) just because one field is initilized. + */ +static uint32_t m_buffer_mask = NRF_LOG_BUF_WORDS - 1; // Size of buffer (must be power of 2) presented as mask + +/** + * brief An internal control block of the logger + * + * @note Circular buffer is using never cleared indexes and a mask. It means + * that logger may break when indexes overflows. However, it is quite unlikely. + * With rate of 1000 log entries with 2 parameters per second such situation + * would happen after 12 days. + */ +typedef struct +{ + bool autoflush; + uint32_t wr_idx; // Current write index (never reset) + uint32_t rd_idx; // Current read index (never_reset) + uint32_t buffer[NRF_LOG_BUF_WORDS]; + nrf_log_timestamp_func_t timestamp_func; // A pointer to function that returns timestamp + nrf_log_backend_t const * p_backend_head; + nrf_atomic_flag_t log_skipping; + nrf_atomic_flag_t log_skipped; + nrf_atomic_u32_t log_dropped_cnt; +} log_data_t; + +static log_data_t m_log_data; + +NRF_LOG_MODULE_REGISTER(); + +// Helper macros for section variables. +#define NRF_LOG_DYNAMIC_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_dynamic_data, nrf_log_module_dynamic_data_t, (i)) +#define NRF_LOG_FILTER_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_filter_data, nrf_log_module_filter_data_t, (i)) + +#define NRF_LOG_CONST_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_const_data, nrf_log_module_const_data_t, (i)) +#define NRF_LOG_CONST_SECTION_VARS_COUNT NRF_SECTION_ITEM_COUNT(log_const_data, nrf_log_module_const_data_t) + +ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func, uint32_t timestamp_freq) +{ + (void)NRF_LOG_ITEM_DATA_CONST(app); + + if (NRF_LOG_USES_TIMESTAMP && (timestamp_func == NULL)) + { + return NRF_ERROR_INVALID_PARAM; + } + + m_log_data.autoflush = NRF_LOG_DEFERRED ? false : true; + + if (NRF_LOG_USES_TIMESTAMP) + { + nrf_log_str_formatter_timestamp_freq_set(timestamp_freq); + m_log_data.timestamp_func = timestamp_func; + } + +#ifdef UNIT_TEST + m_buffer_mask = NRF_LOG_BUF_WORDS - 1; +#endif + + ret_code_t err_code = nrf_memobj_pool_init(&log_mempool); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + nrf_ringbuf_init(&m_log_push_ringbuf); + + uint32_t modules_cnt = NRF_LOG_CONST_SECTION_VARS_COUNT; + uint32_t i; + if (NRF_LOG_FILTERS_ENABLED) + { + uint32_t j; + //sort modules by name + for (i = 0; i < modules_cnt; i++) + { + uint32_t idx = 0; + + for (j = 0; j < modules_cnt; j++) + { + if (i != j) + { + char const * p_name0 = NRF_LOG_CONST_SECTION_VARS_GET(i)->p_module_name; + char const * p_name1 = NRF_LOG_CONST_SECTION_VARS_GET(j)->p_module_name; + if (strncmp(p_name0, p_name1, 20) > 0) + { + idx++; + } + } + + } + nrf_log_module_dynamic_data_t * p_module_ddata = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + p_module_ddata->order_idx = idx; + } + + /* Initialize filters */ + for (i = 0; i < modules_cnt; i++) + { + nrf_log_module_dynamic_data_t * p_module_ddata = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + nrf_log_module_filter_data_t * p_module_filter = NRF_LOG_FILTER_SECTION_VARS_GET(i); + p_module_ddata->filter = 0; + p_module_filter->filter_lvls = 0; + } + } + + return NRF_SUCCESS; +} + +uint32_t nrf_log_module_cnt_get(void) +{ + return NRF_LOG_CONST_SECTION_VARS_COUNT; +} + +static ret_code_t module_idx_get(uint32_t * p_idx, bool ordered_idx) +{ + if (ordered_idx) + { + uint32_t module_cnt = nrf_log_module_cnt_get(); + uint32_t i; + for (i = 0; i < module_cnt; i++) + { + nrf_log_module_dynamic_data_t * p_module_data = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + if (p_module_data->order_idx == *p_idx) + { + *p_idx = i; + return NRF_SUCCESS; + } + } + return NRF_ERROR_NOT_FOUND; + } + else + { + return NRF_SUCCESS; + } +} +const char * nrf_log_module_name_get(uint32_t module_id, bool ordered_idx) +{ + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id); + return p_module_data->p_module_name; + } + else + { + return NULL; + } +} + +uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity) +{ + nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id); + uint8_t color_id; + switch (severity) + { + case NRF_LOG_SEVERITY_ERROR: + color_id = NRF_LOG_ERROR_COLOR; + break; + case NRF_LOG_SEVERITY_WARNING: + color_id = NRF_LOG_WARNING_COLOR; + break; + case NRF_LOG_SEVERITY_INFO: + color_id = p_module_data->info_color_id; + break; + case NRF_LOG_SEVERITY_DEBUG: + color_id = p_module_data->debug_color_id; + break; + default: + color_id = 0; + break; + } + return color_id; +} + +static uint16_t higher_lvl_get(uint32_t lvls) +{ + uint16_t top_lvl = 0; + uint16_t tmp_lvl; + uint32_t i; + + //Find highest level enabled by backends + for (i = 0; i < (32/NRF_LOG_LEVEL_BITS); i+=NRF_LOG_LEVEL_BITS) + { + tmp_lvl = (uint16_t)BF_GET(lvls,NRF_LOG_LEVEL_BITS, i); + if (tmp_lvl > top_lvl) + { + top_lvl = tmp_lvl; + } + } + return top_lvl; +} + +void nrf_log_module_filter_set(uint32_t backend_id, uint32_t module_id, nrf_log_severity_t severity) +{ + if (NRF_LOG_FILTERS_ENABLED) + { + nrf_log_module_dynamic_data_t * p_module_data = NRF_LOG_DYNAMIC_SECTION_VARS_GET(module_id); + nrf_log_module_filter_data_t * p_filter = NRF_LOG_FILTER_SECTION_VARS_GET(module_id); + + p_filter->filter_lvls &= ~BF_MASK(NRF_LOG_LEVEL_BITS, (NRF_LOG_LEVEL_BITS * backend_id)); + p_filter->filter_lvls |= BF_VAL(severity, NRF_LOG_LEVEL_BITS, (NRF_LOG_LEVEL_BITS * backend_id)); + + p_module_data->filter = higher_lvl_get(p_filter->filter_lvls); + } +} + +static nrf_log_severity_t nrf_log_module_init_filter_get(uint32_t module_id) +{ + nrf_log_module_const_data_t * p_module_data = + NRF_LOG_CONST_SECTION_VARS_GET(module_id); + return NRF_LOG_FILTERS_ENABLED ? p_module_data->initial_lvl : p_module_data->compiled_lvl; +} + +nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id, + uint32_t module_id, + bool ordered_idx, + bool dynamic) +{ + nrf_log_severity_t severity = NRF_LOG_SEVERITY_NONE; + if (NRF_LOG_FILTERS_ENABLED && dynamic) + { + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_filter_data_t * p_filter = NRF_LOG_FILTER_SECTION_VARS_GET(module_id); + severity = (nrf_log_severity_t)BF_GET(p_filter->filter_lvls, + NRF_LOG_LEVEL_BITS, + (backend_id*NRF_LOG_LEVEL_BITS)); + } + } + else if (!dynamic) + { + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_const_data_t * p_module_data = + NRF_LOG_CONST_SECTION_VARS_GET(module_id); + severity = (nrf_log_severity_t)p_module_data->compiled_lvl; + } + } + return severity; +} +/** + * Function examines current header and omits packets which are in progress. + */ +static bool invalid_packets_omit(nrf_log_header_t const * p_header, uint32_t * p_rd_idx) +{ + bool ret = false; + if (p_header->base.generic.in_progress == 1) + { + switch (p_header->base.generic.type) + { + case HEADER_TYPE_STD: + *p_rd_idx += (HEADER_SIZE + p_header->base.std.nargs); + break; + case HEADER_TYPE_HEXDUMP: + *p_rd_idx += (HEADER_SIZE + p_header->base.hexdump.len); + break; + default: + break; + } + ret = true; + } + return ret; +} +/** + * @brief Skips the oldest, not processed logs to make space for new logs. + * @details This function moves forward read index to prepare space for new logs. + */ + +static uint32_t log_skip(void) +{ + uint16_t dropped = 0; + + (void)nrf_atomic_flag_set(&m_log_data.log_skipped); + (void)nrf_atomic_flag_set(&m_log_data.log_skipping); + + uint32_t rd_idx = m_log_data.rd_idx; + uint32_t mask = m_buffer_mask; + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_log_header_t header; + + // Skip packets that may be invalid (interrupted while being in progress) + do { + if (invalid_packets_omit(p_header, &rd_idx)) + { + //something was omitted. Point to new header and try again. + p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + } + else + { + break; + } + } while (true); + + uint32_t i; + for (i = 0; i < HEADER_SIZE; i++) + { + ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask]; + } + + switch (header.base.generic.type) + { + case HEADER_TYPE_HEXDUMP: + dropped = header.dropped; + rd_idx += CEIL_DIV(header.base.hexdump.len, sizeof(uint32_t)); + break; + case HEADER_TYPE_STD: + dropped = header.dropped; + rd_idx += header.base.std.nargs; + break; + default: + ASSERT(false); + break; + } + + uint32_t log_skipping_tmp = nrf_atomic_flag_clear_fetch(&m_log_data.log_skipping); + //update read index only if log_skip was not interrupted by another log skip + if (log_skipping_tmp) + { + m_log_data.rd_idx = rd_idx; + } + + return (uint32_t)dropped; +} + +/** + * @brief Function for getting number of dropped logs. Dropped counter is reset after reading. + * + * @return Number of dropped logs saturated to 16 bits. + */ +static inline uint32_t dropped_sat16_get(void) +{ + uint32_t dropped = nrf_atomic_u32_fetch_store(&m_log_data.log_dropped_cnt, 0); + return __USAT(dropped, 16); //Saturate to 16 bits +} + + +static inline void std_header_set(uint32_t severity_mid, + char const * const p_str, + uint32_t nargs, + uint32_t wr_idx, + uint32_t mask) +{ + + + //Prepare header - in reverse order to ensure that packet type is validated (set to STD as last action) + uint32_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS; + uint32_t dropped = dropped_sat16_get(); + ASSERT(module_id < nrf_log_module_cnt_get()); + m_log_data.buffer[(wr_idx + 1) & mask] = module_id | (dropped << 16); + + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.buffer[(wr_idx + 2) & mask] = m_log_data.timestamp_func(); + } + + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[wr_idx & mask]; + p_header->base.std.severity = severity_mid & NRF_LOG_LEVEL_MASK; + p_header->base.std.nargs = nargs; + p_header->base.std.addr = ((uint32_t)(p_str) & STD_ADDR_MASK); + p_header->base.std.type = HEADER_TYPE_STD; + p_header->base.std.in_progress = 0; +} + +/** + * @brief Allocates chunk in a buffer for one entry and injects overflow if + * there is no room for requested entry. + * + * @param content_len Number of 32bit arguments. In case of allocating for hex dump it + * is the size of the buffer in 32bit words (ceiled). + * @param p_wr_idx Pointer to write index. + * + * @return True if successful allocation, false otherwise. + * + */ +static inline bool buf_prealloc(uint32_t content_len, uint32_t * p_wr_idx, bool std) +{ + uint32_t req_len = content_len + HEADER_SIZE; + bool ret = true; + CRITICAL_REGION_ENTER(); + *p_wr_idx = m_log_data.wr_idx; + uint32_t available_words = (m_buffer_mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + while (req_len > available_words) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_log_data.log_dropped_cnt, 1)); + if (NRF_LOG_ALLOW_OVERFLOW) + { + uint32_t dropped_in_skip = log_skip(); + UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_log_data.log_dropped_cnt, dropped_in_skip)); + available_words = (m_buffer_mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + } + else + { + ret = false; + break; + } + } + + if (ret) + { + nrf_log_main_header_t invalid_header; + invalid_header.raw = 0; + + if (std) + { + invalid_header.std.type = HEADER_TYPE_STD; + invalid_header.std.in_progress = 1; + invalid_header.std.nargs = content_len; + } + else + { + invalid_header.hexdump.type = HEADER_TYPE_HEXDUMP; + invalid_header.hexdump.in_progress = 1; + invalid_header.hexdump.len = content_len; + } + + nrf_log_main_header_t * p_header = + (nrf_log_main_header_t *)&m_log_data.buffer[m_log_data.wr_idx & m_buffer_mask]; + + p_header->raw = invalid_header.raw; + + m_log_data.wr_idx += req_len; + } + + CRITICAL_REGION_EXIT(); + return ret; +} + +char const * nrf_log_push(char * const p_str) +{ + if ((m_log_data.autoflush) || (p_str == NULL)) + { + return p_str; + } + + size_t ssize = strlen(p_str) + 1; // + 1 for null termination + uint8_t * p_dst; + // Allocate space in the ring buffer. It may be smaller than the requested string in case of buffer wrapping or when the ring buffer size is too small. + // Once the string is copied into the buffer, the space is immediately freed. The string is kept in the buffer but can be overwritten. + // It is done that way because there is no other place where space could be freed since string processing happens in + // the logger backends, often by modules which are generic and not aware of internals of the logger. + if (nrf_ringbuf_alloc(&m_log_push_ringbuf, &p_dst, &ssize, true) == NRF_SUCCESS) + { + ret_code_t err; + + memcpy(p_dst, p_str, ssize); + + //Terminate in case string was partial. + p_dst[ssize - 1] = '\0'; + + err = nrf_ringbuf_put(&m_log_push_ringbuf, ssize); + ASSERT(err == NRF_SUCCESS); + + //Immediately free the space where string was put. + err = nrf_ringbuf_free(&m_log_push_ringbuf, ssize); + ASSERT(err == NRF_SUCCESS); + + return (char const *)p_dst; + } + else + { + return NULL; + } +} + +static inline void std_n(uint32_t severity_mid, + char const * const p_str, + uint32_t const * args, + uint32_t nargs) +{ + uint32_t mask = m_buffer_mask; + uint32_t wr_idx; + + if (buf_prealloc(nargs, &wr_idx, true)) + { + // Proceed only if buffer was successfully preallocated. + + uint32_t data_idx = wr_idx + HEADER_SIZE; + uint32_t i; + for (i = 0; i < nargs; i++) + { + m_log_data.buffer[data_idx++ & mask] =args[i]; + } + std_header_set(severity_mid, p_str, nargs, wr_idx, mask); + } + if (m_log_data.autoflush) + { +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_ENTER(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + + NRF_LOG_FLUSH(); + +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_EXIT(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + } + +} + +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str) +{ + std_n(severity_mid, p_str, NULL, 0); +} + + +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0) +{ + uint32_t args[] = {val0}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1) +{ + uint32_t args[] = {val0, val1}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2) +{ + uint32_t args[] = {val0, val1, val2}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3) +{ + uint32_t args[] = {val0, val1, val2, val3}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4) +{ + uint32_t args[] = {val0, val1, val2, val3, val4}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5) +{ + uint32_t args[] = {val0, val1, val2, val3, val4, val5}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length) +{ + uint32_t mask = m_buffer_mask; + + uint32_t wr_idx; + if (buf_prealloc(CEIL_DIV(length, sizeof(uint32_t)), &wr_idx, false)) + { + uint32_t header_wr_idx = wr_idx; + wr_idx += HEADER_SIZE; + + uint32_t space0 = sizeof(uint32_t) * (m_buffer_mask + 1 - (wr_idx & mask)); + if (length <= space0) + { + memcpy(&m_log_data.buffer[wr_idx & mask], p_data, length); + } + else + { + memcpy(&m_log_data.buffer[wr_idx & mask], p_data, space0); + memcpy(&m_log_data.buffer[0], &((uint8_t *)p_data)[space0], length - space0); + } + + //Prepare header - in reverse order to ensure that packet type is validated (set to HEXDUMP as last action) + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.buffer[(header_wr_idx + 2) & mask] = m_log_data.timestamp_func(); + } + + uint32_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS; + uint32_t dropped = dropped_sat16_get(); + m_log_data.buffer[(header_wr_idx + 1) & mask] = module_id | (dropped << 16); + //Header prepare + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[header_wr_idx & mask]; + p_header->base.hexdump.severity = severity_mid & NRF_LOG_LEVEL_MASK; + p_header->base.hexdump.offset = 0; + p_header->base.hexdump.len = length; + p_header->base.hexdump.type = HEADER_TYPE_HEXDUMP; + p_header->base.hexdump.in_progress = 0; + + + + } + + if (m_log_data.autoflush) + { +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_ENTER(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + + NRF_LOG_FLUSH(); + +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_EXIT(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + } +} + + +bool buffer_is_empty(void) +{ + return (m_log_data.rd_idx == m_log_data.wr_idx); +} + +bool nrf_log_frontend_dequeue(void) +{ + + if (buffer_is_empty()) + { + return false; + } + m_log_data.log_skipped = 0; + //It has to be ensured that reading rd_idx occurs after skipped flag is cleared. + __DSB(); + uint32_t rd_idx = m_log_data.rd_idx; + uint32_t mask = m_buffer_mask; + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_log_header_t header; + nrf_memobj_t * p_msg_buf = NULL; + size_t memobj_offset = 0; + uint32_t severity = 0; + + // Skip any in progress packets. + do { + if (invalid_packets_omit(p_header, &rd_idx) && (m_log_data.log_skipped == 0)) + { + //Check if end of data is not reached. + if (rd_idx >= m_log_data.wr_idx) + { + m_log_data.rd_idx = m_log_data.wr_idx; + return false; + } + //something was omitted. Point to new header and try again. + p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + } + else + { + break; + } + } while (true); + + uint32_t i; + for (i = 0; i < HEADER_SIZE; i++) + { + ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask]; + } + + if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t orig_data_len = header.base.hexdump.len; + uint32_t data_len = MIN(header.base.hexdump.len, NRF_LOG_MAX_HEXDUMP); //limit the data + header.base.hexdump.len = data_len; + uint32_t msg_buf_size8 = sizeof(uint32_t)*HEADER_SIZE + data_len; + severity = header.base.hexdump.severity; + p_msg_buf = nrf_memobj_alloc(&log_mempool, msg_buf_size8); + + if (p_msg_buf) + { + nrf_memobj_get(p_msg_buf); + nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset += HEADER_SIZE*sizeof(uint32_t); + + uint32_t space0 = sizeof(uint32_t) * (mask + 1 - (rd_idx & mask)); + if (data_len > space0) + { + uint8_t * ptr0 = space0 ? + (uint8_t *)&m_log_data.buffer[rd_idx & mask] : + (uint8_t *)&m_log_data.buffer[0]; + uint8_t len0 = space0 ? space0 : data_len; + uint8_t * ptr1 = space0 ? + (uint8_t *)&m_log_data.buffer[0] : NULL; + uint8_t len1 = space0 ? data_len - space0 : 0; + + nrf_memobj_write(p_msg_buf, ptr0, len0, memobj_offset); + memobj_offset += len0; + if (ptr1) + { + nrf_memobj_write(p_msg_buf, ptr1, len1, memobj_offset); + } + } + else + { + uint8_t * p_data = (uint8_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_memobj_write(p_msg_buf, p_data, data_len, memobj_offset); + } + rd_idx += CEIL_DIV(orig_data_len, 4); + } + } + else if (header.base.generic.type == HEADER_TYPE_STD) // standard entry + { + header.base.std.nargs = MIN(header.base.std.nargs, NRF_LOG_MAX_NUM_OF_ARGS); + uint32_t msg_buf_size32 = HEADER_SIZE + header.base.std.nargs; + severity = header.base.std.severity; + + p_msg_buf = nrf_memobj_alloc(&log_mempool, msg_buf_size32*sizeof(uint32_t)); + + if (p_msg_buf) + { + nrf_memobj_get(p_msg_buf); + nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset += HEADER_SIZE*sizeof(uint32_t); + + for (i = 0; i < header.base.std.nargs; i++) + { + nrf_memobj_write(p_msg_buf, &m_log_data.buffer[rd_idx++ & mask], + sizeof(uint32_t), memobj_offset); + memobj_offset += sizeof(uint32_t); + } + } + } + else + { + //Do nothing. In case of log overflow buffer can contain corrupted data. + } + + if (p_msg_buf) + { + nrf_log_backend_t const * p_backend = m_log_data.p_backend_head; + if (NRF_LOG_ALLOW_OVERFLOW && m_log_data.log_skipped) + { + // Check if any log was skipped during log processing. Do not forward log if skipping + // occured because data may be invalid. + nrf_memobj_put(p_msg_buf); + } + else + { + while (p_backend) + { + bool entry_accepted = false; + if (nrf_log_backend_is_enabled(p_backend) == true) + { + if (NRF_LOG_FILTERS_ENABLED) + { + uint8_t backend_id = nrf_log_backend_id_get(p_backend); + nrf_log_module_filter_data_t * p_module_filter = + NRF_LOG_FILTER_SECTION_VARS_GET(header.module_id); + uint32_t backend_lvl = BF_GET(p_module_filter->filter_lvls, + NRF_LOG_LEVEL_BITS, + (backend_id*NRF_LOG_LEVEL_BITS)); + + //Degrade INFO_RAW level to INFO. + severity = (severity == NRF_LOG_SEVERITY_INFO_RAW) ? + NRF_LOG_SEVERITY_INFO : severity; + if (backend_lvl >= severity) + { + entry_accepted = true; + } + } + else + { + (void)severity; + entry_accepted = true; + } + } + if (entry_accepted) + { + nrf_log_backend_put(p_backend, p_msg_buf); + } + p_backend = p_backend->p_cb->p_next; + } + + nrf_memobj_put(p_msg_buf); + + if (NRF_LOG_ALLOW_OVERFLOW) + { + // Read index can be moved forward only if dequeueing process was not interrupt by + // skipping procedure. If NRF_LOG_ALLOW_OVERFLOW is set then in case of buffer gets full + // and new logger entry occurs, oldest entry is removed. In that case read index is + // changed and updating it here would corrupt the internal circular buffer. + CRITICAL_REGION_ENTER(); + if (m_log_data.log_skipped == 0) + { + m_log_data.rd_idx = rd_idx; + } + CRITICAL_REGION_EXIT(); + } + else + { + m_log_data.rd_idx = rd_idx; + } + } + } + else + { + //Could not allocate memobj - backends are not freeing them on time. + nrf_log_backend_t const * p_backend = m_log_data.p_backend_head; + //Flush all backends + while (p_backend) + { + nrf_log_backend_flush(p_backend); + p_backend = p_backend->p_cb->p_next; + } + NRF_LOG_WARNING("Backends flushed"); + } + + return buffer_is_empty() ? false : true; +} + +static int32_t backend_id_assign(void) +{ + int32_t candidate_id; + nrf_log_backend_t const * p_backend; + bool id_available; + for (candidate_id = 0; candidate_id < NRF_LOG_MAX_BACKENDS; candidate_id++) + { + p_backend = m_log_data.p_backend_head; + id_available = true; + while (p_backend) + { + if (nrf_log_backend_id_get(p_backend) == candidate_id) + { + id_available = false; + break; + } + p_backend = p_backend->p_cb->p_next; + } + if (id_available) + { + return candidate_id; + } + } + return -1; +} + +int32_t nrf_log_backend_add(nrf_log_backend_t const * p_backend, nrf_log_severity_t severity) +{ + int32_t id = backend_id_assign(); + if (id == -1) + { + return id; + } + + nrf_log_backend_id_set(p_backend, id); + //add to list + if (m_log_data.p_backend_head == NULL) + { + m_log_data.p_backend_head = p_backend; + p_backend->p_cb->p_next = NULL; + } + else + { + p_backend->p_cb->p_next = m_log_data.p_backend_head->p_cb->p_next; + m_log_data.p_backend_head->p_cb->p_next = p_backend; + } + + if (NRF_LOG_FILTERS_ENABLED) + { + uint32_t i; + for (i = 0; i < nrf_log_module_cnt_get(); i++) + { + nrf_log_severity_t buildin_lvl = nrf_log_module_init_filter_get(i); + nrf_log_severity_t actual_severity = MIN(buildin_lvl, severity); + nrf_log_module_filter_set(nrf_log_backend_id_get(p_backend), i, actual_severity); + } + } + + return id; +} + +void nrf_log_backend_remove(nrf_log_backend_t const * p_backend) +{ + nrf_log_backend_t const * p_curr = m_log_data.p_backend_head; + nrf_log_backend_t const * p_prev = NULL; + while (p_curr != p_backend) + { + p_prev = p_curr; + p_curr = p_curr->p_cb->p_next; + } + + if (p_prev) + { + p_prev->p_cb->p_next = p_backend->p_cb->p_next; + } + else + { + m_log_data.p_backend_head = NULL; + } + + p_backend->p_cb->id = NRF_LOG_BACKEND_INVALID_ID; +} + +void nrf_log_panic(void) +{ + nrf_log_backend_t const * p_backend = m_log_data.p_backend_head; + m_log_data.autoflush = true; + while (p_backend) + { + nrf_log_backend_enable(p_backend); + nrf_log_backend_panic_set(p_backend); + p_backend = p_backend->p_cb->p_next; + } +} + +#if NRF_MODULE_ENABLED(LOG_CONFIG_LOAD_STORE) +#include "fds.h" +#define LOG_CONFIG_FILE_ID 0x106E +#define LOG_CONFIG_RECORD_ID 0x3427 + +ret_code_t nrf_log_config_store(void) +{ + fds_record_desc_t desc = {0}; + fds_find_token_t token = {0}; + fds_record_t record = { + .file_id = LOG_CONFIG_FILE_ID, + .key = LOG_CONFIG_RECORD_ID, + .data = { + .p_data = NRF_LOG_FILTER_SECTION_VARS_GET(0), + .length_words = NRF_SECTION_LENGTH(log_filter_data)/sizeof(uint32_t) + } + }; + ret_code_t ret = fds_record_find(LOG_CONFIG_FILE_ID, LOG_CONFIG_RECORD_ID, &desc, &token); + if (ret == NRF_SUCCESS) + { + ret = fds_record_update(&desc, &record); + NRF_LOG_INFO("Logger configuration file updated with result:%d", ret); + } + else if (ret == FDS_ERR_NOT_FOUND) + { + ret = fds_record_write(&desc, &record); + NRF_LOG_INFO("Logger configuration file written with result:%d", ret); + } + else + { + ret = NRF_ERROR_INTERNAL; + } + return ret; +} + +ret_code_t nrf_log_config_load(void) +{ + fds_record_desc_t desc = {0}; + fds_find_token_t token = {0}; + + ret_code_t ret = fds_record_find(LOG_CONFIG_FILE_ID, LOG_CONFIG_RECORD_ID, &desc, &token); + if (ret == NRF_SUCCESS) + { + fds_flash_record_t record = {0}; + ret = fds_record_open(&desc, &record); + if (ret == NRF_SUCCESS) + { + void * p_dest = (void *)NRF_LOG_FILTER_SECTION_VARS_GET(0); + uint32_t length = NRF_SECTION_LENGTH(log_filter_data); + memcpy(p_dest, record.p_data, length); + ret = fds_record_close(&desc); + } + } + else if (ret == FDS_ERR_NOT_FOUND) + { + NRF_LOG_WARNING("Logger configuration file not found."); + ret = NRF_ERROR_NOT_FOUND; + } + else + { + ret = NRF_ERROR_INTERNAL; + } + + return ret; +} +#endif //LOG_CONFIG_LOAD_STORE_ENABLED + +#if NRF_LOG_CLI_CMDS && NRF_CLI_ENABLED +#include "nrf_cli.h" + +typedef void (*nrf_log_cli_backend_cmd_t)(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv); + +static const char * m_severity_lvls[] = { + "none", + "error", + "warning", + "info", + "debug", +}; + +static const char * m_severity_lvls_sorted[] = { + "debug", + "error", + "info", + "none", + "warning", +}; + +/** + * @brief Function for finding backend instance with given name. + * + * @param p_name Name of the backend instance. + * + * @return Pointer to the instance or NULL. + * + */ +static nrf_log_backend_t const * backend_find(char const * p_name) +{ + size_t num_of_backends; + nrf_log_backend_t const * p_backend; + + num_of_backends = NRF_SECTION_ITEM_COUNT(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); + for (size_t i = 0; i < num_of_backends; i++) + { + p_backend = NRF_SECTION_ITEM_GET(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t, i); + if (strcmp(p_name, p_backend->p_name) == 0) + { + return p_backend; + } + } + return NULL; +} + +/** + * @brief Function for executing command on given backend. + */ +static void nrf_cli_backend_cmd_execute(nrf_cli_t const * p_cli, + size_t argc, + char * * argv, + nrf_log_cli_backend_cmd_t func) +{ + //Based on the structure of backend commands, name of the backend can be found at -1 (log backend command). + char const * p_backend_name = argv[-1]; + + nrf_log_backend_t const * p_backend = backend_find(p_backend_name); + + if (p_backend) + { + func(p_cli, p_backend, argc, argv); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Invalid backend: %s\r\n", p_backend_name); + } +} + + +static void log_status(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + uint32_t modules_cnt = nrf_log_module_cnt_get(); + uint32_t i; + + + if (!nrf_log_backend_is_enabled(p_backend)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Logs are halted!\r\n"); + } + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-40s | current | built-in \r\n", "module_name"); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "----------------------------------------------------------\r\n"); + for (i = 0; i < modules_cnt; i++) + { + uint32_t backend_id = p_backend->p_cb->id; + nrf_log_severity_t module_dynamic_lvl = + nrf_log_module_filter_get(backend_id, i, true, true); + nrf_log_severity_t module_compiled_lvl = + nrf_log_module_filter_get(backend_id, i, true, false); + nrf_log_severity_t actual_compiled_lvl = + MIN(module_compiled_lvl, (nrf_log_severity_t)NRF_LOG_DEFAULT_LEVEL); + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-40s | %-7s | %s%s\r\n", + nrf_log_module_name_get(i, true), + m_severity_lvls[module_dynamic_lvl], + m_severity_lvls[actual_compiled_lvl], + actual_compiled_lvl < module_compiled_lvl ? "*" : ""); + } +} + + +static void log_self_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_status(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_backend_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_status); +} + + +static bool module_id_get(const char * p_name, uint32_t * p_id) +{ + uint32_t modules_cnt = nrf_log_module_cnt_get(); + const char * p_tmp_name; + uint32_t j; + for (j = 0; j < modules_cnt; j++) + { + p_tmp_name = nrf_log_module_name_get(j, false); + if (strncmp(p_tmp_name, p_name, 32) == 0) + { + *p_id = j; + break; + } + } + return (j != modules_cnt); +} + + +static bool module_id_filter_set(uint32_t backend_id, + uint32_t module_id, + nrf_log_severity_t lvl) +{ + nrf_log_severity_t buildin_lvl = nrf_log_module_filter_get(backend_id, module_id, false, false); + if (lvl > buildin_lvl) + { + return false; + } + else + { + nrf_log_module_filter_set(backend_id, module_id, lvl); + return true; + } +} + + +static void log_ctrl(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + nrf_log_severity_t lvl; + uint32_t first_m_name_idx; + uint32_t i; + bool all_modules = false; + uint32_t backend_id = p_backend->p_cb->id; + + if (argc > 0) + { + if (strncmp(argv[0], "enable", 7) == 0) + { + if (argc == 1) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad parameter count.\r\n"); + return; + } + + if (argc == 2) + { + all_modules = true; + } + + for (i = 0; i < ARRAY_SIZE(m_severity_lvls); i++) + { + if (strncmp(argv[1], m_severity_lvls[i], 10) == 0) + { + break; + } + } + + if (i == ARRAY_SIZE(m_severity_lvls)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown severity level: %s\r\n", argv[1]); + return; + } + + lvl = (nrf_log_severity_t)i; + first_m_name_idx = 2; + + } + else if (strncmp(argv[0], "disable", 8) == 0) + { + if (argc == 1) + { + all_modules = true; + } + lvl = NRF_LOG_SEVERITY_NONE; + first_m_name_idx = 1; + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown option: %s\r\n", argv[0]); + return; + } + + if (all_modules) + { + for (i = 0; i < nrf_log_module_cnt_get(); i++) + { + if (module_id_filter_set(backend_id, i, lvl) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, + "Level unavailable for module: %s\r\n", + nrf_log_module_name_get(i, false)); + } + } + } + else + { + for (i = first_m_name_idx; i < argc; i++) + { + uint32_t module_id = 0; + if (module_id_get(argv[i], &module_id) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown module:%s\r\n", argv[i]); + } + else if (module_id_filter_set(backend_id, module_id, lvl) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, + "Level unavailable for module: %s\r\n", + nrf_log_module_name_get(module_id, false)); + } + else + { + /* empty */ + } + } + } + } +} + + +static void log_self_ctrl(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_ctrl(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_backend_ctrl(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_ctrl); +} + +static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static); + +NRF_CLI_CREATE_DYNAMIC_CMD(m_module_name, module_name_get); + +static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_module_name; + p_static->p_syntax = nrf_log_module_name_get(idx, true); +} + + +static void severity_lvl_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_module_name; + p_static->p_syntax = (idx < ARRAY_SIZE(m_severity_lvls_sorted)) ? + m_severity_lvls_sorted[idx] : NULL; +} + +NRF_CLI_CREATE_DYNAMIC_CMD(m_severity_lvl, severity_lvl_get); + + +static void log_halt(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + nrf_log_backend_disable(p_backend); +} + + +static void log_backend_halt(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_halt); +} + + +static void log_self_halt(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_halt(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_go(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + nrf_log_backend_enable(p_backend); +} + + +static void log_backend_go(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_go); +} + + +static void log_self_go(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_go(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_cmd_backends_list(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + size_t num_of_backends; + + num_of_backends = NRF_SECTION_ITEM_COUNT(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); + for (size_t i = 0; i < num_of_backends; i++) + { + nrf_log_backend_t const * p_backend = + NRF_SECTION_ITEM_GET(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t, i); + + if (p_backend->p_cb->id == NRF_LOG_BACKEND_INVALID_ID) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n" + "\t- Status: deactivated\r\n\r\n", + p_backend->p_name); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n" + "\t- Status: %s\r\n" + "\t- ID: %d\r\n\r\n", + p_backend->p_name, + p_backend->p_cb->enabled ? "enabled" : "disabled", + p_backend->p_cb->id); + } + } +} + + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_backend) +{ + NRF_CLI_CMD(disable, &m_module_name, + "'log disable .. ' disables logs in specified " + "modules (all if no modules specified).", + log_backend_ctrl), + NRF_CLI_CMD(enable, &m_severity_lvl, + "'log enable ... ' enables logs up to given level in " + "specified modules (all if no modules specified).", + log_backend_ctrl), + NRF_CLI_CMD(go, NULL, "Resume logging", log_backend_go), + NRF_CLI_CMD(halt, NULL, "Halt logging", log_backend_halt), + NRF_CLI_CMD(status, NULL, "Logger status", log_backend_status), + NRF_CLI_SUBCMD_SET_END +}; + +static void backend_name_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_sub_log_backend; + p_static->p_syntax = NULL; + + nrf_log_backend_t const * p_backend; + size_t active_idx = 0; + uint32_t i; + + for (i = 0; i < NRF_SECTION_ITEM_COUNT(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); i++) + { + p_backend = NRF_SECTION_ITEM_GET(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t, i); + if (p_backend->p_cb->id != NRF_LOG_BACKEND_INVALID_ID) + { + if (idx == active_idx) + { + p_static->p_syntax = p_backend->p_name; + break; + } + else + { + active_idx++; + } + } + } +} + +NRF_CLI_CREATE_DYNAMIC_CMD(m_backend_name_dynamic, backend_name_get); + +static void log_config_load_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + +#if LOG_CONFIG_LOAD_STORE_ENABLED + if (nrf_log_config_load() == NRF_SUCCESS) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Configuration loaded.\r\n"); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Failed to load the configuration.\r\n"); + } +#else + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Not supported.\r\n"); +#endif +} + +static void log_config_store_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + +#if LOG_CONFIG_LOAD_STORE_ENABLED + if (nrf_log_config_store() == NRF_SUCCESS) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Configuration stored.\r\n"); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Failed to store the configuration.\r\n"); + } +#else + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Not supported.\r\n"); +#endif +} + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_config) +{ + NRF_CLI_CMD(load, NULL, "Load configuration stored in non-volatile memory.", log_config_load_cmd), + NRF_CLI_CMD(store, NULL, "Store current configuration in non-volatile memory.", log_config_store_cmd), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_stat) +{ + NRF_CLI_CMD(backend, &m_backend_name_dynamic, "Logger backends commands.", NULL), + NRF_CLI_CMD(config, &m_sub_log_config, "Manage logger configuration", NULL), + NRF_CLI_CMD(disable, &m_module_name, + "'log disable .. ' disables logs in specified " + "modules (all if no modules specified).", + log_self_ctrl), + NRF_CLI_CMD(enable, &m_severity_lvl, + "'log enable ... ' enables logs up to given level in " + "specified modules (all if no modules specified).", + log_self_ctrl), + NRF_CLI_CMD(go, NULL, "Resume logging", log_self_go), + NRF_CLI_CMD(halt, NULL, "Halt logging", log_self_halt), + NRF_CLI_CMD(list_backends, NULL, "Lists logger backends.", log_cmd_backends_list), + NRF_CLI_CMD(status, NULL, "Logger status", log_self_status), + NRF_CLI_SUBCMD_SET_END +}; + +static void log_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if ((argc == 1) || nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "%s:%s%s\r\n", argv[0], " unknown parameter: ", argv[1]); +} + +NRF_CLI_CMD_REGISTER(log, &m_sub_log_stat, "Commands for controlling logger", log_cmd); + +#endif //NRF_LOG_CLI_CMDS + +#endif // NRF_MODULE_ENABLED(NRF_LOG) diff --git a/libraries/nfc/src/util/nrf_log_instance.h b/libraries/nfc/src/util/nrf_log_instance.h new file mode 100644 index 000000000..6838974d4 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_instance.h @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_INSTANCE_H +#define NRF_LOG_INSTANCE_H + +#include "sdk_config.h" +#include "nrf_section.h" +#include "nrf_log_types.h" +#include + + +/* + * For GCC, sections are sorted in the group by the linker. For IAR and KEIL, it is assumed that linker will sort + * dynamic and const section in the same order (but in different locations). Proper message formatting + * is based on that assumption. + */ +#if defined(__GNUC__) +#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) CONCAT_2(log_dynamic_data_,_module_name) +#define NRF_LOG_FILTER_SECTION_NAME(_module_name) CONCAT_2(log_filter_data_,_module_name) +#define NRF_LOG_CONST_SECTION_NAME(_module_name) CONCAT_2(log_const_data_,_module_name) +#else +#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) log_dynamic_data +#define NRF_LOG_FILTER_SECTION_NAME(_module_name) log_filter_data +#define NRF_LOG_CONST_SECTION_NAME(_module_name) log_const_data +#endif + +#define NRF_LOG_ITEM_DATA(_name) CONCAT_3(m_nrf_log_,_name,_logs_data) +#define NRF_LOG_ITEM_DATA_DYNAMIC(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_dynamic) +#define NRF_LOG_ITEM_DATA_FILTER(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_filter) +#define NRF_LOG_ITEM_DATA_CONST(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_const) + +#ifdef UNIT_TEST +#define _CONST +#else +#define _CONST const +#endif + +/*lint -save -esym(526,log_const_data*) -esym(526,log_dynamic_data*)*/ +NRF_SECTION_DEF(log_dynamic_data, nrf_log_module_dynamic_data_t); +NRF_SECTION_DEF(log_filter_data, nrf_log_module_filter_data_t); +NRF_SECTION_DEF(log_const_data, nrf_log_module_const_data_t); +/*lint -restore*/ + +#define NRF_LOG_INTERNAL_CONST_ITEM_REGISTER( \ + _name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_CONST_SECTION_NAME(_name), \ + _CONST nrf_log_module_const_data_t NRF_LOG_ITEM_DATA_CONST(_name)) = { \ + .p_module_name = _str_name, \ + .info_color_id = (_info_color), \ + .debug_color_id = (_debug_color), \ + .compiled_lvl = (nrf_log_severity_t)(_compiled_lvl), \ + .initial_lvl = (nrf_log_severity_t)(_initial_lvl), \ + } + +#if NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_INTERNAL_ITEM_REGISTER( \ + _name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_LOG_INTERNAL_CONST_ITEM_REGISTER(_name, \ + _str_name, \ + _info_color, \ + _debug_color, \ + _initial_lvl, \ + _compiled_lvl); \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_DYNAMIC_SECTION_NAME(_name), \ + nrf_log_module_dynamic_data_t NRF_LOG_ITEM_DATA_DYNAMIC(_name)); \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_FILTER_SECTION_NAME(_name), \ + nrf_log_module_filter_data_t NRF_LOG_ITEM_DATA_FILTER(_name)) + +#else +#define NRF_LOG_INTERNAL_ITEM_REGISTER( \ + _name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_LOG_INTERNAL_CONST_ITEM_REGISTER(_name, \ + _str_name, \ + _info_color, \ + _debug_color, \ + _initial_lvl, \ + _compiled_lvl) + +#endif +/**@file + * + * @defgroup nrf_log_instance Macros for logging on instance level + * @{ + * @ingroup nrf_log + * + * @brief Macros for logging on instance level + */ + +/** @def NRF_LOG_INSTANCE_PTR_DECLARE + * @brief Macro for declaring a logger instance pointer in the module stucture. + */ + +/** @def NRF_LOG_INSTANCE_REGISTER + * @brief Macro for creating an independent module instance. + * + * Module instance provides filtering of logs on instance level instead of module level. + */ + +/** @def NRF_LOG_INSTANCE_PTR_INIT + * @brief Macro for initializing a pointer to the logger instance. + */ + + + /** @} */ +#if NRF_LOG_ENABLED && NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_INSTANCE_PTR_DECLARE(_p_name) nrf_log_module_dynamic_data_t * _p_name; + +#define NRF_LOG_INSTANCE_REGISTER( \ + _module_name, _inst_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_LOG_INTERNAL_ITEM_REGISTER(CONCAT_3(_module_name,_,_inst_name), \ + STRINGIFY(_module_name._inst_name), \ + _info_color, \ + _debug_color, \ + _initial_lvl, \ + _compiled_lvl) + +#define NRF_LOG_INSTANCE_PTR_INIT(_p_name, _module_name, _inst_name) \ + ._p_name = &NRF_LOG_ITEM_DATA_DYNAMIC(CONCAT_3(_module_name,_,_inst_name)), + +#else +#define NRF_LOG_INSTANCE_PTR_DECLARE(_p_name) +#define NRF_LOG_INSTANCE_REGISTER(_module_name, _inst_name, info_color, debug_color, _initial_lvl, compiled_lvl) +#define NRF_LOG_INSTANCE_PTR_INIT(_p_name, _module_name, _inst_name) +#endif + +#endif //NRF_LOG_INSTANCE_H diff --git a/libraries/nfc/src/util/nrf_log_internal.h b/libraries/nfc/src/util/nrf_log_internal.h new file mode 100644 index 000000000..2ca00c055 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_internal.h @@ -0,0 +1,516 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_INTERNAL_H__ +#define NRF_LOG_INTERNAL_H__ +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_error.h" +#include "app_util.h" +#include +#include +#include "nrf_log_instance.h" +#include "nrf_log_types.h" + +#ifndef NRF_LOG_ERROR_COLOR + #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_WARNING_COLOR + #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_INFO_COLOR + #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_DEBUG_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT +#endif + + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 0 +#endif + +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +#ifndef NRF_LOG_MODULE_NAME + #define NRF_LOG_MODULE_NAME app +#endif + +#define NRF_LOG_LEVEL_BITS 3 +#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1) +#define NRF_LOG_MODULE_ID_BITS 16 +#define NRF_LOG_MODULE_ID_POS 16 + + +#define NRF_LOG_MAX_NUM_OF_ARGS 6 + + +#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED + #define NRF_LOG_FILTER NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).filter + #define NRF_LOG_INST_FILTER(p_inst) (p_inst)->filter +#else + #undef NRF_LOG_FILTER + #define NRF_LOG_FILTER NRF_LOG_SEVERITY_DEBUG + #define NRF_LOG_INST_FILTER(p_inst) NRF_LOG_SEVERITY_DEBUG +#endif + +/** + * @brief Macro for calculating module id based on address and section start address + */ +#define NRF_LOG_MODULE_ID_GET_CONST(addr) (((uint32_t)(addr) - \ + (uint32_t)NRF_SECTION_START_ADDR(log_const_data)) / \ + sizeof(nrf_log_module_const_data_t)) +/** + * @brief Macro for calculating module id based on address and section start address + */ +#define NRF_LOG_MODULE_ID_GET_DYNAMIC(addr) (((uint32_t)(addr) - \ + (uint32_t)NRF_SECTION_START_ADDR(log_dynamic_data)) / \ + sizeof(nrf_log_module_dynamic_data_t)) + + +#if NRF_LOG_ENABLED +#define NRF_LOG_MODULE_ID NRF_LOG_MODULE_ID_GET_CONST(&NRF_LOG_ITEM_DATA_CONST(NRF_LOG_MODULE_NAME)) +#if NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_INST_ID(p_inst) NRF_LOG_MODULE_ID_GET_DYNAMIC(p_inst) +#else +#define NRF_LOG_INST_ID(p_inst) NRF_LOG_MODULE_ID +#endif +#else +#define NRF_LOG_MODULE_ID 0 +#define NRF_LOG_INST_ID(p_inst) 0 +#endif + + +#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) +#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ + __VA_ARGS__), type, __VA_ARGS__) +#if NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str) +#define LOG_INTERNAL_0(type, str) \ + nrf_log_frontend_std_0(type, str) +#define LOG_INTERNAL_1(type, str, arg0) \ + /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/ +#define LOG_INTERNAL_2(type, str, arg0, arg1) \ + /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1))/*lint -restore*/ +#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \ + /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/ +#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \ + /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/ +#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \ + /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/ +#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \ + /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/ + + +#else //NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str) +#define LOG_INTERNAL_0(_type, _str) \ + (void)(_type); (void)(_str) +#define LOG_INTERNAL_1(_type, _str, _arg0) \ + (void)(_type); (void)(_str); (void)(_arg0) +#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1) +#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2) +#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3) +#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4) +#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5) +#endif //NRF_LOG_ENABLED + +#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS) +#define LOG_SEVERITY_INST_ID(severity,p_inst) ((severity) | NRF_LOG_INST_ID(p_inst) << NRF_LOG_MODULE_ID_POS) + +#if NRF_LOG_ENABLED +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + nrf_log_frontend_hexdump((_severity), (_p_data), (_length)) +#else +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + (void)(_severity); (void)(_p_data); (void)_length +#endif + +#define NRF_LOG_INTERNAL_INST(level, level_id, p_inst, ...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_INST_FILTER(p_inst) >= level) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_INST_ID(level_id, p_inst), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= level) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_INST(level, level_id, p_inst, p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_INST_FILTER(p_inst) >= level) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_INST_ID(level_id, p_inst), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_MODULE(level, level_id, p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= level) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(level_id), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_INST_ERROR(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_ERROR(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR,__VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_data, len) + +#define NRF_LOG_INTERNAL_INST_WARNING(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_WARNING(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING,__VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_data, len) + +#define NRF_LOG_INTERNAL_INST_INFO(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_INFO(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_data, len) + +#define NRF_LOG_INTERNAL_RAW_INFO(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, p_data, len) + +#define NRF_LOG_INTERNAL_INST_DEBUG(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_DEBUG(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_data, len) + + +#if NRF_LOG_ENABLED + +#ifdef UNIT_TEST +#define COMPILED_LOG_LEVEL 4 +#else +#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL +#endif + + +#define NRF_LOG_INTERNAL_MODULE_REGISTER() \ + NRF_LOG_INTERNAL_ITEM_REGISTER(NRF_LOG_MODULE_NAME, \ + STRINGIFY(NRF_LOG_MODULE_NAME), \ + NRF_LOG_INFO_COLOR, \ + NRF_LOG_DEBUG_COLOR, \ + NRF_LOG_INITIAL_LEVEL, \ + COMPILED_LOG_LEVEL) + +#else +#define NRF_LOG_INTERNAL_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/ +#endif + +extern nrf_log_module_dynamic_data_t NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME); +extern _CONST nrf_log_module_const_data_t NRF_LOG_ITEM_DATA_CONST(NRF_LOG_MODULE_NAME); + +/** + * Set of macros for encoding and decoding header for log entries. + * There are 2 types of entries: + * 1. Standard entry (STD) + * An entry consists of header, pointer to string and values. Header contains + * severity leveland determines number of arguments and thus size of the entry. + * Since flash address space starts from 0x00000000 and is limited to kB rather + * than MB 22 bits are used to store the address (4MB). It is used that way to + * save one RAM memory. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS| P_STR | + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | ARG0 | + * |------------------------------| + * | .... | + * |------------------------------| + * | ARG(nargs-1) | + * -------------------------------- + * + * 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of + * header, optional timestamp, pointer to string and data. A header contains + * length (10bit) and offset which is updated after backend processes part of + * data. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS|OFFSET|LEN| + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | P_STR | + * |------------------------------| + * | data | + * |------------------------------| + * | data | dummy | + * -------------------------------- + * + */ + +#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U) +#define HEADER_TYPE_STD 1U +#define HEADER_TYPE_HEXDUMP 2U +#define HEADER_TYPE_INVALID 3U + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t data : 29; +} nrf_log_generic_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t severity : 3; + uint32_t nargs : 4; + uint32_t addr : 22; +} nrf_log_std_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t severity : 3; + uint32_t offset : 10; + uint32_t reserved : 6; + uint32_t len : 10; +} nrf_log_hexdump_header_t; + +typedef union +{ + nrf_log_generic_header_t generic; + nrf_log_std_header_t std; + nrf_log_hexdump_header_t hexdump; + uint32_t raw; +} nrf_log_main_header_t; + +typedef struct +{ + nrf_log_main_header_t base; + uint16_t module_id; + uint16_t dropped; + uint32_t timestamp; +} nrf_log_header_t; + +#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \ + (NRF_LOG_USES_TIMESTAMP ? 0 : 1)) + +/** + * @brief A function for logging raw string. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string. + */ +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str); + +/** + * @brief A function for logging a formatted string with one argument. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0 An argument. + */ +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0); + +/** + * @brief A function for logging a formatted string with 2 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1 Arguments for formatting string. + */ +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1); + +/** + * @brief A function for logging a formatted string with 3 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2 Arguments for formatting string. + */ +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2); + +/** + * @brief A function for logging a formatted string with 4 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3 Arguments for formatting string. + */ +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3); + +/** + * @brief A function for logging a formatted string with 5 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4 Arguments for formatting string. + */ +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4); + +/** + * @brief A function for logging a formatted string with 6 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4, val5 Arguments for formatting string. + */ +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5); + +/** + * @brief A function for logging raw data. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string which is prefixing the data. + * @param p_data A pointer to data to be dumped. + * @param length Length of data (in bytes). + * + */ +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length); + +/** + * @brief A function for reading a byte from log backend. + * + * @return Byte. + */ +uint8_t nrf_log_getchar(void); +#endif // NRF_LOG_INTERNAL_H__ diff --git a/libraries/nfc/src/util/nrf_log_str_formatter.c b/libraries/nfc/src/util/nrf_log_str_formatter.c new file mode 100644 index 000000000..c65ff8c93 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_str_formatter.c @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#include "nrf_log_ctrl.h" +#include "nrf_fprintf.h" +#include + +#define NRF_LOG_COLOR_CODE_DEFAULT "\x1B[0m" +#define NRF_LOG_COLOR_CODE_BLACK "\x1B[1;30m" +#define NRF_LOG_COLOR_CODE_RED "\x1B[1;31m" +#define NRF_LOG_COLOR_CODE_GREEN "\x1B[1;32m" +#define NRF_LOG_COLOR_CODE_YELLOW "\x1B[1;33m" +#define NRF_LOG_COLOR_CODE_BLUE "\x1B[1;34m" +#define NRF_LOG_COLOR_CODE_MAGENTA "\x1B[1;35m" +#define NRF_LOG_COLOR_CODE_CYAN "\x1B[1;36m" +#define NRF_LOG_COLOR_CODE_WHITE "\x1B[1;37m" + +#define NRF_LOG_CHAR_CODE_MAX 0x7E + +static const char * severity_names[] = { + NULL, + "error", + "warning", + "info", + "debug" +}; + +static const char * m_colors[] = { + NRF_LOG_COLOR_CODE_DEFAULT, + NRF_LOG_COLOR_CODE_BLACK, + NRF_LOG_COLOR_CODE_RED, + NRF_LOG_COLOR_CODE_GREEN, + NRF_LOG_COLOR_CODE_YELLOW, + NRF_LOG_COLOR_CODE_BLUE, + NRF_LOG_COLOR_CODE_MAGENTA, + NRF_LOG_COLOR_CODE_CYAN, + NRF_LOG_COLOR_CODE_WHITE, +}; + +static uint32_t m_freq; +static uint32_t m_timestamp_div; + +static void timestamp_print(nrf_fprintf_ctx_t * p_ctx, uint32_t timestamp) +{ + if (NRF_LOG_USES_TIMESTAMP) + { + if (NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED) + { + timestamp /= m_timestamp_div; + uint32_t seconds = timestamp/m_freq; + uint32_t hours = seconds/3600; + seconds -= hours * 3600; + uint32_t mins = seconds/60; + seconds -= mins * 60; + + uint32_t reminder = timestamp % m_freq; + uint32_t ms = (reminder * 1000)/m_freq; + uint32_t us = (1000*(1000*reminder - (ms * m_freq)))/m_freq; + + nrf_fprintf(p_ctx, "[%02d:%02d:%02d.%03d,%03d] ", hours, mins, seconds, ms, us); + } + else + { + nrf_fprintf(p_ctx, "[%08lu] ", timestamp); + } + } +} +static void prefix_process(nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + if (p_params->dropped) + { + nrf_fprintf(p_ctx, + "%sLogs dropped (%d)%s\r\n", + NRF_LOG_COLOR_CODE_RED, + p_params->dropped, + NRF_LOG_COLOR_CODE_DEFAULT); + } + + if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW)) + { + if (p_params->use_colors) + { + nrf_fprintf(p_ctx, "%s", + m_colors[nrf_log_color_id_get( p_params->module_id, p_params->severity)]); + } + timestamp_print(p_ctx, p_params->timestamp); + + nrf_fprintf(p_ctx, "<%s> %s: ", + severity_names[p_params->severity], nrf_log_module_name_get(p_params->module_id, false)); + } +} + +static void postfix_process(nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx, + bool newline) +{ + if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW)) + { + if (p_params->use_colors) + { + nrf_fprintf(p_ctx, "%s", m_colors[0]); + } + nrf_fprintf(p_ctx, "\r\n"); + } + else if (newline) + { + nrf_fprintf(p_ctx, "\r\n"); + } + nrf_fprintf_buffer_flush(p_ctx); +} + +void nrf_log_std_entry_process(char const * p_str, + uint32_t const * p_args, + uint32_t nargs, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + bool auto_flush = p_ctx->auto_flush; + p_ctx->auto_flush = false; + + prefix_process(p_params, p_ctx); + + switch (nargs) + { + case 0: + nrf_fprintf(p_ctx, p_str); + break; + case 1: + nrf_fprintf(p_ctx, p_str, p_args[0]); + break; + case 2: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1]); + break; + case 3: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2]); + break; + case 4: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3]); + break; + case 5: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4]); + break; + case 6: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5]); + break; + + default: + break; + } + + postfix_process(p_params, p_ctx, false); + p_ctx->auto_flush = auto_flush; +} + +#define HEXDUMP_BYTES_IN_LINE 8 + +void nrf_log_hexdump_entry_process(uint8_t * p_data, + uint32_t data_len, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + if (data_len > HEXDUMP_BYTES_IN_LINE) + { + return; + } + bool auto_flush = p_ctx->auto_flush; + p_ctx->auto_flush = false; + + prefix_process(p_params, p_ctx); + + uint32_t i; + + for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) + { + if (i < data_len) + { + nrf_fprintf(p_ctx, " %02x", p_data[i]); + } + else + { + nrf_fprintf(p_ctx, " "); + } + } + nrf_fprintf(p_ctx, "|"); + + for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) + { + if (i < data_len) + { + char c = (char)p_data[i]; + nrf_fprintf(p_ctx, "%c", ((c <= NRF_LOG_CHAR_CODE_MAX) && isprint((int)c)) ? c :'.'); + } + else + { + nrf_fprintf(p_ctx, " "); + } + } + + postfix_process(p_params, p_ctx, true); + + p_ctx->auto_flush = auto_flush; +} + +void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq) +{ + m_timestamp_div = 1; + /* There is no point to have frequency higher than 1MHz (ns are not printed) and too high + * frequency leads to overflows in calculations. + */ + while (freq > 1000000) + { + freq /= 2; + m_timestamp_div *= 2; + } + m_freq = freq; +} +#endif //NRF_LOG_ENABLED diff --git a/libraries/nfc/src/util/nrf_log_str_formatter.h b/libraries/nfc/src/util/nrf_log_str_formatter.h new file mode 100644 index 000000000..55b36d759 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_str_formatter.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup nrf_log_str_formatter String formatter for the logger messages + * @{ + * @ingroup nrf_log + */ + +#ifndef NRF_LOG_STR_FORMATTER_H +#define NRF_LOG_STR_FORMATTER_H + +#include +#include "nrf_fprintf.h" +#include "nrf_log_ctrl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint32_t timestamp; + uint16_t module_id; + uint16_t dropped; + nrf_log_severity_t severity; + uint8_t use_colors; +} nrf_log_str_formatter_entry_params_t; + + +void nrf_log_std_entry_process(char const * p_str, + uint32_t const * p_args, + uint32_t nargs, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx); + +void nrf_log_hexdump_entry_process(uint8_t * p_data, + uint32_t data_len, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx); + +void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq); +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_STR_FORMATTER_H +/** @} */ diff --git a/libraries/nfc/src/util/nrf_log_types.h b/libraries/nfc/src/util/nrf_log_types.h new file mode 100644 index 000000000..e0b707807 --- /dev/null +++ b/libraries/nfc/src/util/nrf_log_types.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_TYPES_H +#define NRF_LOG_TYPES_H + +#include + +/** + * @brief Logger severity levels. + */ +typedef enum +{ + NRF_LOG_SEVERITY_NONE, + NRF_LOG_SEVERITY_ERROR, + NRF_LOG_SEVERITY_WARNING, + NRF_LOG_SEVERITY_INFO, + NRF_LOG_SEVERITY_DEBUG, + NRF_LOG_SEVERITY_INFO_RAW, /* Artificial level to pass information about skipping string postprocessing.*/ +} nrf_log_severity_t; + +/** + * @brief Structure holding dynamic data associated with a module. + * + * See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER. + */ +typedef struct +{ + uint16_t order_idx; ///< Ordered index of the module (used for auto-completion). + uint16_t filter; ///< Current highest severity level accepted (redundant to @ref nrf_log_module_filter_data_t::filter_lvls, used for optimization) +} nrf_log_module_dynamic_data_t; + +/** + * @brief Structure holding dynamic filters associated with a module or instance if filtering is enabled (@ref NRF_LOG_FILTERS_ENABLED). + * + * @note Backend filters logically are part of @ref nrf_log_module_dynamic_data_t but they are kept separated to enable storing them in non-volatile memory. + */ +typedef struct +{ + uint32_t filter_lvls; ///< Current severity levels for each backend (3 bits per backend). +} nrf_log_module_filter_data_t; + +/** + * @brief Structure holding constant data associated with a module or instance. + * + * See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER. + */ +typedef struct +{ + const char * p_module_name; ///< Module or instance name. + uint8_t info_color_id; ///< Color code of info messages. + uint8_t debug_color_id; ///< Color code of debug messages. + nrf_log_severity_t compiled_lvl; ///< Compiled highest severity level. + nrf_log_severity_t initial_lvl; ///< Severity level for given module or instance set on backend initialization. +} nrf_log_module_const_data_t; + +#endif //NRF_LOG_TYPES_H diff --git a/libraries/nfc/src/util/nrf_memobj.c b/libraries/nfc/src/util/nrf_memobj.c new file mode 100644 index 000000000..c5bb7d592 --- /dev/null +++ b/libraries/nfc/src/util/nrf_memobj.c @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_memobj.h" +#include "nrf_atomic.h" +#include "nrf_assert.h" + +typedef struct memobj_elem_s memobj_elem_t; + +/** @brief Standard chunk header. */ +typedef struct +{ + memobj_elem_t * p_next; ///< Pointer to the next element. +} memobj_header_t; + +/** @brief Head header extension fields. */ +typedef struct +{ + uint8_t user_cnt; ///< User counter (see @ref nrf_memobj_get and @ref nrf_memobj_put). + uint8_t chunk_cnt; ///< Number of chunks in the object. + uint16_t chunk_size; ///< Single chunk size +} memobj_head_header_fields_t; + +/** @brief Head header extension. */ +typedef struct +{ + union + { + nrf_atomic_u32_t atomic_user_cnt; + memobj_head_header_fields_t fields; + } data; +} memobj_head_header_t; + +/** @brief Head chunk structure. */ +typedef struct +{ + memobj_header_t header; ///< Standard header. + memobj_head_header_t head_header; ///< Head-specific header part. + uint8_t data[1]; ///< Data. +} memobj_head_t; + +STATIC_ASSERT(sizeof(memobj_header_t) == NRF_MEMOBJ_STD_HEADER_SIZE); + +/** @brief Standard chunk structure. */ +struct memobj_elem_s +{ + memobj_header_t header; ///< Standard header. + uint8_t data[1]; ///< Data. +}; + +ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool) +{ + return nrf_balloc_init((nrf_balloc_t const *)p_pool); +} + +nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool, + size_t size) +{ + uint32_t bsize = (uint32_t)NRF_BALLOC_ELEMENT_SIZE((nrf_balloc_t const *)p_pool) - sizeof(memobj_header_t); + uint8_t num_of_chunks = (uint8_t)CEIL_DIV(size + sizeof(memobj_head_header_t), bsize); + + memobj_head_t * p_head = nrf_balloc_alloc((nrf_balloc_t const *)p_pool); + if (p_head == NULL) + { + return NULL; + } + p_head->head_header.data.fields.user_cnt = 0; + p_head->head_header.data.fields.chunk_cnt = 1; + p_head->head_header.data.fields.chunk_size = bsize; + + memobj_header_t * p_prev = (memobj_header_t *)p_head; + memobj_header_t * p_curr; + uint32_t i; + uint32_t chunk_less1 = (uint32_t)num_of_chunks - 1; + + p_prev->p_next = (memobj_elem_t *)p_pool; + for (i = 0; i < chunk_less1; i++) + { + p_curr = (memobj_header_t *)nrf_balloc_alloc((nrf_balloc_t const *)p_pool); + if (p_curr) + { + (p_head->head_header.data.fields.chunk_cnt)++; + p_prev->p_next = (memobj_elem_t *)p_curr; + p_curr->p_next = (memobj_elem_t *)p_pool; + p_prev = p_curr; + } + else + { + //Could not allocate all requested buffers + nrf_memobj_free((nrf_memobj_t *)p_head); + return NULL; + } + } + return (nrf_memobj_t *)p_head; +} + +void nrf_memobj_free(nrf_memobj_t * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint8_t chunk_cnt = p_head->head_header.data.fields.chunk_cnt; + uint32_t i; + memobj_header_t * p_curr = (memobj_header_t *)p_obj; + memobj_header_t * p_next; + uint32_t chunk_less1 = (uint32_t)chunk_cnt - 1; + + for (i = 0; i < chunk_less1; i++) + { + p_curr = (memobj_header_t *)p_curr->p_next; + } + nrf_balloc_t const * p_pool2 = (nrf_balloc_t const *)p_curr->p_next; + + p_curr = (memobj_header_t *)p_obj; + for (i = 0; i < chunk_cnt; i++) + { + p_next = (memobj_header_t *)p_curr->p_next; + nrf_balloc_free(p_pool2, p_curr); + p_curr = p_next; + } +} + +void nrf_memobj_get(nrf_memobj_t const * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + (void)nrf_atomic_u32_add(&p_head->head_header.data.atomic_user_cnt, 1); +} + +void nrf_memobj_put(nrf_memobj_t * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint32_t user_cnt = nrf_atomic_u32_sub(&p_head->head_header.data.atomic_user_cnt, 1); + memobj_head_header_fields_t * p_fields = (memobj_head_header_fields_t *)&user_cnt; + if (p_fields->user_cnt == 0) + { + nrf_memobj_free(p_obj); + } +} + +static void memobj_op(nrf_memobj_t * p_obj, + void * p_data, + size_t * p_len, + size_t offset, + bool read) +{ + + ASSERT(p_obj); + + memobj_head_t * p_head = (memobj_head_t *)p_obj; + memobj_elem_t * p_curr_chunk = (memobj_elem_t *)p_obj; + size_t obj_capacity; + size_t chunk_size; + size_t chunk_idx; + size_t chunk_offset; + size_t len; + + obj_capacity = (p_head->head_header.data.fields.chunk_size * + p_head->head_header.data.fields.chunk_cnt) - + sizeof(memobj_head_header_fields_t); + + ASSERT(offset < obj_capacity); + + chunk_size = p_head->head_header.data.fields.chunk_size; + chunk_idx = (offset + sizeof(memobj_head_header_fields_t)) / chunk_size; + chunk_offset = (offset + sizeof(memobj_head_header_fields_t)) % chunk_size; + len = ((*p_len + offset) > obj_capacity) ? obj_capacity - offset : *p_len; + + //Return number of available bytes + *p_len = len; + + //Move to the first chunk to be used + while (chunk_idx > 0) + { + p_curr_chunk = p_curr_chunk->header.p_next; + chunk_idx--; + } + + size_t user_mem_offset = 0; + size_t curr_cpy_size = chunk_size - chunk_offset; + curr_cpy_size = curr_cpy_size > len ? len : curr_cpy_size; + + while (len) + { + void * p_user_mem = &((uint8_t *)p_data)[user_mem_offset]; + void * p_obj_mem = &p_curr_chunk->data[chunk_offset]; + if (read) + { + memcpy(p_user_mem, p_obj_mem, curr_cpy_size); + } + else + { + memcpy(p_obj_mem, p_user_mem, curr_cpy_size); + } + + chunk_offset = 0; + p_curr_chunk = p_curr_chunk->header.p_next; + len -= curr_cpy_size; + user_mem_offset += curr_cpy_size; + curr_cpy_size = (chunk_size > len) ? len : chunk_size; + } +} + +void nrf_memobj_write(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset) +{ + + size_t op_len = len; + memobj_op(p_obj, p_data, &op_len, offset, false); + ASSERT(op_len == len); +} + +void nrf_memobj_read(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset) +{ + size_t op_len = len; + memobj_op(p_obj, p_data, &op_len, offset, true); + ASSERT(op_len == len); + +} diff --git a/libraries/nfc/src/util/nrf_memobj.h b/libraries/nfc/src/util/nrf_memobj.h new file mode 100644 index 000000000..66760456e --- /dev/null +++ b/libraries/nfc/src/util/nrf_memobj.h @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_MEMOBJ_H +#define NRF_MEMOBJ_H + +/** +* @defgroup nrf_memobj Memory Object module +* @{ +* @ingroup app_common +* @brief Functions for controlling a memory object. +*/ +#include +#include +#include "sdk_errors.h" +#include "nrf_balloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A memory object can consist of multiple chunks with the same size. Each object has a header part + * and a data part. The first element in a memory object is memory object head which has a special header. + * The remaining objects have a header of the same size. + * +@verbatim + _____________________ _____________________ _____________________ +| | | | | | +|4 B head header | --> |4 B p_next |------->|4 B p_memobj_pool | +|_____________________| | |_____________________| |_____________________| +| | | | | | | +|4 B p_next |--| | | | | +|_____________________| | | .... | | +| | | data | | data | +| | | | | | +| data | | | | | +| | | | | | +|_____________________| |_____________________| |_____________________| + head mid_element last_element +@endverbatim + * + */ +#define NRF_MEMOBJ_STD_HEADER_SIZE sizeof(uint32_t) + +/** + * @brief Macro for creating an nrf_memobj pool. + * + * This macro declares an nrf_balloc object. The element in the pool contains a user-defined data part and + * a memory object header. + * + * @param _name Name of the instance. + * @param _chunk_size Size of a single chunk. + * @param _pool_size Number of chunks in the pool. + */ +#define NRF_MEMOBJ_POOL_DEF(_name, _chunk_size, _pool_size) \ + STATIC_ASSERT((_chunk_size) > sizeof(uint32_t)); \ + NRF_BALLOC_DEF(_name, ((_chunk_size)+NRF_MEMOBJ_STD_HEADER_SIZE), (_pool_size)) + +/** + * @brief Pool of memory objects. + */ +typedef nrf_balloc_t nrf_memobj_pool_t; + +/** + * @brief Memory object handle. + */ +typedef void * nrf_memobj_t; + +/** + * @brief Function for initializing the memobj pool instance. + * + * This function initializes the pool. + * + * @param[in] p_pool Pointer to the memobj pool instance structure. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool); + +/** + * @brief Function for allocating a memobj with a requested size. + * + * Fixed length elements in the pool are linked together to provide the amount of memory requested by + * the user. If a memory object is successfully allocated, then the users can use the memory. + * However, it is fragmented into multiple objects so it must be accessed through the API: + * @ref nrf_memobj_write and @ref nrf_memobj_read. + * + * @param[in] p_pool Pointer to the memobj pool instance structure. + * @param[in] size Data size of requested object. + * + * @return Pointer to a memory object or NULL if the requested size cannot be allocated. + */ +nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool, + size_t size); + +/** + * @brief Function for indicating that a memory object is used and cannot be freed. + * + * Memory object can be shared and reused between multiple modules and this mechanism ensures that + * object is freed when no longer used by any module. Memory object has a counter which is incremented + * whenever this function is called. @ref nrf_memobj_put function decrements the counter. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_get(nrf_memobj_t const * p_obj); + + +/** + * @brief Function for indicated that memory object is no longer used by the module and can be freed + * if no other module is using it. + * + * Memory object is returned to the pool if internal counter reaches 0 after decrementing. It means + * that no other module is needing it anymore. + * + * @note Memory object holds pointer to the pool which was used to allocate it so it does not have + * to be provided explicitly to this function. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_put(nrf_memobj_t * p_obj); + + +/** + * @brief Function for forcing freeing of the memory object. + * + * @note This function should be use with caution because it can lead to undefined behavior of the + * modules since modules using the memory object are not aware that it has been freed. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_free(nrf_memobj_t * p_obj); + +/** + * @brief Function for writing data to the memory object. + * + * @param[in] p_obj Pointer to memory object. + * @param[in] p_data Pointer to data to be written to the memory object. + * @param[in] len Amount of data to be written to the memory object. + * @param[in] offset Offset. + */ +void nrf_memobj_write(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset); + +/** + * @brief Function for reading data from the memory object. + * + * @param[in] p_obj Pointer to memory object. + * @param[in] p_data Pointer to the destination buffer. + * @param[in] len Amount of data to be read from the memory object. + * @param[in] offset Offset. + */ +void nrf_memobj_read(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_MEMOBJ_H + +/** @} */ diff --git a/libraries/nfc/src/util/nrf_ringbuf.c b/libraries/nfc/src/util/nrf_ringbuf.c new file mode 100644 index 000000000..24cca7913 --- /dev/null +++ b/libraries/nfc/src/util/nrf_ringbuf.c @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_ringbuf.h" +#include "app_util_platform.h" +#include "nrf_assert.h" + +#define WR_OFFSET 0 +#define RD_OFFSET 1 + +void nrf_ringbuf_init(nrf_ringbuf_t const * p_ringbuf) +{ + p_ringbuf->p_cb->wr_idx = 0; + p_ringbuf->p_cb->rd_idx = 0; + p_ringbuf->p_cb->tmp_rd_idx = 0; + p_ringbuf->p_cb->tmp_wr_idx = 0; + p_ringbuf->p_cb->rd_flag = 0; + p_ringbuf->p_cb->wr_flag = 0; +} + +ret_code_t nrf_ringbuf_alloc(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start) +{ + ASSERT(pp_data); + ASSERT(p_length); + + if (start) + { + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->wr_flag)) + { + return NRF_ERROR_BUSY; + } + } + + if (p_ringbuf->p_cb->tmp_wr_idx - p_ringbuf->p_cb->rd_idx == p_ringbuf->bufsize_mask + 1) + { + *p_length = 0; + if (start) + { + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->wr_flag)); + } + return NRF_SUCCESS; + } + + uint32_t wr_idx = p_ringbuf->p_cb->tmp_wr_idx & p_ringbuf->bufsize_mask; + uint32_t rd_idx = p_ringbuf->p_cb->rd_idx & p_ringbuf->bufsize_mask; + uint32_t available = (wr_idx >= rd_idx) ? p_ringbuf->bufsize_mask + 1 - wr_idx : + p_ringbuf->p_cb->rd_idx - (p_ringbuf->p_cb->tmp_wr_idx - (p_ringbuf->bufsize_mask + 1)); + *p_length = *p_length < available ? *p_length : available; + *pp_data = &p_ringbuf->p_buffer[wr_idx]; + p_ringbuf->p_cb->tmp_wr_idx += *p_length; + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_put(nrf_ringbuf_t const * p_ringbuf, size_t length) +{ + uint32_t available = p_ringbuf->bufsize_mask + 1 - + (p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx); + if (length > available) + { + return NRF_ERROR_NO_MEM; + } + + p_ringbuf->p_cb->wr_idx += length; + p_ringbuf->p_cb->tmp_wr_idx = p_ringbuf->p_cb->wr_idx; + if (nrf_atomic_flag_clear_fetch(&p_ringbuf->p_cb->wr_flag) == 0) + { + /* Flag was already cleared. Suggests misuse. */ + return NRF_ERROR_INVALID_STATE; + } + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_cpy_put(nrf_ringbuf_t const * p_ringbuf, + uint8_t const * p_data, + size_t * p_length) +{ + ASSERT(p_data); + ASSERT(p_length); + + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->wr_flag)) + { + return NRF_ERROR_BUSY; + } + + uint32_t available = p_ringbuf->bufsize_mask + 1 - + (p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx); + *p_length = available > *p_length ? *p_length : available; + size_t length = *p_length; + uint32_t masked_wr_idx = (p_ringbuf->p_cb->wr_idx & p_ringbuf->bufsize_mask); + uint32_t trail = p_ringbuf->bufsize_mask + 1 - masked_wr_idx; + + if (length > trail) + { + memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, trail); + length -= trail; + masked_wr_idx = 0; + p_data += trail; + } + memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, length); + p_ringbuf->p_cb->wr_idx += *p_length; + + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->wr_flag)); + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_get(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start) +{ + ASSERT(pp_data); + ASSERT(p_length); + + if (start) + { + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->rd_flag)) + { + return NRF_ERROR_BUSY; + } + } + + uint32_t available = p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->tmp_rd_idx; + if (available == 0) + { + *p_length = 0; + if (start) + { + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->rd_flag)); + } + return NRF_SUCCESS; + } + + uint32_t masked_tmp_rd_idx = p_ringbuf->p_cb->tmp_rd_idx & p_ringbuf->bufsize_mask; + uint32_t masked_wr_idx = p_ringbuf->p_cb->wr_idx & p_ringbuf->bufsize_mask; + + if ((masked_wr_idx > masked_tmp_rd_idx) && (available < *p_length)) + { + *p_length = available; + } + else if (masked_wr_idx <= masked_tmp_rd_idx) + { + uint32_t trail = p_ringbuf->bufsize_mask + 1 - masked_tmp_rd_idx; + if (*p_length > trail) + { + *p_length = trail; + } + } + *pp_data = &p_ringbuf->p_buffer[masked_tmp_rd_idx]; + p_ringbuf->p_cb->tmp_rd_idx += *p_length; + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_cpy_get(nrf_ringbuf_t const * p_ringbuf, + uint8_t * p_data, + size_t * p_length) +{ + ASSERT(p_data); + ASSERT(p_length); + + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->rd_flag)) + { + return NRF_ERROR_BUSY; + } + + uint32_t available = p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx; + *p_length = available > *p_length ? *p_length : available; + size_t length = *p_length; + uint32_t masked_rd_idx = (p_ringbuf->p_cb->rd_idx & p_ringbuf->bufsize_mask); + uint32_t masked_wr_idx = (p_ringbuf->p_cb->wr_idx & p_ringbuf->bufsize_mask); + uint32_t trail = (masked_wr_idx > masked_rd_idx) ? masked_wr_idx - masked_rd_idx : + p_ringbuf->bufsize_mask + 1 - masked_rd_idx; + + if (length > trail) + { + memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], trail); + length -= trail; + masked_rd_idx = 0; + p_data += trail; + } + memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], length); + p_ringbuf->p_cb->rd_idx += *p_length; + + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->rd_flag)); + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_free(nrf_ringbuf_t const * p_ringbuf, size_t length) +{ + uint32_t available = (p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx); + if (length > available) + { + return NRF_ERROR_NO_MEM; + } + + p_ringbuf->p_cb->rd_idx += length; + p_ringbuf->p_cb->tmp_rd_idx = p_ringbuf->p_cb->rd_idx; + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->rd_flag)); + + return NRF_SUCCESS; +} diff --git a/libraries/nfc/src/util/nrf_ringbuf.h b/libraries/nfc/src/util/nrf_ringbuf.h new file mode 100644 index 000000000..3ad80b2c3 --- /dev/null +++ b/libraries/nfc/src/util/nrf_ringbuf.h @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_RINGBUF_H +#define NRF_RINGBUF_H + +/** +* @defgroup nrf_ringbuf Ring buffer +* @{ +* @ingroup app_common +* @brief Functions for controlling the ring buffer. +*/ + +#include +#include "nrf_atomic.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief Ring buffer instance control block. + * */ +typedef struct +{ + nrf_atomic_flag_t wr_flag; //!< Protection flag. + nrf_atomic_flag_t rd_flag; //!< Protection flag. + uint32_t wr_idx; //!< Write index (updated when putting). + uint32_t tmp_wr_idx; //!< Temporary write index (updated when allocating). + uint32_t rd_idx; //!< Read index (updated when freeing). + uint32_t tmp_rd_idx; //!< Temporary read index (updated when getting). +} nrf_ringbuf_cb_t; + +/** + * @brief Ring buffer instance structure. + * */ +typedef struct +{ + uint8_t * p_buffer; //!< Pointer to the memory used by the ring buffer. + uint32_t bufsize_mask; //!< Buffer size mask (buffer size must be a power of 2). + nrf_ringbuf_cb_t * p_cb; //!< Pointer to the instance control block. +} nrf_ringbuf_t; + +/** + * @brief Macro for defining a ring buffer instance. + * + * @param _name Instance name. + * @param _size Size of the ring buffer (must be a power of 2). + * */ +#define NRF_RINGBUF_DEF(_name, _size) \ + STATIC_ASSERT(IS_POWER_OF_TWO(_size)); \ + static uint8_t CONCAT_2(_name,_buf)[_size]; \ + static nrf_ringbuf_cb_t CONCAT_2(_name,_cb); \ + static const nrf_ringbuf_t _name = { \ + .p_buffer = CONCAT_2(_name,_buf), \ + .bufsize_mask = _size - 1, \ + .p_cb = &CONCAT_2(_name,_cb), \ + } + +/** + * @brief Function for initializing a ring buffer instance. + * + * @param p_ringbuf Pointer to the ring buffer instance. + * + * */ +void nrf_ringbuf_init(nrf_ringbuf_t const * p_ringbuf); + +/** + * @brief Function for allocating memory from a ring buffer. + * + * This function attempts to allocate the amount of memory requested by the user, or a smaller amount if + * the requested amount is not available. If a start flag is set, then exclusive access to allocation + * is established. @ref nrf_ringbuf_put frees access to allocation. If a start flag is not set, then + * exclusive access check is omitted. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] pp_data Pointer to the pointer to the allocated buffer. + * @param[in, out] p_length Pointer to length. Length is set to the requested amount and filled + * by the function with actually allocated amount. + * @param[in] start Set to true if exclusive access should be controlled. + * + * @retval NRF_SUCCESS Successful allocation (can be smaller amount than requested). + * NRF_ERROR_BUSY Ring buffer allocation process (alloc-put) is ongoing. + * + * */ +ret_code_t nrf_ringbuf_alloc(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start); + +/** + * @brief Function for commiting data to a ring buffer. + * + * When an allocated buffer (see @ref nrf_ringbuf_alloc) has been filled with data, it must be committed + * to make it available for @ref nrf_ringbuf_get and @ref nrf_ringbuf_cpy_get. This function commits + * the data (can be smaller amount than allocated). + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] length Amount of bytes to put. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_put(nrf_ringbuf_t const * p_ringbuf, size_t length); + +/** + * @brief Function for copying data directly into the ring buffer. + * + * This function copies a user buffer to the ring buffer. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] p_data Pointer to the input buffer. + * @param[in, out] p_length Amount of bytes to copy. Amount of bytes copied. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_cpy_put(nrf_ringbuf_t const * p_ringbuf, + uint8_t const* p_data, + size_t * p_length); + + +/** + * Function for getting data from the ring buffer. + * + * This function attempts to get the requested amount of data from the ring buffer. If a start flag is set, then + * exclusive access to getting data from the ring buffer is established. @ref nrf_ringbuf_free frees + * access to getting data from the ring buffer. If a start flag is not set, then + * exclusive access check is omitted. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] pp_data Pointer to the pointer to the buffer with data. + * @param[in, out] p_length Pointer to length. Length is set to the requested amount and filled + * by the function with the actual amount. + * @param[in] start Set to true if exclusive access should be controlled. + * + * @retval NRF_SUCCESS Successful getting (can be smaller amount than requested). + * NRF_ERROR_BUSY Ring buffer getting process (get-free) is ongoing. + */ +ret_code_t nrf_ringbuf_get(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start); + +/** + * @brief Function for freeing a buffer back to the ring buffer. + * + * When a buffer with data taken from the ring buffer (see @ref nrf_ringbuf_get) has been processed, it + * must be freed to make it available for further use. This function frees the buffer (can be smaller + * amount than get). + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] length Amount of bytes to free. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_free(nrf_ringbuf_t const * p_ringbuf, size_t length); + +/** + * @brief Function for copying data directly out of the ring buffer. + * + * This function copies available data from the ring buffer to a user buffer. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] p_data Pointer to the input buffer. + * @param[in, out] p_length Amount of bytes to copy. Amount of bytes copied. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_cpy_get(nrf_ringbuf_t const * p_ringbuf, + uint8_t * p_data, + size_t * p_length); +#ifdef __cplusplus +} +#endif + +#endif //NRF_RINGBUF_H +/** @} */ diff --git a/libraries/nfc/src/util/nrf_section.h b/libraries/nfc/src/util/nrf_section.h new file mode 100644 index 000000000..1a38ecde7 --- /dev/null +++ b/libraries/nfc/src/util/nrf_section.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SECTION_H__ +#define NRF_SECTION_H__ + +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup section_vars Section variables + * @ingroup app_common + * @{ + * + * @brief Section variables. + */ + +//lint -save -e27 -esym(526,*) + +#if defined(__ICCARM__) +// Enable IAR language extensions +#pragma language=extended +#endif + +/**@brief Macro for obtaining the address of the beginning of a section. + * + * param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(section_name, $$Base) + +#elif defined(__GNUC__) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(__start_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_START_ADDR(section_name) __section_begin(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for obtaining the address of the end of a section. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_END_ADDR(section_name) __section_end(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for retrieving the length of a given section, in bytes. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#define NRF_SECTION_LENGTH(section_name) \ + ((size_t)NRF_SECTION_END_ADDR(section_name) - \ + (size_t)NRF_SECTION_START_ADDR(section_name)) + + +/**@brief Macro for creating a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables to be registered in the section. + * + * @warning Data type must be word aligned to prevent padding. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(section_name, $$Base); \ + extern void * CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(__start_, section_name); \ + extern void * CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_DEF(section_name, data_type) \ + _Pragma(STRINGIFY(section = STRINGIFY(section_name))); + +#endif + + +/**@brief Macro for declaring a variable and registering it in a section. + * + * @details Declares a variable and registers it in a named section. This macro ensures that the + * variable is not stripped away when using optimizations. + * + * @note The order in which variables are placed in a section is dependent on the order in + * which the linker script encounters the variables during linking. + * + * @param[in] section_name Name of the section. + * @param[in] section_var Variable to register in the given section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section(STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__GNUC__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section("." STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__ICCARM__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + __root section_var @ STRINGIFY(section_name) +#endif + + +/**@brief Macro for retrieving a variable from a section. + * + * @warning The stored symbol can only be resolved using this macro if the + * type of the data is word aligned. The operation of acquiring + * the stored symbol relies on the size of the stored type. No + * padding can exist in the named section in between individual + * stored items or this macro will fail. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variable. + * @param[in] i Index of the variable in section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_GET(section_name, data_type, i) \ + ((data_type*)NRF_SECTION_START_ADDR(section_name) + (i)) + + +/**@brief Macro for getting the number of variables in a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables in the section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_COUNT(section_name, data_type) \ + NRF_SECTION_LENGTH(section_name) / sizeof(data_type) + +/** @} */ + +//lint -restore + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_H__ diff --git a/libraries/nfc/src/util/nrf_section_iter.c b/libraries/nfc/src/util/nrf_section_iter.c new file mode 100644 index 000000000..2d64763ca --- /dev/null +++ b/libraries/nfc/src/util/nrf_section_iter.c @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_SECTION_ITER) + +#include "nrf_section_iter.h" + + +#if !defined(__GNUC__) +static void nrf_section_iter_item_set(nrf_section_iter_t * p_iter) +{ + ASSERT(p_iter != NULL); + ASSERT(p_iter->p_set != NULL); + ASSERT(p_iter->p_section != NULL); + + while (true) + { + if (p_iter->p_section == p_iter->p_set->p_last) + { + // End of the section set. + p_iter->p_item = NULL; + return; + } + + if (p_iter->p_section->p_start != p_iter->p_section->p_end) + { + // Not empty section. + p_iter->p_item = p_iter->p_section->p_start; + return; + } + + // Next section. + p_iter->p_section++; + } +} +#endif + + +void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set) +{ + ASSERT(p_iter != NULL); + ASSERT(p_set != NULL); + + p_iter->p_set = p_set; + +#if defined(__GNUC__) + p_iter->p_item = p_iter->p_set->section.p_start; + if (p_iter->p_item == p_iter->p_set->section.p_end) + { + p_iter->p_item = NULL; + } +#else + p_iter->p_section = p_set->p_first; + nrf_section_iter_item_set(p_iter); +#endif +} + +void nrf_section_iter_next(nrf_section_iter_t * p_iter) +{ + ASSERT(p_iter != NULL); + ASSERT(p_iter->p_set != NULL); + + if (p_iter->p_item == NULL) + { + return; + } + + p_iter->p_item = (void *)((size_t)(p_iter->p_item) + p_iter->p_set->item_size); + +#if defined(__GNUC__) + if (p_iter->p_item == p_iter->p_set->section.p_end) + { + p_iter->p_item = NULL; + } +#else + ASSERT(p_iter->p_section != NULL); + // End of current section reached? + if (p_iter->p_item == p_iter->p_section->p_end) + { + p_iter->p_section++; + nrf_section_iter_item_set(p_iter); + } +#endif +} + +#endif // NRF_MODULE_ENABLED(NRF_SECTION_ITER) diff --git a/libraries/nfc/src/util/nrf_section_iter.h b/libraries/nfc/src/util/nrf_section_iter.h new file mode 100644 index 000000000..874f0ac35 --- /dev/null +++ b/libraries/nfc/src/util/nrf_section_iter.h @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SECTION_ITER_H__ +#define NRF_SECTION_ITER_H__ + +#include +#include "nrf_section.h" +#include "nrf_assert.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup nrf_section_iter Section variables iterator + * @ingroup app_common + * @{ + */ + +/**@brief Single section description structure. */ +typedef struct +{ + void * p_start; //!< Pointer to the start of section. + void * p_end; //!< Pointer to the end of section. +} nrf_section_t; + + +/**@brief Set of the sections description structure. */ +typedef struct +{ +#if defined(__GNUC__) + nrf_section_t section; //!< Description of the set of sections. + /**< + * In case of GCC all sections in the set are sorted and + * placed in contiguous area, because they are treated as + * one section. + */ +#else + nrf_section_t const * p_first; //!< Pointer to the first section in the set. + nrf_section_t const * p_last; //!< Pointer to the last section in the set. +#endif + size_t item_size; //!< Size of the single item in the section. +} nrf_section_set_t; + + +/**@brief Section iterator structure. */ +typedef struct +{ + nrf_section_set_t const * p_set; //!< Pointer to the appropriate section set. +#if !defined(__GNUC__) + nrf_section_t const * p_section; //!< Pointer to the selected section. + /**< + * In case of GCC all sections in the set are sorted and + * placed in contiguous area, because they are treated + * as one section. + */ +#endif + void * p_item; //!< Pointer to the selected item in the section. +} nrf_section_iter_t; + + +/**@brief Create a set of sections. + * + * @note This macro reserves memory for the given set of sections. + * + * @details A set of sections, is an ordered collections of sections. + * + * @param[in] _name Name of the set. + * @param[in] _type Type of the elements stored in the sections. + * @param[in] _count Number of the sections in the set. This parameter is ignored in case of GCC. + * @hideinitializer + */ +#if defined(__GNUC__) + +#define NRF_SECTION_SET_DEF(_name, _type, _count) \ + \ + NRF_SECTION_DEF(_name, _type); \ + static nrf_section_set_t const _name = \ + { \ + .section = \ + { \ + .p_start = NRF_SECTION_START_ADDR(_name), \ + .p_end = NRF_SECTION_END_ADDR(_name), \ + }, \ + .item_size = sizeof(_type), \ + } + +#else + +#define NRF_SECTION_SET_DEF(_name, _type, _count) \ +/*lint -save -emacro(14, MACRO_REPEAT_FOR*) */ \ +MACRO_REPEAT_FOR(_count, NRF_SECTION_DEF_, _name, _type) \ +static nrf_section_t const CONCAT_2(_name, _array)[] = \ +{ \ + MACRO_REPEAT_FOR(_count, NRF_SECTION_SET_DEF_, _name) \ +}; \ +/*lint -restore */ \ +static nrf_section_set_t const _name = \ +{ \ + .p_first = CONCAT_2(_name, _array), \ + .p_last = CONCAT_2(_name, _array) + ARRAY_SIZE(CONCAT_2(_name, _array)), \ + .item_size = sizeof(_type), \ +} + +#ifndef DOXYGEN +#define NRF_SECTION_DEF_(_priority, _name, _type) \ +NRF_SECTION_DEF(CONCAT_2(_name, _priority), _type); + +#define NRF_SECTION_SET_DEF_(_priority, _name) \ +{ \ + .p_start = NRF_SECTION_START_ADDR(CONCAT_2(_name, _priority)), \ + .p_end = NRF_SECTION_END_ADDR(CONCAT_2(_name, _priority)), \ +}, +#endif // DOXYGEN +#endif // __GNUC__ + + +/**@brief Macro to declare a variable and register it in the section set. + * + * @note The order of the section in the set is based on the priority. The order with which + * variables are placed in a section is dependant on the order with which the linker + * encouters the variables during linking. + * + * @param[in] _name Name of the section set. + * @param[in] _priority Priority of the desired section. + * @param[in] _var The variable to register in the given section. + * @hideinitializer + */ +#define NRF_SECTION_SET_ITEM_REGISTER(_name, _priority, _var) \ + NRF_SECTION_ITEM_REGISTER(CONCAT_2(_name, _priority), _var) + + +/**@brief Function for initializing the section set iterator. + * + * @param[in] p_iter Pointer to the iterator. + * @param[in] p_set Pointer to the sections set. + */ +void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set); + + +/**@brief Function for incrementing iterator. + * + * @param[in] p_iter Pointer to the iterator. + */ +void nrf_section_iter_next(nrf_section_iter_t * p_iter); + + +/**@brief Function for getting the element pointed to by the iterator. + * + * @param[in] p_iter Pointer to the iterator. + * + * @retval Pointer to the element or NULL if iterator points end of the set. + */ +static inline void * nrf_section_iter_get(nrf_section_iter_t const * p_iter) +{ + ASSERT(p_iter); + return p_iter->p_item; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_ITER_H__ diff --git a/libraries/nfc/src/util/nrf_strerror.c b/libraries/nfc/src/util/nrf_strerror.c new file mode 100644 index 000000000..53746fa86 --- /dev/null +++ b/libraries/nfc/src/util/nrf_strerror.c @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2011 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_STRERROR) +#include "nrf_strerror.h" + +/** + * @brief Macro for adding an entity to the description array. + * + * Macro that helps to create a single entity in the description array. + */ +#define NRF_STRERROR_ENTITY(mnemonic) {.code = mnemonic, .name = #mnemonic} + +/** + * @brief Array entity element that describes an error. + */ +typedef struct +{ + ret_code_t code; /**< Error code. */ + char const * name; /**< Descriptive name (the same as the internal error mnemonic). */ +}nrf_strerror_desc_t; + +/** + * @brief Unknown error code. + * + * The constant string used by @ref nrf_strerror_get when the error description was not found. + */ +static char const m_unknown_str[] = "Unknown error code"; + +/** + * @brief Array with error codes. + * + * Array that describes error codes. + * + * @note It is required for this array to have error codes placed in ascending order. + * This condition is checked in automatic unit test before the release. + */ +static nrf_strerror_desc_t const nrf_strerror_array[] = +{ + NRF_STRERROR_ENTITY(NRF_SUCCESS), + NRF_STRERROR_ENTITY(NRF_ERROR_SVC_HANDLER_MISSING), + NRF_STRERROR_ENTITY(NRF_ERROR_SOFTDEVICE_NOT_ENABLED), + NRF_STRERROR_ENTITY(NRF_ERROR_INTERNAL), + NRF_STRERROR_ENTITY(NRF_ERROR_NO_MEM), + NRF_STRERROR_ENTITY(NRF_ERROR_NOT_FOUND), + NRF_STRERROR_ENTITY(NRF_ERROR_NOT_SUPPORTED), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_PARAM), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_STATE), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_LENGTH), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_FLAGS), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_DATA), + NRF_STRERROR_ENTITY(NRF_ERROR_DATA_SIZE), + NRF_STRERROR_ENTITY(NRF_ERROR_TIMEOUT), + NRF_STRERROR_ENTITY(NRF_ERROR_NULL), + NRF_STRERROR_ENTITY(NRF_ERROR_FORBIDDEN), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_ADDR), + NRF_STRERROR_ENTITY(NRF_ERROR_BUSY), +#ifdef NRF_ERROR_CONN_COUNT + NRF_STRERROR_ENTITY(NRF_ERROR_CONN_COUNT), +#endif +#ifdef NRF_ERROR_RESOURCES + NRF_STRERROR_ENTITY(NRF_ERROR_RESOURCES), +#endif + + /* SDK Common errors */ + NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_NOT_INITIALIZED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_INIT_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_LOCK_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_UNLOCK_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_COND_INIT_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_ALREADY_INITIALIZED), + NRF_STRERROR_ENTITY(NRF_ERROR_STORAGE_FULL), + NRF_STRERROR_ENTITY(NRF_ERROR_API_NOT_IMPLEMENTED), + NRF_STRERROR_ENTITY(NRF_ERROR_FEATURE_NOT_ENABLED), + NRF_STRERROR_ENTITY(NRF_ERROR_IO_PENDING), + + /* TWI error codes */ + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_OVERRUN), + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_ANACK), + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_DNACK), + + /* IPSP error codes */ + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED), + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS), + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED), + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_PEER_REJECTED) +}; + + +char const * nrf_strerror_get(ret_code_t code) +{ + char const * p_ret = nrf_strerror_find(code); + return (p_ret == NULL) ? m_unknown_str : p_ret; +} + +char const * nrf_strerror_find(ret_code_t code) +{ + nrf_strerror_desc_t const * p_start; + nrf_strerror_desc_t const * p_end; + p_start = nrf_strerror_array; + p_end = nrf_strerror_array + ARRAY_SIZE(nrf_strerror_array); + + while (p_start < p_end) + { + nrf_strerror_desc_t const * p_mid = p_start + ((p_end - p_start) / 2); + ret_code_t mid_c = p_mid->code; + if (mid_c > code) + { + p_end = p_mid; + } + else if (mid_c < code) + { + p_start = p_mid + 1; + } + else + { + return p_mid->name; + } + } + return NULL; +} + +#endif /* NRF_STRERROR enabled */ diff --git a/libraries/nfc/src/util/nrf_strerror.h b/libraries/nfc/src/util/nrf_strerror.h new file mode 100644 index 000000000..6c89a5e22 --- /dev/null +++ b/libraries/nfc/src/util/nrf_strerror.h @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ + +/** + * @defgroup nrf_strerror Error code to string converter + * @ingroup app_common + * + * @brief Module for converting error code into a printable string. + * @{ + */ +#ifndef NRF_STRERROR_H__ +#define NRF_STRERROR_H__ + +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for getting a printable error string. + * + * @param code Error code to convert. + * + * @note This function cannot fail. + * For the function that may fail with error translation, see @ref nrf_strerror_find. + * + * @return Pointer to the printable string. + * If the string is not found, + * it returns a simple string that says that the error is unknown. + */ +char const * nrf_strerror_get(ret_code_t code); + +/** + * @brief Function for finding a printable error string. + * + * This function gets the error string in the same way as @ref nrf_strerror_get, + * but if the string is not found, it returns NULL. + * + * @param code Error code to convert. + * @return Pointer to the printable string. + * If the string is not found, NULL is returned. + */ +char const * nrf_strerror_find(ret_code_t code); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_STRERROR_H__ */ diff --git a/libraries/nfc/src/util/nrfx_clock.c b/libraries/nfc/src/util/nrfx_clock.c new file mode 100644 index 000000000..1b1a436cc --- /dev/null +++ b/libraries/nfc/src/util/nrfx_clock.c @@ -0,0 +1,403 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +//#if NRFX_CHECK(NRFX_CLOCK_ENABLED) + +#include "nrfx_clock.h" + +#define NRFX_LOG_MODULE CLOCK +#include + +#if NRFX_CHECK(NRFX_POWER_ENABLED) +extern bool nrfx_power_irq_enabled; +#endif + +#define EVT_TO_STR(event) \ + (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ + (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \ + "UNKNOWN EVENT")))) + +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + #if (NRF_CLOCK_HAS_CALIBRATION == 0) + #error "Calibration is not available in the SoC that is used." + #endif + #if (NRFX_CLOCK_CONFIG_LF_SRC != CLOCK_LFCLKSRC_SRC_RC) + #error "Calibration can be performed only for the RC Oscillator." + #endif +#endif + +#if !defined(USE_WORKAROUND_FOR_ANOMALY_132) && \ + (defined(NRF52832_XXAA) || defined(NRF52832_XXAB)) + // ANOMALY 132 - LFCLK needs to avoid frame from 66us to 138us after LFCLK stop. This solution + // applies delay of 138us before starting LFCLK. + #define USE_WORKAROUND_FOR_ANOMALY_132 1 + + // Convert time to cycles (nRF52832 is clocked with 64 MHz, use delay of 138 us). + #define ANOMALY_132_DELAY_CYCLES (64UL * 138) +#endif + +#if !defined(USE_WORKAROUND_FOR_ANOMALY_192) && \ + (defined(NRF52810_XXAA) || \ + defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \ + defined(NRF52840_XXAA)) + // Enable workaround for nRF52 anomaly 192 (LFRC oscillator frequency is wrong + // after calibration, exceeding 500 ppm). + #define USE_WORKAROUND_FOR_ANOMALY_192 1 +#endif + +#if !defined(USE_WORKAROUND_FOR_ANOMALY_201) && \ + (defined(NRF52810_XXAA) || \ + defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \ + defined(NRF52840_XXAA)) + // Enable workaround for nRF52 anomaly 201 (EVENTS_HFCLKSTARTED might be generated twice). + #define USE_WORKAROUND_FOR_ANOMALY_201 1 +#endif + +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) +typedef enum +{ + CAL_STATE_IDLE, + CAL_STATE_CAL +} nrfx_clock_cal_state_t; +#endif + +/**@brief CLOCK control block. */ +typedef struct +{ + nrfx_clock_event_handler_t event_handler; + bool module_initialized; /*< Indicate the state of module */ +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201) + bool hfclk_started; /*< Anomaly 201 workaround. */ +#endif + +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + volatile nrfx_clock_cal_state_t cal_state; +#endif +} nrfx_clock_cb_t; + +static nrfx_clock_cb_t m_clock_cb; + +/** + * This variable is used to check whether common POWER_CLOCK common interrupt + * should be disabled or not if @ref nrfx_power tries to disable the interrupt. + */ +#if NRFX_CHECK(NRFX_POWER_ENABLED) +bool nrfx_clock_irq_enabled; +#endif + +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132) +/** + * @brief Function for applying delay of 138us before starting LFCLK. + */ +static void nrfx_clock_anomaly_132(void) +{ + uint32_t cyccnt_inital; + uint32_t core_debug; + uint32_t dwt_ctrl; + + // Preserve DEMCR register to do not influence into its configuration. Enable the trace and + // debug blocks. It is required to read and write data to DWT block. + core_debug = CoreDebug->DEMCR; + CoreDebug->DEMCR = core_debug | CoreDebug_DEMCR_TRCENA_Msk; + + // Preserve CTRL register in DWT block to do not influence into its configuration. Make sure + // that cycle counter is enabled. + dwt_ctrl = DWT->CTRL; + DWT->CTRL = dwt_ctrl | DWT_CTRL_CYCCNTENA_Msk; + + // Store start value of cycle counter. + cyccnt_inital = DWT->CYCCNT; + + // Delay required time. + while ((DWT->CYCCNT - cyccnt_inital) < ANOMALY_132_DELAY_CYCLES) + {} + + // Restore preserved registers. + DWT->CTRL = dwt_ctrl; + CoreDebug->DEMCR = core_debug; +} +#endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132) + +nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler) +{ + NRFX_ASSERT(event_handler); + + nrfx_err_t err_code = NRFX_SUCCESS; + if (m_clock_cb.module_initialized) + { + err_code = NRFX_ERROR_ALREADY_INITIALIZED; + } + else + { +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + m_clock_cb.cal_state = CAL_STATE_IDLE; +#endif + m_clock_cb.event_handler = event_handler; + m_clock_cb.module_initialized = true; +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201) + m_clock_cb.hfclk_started = false; +#endif + } + + NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrfx_clock_enable(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); + nrfx_power_clock_irq_init(); + nrf_clock_lf_src_set(NRF_CLOCK,(nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC); + +#if NRFX_CHECK(NRFX_POWER_ENABLED) + nrfx_clock_irq_enabled = true; +#endif + + NRFX_LOG_INFO("Module enabled."); +} + +void nrfx_clock_disable(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); +#if NRFX_CHECK(NRFX_POWER_ENABLED) + NRFX_ASSERT(nrfx_clock_irq_enabled); + if (!nrfx_power_irq_enabled) +#endif + { + NRFX_IRQ_DISABLE(nrfx_get_irq_number(NRF_CLOCK)); + } + nrf_clock_int_disable(NRF_CLOCK,CLOCK_INTENSET_HFCLKSTARTED_Msk | + CLOCK_INTENSET_LFCLKSTARTED_Msk | +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + CLOCK_INTENSET_DONE_Msk | + CLOCK_INTENSET_CTTO_Msk | +#endif + 0); +#if NRFX_CHECK(NRFX_POWER_ENABLED) + nrfx_clock_irq_enabled = false; +#endif + NRFX_LOG_INFO("Module disabled."); +} + +void nrfx_clock_uninit(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); + nrfx_clock_lfclk_stop(); + nrfx_clock_hfclk_stop(); + m_clock_cb.module_initialized = false; + NRFX_LOG_INFO("Uninitialized."); +} + +void nrfx_clock_lfclk_start(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_LFCLKSTARTED); + nrf_clock_int_enable(NRF_CLOCK,NRF_CLOCK_INT_LF_STARTED_MASK); + +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132) + nrfx_clock_anomaly_132(); +#endif + + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_LFCLKSTART); +} + +void nrfx_clock_lfclk_stop(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); + + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_LF_STARTED_MASK); + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_LFCLKSTARTED); + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_LFCLKSTOP); + while (nrf_clock_lf_is_running(NRF_CLOCK)) + {} +} + +void nrfx_clock_hfclk_start(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_HFCLKSTARTED); + nrf_clock_int_enable(NRF_CLOCK,NRF_CLOCK_INT_HF_STARTED_MASK); + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_HFCLKSTART); +} + +void nrfx_clock_hfclk_stop(void) +{ + NRFX_ASSERT(m_clock_cb.module_initialized); + + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_HF_STARTED_MASK); + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_HFCLKSTARTED); + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_HFCLKSTOP); + while (nrf_clock_hf_is_running(NRF_CLOCK,NRF_CLOCK_HFCLK_HIGH_ACCURACY)) + {} +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201) + m_clock_cb.hfclk_started = false; +#endif +} + +nrfx_err_t nrfx_clock_calibration_start(void) +{ + nrfx_err_t err_code = NRFX_SUCCESS; + +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + if (nrfx_clock_hfclk_is_running() == false) + { + return NRFX_ERROR_INVALID_STATE; + } + + if (nrfx_clock_lfclk_is_running() == false) + { + return NRFX_ERROR_INVALID_STATE; + } + + if (m_clock_cb.cal_state == CAL_STATE_IDLE) + { + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_DONE); + nrf_clock_int_enable(NRF_CLOCK,NRF_CLOCK_INT_DONE_MASK); + m_clock_cb.cal_state = CAL_STATE_CAL; +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_192) + *(volatile uint32_t *)0x40000C34 = 0x00000002; +#endif + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_CAL); + } + else + { + err_code = NRFX_ERROR_BUSY; + } +#endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +nrfx_err_t nrfx_clock_is_calibrating(void) +{ +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + if (m_clock_cb.cal_state == CAL_STATE_CAL) + { + return NRFX_ERROR_BUSY; + } +#endif + return NRFX_SUCCESS; +} + +void nrfx_clock_calibration_timer_start(uint8_t interval) +{ +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + nrf_clock_cal_timer_timeout_set(interval); + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_CTTO); + nrf_clock_int_enable(NRF_CLOCK,NRF_CLOCK_INT_CTTO_MASK); + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_CTSTART); +#endif +} + +void nrfx_clock_calibration_timer_stop(void) +{ +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_CTTO_MASK); + nrf_clock_task_trigger(NRF_CLOCK,NRF_CLOCK_TASK_CTSTOP); +#endif +} + +void nrfx_clock_irq_handler(void) +{ + if (nrf_clock_event_check(NRF_CLOCK,NRF_CLOCK_EVENT_HFCLKSTARTED)) + { + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_HFCLKSTARTED); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED)); + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_HF_STARTED_MASK); + +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201) + if (!m_clock_cb.hfclk_started) + { + m_clock_cb.hfclk_started = true; + if(m_clock_cb.event_handler != NULL){ + m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED); + } + } +#else + if(m_clock_cb.event_handler != NULL){ + m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED); + } +#endif + } + if (nrf_clock_event_check(NRF_CLOCK,NRF_CLOCK_EVENT_LFCLKSTARTED)) + { + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_LFCLKSTARTED); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED)); + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_LF_STARTED_MASK); + if(m_clock_cb.event_handler != NULL){ + m_clock_cb.event_handler(NRFX_CLOCK_EVT_LFCLK_STARTED); + } + } + +#if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) + if (nrf_clock_event_check(NRF_CLOCK,NRF_CLOCK_EVENT_CTTO)) + { + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_CTTO); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_CTTO)); + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_CTTO_MASK); + + if(m_clock_cb.event_handler != NULL){ + m_clock_cb.event_handler(NRFX_CLOCK_EVT_CTTO); + } + } + + if (nrf_clock_event_check(NRF_CLOCK,NRF_CLOCK_EVENT_DONE)) + { +#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_192) + *(volatile uint32_t *)0x40000C34 = 0x00000000; +#endif + nrf_clock_event_clear(NRF_CLOCK,NRF_CLOCK_EVENT_DONE); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_CLOCK_EVENT_DONE)); + nrf_clock_int_disable(NRF_CLOCK,NRF_CLOCK_INT_DONE_MASK); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if(m_clock_cb.event_handler != NULL){ + m_clock_cb.event_handler(NRFX_CLOCK_EVT_CAL_DONE); + } + } +#endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) +} + +//#endif // NRFX_CHECK(NRFX_CLOCK_ENABLED) diff --git a/libraries/nfc/src/util/nrfx_clock.h b/libraries/nfc/src/util/nrfx_clock.h new file mode 100644 index 000000000..988744196 --- /dev/null +++ b/libraries/nfc/src/util/nrfx_clock.h @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRFX_CLOCK_H__ +#define NRFX_CLOCK_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrfx_clock CLOCK driver + * @{ + * @ingroup nrf_clock + * @brief CLOCK peripheral driver. + */ + +/** @brief Clock events. */ +typedef enum +{ + NRFX_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. + NRFX_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. + NRFX_CLOCK_EVT_CTTO, ///< Calibration timeout. + NRFX_CLOCK_EVT_CAL_DONE ///< Calibration has been done. +} nrfx_clock_evt_type_t; + +/** + * @brief Clock event handler. + * + * @param[in] event Event. + */ +typedef void (*nrfx_clock_event_handler_t)(nrfx_clock_evt_type_t event); + +/** + * @brief Function for initializing internal structures in the nrfx_clock module. + * + * After initialization, the module is in power off state (clocks are not started). + * + * @param[in] event_handler Event handler provided by the user. + * Must not be NULL. + * + * @retval NRFX_SUCCESS The procedure is successful. + * @retval NRFX_ERROR_ALREADY_INITIALIZED The driver is already initialized. + */ +nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler); + +/** @brief Function for enabling interrupts in the clock module. */ +void nrfx_clock_enable(void); + +/** @brief Function for disabling interrupts in the clock module. */ +void nrfx_clock_disable(void); + +/** @brief Function for uninitializing the clock module. */ +void nrfx_clock_uninit(void); + +/** @brief Function for starting the LFCLK. */ +void nrfx_clock_lfclk_start(void); + +/** @brief Function for stopping the LFCLK. */ +void nrfx_clock_lfclk_stop(void); + +/** + * @brief Function for checking the LFCLK state. + * + * @retval true The LFCLK is running. + * @retval false The LFCLK is not running. + */ +__STATIC_INLINE bool nrfx_clock_lfclk_is_running(void); + +/** @brief Function for starting the high-accuracy source HFCLK. */ +void nrfx_clock_hfclk_start(void); + +/** @brief Function for stopping the external high-accuracy source HFCLK. */ +void nrfx_clock_hfclk_stop(void); + +/** + * @brief Function for checking the HFCLK state. + * + * @retval true The HFCLK is running (XTAL source). + * @retval false The HFCLK is not running. + */ +__STATIC_INLINE bool nrfx_clock_hfclk_is_running(void); + +/** + * @brief Function for starting the calibration of internal LFCLK. + * + * This function starts the calibration process. The process cannot be aborted. LFCLK and HFCLK + * must be running before this function is called. + * + * @retval NRFX_SUCCESS The procedure is successful. + * @retval NRFX_ERROR_INVALID_STATE The low-frequency of high-frequency clock is off. + * @retval NRFX_ERROR_BUSY Clock is in the calibration phase. + */ +nrfx_err_t nrfx_clock_calibration_start(void); + +/** + * @brief Function for checking if calibration is in progress. + * + * This function indicates that the system is in calibration phase. + * + * @retval NRFX_SUCCESS The procedure is successful. + * @retval NRFX_ERROR_BUSY Clock is in the calibration phase. + */ +nrfx_err_t nrfx_clock_is_calibrating(void); + +/** + * @brief Function for starting calibration timer. + * + * @param[in] interval Time after which the CTTO event and interrupt will be generated (in 0.25 s units). + */ +void nrfx_clock_calibration_timer_start(uint8_t interval); + +/** @brief Function for stopping the calibration timer. */ +void nrfx_clock_calibration_timer_stop(void); + +/**@brief Function for returning a requested task address for the clock driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrfx_clock_ppi_task_addr(nrf_clock_task_t task); + +/**@brief Function for returning a requested event address for the clock driver module. + * + * @param[in] event One of the peripheral events. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrfx_clock_ppi_event_addr(nrf_clock_event_t event); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrfx_clock_ppi_task_addr(nrf_clock_task_t task) +{ + return nrf_clock_task_address_get(NRF_CLOCK,task); +} + +__STATIC_INLINE uint32_t nrfx_clock_ppi_event_addr(nrf_clock_event_t event) +{ + return nrf_clock_event_address_get(NRF_CLOCK,event); +} + +__STATIC_INLINE bool nrfx_clock_hfclk_is_running(void) +{ + return nrf_clock_hf_is_running(NRF_CLOCK,NRF_CLOCK_HFCLK_HIGH_ACCURACY); +} + +__STATIC_INLINE bool nrfx_clock_lfclk_is_running(void) +{ + return nrf_clock_lf_is_running(NRF_CLOCK); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + + +void nrfx_clock_irq_handler(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRFX_CLOCK_H__ diff --git a/libraries/nfc/src/util/nrfx_glue.h b/libraries/nfc/src/util/nrfx_glue.h new file mode 100644 index 000000000..80e308cb6 --- /dev/null +++ b/libraries/nfc/src/util/nrfx_glue.h @@ -0,0 +1,338 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRFX_GLUE_H__ +#define NRFX_GLUE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrfx_glue nrfx_glue.h + * @{ + * @ingroup nrfx + * + * @brief This file contains macros that should be implemented according to + * the needs of the host environment into which @em nrfx is integrated. + */ + +#include + +#include + +//------------------------------------------------------------------------------ + +#include +/** + * @brief Macro for placing a runtime assertion. + * + * @param expression Expression to evaluate. + */ +#define NRFX_ASSERT(expression) ASSERT(expression) + +#include +/** + * @brief Macro for placing a compile time assertion. + * + * @param expression Expression to evaluate. + */ +#define NRFX_STATIC_ASSERT(expression) STATIC_ASSERT(expression) + +//------------------------------------------------------------------------------ + +#ifdef NRF51 +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) (((pri) == 1) || ((pri) == 3)) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 4) +#endif //SOFTDEVICE_PRESENT +#else +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((((pri) > 1) && ((pri) < 4)) || \ + (((pri) > 4) && ((pri) < 8))) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 8) +#endif //SOFTDEVICE_PRESENT +#endif //NRF52 + +/** + * @brief Macro for setting the priority of a specific IRQ. + * + * @param irq_number IRQ number. + * @param priority Priority to set. + */ +#define NRFX_IRQ_PRIORITY_SET(irq_number, priority) \ + _NRFX_IRQ_PRIORITY_SET(irq_number, priority) +static inline void _NRFX_IRQ_PRIORITY_SET(IRQn_Type irq_number, + uint8_t priority) +{ + ASSERT(INTERRUPT_PRIORITY_IS_VALID(priority)); + NVIC_SetPriority(irq_number, priority); +} + +/** + * @brief Macro for enabling a specific IRQ. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_ENABLE(irq_number) _NRFX_IRQ_ENABLE(irq_number) +static inline void _NRFX_IRQ_ENABLE(IRQn_Type irq_number) +{ + NVIC_EnableIRQ(irq_number); +} + +/** + * @brief Macro for checking if a specific IRQ is enabled. + * + * @param irq_number IRQ number. + * + * @retval true If the IRQ is enabled. + * @retval false Otherwise. + */ +#define NRFX_IRQ_IS_ENABLED(irq_number) _NRFX_IRQ_IS_ENABLED(irq_number) +static inline bool _NRFX_IRQ_IS_ENABLED(IRQn_Type irq_number) +{ + return 0 != (NVIC->ISER[irq_number / 32] & (1UL << (irq_number % 32))); +} + +/** + * @brief Macro for disabling a specific IRQ. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_DISABLE(irq_number) _NRFX_IRQ_DISABLE(irq_number) +static inline void _NRFX_IRQ_DISABLE(IRQn_Type irq_number) +{ + NVIC_DisableIRQ(irq_number); +} + +/** + * @brief Macro for setting a specific IRQ as pending. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_PENDING_SET(irq_number) _NRFX_IRQ_PENDING_SET(irq_number) +static inline void _NRFX_IRQ_PENDING_SET(IRQn_Type irq_number) +{ + NVIC_SetPendingIRQ(irq_number); +} + +/** + * @brief Macro for clearing the pending status of a specific IRQ. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_PENDING_CLEAR(irq_number) _NRFX_IRQ_PENDING_CLEAR(irq_number) +static inline void _NRFX_IRQ_PENDING_CLEAR(IRQn_Type irq_number) +{ + NVIC_ClearPendingIRQ(irq_number); +} + +/** + * @brief Macro for checking the pending status of a specific IRQ. + * + * @retval true If the IRQ is pending. + * @retval false Otherwise. + */ +#define NRFX_IRQ_IS_PENDING(irq_number) _NRFX_IRQ_IS_PENDING(irq_number) +static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number) +{ + return (NVIC_GetPendingIRQ(irq_number) == 1); +} + +#include +#include +/** + * @brief Macro for entering into a critical section. + */ +#define NRFX_CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER() + +/** + * @brief Macro for exiting from a critical section. + */ +#define NRFX_CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT() + +//------------------------------------------------------------------------------ + +/** + * @brief When set to a non-zero value, this macro specifies that + * @ref nrfx_coredep_delay_us uses a precise DWT-based solution. + * A compilation error is generated if the DWT unit is not present + * in the SoC used. + */ +#define NRFX_DELAY_DWT_BASED 0 + +#include + +#define NRFX_DELAY_US(us_time) nrfx_coredep_delay_us(us_time) + +//------------------------------------------------------------------------------ + +#include + +/** + * @brief Atomic 32 bit unsigned type. + */ +#define nrfx_atomic_t nrfx_atomic_u32_t + +/** + * @brief Stores value to an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value to store. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_STORE(p_data, value) nrfx_atomic_u32_fetch_store(p_data, value) + +/** + * @brief Performs logical OR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of OR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_OR(p_data, value) nrfx_atomic_u32_fetch_or(p_data, value) + +/** + * @brief Performs logical AND operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of AND operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_AND(p_data, value) nrfx_atomic_u32_fetch_and(p_data, value) + +/** + * @brief Performs logical XOR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of XOR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_XOR(p_data, value) nrfx_atomic_u32_fetch_xor(p_data, value) + +/** + * @brief Performs logical ADD operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of ADD operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_ADD(p_data, value) nrfx_atomic_u32_fetch_add(p_data, value) + +/** + * @brief Performs logical SUB operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of SUB operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_SUB(p_data, value) nrfx_atomic_u32_fetch_sub(p_data, value) + +//------------------------------------------------------------------------------ +#ifndef NRFX_CUSTOM_ERROR_CODES + +#include +/** + * @brief When set to a non-zero value, this macro specifies that the + * @ref nrfx_error_codes and the @ref ret_code_t type itself are defined + * in a customized way and the default definitions from @c + * should not be used. + */ +#define NRFX_CUSTOM_ERROR_CODES 1 + +typedef ret_code_t nrfx_err_t; + +#define NRFX_SUCCESS NRF_SUCCESS +#define NRFX_ERROR_INTERNAL NRF_ERROR_INTERNAL +#define NRFX_ERROR_NO_MEM NRF_ERROR_NO_MEM +#define NRFX_ERROR_NOT_SUPPORTED NRF_ERROR_NOT_SUPPORTED +#define NRFX_ERROR_INVALID_PARAM NRF_ERROR_INVALID_PARAM +#define NRFX_ERROR_INVALID_STATE NRF_ERROR_INVALID_STATE +#define NRFX_ERROR_INVALID_LENGTH NRF_ERROR_INVALID_LENGTH +#define NRFX_ERROR_TIMEOUT NRF_ERROR_TIMEOUT +#define NRFX_ERROR_FORBIDDEN NRF_ERROR_FORBIDDEN +#define NRFX_ERROR_NULL NRF_ERROR_NULL +#define NRFX_ERROR_INVALID_ADDR NRF_ERROR_INVALID_ADDR +#define NRFX_ERROR_BUSY NRF_ERROR_BUSY +#define NRFX_ERROR_ALREADY_INITIALIZED NRF_ERROR_MODULE_ALREADY_INITIALIZED + +#define NRFX_ERROR_DRV_TWI_ERR_OVERRUN NRF_ERROR_DRV_TWI_ERR_OVERRUN +#define NRFX_ERROR_DRV_TWI_ERR_ANACK NRF_ERROR_DRV_TWI_ERR_ANACK +#define NRFX_ERROR_DRV_TWI_ERR_DNACK NRF_ERROR_DRV_TWI_ERR_DNACK + +#endif // NRFX_CUSTOM_ERROR_CODES +//------------------------------------------------------------------------------ + +#include +/** + * @brief Bitmask defining PPI channels reserved to be used outside of nrfx. + */ +#define NRFX_PPI_CHANNELS_USED NRF_PPI_CHANNELS_USED + +/** + * @brief Bitmask defining PPI groups reserved to be used outside of nrfx. + */ +#define NRFX_PPI_GROUPS_USED NRF_PPI_GROUPS_USED + +/** + * @brief Bitmask defining SWI instances reserved to be used outside of nrfx. + */ +#define NRFX_SWI_USED NRF_SWI_USED + +/** + * @brief Bitmask defining TIMER instances reserved to be used outside of nrfx. + */ +#define NRFX_TIMERS_USED NRF_TIMERS_USED + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRFX_GLUE_H__ diff --git a/libraries/nfc/src/util/sdk_alloca.h b/libraries/nfc/src/util/sdk_alloca.h new file mode 100644 index 000000000..4811e2dbf --- /dev/null +++ b/libraries/nfc/src/util/sdk_alloca.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 sdk_alloca.h + * + * @brief Defines alloca() function. + * + * @details This file defines alloca() function. This can be done directly or by including system + * header files. Not all platforms support alloca(). In this case no error will be shown, but + * SDK_ALLOCA_DEFINED will be set to 0. + */ + +#ifndef SDK_ALLOCA_H__ +#define SDK_ALLOCA_H__ + + +#if defined(__SDK_DOXYGEN__) + /** @brief Set to one it alloca() function is available on this platform and it is correctly defined + * by this header file. + */ + #define SDK_ALLOCA_DEFINED 1 +#elif defined(__GNUC__) + #if defined(__SES_ARM) + // SES does not have definition of alloca(), but it have working GCC's __builtin_alloca(). + #if !defined(alloca) + #define alloca(size) __builtin_alloca((size)) + #endif + #else + // alloca() can be defined in on some platforms, but if not then try standard header file. + #include + #if !defined(alloca) + #include + #endif + #endif + #define SDK_ALLOCA_DEFINED 1 +#elif defined(__IAR_SYSTEMS_ICC__) + // IAR does not support alloca() function. + #define SDK_ALLOCA_DEFINED 0 +#else + // All other supported compilers have alloca() definition in header file. + #include + #define SDK_ALLOCA_DEFINED 1 +#endif + + +/*lint -"d__builtin_alloca=(void*)" */ + + +#endif // NRF_ALLOCA_H__ diff --git a/libraries/nfc/src/util/sdk_common.h b/libraries/nfc/src/util/sdk_common.h new file mode 100644 index 000000000..ef3049f2a --- /dev/null +++ b/libraries/nfc/src/util/sdk_common.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/** @cond */ +/**@file + * + * @ingroup experimental_api + * @defgroup sdk_common SDK Common Header + * @brief All common headers needed for SDK examples will be included here so that application + * developer does not have to include headers on him/herself. + * @{ + */ + +#ifndef SDK_COMMON_H__ +#define SDK_COMMON_H__ + +#include +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "compiler_abstraction.h" +#include "sdk_os.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "sdk_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_COMMON_H__ + diff --git a/libraries/nfc/src/util/sdk_config.h b/libraries/nfc/src/util/sdk_config.h new file mode 100644 index 000000000..84f766958 --- /dev/null +++ b/libraries/nfc/src/util/sdk_config.h @@ -0,0 +1,4231 @@ +/** + * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDK_CONFIG_H +#define SDK_CONFIG_H +// <<< Use Configuration Wizard in Context Menu >>>\n +#ifdef USE_APP_CONFIG +#include "app_config.h" +#endif +// nRF_Drivers + +//========================================================== +// NRFX_CLOCK_ENABLED - nrfx_clock - CLOCK peripheral driver +//========================================================== +#ifndef NRFX_CLOCK_ENABLED +#define NRFX_CLOCK_ENABLED 1 +#endif +// NRFX_CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth +// <131073=> External Low Swing +// <196609=> External Full Swing + +#ifndef NRFX_CLOCK_CONFIG_LF_SRC +#define NRFX_CLOCK_CONFIG_LF_SRC 1 +#endif + +// NRFX_CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_CLOCK_CONFIG_IRQ_PRIORITY +#define NRFX_CLOCK_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_CLOCK_CONFIG_LOG_ENABLED +#define NRFX_CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_CLOCK_CONFIG_LOG_LEVEL +#define NRFX_CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_CLOCK_CONFIG_INFO_COLOR +#define NRFX_CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_CLOCK_CONFIG_DEBUG_COLOR +#define NRFX_CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_NFCT_ENABLED - nrfx_nfct - NFCT peripheral driver +//========================================================== +#ifndef NRFX_NFCT_ENABLED +#define NRFX_NFCT_ENABLED 1 +#endif +// NRFX_NFCT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_NFCT_CONFIG_IRQ_PRIORITY +#define NRFX_NFCT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_NFCT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_NFCT_CONFIG_LOG_ENABLED +#define NRFX_NFCT_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_NFCT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_NFCT_CONFIG_LOG_LEVEL +#define NRFX_NFCT_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_NFCT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_NFCT_CONFIG_INFO_COLOR +#define NRFX_NFCT_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_NFCT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_NFCT_CONFIG_DEBUG_COLOR +#define NRFX_NFCT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_PRS_ENABLED - nrfx_prs - Peripheral Resource Sharing module +//========================================================== +#ifndef NRFX_PRS_ENABLED +#define NRFX_PRS_ENABLED 1 +#endif +// NRFX_PRS_BOX_0_ENABLED - Enables box 0 in the module. + + +#ifndef NRFX_PRS_BOX_0_ENABLED +#define NRFX_PRS_BOX_0_ENABLED 0 +#endif + +// NRFX_PRS_BOX_1_ENABLED - Enables box 1 in the module. + + +#ifndef NRFX_PRS_BOX_1_ENABLED +#define NRFX_PRS_BOX_1_ENABLED 0 +#endif + +// NRFX_PRS_BOX_2_ENABLED - Enables box 2 in the module. + + +#ifndef NRFX_PRS_BOX_2_ENABLED +#define NRFX_PRS_BOX_2_ENABLED 0 +#endif + +// NRFX_PRS_BOX_3_ENABLED - Enables box 3 in the module. + + +#ifndef NRFX_PRS_BOX_3_ENABLED +#define NRFX_PRS_BOX_3_ENABLED 0 +#endif + +// NRFX_PRS_BOX_4_ENABLED - Enables box 4 in the module. + + +#ifndef NRFX_PRS_BOX_4_ENABLED +#define NRFX_PRS_BOX_4_ENABLED 1 +#endif + +// NRFX_PRS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_PRS_CONFIG_LOG_ENABLED +#define NRFX_PRS_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_PRS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_PRS_CONFIG_LOG_LEVEL +#define NRFX_PRS_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_PRS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PRS_CONFIG_INFO_COLOR +#define NRFX_PRS_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_PRS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PRS_CONFIG_DEBUG_COLOR +#define NRFX_PRS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_TIMER_ENABLED - nrfx_timer - TIMER periperal driver +//========================================================== +#ifndef NRFX_TIMER_ENABLED +#define NRFX_TIMER_ENABLED 1 +#endif +// NRFX_TIMER0_ENABLED - Enable TIMER0 instance + + +#ifndef NRFX_TIMER0_ENABLED +#define NRFX_TIMER0_ENABLED 0 +#endif + +// NRFX_TIMER1_ENABLED - Enable TIMER1 instance + + +#ifndef NRFX_TIMER1_ENABLED +#define NRFX_TIMER1_ENABLED 0 +#endif + +// NRFX_TIMER2_ENABLED - Enable TIMER2 instance + + +#ifndef NRFX_TIMER2_ENABLED +#define NRFX_TIMER2_ENABLED 0 +#endif + +// NRFX_TIMER3_ENABLED - Enable TIMER3 instance + + +#ifndef NRFX_TIMER3_ENABLED +#define NRFX_TIMER3_ENABLED 0 +#endif + +// NRFX_TIMER4_ENABLED - Enable TIMER4 instance + + +#ifndef NRFX_TIMER4_ENABLED +#define NRFX_TIMER4_ENABLED 1 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY - Timer frequency if in Timer mode + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz +// <8=> 62.5 kHz +// <9=> 31.25 kHz + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_MODE - Timer mode or operation + +// <0=> Timer +// <1=> Counter + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_MODE +#define NRFX_TIMER_DEFAULT_CONFIG_MODE 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH - Timer counter bit width + +// <0=> 16 bit +// <1=> 8 bit +// <2=> 24 bit +// <3=> 32 bit + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_TIMER_CONFIG_LOG_ENABLED +#define NRFX_TIMER_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_TIMER_CONFIG_LOG_LEVEL +#define NRFX_TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TIMER_CONFIG_INFO_COLOR +#define NRFX_TIMER_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TIMER_CONFIG_DEBUG_COLOR +#define NRFX_TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_UARTE_ENABLED - nrfx_uarte - UARTE peripheral driver +//========================================================== +#ifndef NRFX_UARTE_ENABLED +#define NRFX_UARTE_ENABLED 0//1 +#endif +// NRFX_UARTE0_ENABLED - Enable UARTE0 instance +#ifndef NRFX_UARTE0_ENABLED +#define NRFX_UARTE0_ENABLED 0 +#endif + +// NRFX_UARTE1_ENABLED - Enable UARTE1 instance +#ifndef NRFX_UARTE1_ENABLED +#define NRFX_UARTE1_ENABLED 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_HWFC +#define NRFX_UARTE_DEFAULT_CONFIG_HWFC 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_PARITY +#define NRFX_UARTE_DEFAULT_CONFIG_PARITY 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <8388608=> 31250 baud +// <10289152=> 38400 baud +// <15007744=> 56000 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE 30801920 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_UARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_UARTE_CONFIG_LOG_ENABLED +#define NRFX_UARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_UARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_UARTE_CONFIG_LOG_LEVEL +#define NRFX_UARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_UARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UARTE_CONFIG_INFO_COLOR +#define NRFX_UARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_UARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UARTE_CONFIG_DEBUG_COLOR +#define NRFX_UARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_UART_ENABLED - nrfx_uart - UART peripheral driver +//========================================================== +#ifndef NRFX_UART_ENABLED +#define NRFX_UART_ENABLED 0//1 +#endif +// NRFX_UART0_ENABLED - Enable UART0 instance +#ifndef NRFX_UART0_ENABLED +#define NRFX_UART0_ENABLED 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef NRFX_UART_DEFAULT_CONFIG_HWFC +#define NRFX_UART_DEFAULT_CONFIG_HWFC 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef NRFX_UART_DEFAULT_CONFIG_PARITY +#define NRFX_UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3866624=> 14400 baud +// <5152768=> 19200 baud +// <7729152=> 28800 baud +// <8388608=> 31250 baud +// <10309632=> 38400 baud +// <15007744=> 56000 baud +// <15462400=> 57600 baud +// <20615168=> 76800 baud +// <30924800=> 115200 baud +// <61845504=> 230400 baud +// <67108864=> 250000 baud +// <123695104=> 460800 baud +// <247386112=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRFX_UART_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE 30924800 +#endif + +// NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_UART_CONFIG_LOG_ENABLED +#define NRFX_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_UART_CONFIG_LOG_LEVEL +#define NRFX_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UART_CONFIG_INFO_COLOR +#define NRFX_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UART_CONFIG_DEBUG_COLOR +#define NRFX_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRF_CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer +//========================================================== +#ifndef NRF_CLOCK_ENABLED +#define NRF_CLOCK_ENABLED 1 +#endif +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth +// <131073=> External Low Swing +// <196609=> External Full Swing + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_LF_CAL_ENABLED - Calibration enable for LF Clock Source + + +#ifndef CLOCK_CONFIG_LF_CAL_ENABLED +#define CLOCK_CONFIG_LF_CAL_ENABLED 0 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver - legacy layer +//========================================================== +#ifndef UART_ENABLED +#define UART_ENABLED 0//1 +#endif +// UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef UART_DEFAULT_CONFIG_HWFC +#define UART_DEFAULT_CONFIG_HWFC 0 +#endif + +// UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef UART_DEFAULT_CONFIG_PARITY +#define UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef UART_DEFAULT_CONFIG_BAUDRATE +#define UART_DEFAULT_CONFIG_BAUDRATE 30801920 +#endif + +// UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA + + +#ifndef UART_EASY_DMA_SUPPORT +#define UART_EASY_DMA_SUPPORT 1 +#endif + +// UART_LEGACY_SUPPORT - Driver supporting Legacy mode + + +#ifndef UART_LEGACY_SUPPORT +#define UART_LEGACY_SUPPORT 0//1 +#endif + +// UART0_ENABLED - Enable UART0 instance +//========================================================== +#ifndef UART0_ENABLED +#define UART0_ENABLED 0//1 +#endif +// UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART0_CONFIG_USE_EASY_DMA +#define UART0_CONFIG_USE_EASY_DMA 0//1 +#endif + +// + +// UART1_ENABLED - Enable UART1 instance +//========================================================== +#ifndef UART1_ENABLED +#define UART1_ENABLED 0 +#endif +// + +// + +// +//========================================================== + +// nRF_Libraries + +//========================================================== +// APP_FIFO_ENABLED - app_fifo - Software FIFO implementation + + +#ifndef APP_FIFO_ENABLED +#define APP_FIFO_ENABLED 1 +#endif + +// APP_UART_ENABLED - app_uart - UART driver +//========================================================== +#ifndef APP_UART_ENABLED +#define APP_UART_ENABLED 0//1 +#endif +// APP_UART_DRIVER_INSTANCE - UART instance used + +// <0=> 0 + +#ifndef APP_UART_DRIVER_INSTANCE +#define APP_UART_DRIVER_INSTANCE 0 +#endif + +// + +// HARDFAULT_HANDLER_ENABLED - hardfault_default - HardFault default handler for debugging and release + + +#ifndef HARDFAULT_HANDLER_ENABLED +#define HARDFAULT_HANDLER_ENABLED 1 +#endif + +// NRF_BALLOC_ENABLED - nrf_balloc - Block allocator module +//========================================================== +#ifndef NRF_BALLOC_ENABLED +#define NRF_BALLOC_ENABLED 1 +#endif +// NRF_BALLOC_CONFIG_DEBUG_ENABLED - Enables debug mode in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_CONFIG_DEBUG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS - Number of words used as head guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS +#define NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS - Number of words used as tail guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS +#define NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED - Enables basic checks in this module. + + +#ifndef NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED +#define NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED - Enables double memory free check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED - Enables free memory corruption check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_BALLOC_CLI_CMDS +#define NRF_BALLOC_CLI_CMDS 0 +#endif + +// + +// + +// NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module + + +#ifndef NRF_MEMOBJ_ENABLED +#define NRF_MEMOBJ_ENABLED 1 +#endif + +// NRF_STRERROR_ENABLED - nrf_strerror - Library for converting error code to string. + + +#ifndef NRF_STRERROR_ENABLED +#define NRF_STRERROR_ENABLED 1 +#endif + +// nrf_fprintf - fprintf function. + +//========================================================== +// NRF_FPRINTF_ENABLED - Enable/disable fprintf module. + + +#ifndef NRF_FPRINTF_ENABLED +#define NRF_FPRINTF_ENABLED 0//1 +#endif + +// NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED - For each printed LF, function will add CR. + + +#ifndef NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED +#define NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 0//1 +#endif + +// NRF_FPRINTF_DOUBLE_ENABLED - Enable IEEE-754 double precision formatting. + + +#ifndef NRF_FPRINTF_DOUBLE_ENABLED +#define NRF_FPRINTF_DOUBLE_ENABLED 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Log + +//========================================================== +// NRF_LOG_BACKEND_RTT_ENABLED - nrf_log_backend_rtt - Log RTT backend +//========================================================== +#ifndef NRF_LOG_BACKEND_RTT_ENABLED +#define NRF_LOG_BACKEND_RTT_ENABLED 0 +#endif +// NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64 +#endif + +// NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS - Period before retrying writing to RTT +#ifndef NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS +#define NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS 1 +#endif + +// NRF_LOG_BACKEND_RTT_TX_RETRY_CNT - Writing to RTT retries. +// If RTT fails to accept any new data after retries +// module assumes that host is not active and on next +// request it will perform only one write attempt. +// On successful writing, module assumes that host is active +// and scheme with retry is applied again. + +#ifndef NRF_LOG_BACKEND_RTT_TX_RETRY_CNT +#define NRF_LOG_BACKEND_RTT_TX_RETRY_CNT 3 +#endif + +// + +// NRF_LOG_BACKEND_UART_ENABLED - nrf_log_backend_uart - Log UART backend +//========================================================== +#ifndef NRF_LOG_BACKEND_UART_ENABLED +#define NRF_LOG_BACKEND_UART_ENABLED 0//1 +#endif +// NRF_LOG_BACKEND_UART_TX_PIN - UART TX pin +#ifndef NRF_LOG_BACKEND_UART_TX_PIN +#define NRF_LOG_BACKEND_UART_TX_PIN 6 +#endif + +// NRF_LOG_BACKEND_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRF_LOG_BACKEND_UART_BAUDRATE +#define NRF_LOG_BACKEND_UART_BAUDRATE 30801920 +#endif + +// NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE 64 +#endif + +// + +// NRF_LOG_ENABLED - nrf_log - Logger +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 0//1 +#endif +// Log message pool - Configuration of log message pool + +//========================================================== +// NRF_LOG_MSGPOOL_ELEMENT_SIZE - Size of a single element in the pool of memory objects. +// If a small value is set, then performance of logs processing +// is degraded because data is fragmented. Bigger value impacts +// RAM memory utilization. The size is set to fit a message with +// a timestamp and up to 2 arguments in a single memory object. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_SIZE +#define NRF_LOG_MSGPOOL_ELEMENT_SIZE 20 +#endif + +// NRF_LOG_MSGPOOL_ELEMENT_COUNT - Number of elements in the pool of memory objects +// If a small value is set, then it may lead to a deadlock +// in certain cases if backend has high latency and holds +// multiple messages for long time. Bigger value impacts +// RAM memory usage. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_COUNT +#define NRF_LOG_MSGPOOL_ELEMENT_COUNT 8 +#endif + +// +//========================================================== + +// NRF_LOG_ALLOW_OVERFLOW - Configures behavior when circular buffer is full. + + +// If set then oldest logs are overwritten. Otherwise a +// marker is injected informing about overflow. + +#ifndef NRF_LOG_ALLOW_OVERFLOW +#define NRF_LOG_ALLOW_OVERFLOW 1 +#endif + +// NRF_LOG_BUFSIZE - Size of the buffer for storing logs (in bytes). + + +// Must be power of 2 and multiple of 4. +// If NRF_LOG_DEFERRED = 0 then buffer size can be reduced to minimum. +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 +// <2048=> 2048 +// <4096=> 4096 +// <8192=> 8192 +// <16384=> 16384 + +#ifndef NRF_LOG_BUFSIZE +#define NRF_LOG_BUFSIZE 1024 +#endif + +// NRF_LOG_CLI_CMDS - Enable CLI commands for the module. + + +#ifndef NRF_LOG_CLI_CMDS +#define NRF_LOG_CLI_CMDS 0 +#endif + +// NRF_LOG_DEFAULT_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 3 +#endif + +// NRF_LOG_DEFERRED - Enable deffered logger. + + +// Log data is buffered and can be processed in idle. + +#ifndef NRF_LOG_DEFERRED +#define NRF_LOG_DEFERRED 0//1 +#endif + +// NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs. + + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +// NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED - Enable use of critical region for non deffered mode when flushing logs. + + +// When enabled NRF_LOG_FLUSH is called from critical section when non deffered mode is used. +// Log output will never be corrupted as access to the log backend is exclusive +// but system will spend significant amount of time in critical section + +#ifndef NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED +#define NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED 0 +#endif + +// NRF_LOG_STR_PUSH_BUFFER_SIZE - Size of the buffer dedicated for strings stored using @ref NRF_LOG_PUSH. + +// <16=> 16 +// <32=> 32 +// <64=> 64 +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 + +#ifndef NRF_LOG_STR_PUSH_BUFFER_SIZE +#define NRF_LOG_STR_PUSH_BUFFER_SIZE 128 +#endif + +// NRF_LOG_STR_PUSH_BUFFER_SIZE - Size of the buffer dedicated for strings stored using @ref NRF_LOG_PUSH. + +// <16=> 16 +// <32=> 32 +// <64=> 64 +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 + +#ifndef NRF_LOG_STR_PUSH_BUFFER_SIZE +#define NRF_LOG_STR_PUSH_BUFFER_SIZE 128 +#endif + +// NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string +//========================================================== +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif +// NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +// NRF_LOG_ERROR_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_ERROR_COLOR +#define NRF_LOG_ERROR_COLOR 2 +#endif + +// NRF_LOG_WARNING_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_WARNING_COLOR +#define NRF_LOG_WARNING_COLOR 4 +#endif + +// + +// NRF_LOG_USES_TIMESTAMP - Enable timestamping + +// Function for getting the timestamp is provided by the user +//========================================================== +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif +// NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY - Default frequency of the timestamp (in Hz) or 0 to use app_timer frequency. +#ifndef NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY +#define NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY 0 +#endif + +// + +// nrf_log module configuration + +//========================================================== +// nrf_log in nRF_Core + +//========================================================== +// NRF_MPU_LIB_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MPU_LIB_CONFIG_LOG_ENABLED +#define NRF_MPU_LIB_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MPU_LIB_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MPU_LIB_CONFIG_LOG_LEVEL +#define NRF_MPU_LIB_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MPU_LIB_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_LIB_CONFIG_INFO_COLOR +#define NRF_MPU_LIB_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MPU_LIB_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_LIB_CONFIG_DEBUG_COLOR +#define NRF_MPU_LIB_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_STACK_GUARD_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_STACK_GUARD_CONFIG_LOG_ENABLED +#define NRF_STACK_GUARD_CONFIG_LOG_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_STACK_GUARD_CONFIG_LOG_LEVEL +#define NRF_STACK_GUARD_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_STACK_GUARD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_INFO_COLOR +#define NRF_STACK_GUARD_CONFIG_INFO_COLOR 0 +#endif + +// NRF_STACK_GUARD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_DEBUG_COLOR +#define NRF_STACK_GUARD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TASK_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TASK_MANAGER_CONFIG_LOG_ENABLED +#define TASK_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// TASK_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TASK_MANAGER_CONFIG_LOG_LEVEL +#define TASK_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// TASK_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_INFO_COLOR +#define TASK_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// TASK_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_DEBUG_COLOR +#define TASK_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Drivers + +//========================================================== +// CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef CLOCK_CONFIG_LOG_ENABLED +#define CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef CLOCK_CONFIG_LOG_LEVEL +#define CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_INFO_COLOR +#define CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_DEBUG_COLOR +#define CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMP_CONFIG_LOG_ENABLED +#define COMP_CONFIG_LOG_ENABLED 0 +#endif +// COMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMP_CONFIG_LOG_LEVEL +#define COMP_CONFIG_LOG_LEVEL 3 +#endif + +// COMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_INFO_COLOR +#define COMP_CONFIG_INFO_COLOR 0 +#endif + +// COMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_DEBUG_COLOR +#define COMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef GPIOTE_CONFIG_LOG_ENABLED +#define GPIOTE_CONFIG_LOG_ENABLED 0 +#endif +// GPIOTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef GPIOTE_CONFIG_LOG_LEVEL +#define GPIOTE_CONFIG_LOG_LEVEL 3 +#endif + +// GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_INFO_COLOR +#define GPIOTE_CONFIG_INFO_COLOR 0 +#endif + +// GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_DEBUG_COLOR +#define GPIOTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// LPCOMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef LPCOMP_CONFIG_LOG_ENABLED +#define LPCOMP_CONFIG_LOG_ENABLED 0 +#endif +// LPCOMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef LPCOMP_CONFIG_LOG_LEVEL +#define LPCOMP_CONFIG_LOG_LEVEL 3 +#endif + +// LPCOMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_INFO_COLOR +#define LPCOMP_CONFIG_INFO_COLOR 0 +#endif + +// LPCOMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_DEBUG_COLOR +#define LPCOMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MAX3421E_HOST_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef MAX3421E_HOST_CONFIG_LOG_ENABLED +#define MAX3421E_HOST_CONFIG_LOG_ENABLED 0 +#endif +// MAX3421E_HOST_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef MAX3421E_HOST_CONFIG_LOG_LEVEL +#define MAX3421E_HOST_CONFIG_LOG_LEVEL 3 +#endif + +// MAX3421E_HOST_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MAX3421E_HOST_CONFIG_INFO_COLOR +#define MAX3421E_HOST_CONFIG_INFO_COLOR 0 +#endif + +// MAX3421E_HOST_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MAX3421E_HOST_CONFIG_DEBUG_COLOR +#define MAX3421E_HOST_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRFX_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef NRFX_USBD_CONFIG_LOG_ENABLED +#define NRFX_USBD_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_USBD_CONFIG_LOG_LEVEL +#define NRFX_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_USBD_CONFIG_INFO_COLOR +#define NRFX_USBD_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_USBD_CONFIG_DEBUG_COLOR +#define NRFX_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PDM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PDM_CONFIG_LOG_ENABLED +#define PDM_CONFIG_LOG_ENABLED 0 +#endif +// PDM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PDM_CONFIG_LOG_LEVEL +#define PDM_CONFIG_LOG_LEVEL 3 +#endif + +// PDM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_INFO_COLOR +#define PDM_CONFIG_INFO_COLOR 0 +#endif + +// PDM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_DEBUG_COLOR +#define PDM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PPI_CONFIG_LOG_ENABLED +#define PPI_CONFIG_LOG_ENABLED 0 +#endif +// PPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PPI_CONFIG_LOG_LEVEL +#define PPI_CONFIG_LOG_LEVEL 3 +#endif + +// PPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_INFO_COLOR +#define PPI_CONFIG_INFO_COLOR 0 +#endif + +// PPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_DEBUG_COLOR +#define PPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PWM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PWM_CONFIG_LOG_ENABLED +#define PWM_CONFIG_LOG_ENABLED 0 +#endif +// PWM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PWM_CONFIG_LOG_LEVEL +#define PWM_CONFIG_LOG_LEVEL 3 +#endif + +// PWM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_INFO_COLOR +#define PWM_CONFIG_INFO_COLOR 0 +#endif + +// PWM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_DEBUG_COLOR +#define PWM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// QDEC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef QDEC_CONFIG_LOG_ENABLED +#define QDEC_CONFIG_LOG_ENABLED 0 +#endif +// QDEC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef QDEC_CONFIG_LOG_LEVEL +#define QDEC_CONFIG_LOG_LEVEL 3 +#endif + +// QDEC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_INFO_COLOR +#define QDEC_CONFIG_INFO_COLOR 0 +#endif + +// QDEC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_DEBUG_COLOR +#define QDEC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// RNG_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RNG_CONFIG_LOG_ENABLED +#define RNG_CONFIG_LOG_ENABLED 0 +#endif +// RNG_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RNG_CONFIG_LOG_LEVEL +#define RNG_CONFIG_LOG_LEVEL 3 +#endif + +// RNG_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_INFO_COLOR +#define RNG_CONFIG_INFO_COLOR 0 +#endif + +// RNG_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_DEBUG_COLOR +#define RNG_CONFIG_DEBUG_COLOR 0 +#endif + +// RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED - Enables logging of random numbers. + + +#ifndef RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED +#define RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED 0 +#endif + +// + +// RTC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RTC_CONFIG_LOG_ENABLED +#define RTC_CONFIG_LOG_ENABLED 0 +#endif +// RTC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RTC_CONFIG_LOG_LEVEL +#define RTC_CONFIG_LOG_LEVEL 3 +#endif + +// RTC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_INFO_COLOR +#define RTC_CONFIG_INFO_COLOR 0 +#endif + +// RTC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_DEBUG_COLOR +#define RTC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SAADC_CONFIG_LOG_ENABLED +#define SAADC_CONFIG_LOG_ENABLED 0 +#endif +// SAADC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SAADC_CONFIG_LOG_LEVEL +#define SAADC_CONFIG_LOG_LEVEL 3 +#endif + +// SAADC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_INFO_COLOR +#define SAADC_CONFIG_INFO_COLOR 0 +#endif + +// SAADC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_DEBUG_COLOR +#define SAADC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPIS_CONFIG_LOG_ENABLED +#define SPIS_CONFIG_LOG_ENABLED 0 +#endif +// SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPIS_CONFIG_LOG_LEVEL +#define SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_INFO_COLOR +#define SPIS_CONFIG_INFO_COLOR 0 +#endif + +// SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_DEBUG_COLOR +#define SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPI_CONFIG_LOG_ENABLED +#define SPI_CONFIG_LOG_ENABLED 0 +#endif +// SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPI_CONFIG_LOG_LEVEL +#define SPI_CONFIG_LOG_LEVEL 3 +#endif + +// SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_INFO_COLOR +#define SPI_CONFIG_INFO_COLOR 0 +#endif + +// SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_DEBUG_COLOR +#define SPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TIMER_CONFIG_LOG_ENABLED +#define TIMER_CONFIG_LOG_ENABLED 0 +#endif +// TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TIMER_CONFIG_LOG_LEVEL +#define TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_INFO_COLOR +#define TIMER_CONFIG_INFO_COLOR 0 +#endif + +// TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_DEBUG_COLOR +#define TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWIS_CONFIG_LOG_ENABLED +#define TWIS_CONFIG_LOG_ENABLED 0 +#endif +// TWIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWIS_CONFIG_LOG_LEVEL +#define TWIS_CONFIG_LOG_LEVEL 3 +#endif + +// TWIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_INFO_COLOR +#define TWIS_CONFIG_INFO_COLOR 0 +#endif + +// TWIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_DEBUG_COLOR +#define TWIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWI_CONFIG_LOG_ENABLED +#define TWI_CONFIG_LOG_ENABLED 0 +#endif +// TWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWI_CONFIG_LOG_LEVEL +#define TWI_CONFIG_LOG_LEVEL 3 +#endif + +// TWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_INFO_COLOR +#define TWI_CONFIG_INFO_COLOR 0 +#endif + +// TWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_DEBUG_COLOR +#define TWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef UART_CONFIG_LOG_ENABLED +#define UART_CONFIG_LOG_ENABLED 0 +#endif +// UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef UART_CONFIG_LOG_LEVEL +#define UART_CONFIG_LOG_LEVEL 3 +#endif + +// UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_INFO_COLOR +#define UART_CONFIG_INFO_COLOR 0 +#endif + +// UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_DEBUG_COLOR +#define UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef USBD_CONFIG_LOG_ENABLED +#define USBD_CONFIG_LOG_ENABLED 0 +#endif +// USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef USBD_CONFIG_LOG_LEVEL +#define USBD_CONFIG_LOG_LEVEL 3 +#endif + +// USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_INFO_COLOR +#define USBD_CONFIG_INFO_COLOR 0 +#endif + +// USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_DEBUG_COLOR +#define USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// WDT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef WDT_CONFIG_LOG_ENABLED +#define WDT_CONFIG_LOG_ENABLED 0 +#endif +// WDT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef WDT_CONFIG_LOG_LEVEL +#define WDT_CONFIG_LOG_LEVEL 3 +#endif + +// WDT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_INFO_COLOR +#define WDT_CONFIG_INFO_COLOR 0 +#endif + +// WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_DEBUG_COLOR +#define WDT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Libraries + +//========================================================== +// APP_BUTTON_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_BUTTON_CONFIG_LOG_ENABLED +#define APP_BUTTON_CONFIG_LOG_ENABLED 0 +#endif +// APP_BUTTON_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_BUTTON_CONFIG_LOG_LEVEL +#define APP_BUTTON_CONFIG_LOG_LEVEL 3 +#endif + +// APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL +#define APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// APP_BUTTON_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_BUTTON_CONFIG_INFO_COLOR +#define APP_BUTTON_CONFIG_INFO_COLOR 0 +#endif + +// APP_BUTTON_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_BUTTON_CONFIG_DEBUG_COLOR +#define APP_BUTTON_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_TIMER_CONFIG_LOG_ENABLED +#define APP_TIMER_CONFIG_LOG_ENABLED 0 +#endif +// APP_TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_TIMER_CONFIG_LOG_LEVEL +#define APP_TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// APP_TIMER_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_TIMER_CONFIG_INITIAL_LOG_LEVEL +#define APP_TIMER_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// APP_TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_TIMER_CONFIG_INFO_COLOR +#define APP_TIMER_CONFIG_INFO_COLOR 0 +#endif + +// APP_TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_TIMER_CONFIG_DEBUG_COLOR +#define APP_TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CDC_ACM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define APP_USBD_CDC_ACM_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#define APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module. +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CONFIG_LOG_LEVEL +#define APP_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_INFO_COLOR +#define APP_USBD_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_DEBUG_COLOR +#define APP_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_DUMMY_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_DUMMY_CONFIG_LOG_ENABLED +#define APP_USBD_DUMMY_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_DUMMY_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_DUMMY_CONFIG_LOG_LEVEL +#define APP_USBD_DUMMY_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_DUMMY_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_DUMMY_CONFIG_INFO_COLOR +#define APP_USBD_DUMMY_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_DUMMY_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_DUMMY_CONFIG_DEBUG_COLOR +#define APP_USBD_DUMMY_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_MSC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_MSC_CONFIG_LOG_ENABLED +#define APP_USBD_MSC_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_MSC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_MSC_CONFIG_LOG_LEVEL +#define APP_USBD_MSC_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_MSC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_INFO_COLOR +#define APP_USBD_MSC_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_MSC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_DEBUG_COLOR +#define APP_USBD_MSC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_ATFIFO_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_ATFIFO_CONFIG_LOG_ENABLED +#define NRF_ATFIFO_CONFIG_LOG_ENABLED 0 +#endif +// NRF_ATFIFO_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_ATFIFO_CONFIG_LOG_LEVEL +#define NRF_ATFIFO_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_ATFIFO_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_ATFIFO_CONFIG_INFO_COLOR +#define NRF_ATFIFO_CONFIG_INFO_COLOR 0 +#endif + +// NRF_ATFIFO_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_ATFIFO_CONFIG_DEBUG_COLOR +#define NRF_ATFIFO_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BALLOC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_LOG_ENABLED +#define NRF_BALLOC_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_LOG_LEVEL +#define NRF_BALLOC_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL +#define NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_INFO_COLOR +#define NRF_BALLOC_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BALLOC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_DEBUG_COLOR +#define NRF_BALLOC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_BLE_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_INFO_COLOR +#define NRF_CLI_BLE_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR +#define NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_INFO_COLOR +#define NRF_CLI_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_LIBUARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_LIBUARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_LIBUARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_LIBUARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_LIBUARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_LIBUARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_LIBUARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LIBUARTE_CONFIG_DEBUG_COLOR +#define NRF_LIBUARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_MEMOBJ_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MEMOBJ_CONFIG_LOG_ENABLED +#define NRF_MEMOBJ_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MEMOBJ_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MEMOBJ_CONFIG_LOG_LEVEL +#define NRF_MEMOBJ_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MEMOBJ_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_INFO_COLOR +#define NRF_MEMOBJ_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MEMOBJ_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_DEBUG_COLOR +#define NRF_MEMOBJ_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_LOG_ENABLED +#define NRF_PWR_MGMT_CONFIG_LOG_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_PWR_MGMT_CONFIG_LOG_LEVEL +#define NRF_PWR_MGMT_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_PWR_MGMT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_INFO_COLOR +#define NRF_PWR_MGMT_CONFIG_INFO_COLOR 0 +#endif + +// NRF_PWR_MGMT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_COLOR +#define NRF_PWR_MGMT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_QUEUE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_QUEUE_CONFIG_LOG_ENABLED +#define NRF_QUEUE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_QUEUE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_QUEUE_CONFIG_LOG_LEVEL +#define NRF_QUEUE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_QUEUE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_QUEUE_CONFIG_INFO_COLOR +#define NRF_QUEUE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_QUEUE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_QUEUE_CONFIG_DEBUG_COLOR +#define NRF_QUEUE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_ANT_LOG_ENABLED - Enable logging in SoftDevice handler (ANT) module. +//========================================================== +#ifndef NRF_SDH_ANT_LOG_ENABLED +#define NRF_SDH_ANT_LOG_ENABLED 0 +#endif +// NRF_SDH_ANT_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_ANT_LOG_LEVEL +#define NRF_SDH_ANT_LOG_LEVEL 3 +#endif + +// NRF_SDH_ANT_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_INFO_COLOR +#define NRF_SDH_ANT_INFO_COLOR 0 +#endif + +// NRF_SDH_ANT_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_DEBUG_COLOR +#define NRF_SDH_ANT_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_BLE_LOG_ENABLED - Enable logging in SoftDevice handler (BLE) module. +//========================================================== +#ifndef NRF_SDH_BLE_LOG_ENABLED +#define NRF_SDH_BLE_LOG_ENABLED 0 +#endif +// NRF_SDH_BLE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_BLE_LOG_LEVEL +#define NRF_SDH_BLE_LOG_LEVEL 3 +#endif + +// NRF_SDH_BLE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_INFO_COLOR +#define NRF_SDH_BLE_INFO_COLOR 0 +#endif + +// NRF_SDH_BLE_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_DEBUG_COLOR +#define NRF_SDH_BLE_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_LOG_ENABLED - Enable logging in SoftDevice handler module. +//========================================================== +#ifndef NRF_SDH_LOG_ENABLED +#define NRF_SDH_LOG_ENABLED 0 +#endif +// NRF_SDH_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_LOG_LEVEL +#define NRF_SDH_LOG_LEVEL 3 +#endif + +// NRF_SDH_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_INFO_COLOR +#define NRF_SDH_INFO_COLOR 0 +#endif + +// NRF_SDH_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_DEBUG_COLOR +#define NRF_SDH_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_SOC_LOG_ENABLED - Enable logging in SoftDevice handler (SoC) module. +//========================================================== +#ifndef NRF_SDH_SOC_LOG_ENABLED +#define NRF_SDH_SOC_LOG_ENABLED 0 +#endif +// NRF_SDH_SOC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_SOC_LOG_LEVEL +#define NRF_SDH_SOC_LOG_LEVEL 3 +#endif + +// NRF_SDH_SOC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_INFO_COLOR +#define NRF_SDH_SOC_INFO_COLOR 0 +#endif + +// NRF_SDH_SOC_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_DEBUG_COLOR +#define NRF_SDH_SOC_DEBUG_COLOR 0 +#endif + +// + +// NRF_SORTLIST_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_SORTLIST_CONFIG_LOG_ENABLED +#define NRF_SORTLIST_CONFIG_LOG_ENABLED 0 +#endif +// NRF_SORTLIST_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SORTLIST_CONFIG_LOG_LEVEL +#define NRF_SORTLIST_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_SORTLIST_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SORTLIST_CONFIG_INFO_COLOR +#define NRF_SORTLIST_CONFIG_INFO_COLOR 0 +#endif + +// NRF_SORTLIST_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SORTLIST_CONFIG_DEBUG_COLOR +#define NRF_SORTLIST_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_TWI_SENSOR_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_TWI_SENSOR_CONFIG_LOG_ENABLED +#define NRF_TWI_SENSOR_CONFIG_LOG_ENABLED 0 +#endif +// NRF_TWI_SENSOR_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_TWI_SENSOR_CONFIG_LOG_LEVEL +#define NRF_TWI_SENSOR_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_TWI_SENSOR_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_TWI_SENSOR_CONFIG_INFO_COLOR +#define NRF_TWI_SENSOR_CONFIG_INFO_COLOR 0 +#endif + +// NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR +#define NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PM_LOG_ENABLED - Enable logging in Peer Manager and its submodules. +//========================================================== +#ifndef PM_LOG_ENABLED +#define PM_LOG_ENABLED 1 +#endif +// PM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PM_LOG_LEVEL +#define PM_LOG_LEVEL 3 +#endif + +// PM_LOG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PM_LOG_INFO_COLOR +#define PM_LOG_INFO_COLOR 0 +#endif + +// PM_LOG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PM_LOG_DEBUG_COLOR +#define PM_LOG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Serialization + +//========================================================== +// SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED +#define SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED 0 +#endif +// SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL +#define SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL 3 +#endif + +// SER_HAL_TRANSPORT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SER_HAL_TRANSPORT_CONFIG_INFO_COLOR +#define SER_HAL_TRANSPORT_CONFIG_INFO_COLOR 0 +#endif + +// SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR +#define SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// +//========================================================== + +// + +// NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED - nrf_log_str_formatter - Log string formatter + + +#ifndef NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED +#define NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED 1 +#endif + +// +//========================================================== + +// nRF_NFC + +#ifndef NFC_NDEF_LAUNCHAPP_MSG_ENABLED +#define NFC_NDEF_LAUNCHAPP_MSG_ENABLED 1 +#endif + +// NFC_NDEF_LAUNCHAPP_REC_ENABLED - nfc_launchapp_rec - Encoding data for NDEF Application Launching record for NFC Tag + + +#ifndef NFC_NDEF_LAUNCHAPP_REC_ENABLED +#define NFC_NDEF_LAUNCHAPP_REC_ENABLED 1 +#endif +//========================================================== +// NFC_NDEF_MSG_ENABLED - nfc_ndef_msg - NFC NDEF Message generator module +//========================================================== +#ifndef NFC_NDEF_MSG_ENABLED +#define NFC_NDEF_MSG_ENABLED 1 +#endif +// NFC_NDEF_MSG_TAG_TYPE - NFC Tag Type + +// <2=> Type 2 Tag +// <4=> Type 4 Tag + +#ifndef NFC_NDEF_MSG_TAG_TYPE +#define NFC_NDEF_MSG_TAG_TYPE 2 +#endif + +// + +// NFC_NDEF_RECORD_ENABLED - nfc_ndef_record - NFC NDEF Record generator module + + +#ifndef NFC_NDEF_RECORD_ENABLED +#define NFC_NDEF_RECORD_ENABLED 1 +#endif + +// NFC_NDEF_URI_MSG_ENABLED - nfc_uri_msg - Encoding data for NDEF message with URI record for NFC Tag + + +#ifndef NFC_NDEF_URI_MSG_ENABLED +#define NFC_NDEF_URI_MSG_ENABLED 1 +#endif + +// NFC_NDEF_URI_REC_ENABLED - nfc_uri_rec - Encoding data for a URI record for NFC Tag + + +#ifndef NFC_NDEF_URI_REC_ENABLED +#define NFC_NDEF_URI_REC_ENABLED 1 +#endif + +// NFC_NDEF_TEXT_RECORD_ENABLED - nfc_text_rec - Encoding data for a text record for NFC Tag + + +#ifndef NFC_NDEF_TEXT_RECORD_ENABLED +#define NFC_NDEF_TEXT_RECORD_ENABLED 1 +#endif +// NFC_PLATFORM_ENABLED - nfc_platform - NFC platform module for Clock control. +//========================================================== +#ifndef NFC_PLATFORM_ENABLED +#define NFC_PLATFORM_ENABLED 1 +#endif +// NFC_PLATFORM_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_PLATFORM_LOG_ENABLED +#define NFC_PLATFORM_LOG_ENABLED 0 +#endif +// NFC_PLATFORM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_PLATFORM_LOG_LEVEL +#define NFC_PLATFORM_LOG_LEVEL 3 +#endif + +// NFC_PLATFORM_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_PLATFORM_INFO_COLOR +#define NFC_PLATFORM_INFO_COLOR 0 +#endif + +// NFC_PLATFORM_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_PLATFORM_DEBUG_COLOR +#define NFC_PLATFORM_DEBUG_COLOR 0 +#endif + +// + +// + +// +//========================================================== + +// nRF_Segger_RTT + +//========================================================== +// segger_rtt - SEGGER RTT + +//========================================================== +// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. +// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE +// or this value is actually used. It depends on which one is bigger. + +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Maximum number of upstream buffers. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of downstream buffer. +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Maximum number of downstream buffers. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. + + +// The following modes are supported: +// - SKIP - Do not block, output nothing. +// - TRIM - Do not block, output as much as fits. +// - BLOCK - Wait until there is space in the buffer. +// <0=> SKIP +// <1=> TRIM +// <2=> BLOCK_IF_FIFO_FULL + +#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE +#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_SOC_ENABLED - nrf_sdh_soc - SoftDevice SoC event handler +//========================================================== +#ifndef NRF_SDH_SOC_ENABLED +#define NRF_SDH_SOC_ENABLED 1//0 +#endif +// SoC Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_SOC_OBSERVER_PRIO_LEVELS - Total number of priority levels for SoC observers. +// This setting configures the number of priority levels available for the SoC event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_SOC_OBSERVER_PRIO_LEVELS +#define NRF_SDH_SOC_OBSERVER_PRIO_LEVELS 2 +#endif + +// SoC Observers priorities - Invididual priorities + +//========================================================== +// BLE_DFU_SOC_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_SOC_OBSERVER_PRIO +#define BLE_DFU_SOC_OBSERVER_PRIO 1 +#endif + +// CLOCK_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_SOC_OBSERVER_PRIO +#define CLOCK_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_SOC_OBSERVER_PRIO +#define POWER_CONFIG_SOC_OBSERVER_PRIO 0 +#endif +// +//========================================================== + +// +//========================================================== + +// <<< end of configuration section >>> +#endif //SDK_CONFIG_H + diff --git a/libraries/nfc/src/util/sdk_errors.h b/libraries/nfc/src/util/sdk_errors.h new file mode 100644 index 000000000..21eb0b271 --- /dev/null +++ b/libraries/nfc/src/util/sdk_errors.h @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + * @defgroup sdk_error SDK Error codes + * @{ + * @ingroup app_common + * @{ + * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for + * identifying the module where the error occurred while the least least significant LSB + * are used to provide the cause or nature of error. Each module is assigned a 16-bit + * unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit + * LSB range is with module id as the MSB in the 32-bit error code is reserved for the + * module. As an example, if 0x8800 identifies a certain SDK module, all values from + * 0x88000000 - 0x8800FFFF are reserved for this module. + * It should be noted that common error reasons have been assigned values to make it + * possible to decode error reason easily. As an example, lets module uninitialized has + * been assigned an error code 0x000A0. Then, if application encounters an error code + * 0xZZZZ00A0, it knows that it accessing a certain module without initializing it. + * Apart from this, each module is allowed to define error codes that are not covered by + * the common ones, however, these values are defined in a range that does not conflict + * with common error values. For module, specific error however, it is possible that the + * same error value is used by two different modules to indicated errors of very different + * nature. If error is already defined by the NRF common error codes, these are reused. + * A range is reserved for application as well, it can use this range for defining + * application specific errors. + * + * @note Success code, NRF_SUCCESS, does not include any module identifier. + + */ + +#ifndef SDK_ERRORS_H__ +#define SDK_ERRORS_H__ + +#include +#include "nrf_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup sdk_err_base Base defined for SDK Modules + * @{ + */ +#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */ +#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */ +/** @} */ + +/** + * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred. + * @{ + */ +#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) /**< Base address for Memory Manager related errors. */ +#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) /**< Base address for Peripheral drivers related errors. */ +#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) /**< Base address for Gazelle related errors. */ +#define NRF_ERROR_BLE_IPSP_ERR_BASE (0x8400) /**< Base address for BLE IPSP related errors. */ +#define NRF_ERROR_CRYPTO_ERR_BASE (0x8500) /**< Base address for crypto related errors. */ +#define NRF_ERROR_FDS_ERR_BASE (0x8600) /**< Base address for FDS related errors. */ +/** @} */ + + +/** + * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors. + * @{ + */ +#define NRF_ERROR_IOT_ERR_BASE_START (0xA000) +#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF) +/** @} */ + + +/** + * @defgroup sdk_common_errors Codes reserved as identification for common errors. + * @{ + */ +#define NRF_ERROR_MODULE_NOT_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) ///< Module not initialized +#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) ///< Mutex initialization failed +#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) ///< Mutex lock failed +#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) ///< Mutex unlock failed +#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) ///< Mutex conditional initialization failed +#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) ///< Module already initialized +#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) ///< Storage full +#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) ///< API not implemented +#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) ///< Feature not enabled +#define NRF_ERROR_IO_PENDING (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0012) ///< Input/Output pending +/** @} */ + + +/** + * @defgroup drv_specific_errors Error / status codes specific to drivers. + * @{ + */ +#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000) +#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001) +#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002) +/** @} */ + + +/** + * @defgroup ble_ipsp_errors IPSP codes + * @brief Error and status codes specific to IPSP. + * @{ + */ +#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000) +#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001) +#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002) +#define NRF_ERROR_BLE_IPSP_PEER_REJECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003) +/* @} */ + + +/** + * @brief API Result. + * + * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive + * error code indicating cause or reason for failure is provided. + * + * Though called an API result, it could used in Asynchronous notifications callback along + * with asynchronous callback as event result. This mechanism is employed when an event + * marks the end of procedure initiated using API. API result, in this case, will only be + * an indicative of whether the procedure has been requested successfully. + */ +typedef uint32_t ret_code_t; + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_ERRORS_H__ diff --git a/libraries/nfc/src/util/sdk_macros.h b/libraries/nfc/src/util/sdk_macros.h new file mode 100644 index 000000000..e2f800687 --- /dev/null +++ b/libraries/nfc/src/util/sdk_macros.h @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * + + * @defgroup sdk_common_macros SDK Common Header + * @ingroup app_common + * @brief Macros for parameter checking and similar tasks + * @{ + */ + +#ifndef SDK_MACROS_H__ +#define SDK_MACROS_H__ + +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for parameter checking. + * + * If @p _cond evaluates to true, does nothing. Otherwise, + * if @p _module ## _PARAM_CHECK_DISABLED is @e not set (default), prints an error message + * if @p _printfn is provided, and returns from the calling function context with code @p _err. + * If @p _module ## _PARAM_CHECK_DISABLED is set, behaves like the ASSERT macro. + * + * Parameter checking implemented using this macro can be optionally turned off for release code. + * Only disable runtime parameter checks if size if a major concern. + * + * @param _module The module name. + * @param _cond The condition to be evaluated. + * @param _err The error to be returned. + * @param _printfn A printf-compatible function used to log the error. + * Leave empty if no logging is needed. + * + * @hideinitializer + */ +/*lint -esym(666, NRF_PARAM_CHECK*) : Expression with side effects passed to macro */ +#define NRF_PARAM_CHECK(_module, _cond, _err, _printfn) \ + do \ + { \ + if ((_cond)) \ + { \ + /* Do nothing. */ \ + } \ + else if (!(_module ## _PARAM_CHECK_DISABLED)) \ + { \ + _printfn("%s check failed in %s() with value 0x%x.", #_cond, __func__, _err); \ + return (_err); \ + } \ + else \ + { \ + ASSERT((_cond)); \ + } \ + } while (0); + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * err_code if the statement is not true. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is false. + */ +#define VERIFY_TRUE(statement, err_code) \ +do \ +{ \ + if (!(statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * if the statement is not true. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), ) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * err_code if the statement is not false. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is true. + */ +#define VERIFY_FALSE(statement, err_code) \ +do \ +{ \ + if ((statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * if the statement is not false. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), ) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return error code of statement if it is not @ref NRF_SUCCESS. + * + * @param[in] statement Statement to check against NRF_SUCCESS. + */ +#define VERIFY_SUCCESS(statement) \ +do \ +{ \ + uint32_t _err_code = (uint32_t) (statement); \ + if (_err_code != NRF_SUCCESS) \ + { \ + return _err_code; \ + } \ +} while(0) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return @ref NRF_ERROR_INVALID_STATE if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED)) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return false if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED_BOOL() VERIFY_TRUE((MODULE_INITIALIZED), false) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL)) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_MACROS_H__ + diff --git a/libraries/nfc/src/util/sdk_mapped_flags.c b/libraries/nfc/src/util/sdk_mapped_flags.c new file mode 100644 index 000000000..de510b4ac --- /dev/null +++ b/libraries/nfc/src/util/sdk_mapped_flags.c @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_mapped_flags.h" +#include +#include +#include +#include "compiler_abstraction.h" + + +// Test whether the flag collection type is large enough to hold all the flags. If this fails, +// reduce SDK_MAPPED_FLAGS_N_KEYS or increase the size of sdk_mapped_flags_t. +STATIC_ASSERT((sizeof(sdk_mapped_flags_t) * SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE) >= SDK_MAPPED_FLAGS_N_KEYS); + + +/**@brief Function for setting the state of a flag to true. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to modify. + * @param[in] index The index of the flag to modify. + */ +static __INLINE void sdk_mapped_flags_set_by_index(sdk_mapped_flags_t * p_flags, uint16_t index) +{ + *p_flags |= (1U << index); +} + + +/**@brief Function for setting the state of a flag to false. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to modify. + * @param[in] index The index of the flag to modify. + */ +static __INLINE void sdk_mapped_flags_clear_by_index(sdk_mapped_flags_t * p_flags, uint16_t index) +{ + *p_flags &= ~(1U << index); +} + + +/**@brief Function for getting the state of a flag. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to read. + * @param[in] index The index of the flag to get. + */ +static __INLINE bool sdk_mapped_flags_get_by_index(sdk_mapped_flags_t flags, uint16_t index) +{ + return ((flags & (1 << index)) != 0); +} + + + +uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags) +{ + for (uint16_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + return i; + } + } + return SDK_MAPPED_FLAGS_INVALID_INDEX; +} + + +void sdk_mapped_flags_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint16_t key, + bool value) +{ + sdk_mapped_flags_bulk_update_by_key(p_keys, p_flags, 1, key, value); +} + + +void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint32_t n_flag_collections, + uint16_t key, + bool value) +{ + if ((p_keys != NULL) && (p_flags != NULL) && (n_flag_collections > 0)) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + for (uint32_t j = 0; j < n_flag_collections; j++) + { + if (value) + { + sdk_mapped_flags_set_by_index(&p_flags[j], i); + } + else + { + sdk_mapped_flags_clear_by_index(&p_flags[j], i); + } + } + return; + } + } + } +} + + +bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys, + sdk_mapped_flags_t flags, + uint16_t key, + uint8_t * p_index) +{ + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + if (p_index != NULL) + { + *p_index = i; + } + return sdk_mapped_flags_get_by_index(flags, i); + } + } + } + if (p_index != NULL) + { + *p_index = SDK_MAPPED_FLAGS_N_KEYS; + } + return false; +} + + +bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key) +{ + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + return sdk_mapped_flags_get_by_index(flags, i); + } + } + } + return false; +} + + +sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys, + sdk_mapped_flags_t flags) +{ + sdk_mapped_flags_key_list_t key_list; + key_list.len = 0; + + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + key_list.flag_keys[key_list.len++] = p_keys[i]; + } + } + } + + return key_list; +} + + +uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags) +{ + uint32_t n_flags_set = 0; + + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + n_flags_set += 1; + } + } + return n_flags_set; +} diff --git a/libraries/nfc/src/util/sdk_mapped_flags.h b/libraries/nfc/src/util/sdk_mapped_flags.h new file mode 100644 index 000000000..93075e6e7 --- /dev/null +++ b/libraries/nfc/src/util/sdk_mapped_flags.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDK_MAPPED_FLAGS_H__ +#define SDK_MAPPED_FLAGS_H__ + +#include +#include +#include "app_util.h" +#include "compiler_abstraction.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup sdk_mapped_flags Mapped flags + * @ingroup app_common + * @{ + * @brief Module for writing and reading flags that are associated + * with keys. + * + * @details The flags are represented as bits in a bitmap called a flag collection. The keys + * are uint16_t. Each flag collection contains all flags of the same type, one flag for + * each key. + * + * The mapped flags module does not keep the flag states, nor the list of keys. These are + * provided in the API calls. A key's index in the key list determines which bit in the + * flag collection is associated with it. This module does not ever edit the key list, and + * does not edit flags except in function calls that take the flag collection as a pointer. + * + */ + +#define SDK_MAPPED_FLAGS_N_KEYS 32 /**< The number of keys to keep flags for. This is also the number of flags in a flag collection. If changing this value, you might also need change the width of the sdk_mapped_flags_t type. */ +#define SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE 8 /**< The number of flags that fit in one byte. */ +#define SDK_MAPPED_FLAGS_INVALID_INDEX 0xFFFF /**< A flag index guaranteed to be invalid. */ + +typedef uint32_t sdk_mapped_flags_t; /**< The bitmap to hold flags. Each flag is one bit, and each bit represents the flag state associated with one key. */ + + +/**@brief Type used to present a subset of the registered keys. + */ +typedef struct +{ + uint32_t len; /**< The length of the list. */ + uint16_t flag_keys[SDK_MAPPED_FLAGS_N_KEYS]; /**< The list of keys. */ +} sdk_mapped_flags_key_list_t; + + +/**@brief Function for getting the first index at which the flag is true in the provided + * collection. + * + * @param[in] flags The flag collection to search for a flag set to true. + * + * @return The first index that has its flag set to true. If none were found, the + * function returns @ref SDK_MAPPED_FLAGS_INVALID_INDEX. + */ +uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags); + + +/**@brief Function for updating the state of a flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[out] p_flags The flag collection to modify. + * @param[in] key The key to modify the flag of. + * @param[in] value The state to set the flag to. + */ +void sdk_mapped_flags_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint16_t key, + bool value); + + +/**@brief Function for updating the state of the same flag in multiple flag collections. + * + * @details The key and value are the same for all flag collections in the p_flags array. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[out] p_flags The flag collections to modify. + * @param[out] n_flag_collections The number of flag collections in p_flags. + * @param[in] key The key to modify the flag of. + * @param[in] value The state to set the flag to. + */ +void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint32_t n_flag_collections, + uint16_t key, + bool value); + + +/**@brief Function for getting the state of a specific flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection to read from. + * @param[in] key The key to get the flag for. + * + * @return The state of the flag. + */ +bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key); + + +/**@brief Function for getting the state of a specific flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection from which to read. + * @param[in] key The key for which to get the flag. + * @param[out] p_index If not NULL, the index of the key. + * + * @return The state of the flag. + */ +bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys, + sdk_mapped_flags_t flags, + uint16_t key, + uint8_t * p_index); + + +/**@brief Function for getting a list of all keys that have a specific flag set to true. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection to search. + * + * @return The list of keys. + */ +sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys, + sdk_mapped_flags_t flags); + + +/**@brief Function for getting the number of keys that have a specific flag set to true. + * + * @param[in] flags The flag collection to search. + * + * @return The number of keys. + */ +uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags); + + +/**@brief Function for querying whether any flags in the collection are set. + * + * @param[in] flags The flag collection to query. + * + * @retval true If one or more flags are set to true. + * @retval false Otherwise. + */ +static __INLINE bool sdk_mapped_flags_any_set(sdk_mapped_flags_t flags) +{ + return (flags != 0); +} + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SDK_MAPPED_FLAGS_H__ */ diff --git a/libraries/nfc/src/util/sdk_os.h b/libraries/nfc/src/util/sdk_os.h new file mode 100644 index 000000000..3cc9c9db1 --- /dev/null +++ b/libraries/nfc/src/util/sdk_os.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/** @cond */ +/**@file + * + * @defgroup sdk_os SDK OS Abstraction + * @ingroup experimental_api + * @details In order to made SDK modules independent of use of an embedded OS, and permit + * application with varied task architecture, SDK abstracts the OS specific + * elements here in order to make all other modules agnostic to the OS or task + * architecture. + * @{ + */ + +#ifndef SDK_OS_H__ +#define SDK_OS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDK_MUTEX_DEFINE(X) +#define SDK_MUTEX_INIT(X) +#define SDK_MUTEX_LOCK(X) +#define SDK_MUTEX_UNLOCK(X) + +/** + * @defgroup os_data_type Data types. + */ + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_OS_H__ + diff --git a/libraries/nfc/src/util/sdk_resources.h b/libraries/nfc/src/util/sdk_resources.h new file mode 100644 index 000000000..2d1f7379d --- /dev/null +++ b/libraries/nfc/src/util/sdk_resources.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA + * + * All rights reserved. + * + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Definition file for resource usage by SoftDevice, ESB and Gazell. + */ + +#ifndef SDK_RESOURCES_H__ +#define SDK_RESOURCES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD) // defined(SOFTDEVICE_PRESENT) || + #include "nrf_sd_def.h" +#else + #define SD_PPI_RESTRICTED 0uL /**< 1 if PPI peripheral is restricted, 0 otherwise. */ + #define SD_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by SotfDevice (not available to th spplication). */ + #define SD_PPI_GROUPS_USED 0uL /**< PPI groups utilized by SotfDevice (not available to th spplication). */ + #define SD_TIMERS_USED 0uL /**< Timers used by SoftDevice. */ + #define SD_SWI_USED 0uL /**< Software interrupts used by SoftDevice. */ +#endif + +#ifdef GAZELL_PRESENT + #include "nrf_gzll_resources.h" +#else + #define GZLL_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by Gazell (not available to th spplication). */ + #define GZLL_TIMERS_USED 0uL /**< Timers used by Gazell. */ + #define GZLL_SWI_USED 0uL /**< Software interrupts used by Gazell */ +#endif + +#ifdef ESB_PRESENT + #include "nrf_esb_resources.h" +#else + #define ESB_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by ESB (not available to th spplication). */ + #define ESB_TIMERS_USED 0uL /**< Timers used by ESB. */ + #define ESB_SWI_USED 0uL /**< Software interrupts used by ESB */ +#endif + +#define NRF_PPI_CHANNELS_USED (SD_PPI_CHANNELS_USED | GZLL_PPI_CHANNELS_USED | ESB_PPI_CHANNELS_USED) +#define NRF_PPI_GROUPS_USED (SD_PPI_GROUPS_USED) +#define NRF_SWI_USED (SD_SWI_USED | GZLL_SWI_USED | ESB_SWI_USED) +#define NRF_TIMERS_USED (SD_TIMERS_USED | GZLL_TIMERS_USED | ESB_TIMERS_USED) + +#ifdef __cplusplus +} +#endif + +#endif // SDK_RESOURCES_H__