初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_AC_REC_PARSER)
#include "nfc_ac_rec_parser.h"
#include "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)

View File

@@ -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__
/** @} */

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_BLE_OOB_ADVDATA_PARSER)
#include "nfc_ble_oob_advdata_parser.h"
#include "app_util.h"
#include "nfc_ble_pair_common.h"
#define NRF_LOG_MODULE_NAME ble_oob_ad_parser
#include "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)

View File

@@ -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 "sdk_errors.h"
#include "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__
/** @} */

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_LE_OOB_REC_PARSER)
#include "nfc_le_oob_rec_parser.h"
#include "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)

View File

@@ -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__
/** @} */

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_AC_REC)
#include "nfc_ac_rec.h"
#include <string.h>
#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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_BLE_OOB_ADVDATA)
#include "nfc_ble_oob_advdata.h"
#include "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)

View File

@@ -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 <stdint.h>
#include "ble_advdata.h"
#include "app_util.h"
#include "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__
/** @} */

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_BLE_PAIR_LIB)
#include "nfc_ble_pair_lib.h"
#include "sdk_macros.h"
#include "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 "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)

View File

@@ -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 <stdbool.h>
#include "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__

View File

@@ -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 "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 "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)

View File

@@ -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 <stdint.h>
#include "ble_advdata.h"
#include "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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_CH_COMMON)
#include "nfc_ble_pair_common.h"
#include <stdint.h>
/* 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)

View File

@@ -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 <stdint.h>
#include "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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_EP_OOB_REC)
#include "nfc_ep_oob_rec.h"
#include "sdk_errors.h"
#include "ble_gap.h"
#include "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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_LE_OOB_REC)
#include "nfc_le_oob_rec.h"
#include "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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_MSG)
#include "app_util.h"
#include "nfc_ndef_msg.h"
#include "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)

View File

@@ -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

View File

@@ -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 "sdk_config.h"
#include "nordic_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_RECORD)
#include <string.h>
#include "nfc_ndef_record.h"
#include "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)

View File

@@ -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 <stdint.h>
#include <string.h>
#include "compiler_abstraction.h"
#include "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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_LAUNCHAPP_MSG)
#include <stdint.h>
#include <string.h>
#include "nfc_launchapp_rec.h"
#include "nfc_launchapp_msg.h"
#include "nrf_error.h"
#include "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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_LAUNCHAPP_REC)
#include "nfc_launchapp_rec.h"
#include <string.h>
#include "nrf_error.h"
#include "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)

View File

@@ -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 <stdint.h>
#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

View File

@@ -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 "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 "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_NDEF_MSG_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "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)

View File

@@ -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 <stdint.h>
#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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_RECORD_PARSER)
#include <stdint.h>
#include <stdbool.h>
#include "nfc_ndef_record_parser.h"
#include "app_util.h"
#include "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 "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_NDEF_RECORD_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "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)

View File

@@ -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 <stdint.h>
#include "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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_TEXT_RECORD)
#include <string.h>
#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)

View File

@@ -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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_URI_MSG)
#include <string.h>
#include "nfc_uri_msg.h"
#include "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)

View File

@@ -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__

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_NDEF_URI_REC)
#include <string.h>
#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)

View File

@@ -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__

View File

@@ -0,0 +1,126 @@
/**
* 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"
#if NRF_MODULE_ENABLED(NFC_PLATFORM)
#include "nfc_platform.h"
#include "nrf_drv_clock.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)

View File

@@ -0,0 +1,98 @@
/**
* 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 "nrfx_nfct.h"
#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__ */

View File

@@ -0,0 +1,36 @@
Copyright (c) 2015 - 2020, Telit Communications Cyprus Ltd
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.

View File

@@ -0,0 +1,271 @@
/**
* Copyright (c) 2015 - 2020, Telit Communications Cyprus Ltd
*
* 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_T2T_LIB_H__
#define NFC_T2T_LIB_H__
/** @file
*
* @addtogroup nfc_api
*
* @defgroup nfc_t2t NFC Type 2 Tag
* @ingroup nfc_api
* @brief Implementation of NFC Type 2 Tag.
*
* @defgroup nfc_t2t_lib NFC tag 2 type emulation library
* @{
* @ingroup nfc_t2t
* @brief The T2T emulation library interface.
*/
#include <string.h>
#include <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__

Binary file not shown.

View File

@@ -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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NFC_T2T_PARSER)
#include <string.h>
#include <stdbool.h>
#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 "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_T2T_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "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)

View File

@@ -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 <stdint.h>
#include "nfc_tlv_block.h"
#include "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__ */

View File

@@ -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 <stdint.h>
#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__ */

View File

@@ -0,0 +1,36 @@
Copyright (c) 2016 - 2020, Telit Communications Cyprus Ltd
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.

View File

@@ -0,0 +1,332 @@
/**
* Copyright (c) 2016 - 2020, Telit Communications Cyprus Ltd
*
* 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_T4T_LIB_H__
#define NFC_T4T_LIB_H__
/** @file
*
* @addtogroup nfc_api
*
* @defgroup nfc_t4t NFC Type 4 Tag
* @ingroup nfc_api
* @brief Implementation of NFC Type 4 Tag.
*
* @defgroup nfc_t4t_lib NFC tag 4 type emulation library
* @{
* @ingroup nfc_t4t
* @brief The T4T emulation library interface
*
* This is the NFC Forum NDEF tag 4 type emulation library. It implements the ISO14443-4A protocol
* (ISO-DEP) and additionally can emulate a read-writable NDEF content. If the emulation of the NDEF
* content is not needed, the library works in a raw mode where all APDUs are delivered to the user,
* who is then responsible to generate a timely RPDU as a response.
*
* The sequence of initializing functions determines whether the NDEF emulation will run or whether
* the raw mode is used.
*
* - E.g. NDEF emulation
* * @ref nfc_t4t_setup
* * @ref nfc_t4t_ndef_rwpayload_set or @ref nfc_t4t_ndef_staticpayload_set
* * @ref nfc_t4t_emulation_start
* * ... running in NDEF emulation mode ...
* - E.g. RAW mode
* * @ref nfc_t4t_setup
* * @ref nfc_t4t_emulation_start
* * ... running in RAW emulation mode ...
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "sdk_errors.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NFC_T4T_MAX_PAYLOAD_SIZE 0xFFF0U
/**< @brief Emulation mode. */
typedef enum
{
NFC_T4T_EMUMODE_NDEF, ///< Emulated NDEF AID and EF-Files.
NFC_T4T_EMUMODE_PICC ///< Run just ISO-DEP, deliver I-Frames up.
} nfc_t4t_emu_mode_t;
/**< @brief Event identifiers used by the @ref nfc_t4t_callback_t */
typedef enum
{
NFC_T4T_EVENT_NONE,
///< This ID is never used. Dummy value for completeness.
NFC_T4T_EVENT_FIELD_ON,
///< External Reader polling detected.
NFC_T4T_EVENT_FIELD_OFF,
///< External Reader polling ended.
NFC_T4T_EVENT_NDEF_READ,
///< External Reader has read static NDEF-Data from Emulation.
/**<
* A Read operation happened on last byte of NDEF-Data.
*/
NFC_T4T_EVENT_NDEF_UPDATED,
///< External Reader has written to length information of NDEF-Data from Emulation.
/**<
* The usual behavior of a Reader-Writer that accesses NDEF information
* for update is to set the length to zero at the beginning of the
* update process. It then writes the content of NDEF-Data. When all
* content is written it will update the length information inside the
* NDEF file. This event will be generated every time an update to the
* length is happening. This length information is residing in the first
* 2 bytes of the NDEF-Content container and is called 'NLEN'. Since
* this callback is triggered on any access to these bytes the returned
* data_length information might not be consistent (e.g. in case of only
* a single byte write to the length).
*
* @param[out] data Pointer to current data of NDEF message
* @param[out] data_length Current value of NDEF content length
* information i.e. 'NLEN' field.
*/
NFC_T4T_EVENT_DATA_TRANSMITTED,
///< In Raw mode it signals that the data from @ref nfc_t4t_response_pdu_send have been sent out.
NFC_T4T_EVENT_DATA_IND,
///< In Raw mode delivers the APDU fragments
/**<
* All @ref NFC_T4T_EVENT_DATA_IND events that have the @ref NFC_T4T_DI_FLAG_MORE flag set
* belong to the same APDU. The first @ref NFC_T4T_EVENT_DATA_IND without @ref NFC_T4T_DI_FLAG_MORE
* flag signals the completeness of the APDU. The Application then has to reply with a call
* to @ref nfc_t4t_response_pdu_send. The library will handle internally the fragmentation of
* the response towards the Reader-Writer. The data of the response PDU must be kept
* valid until the next callback from the library happens (e.g. next @ref NFC_T4T_EVENT_DATA_IND
* or @ref NFC_T4T_EVENT_FIELD_OFF).
*
* @param[out] p_data Pointer to the fragment of APDU.
* @param[out] data_length Length of data.
* @param[out] flags @ref nfc_t4t_data_ind_flags_t.
*/
} nfc_t4t_event_t;
/**< @brief Flags coming with nfc_t4t_callback_t at @ref NFC_T4T_EVENT_DATA_IND event.*/
typedef enum
{
NFC_T4T_DI_FLAG_NONE = 0x00, ///< Dummy value.
NFC_T4T_DI_FLAG_MORE = 0x01 ///< This signals that more data is expected to be received.
} nfc_t4t_data_ind_flags_t;
/**< @brief Parameter IDs that can be set/get with @ref nfc_t4t_parameter_set or
* @ref nfc_t4t_parameter_get.
*/
typedef enum
{
NFC_T4T_PARAM_TESTING, ///< Internal usage only for Unit-Testing.
NFC_T4T_PARAM_FWI, ///< Frame Wait Time parameter
NFC_T4T_PARAM_SELRES, ///< Parameter for setting 'Protocol' bits for SEL_RES packet
NFC_T4T_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_t4t_param_id_t;
/** @brief Callback to pass events from NFCLib to application.
*
* @param[out] p_context Application context for callback execution.
* @param[out] event The event that occurred. see @ref nfc_t4t_event_t.
* @param[out] p_data Data to send to the application (event specific).
* @param[out] data_length Length of the data. In case of @ref NFC_T4T_EVENT_NDEF_UPDATED, this parameter
* contains the value of the 'NLEN' field of the NDEF File;
* if the value is non-zero, it corresponds to the new size of the NDEF Message in the updated NDEF File.
* @param[out] flags Some events deliver flags. see @ref nfc_t4t_event_t for details.
*/
typedef void (*nfc_t4t_callback_t)(void * p_context,
nfc_t4t_event_t event,
const uint8_t * p_data,
size_t data_length,
uint32_t flags);
/** @brief Register the application callback for event signaling.
*
* The callback will be called by NFCLib to notify the application of relevant events. It will be
* called from the HAL_NFC callback context. The library support 3 different Modes of Emulation:
* - Raw ISO-Dep exchanges. All PDUs are signaled through the callback.
* - Read-Only T4T NDEF-Tag. A static buffer is served. Only Field-Status callbacks.
* - Read-Write T4T NDEF-Tag. A mutable buffer is used. Only Field-Status callbacks.
*
* The default mode is Raw ISO-Dep mode. The two other NDEF T4T modes are activated through
* the corresponding @ref nfc_t4t_ndef_rwpayload_set/ @ref nfc_t4t_ndef_staticpayload_set functions.
* The mode is locked in with a call to @ref nfc_t4t_emulation_start.
*
* @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 Success.
* @retval NRF_ERROR_INVALID_STATE If emulation is in running state.
*/
ret_code_t nfc_t4t_setup(nfc_t4t_callback_t callback, void * p_context);
/** @brief Set emulation buffer and content for a NDEF Tag emulation that is Read/Writable.
*
* The buffer needs to be kept accessible for the lifetime of the emulation.
* If an external Reader-Writer changes the NDEF content it is signaled through
* the app-callback. Buffer can be changed during the lifetime of the emulation,
* when NDEF READ or UPDATE procedure is pending, and it will be changed after
* this procedure is finished. To perform this procedure safely use
* critical sections or disable the interrupts.
*
* @param[in] p_emulation_buffer Buffer pointer
* @param[in] buffer_length Length of buffer (maximum writable NDEF size)
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_DATA_SIZE Invalid argument (e.g. wrong data length).
* @retval NRF_ERROR_INVALID_PARAM Invalid argument (e.g. NULL pointer).
* @retval NRF_ERROR_NOT_SUPPORTED If the new buffer has a different length than the first one.
* @retval NRF_ERROR_INVALID_DATA If the provided buffer is the currently used buffer.
*/
ret_code_t nfc_t4t_ndef_rwpayload_set(uint8_t * p_emulation_buffer, size_t buffer_length);
/** @brief Set emulationBuffer and Content for a NDEF Tag emulation that is Read-Only.
*
* The buffer needs to be kept accessible for the lifetime of the emulation.
* Since no write access is done to the buffer, the content could reside in flash memory.
*
* @param[in] p_emulation_buffer Const buffer pointer
* @param[in] buffer_length Length of contained NDEF payload message
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_DATA_SIZE Invalid argument (e.g. wrong data length).
* @retval NRF_ERROR_INVALID_PARAM Invalid argument (e.g. NULL pointer).
* @retval NRF_ERROR_INVALID_STATE Emulation is in running stated.
*/
ret_code_t nfc_t4t_ndef_staticpayload_set(const uint8_t * p_emulation_buffer, size_t buffer_length);
/** @brief Send a raw response PDU after getting a Request PDU callback.
*
* When the library works in raw ISO-DEP mode it will signal request PDUs through the callback.
* The application then has to answer with a response PDU. It will use this function to send back
* the response PDU. This function can not be used in T4T NDEF (RW / STATIC) emulation modes.
*
* The lower ISODEP layer will handle the defragmentation of a long response PDU into smaller
* pieces that the PCD can understand.
*
* @param[in] p_pdu Const PDU pointer.
* @param[in] pdu_length Length of PDU.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_DATA_SIZE Invalid argument (e.g. wrong data length).
* @retval NRF_ERROR_INVALID_PARAM Invalid argument (e.g. NULL pointer).
* @retval NRF_ERROR_INVALID_STATE Emulation is in running state.
*/
ret_code_t nfc_t4t_response_pdu_send(const uint8_t * p_pdu, size_t pdu_length);
/** @brief Set an NFC parameter.
*
* 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 Success.
* @retval NRF_ERROR_DATA_SIZE Invalid argument (e.g. wrong data length).
* @retval NRF_ERROR_INVALID_PARAM Invalid argument (e.g. NULL pointer).
*/
ret_code_t nfc_t4t_parameter_set(nfc_t4t_param_id_t id, void * p_data, size_t data_length);
/** @brief Query 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[out] p_data Pointer to a buffer receiving the queried data.
* @param[out] p_max_data_length Size of the buffer, receives actual size of queried data.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_DATA_SIZE Invalid argument (e.g. wrong data length).
* @retval NRF_ERROR_INVALID_PARAM Invalid argument (e.g. NULL pointer).
*/
ret_code_t nfc_t4t_parameter_get(nfc_t4t_param_id_t id, void * p_data, size_t * p_max_data_length);
/** @brief Activate the NFC frontend.
*
* Only after calling this function, events will be posted to the application callback.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_INVALID_STATE Already started.
*/
ret_code_t nfc_t4t_emulation_start(void);
/**
* @brief Deactivate the NFC frontend.
*
* After calling this function, no more events will be posted to the application callback.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_INVALID_STATE Emulation was already stopped
*/
ret_code_t nfc_t4t_emulation_stop(void);
/**
* @brief Release reference to application callback.
*
* After calling this function, the passed callback pointer is no longer considered valid.
* After calling this function, the passed p_ndef pointer is no longer considered valid.
*
* You need to restart with @ref nfc_t4t_setup to run a new Emulation.
*
* @retval NRF_SUCCESS Always succeeds.
*/
ret_code_t nfc_t4t_done(void);
#ifdef __cplusplus
}
#endif
/**
@}
*/
#endif // NFC_T4T_LIB_H__

Binary file not shown.

View File

@@ -0,0 +1,261 @@
/**
* 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_config.h"
#if NFC_T4T_APDU_ENABLED
#include "nfc_t4t_apdu.h"
#include "sdk_macros.h"
#include "nordic_common.h"
#include "app_util.h"
#define NRF_LOG_MODULE_NAME nfc_t4t_apdu
#if NFC_T4T_APDU_LOG_ENABLED
#define NRF_LOG_LEVEL NFC_T4T_APDU_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NFC_T4T_APDU_LOG_COLOR
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_T4T_APDU_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "nrf_log.h"
#endif // NFC_T4T_APDU_LOG_ENABLED
/**
* @brief Field sizes that can be present in CAPDU.
*/
#define CLASS_TYPE_SIZE 1U
#define INSTRUCTION_TYPE_SIZE 1U
#define PARAMETER_SIZE 2U
#define LC_SHORT_FORMAT_SIZE 1U
#define LC_LONG_FORMAT_SIZE 3U
#define LE_SHORT_FORMAT_SIZE 1U
#define LE_LONG_FORMAT_SIZE 2U
/**
* @brief Values used to encode Lc field in CAPDU.
*/
#define LC_LONG_FORMAT_TOKEN 0x00
#define LC_LONG_FORMAT_THR 0xFF
/**
* @brief Values used to encode Le field in CAPDU.
*/
#define LE_FIELD_ABSENT 0U
#define LE_LONG_FORMAT_THR 0x0100
#define LE_ENCODED_VAL_256 0x00
#define STATUS_SIZE 2U ///< Size of Status field contained in RAPDU.
/**
* @brief Function for calculating size of CAPDU.
*/
__STATIC_INLINE uint16_t nfc_t4t_comm_apdu_size_calc(nfc_t4t_comm_apdu_t const * const p_cmd_apdu)
{
uint16_t res = CLASS_TYPE_SIZE + INSTRUCTION_TYPE_SIZE + PARAMETER_SIZE;
if (p_cmd_apdu->data.p_buff != NULL)
{
if (p_cmd_apdu->data.len > LC_LONG_FORMAT_THR)
{
res += LC_LONG_FORMAT_SIZE;
}
else
{
res += LC_SHORT_FORMAT_SIZE;
}
}
res += p_cmd_apdu->data.len;
if (p_cmd_apdu->resp_len != LE_FIELD_ABSENT)
{
if (p_cmd_apdu->resp_len > LE_LONG_FORMAT_THR)
{
res += LE_LONG_FORMAT_SIZE;
}
else
{
res += LE_SHORT_FORMAT_SIZE;
}
}
return res;
}
/**
* @brief Function for validating arguments used by CAPDU encoding procedure.
*/
__STATIC_INLINE ret_code_t nfc_t4t_comm_apdu_args_validate(nfc_t4t_comm_apdu_t const * const p_cmd_apdu,
uint8_t * p_raw_data,
uint16_t * const p_len)
{
if ((p_cmd_apdu == NULL) || (p_raw_data == NULL) || (p_len == NULL))
{
return NRF_ERROR_NULL;
}
if ((p_cmd_apdu->data.p_buff != NULL) && (p_cmd_apdu->data.len == 0))
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
ret_code_t nfc_t4t_comm_apdu_encode(nfc_t4t_comm_apdu_t const * const p_cmd_apdu,
uint8_t * p_raw_data,
uint16_t * const p_len)
{
// Validate passed arguments.
ret_code_t err_code = nfc_t4t_comm_apdu_args_validate(p_cmd_apdu, p_raw_data, p_len);
VERIFY_SUCCESS(err_code);
// Check if there is enough memory in the provided buffer to store described CAPDU.
uint16_t comm_apdu_len = nfc_t4t_comm_apdu_size_calc(p_cmd_apdu);
if (comm_apdu_len > *p_len)
{
return NRF_ERROR_NO_MEM;
}
*p_len = comm_apdu_len;
// Start to encode described CAPDU in the buffer.
*p_raw_data++ = p_cmd_apdu->class_byte;
*p_raw_data++ = p_cmd_apdu->instruction;
*p_raw_data++ = MSB_16(p_cmd_apdu->parameter);
*p_raw_data++ = LSB_16(p_cmd_apdu->parameter);
// Check if optional data field should be included.
if (p_cmd_apdu->data.p_buff != NULL)
{
if (p_cmd_apdu->data.len > LC_LONG_FORMAT_THR) // Use long data length encoding.
{
*p_raw_data++ = LC_LONG_FORMAT_TOKEN;
*p_raw_data++ = MSB_16(p_cmd_apdu->data.len);
*p_raw_data++ = LSB_16(p_cmd_apdu->data.len);
}
else // Use short data length encoding.
{
*p_raw_data++ = LSB_16(p_cmd_apdu->data.len);
}
memcpy(p_raw_data, p_cmd_apdu->data.p_buff, p_cmd_apdu->data.len);
p_raw_data += p_cmd_apdu->data.len;
}
// Check if optional response length field present (Le) should be included.
if (p_cmd_apdu->resp_len != LE_FIELD_ABSENT)
{
if (p_cmd_apdu->resp_len > LE_LONG_FORMAT_THR) // Use long response length encoding.
{
*p_raw_data++ = MSB_16(p_cmd_apdu->resp_len);
*p_raw_data++ = LSB_16(p_cmd_apdu->resp_len);
}
else // Use short response length encoding.
{
if (p_cmd_apdu->resp_len == LE_LONG_FORMAT_THR)
{
*p_raw_data++ = LE_ENCODED_VAL_256;
}
else
{
*p_raw_data++ = LSB_16(p_cmd_apdu->resp_len);
}
}
}
return NRF_SUCCESS;
}
/**
* @brief Function for validating arguments used by RAPDU decoding procedure.
*/
__STATIC_INLINE ret_code_t nfc_t4t_resp_apdu_args_validate(nfc_t4t_resp_apdu_t const * const p_resp_apdu,
uint8_t const * const p_raw_data,
uint16_t len)
{
if ((p_resp_apdu == NULL) || (p_raw_data == NULL))
{
return NRF_ERROR_NULL;
}
if (len < STATUS_SIZE)
{
return NRF_ERROR_INVALID_LENGTH;
}
return NRF_SUCCESS;
}
ret_code_t nfc_t4t_resp_apdu_decode(nfc_t4t_resp_apdu_t * const p_resp_apdu,
uint8_t const * const p_raw_data,
uint16_t len)
{
// Validate passed arguments.
ret_code_t err_code = nfc_t4t_resp_apdu_args_validate(p_resp_apdu, p_raw_data, len);
VERIFY_SUCCESS(err_code);
nfc_t4t_resp_apdu_clear(p_resp_apdu);
if (len != STATUS_SIZE) // Optional data field is present in RAPDU.
{
p_resp_apdu->data.len = len - STATUS_SIZE;
p_resp_apdu->data.p_buff = (uint8_t *) p_raw_data;
}
p_resp_apdu->status = uint16_big_decode(p_raw_data + p_resp_apdu->data.len);
return NRF_SUCCESS;
}
void nfc_t4t_resp_apdu_printout(nfc_t4t_resp_apdu_t * p_resp_apdu)
{
NRF_LOG_INFO("R-APDU status: %4X ", p_resp_apdu->status);
if (p_resp_apdu->data.p_buff != NULL)
{
NRF_LOG_INFO("R-APDU data: ");
NRF_LOG_HEXDUMP_INFO(p_resp_apdu->data.p_buff, p_resp_apdu->data.len);
}
else
{
NRF_LOG_INFO("R-APDU no data field present.");
}
}
#endif // NFC_T4T_APDU_ENABLED

View File

@@ -0,0 +1,221 @@
/**
* 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_T4T_APDU_H__
#define NFC_T4T_APDU_H__
/**@file
*
* @defgroup nfc_t4t_apdu APDU reader/writer
* @{
* @ingroup nfc_t4t_parser
*
* @brief APDU reader/writer for Type 4 Tag communication.
*
*/
#include <stdint.h>
#include <string.h>
#include "sdk_errors.h"
#include "nrf.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CLASS_BYTE_NO_SECURE_MSG 0x00 ///< Class byte indicating no secure messaging, used in C-APDU.
/**
* @name Parameters used when selecting instruction code in C-APDU.
* @{
*/
#define SELECT_BY_FILE_ID 0x000C ///< Select by file identifier, first or only occurence.
#define SELECT_BY_NAME 0x0400 ///< Select by name, first or only occurence.
/** @} */
/**
* @name Status codes contained in R-APDU.
* @{
*/
#define RAPDU_STATUS_CMD_COMPLETED 0x9000 ///< Command completed successfully.
#define RAPDU_STATUS_SEL_ITEM_NOT_FOUND 0x6A82 ///< Selected item has not been found.
/** @} */
/**
* @brief Possible instruction codes in C-APDU.
*/
typedef enum
{
NFC_T4T_CAPDU_SELECT_INS = 0xA4, ///< Code used for selecting EF or NDEF application.
NFC_T4T_CAPDU_READ_INS = 0xB0, ///< Code used for selecting EF or NDEF application.
NFC_T4T_CAPDU_UPDATE_INS = 0xD6 ///< Code used for selecting EF or NDEF application.
} nfc_t4t_comm_apdu_ins_type_t;
/**
* @brief APDU data field descriptor.
*/
typedef struct
{
uint16_t len; ///< Data field length.
uint8_t * p_buff; ///< Pointer to data field.
} nfc_t4t_apdu_data_t;
/**
* @brief Command Application Protocol Data Unit (C-APDU) descriptor.
*/
typedef struct
{
uint8_t class_byte; ///< Class byte.
nfc_t4t_comm_apdu_ins_type_t instruction; ///< The chosen code of instruction.
uint16_t parameter; ///< Parameters associated with the instruction code.
nfc_t4t_apdu_data_t data; ///< Optional data fields (Lc + data bytes).
uint16_t resp_len; ///< Optional response length field (Le).
} nfc_t4t_comm_apdu_t;
/**
* @brief Response Application Protocol Data Unit (R-APDU) descriptor.
*/
typedef struct
{
uint16_t status; ///< Mandatory status field.
nfc_t4t_apdu_data_t data; ///< Optional data field.
} nfc_t4t_resp_apdu_t;
/**
* @brief Macro for verifying R-APDU descriptor status.
*
* This macro verifies R-APDU descriptor status. It will cause the exterior
* function to return nrf_error translated from R-APDU status, if the status is
* not equal to @ref RAPDU_STATUS_CMD_COMPLETED.
*
* @param[in] P_RAPDU Pointer to R-APDU descriptor.
*
* @retval NRF_ERROR_NOT_FOUND If C-APDU select command could not find the selected item.
* @retval NRF_ERROR_INTERNAL Unknown R-APDU error.
*/
#define VERIFY_RAPDU_SUCCESS(P_RAPDU) \
if (P_RAPDU->status == RAPDU_STATUS_SEL_ITEM_NOT_FOUND) \
{ \
return NRF_ERROR_NOT_FOUND; \
} \
if (P_RAPDU->status != RAPDU_STATUS_CMD_COMPLETED) \
{ \
return NRF_ERROR_INTERNAL; \
}
/**
* @brief Function for clearing C-APDU descriptor and restoring its default values.
*
* @param[in] p_cmd_apdu Pointer to C-APDU descriptor.
*/
__STATIC_INLINE void nfc_t4t_comm_apdu_clear(nfc_t4t_comm_apdu_t * const p_cmd_apdu);
/**
* @brief Function for clearing R-APDU descriptor and restoring its default values.
*
* @param[in] p_resp_apdu Pointer to R-APDU descriptor.
*/
__STATIC_INLINE void nfc_t4t_resp_apdu_clear(nfc_t4t_resp_apdu_t * const p_resp_apdu);
/**
* @brief Function for encoding C-APDU.
*
* This function encodes C-APDU according to the provided descriptor.
*
* @param[in] p_cmd_apdu Pointer to the C-APDU descriptor.
* @param[out] p_raw_data Pointer to the buffer with encoded C-APDU.
* @param[in,out] p_len Size of the available memory for the C-APDU as input.
* Size of the generated C-APDU as output.
*
* @retval NRF_SUCCESS If C-APDU was encoded successfully.
* @retval NRF_ERROR_NO_MEM If the predicted C-APDU size is bigger than the provided buffer space.
* @retval NRF_ERROR_INVALID_PARAM If C-APDU descriptor is invalid.
* @retval NRF_ERROR_NULL If any passed argument is NULL.
*/
ret_code_t nfc_t4t_comm_apdu_encode(nfc_t4t_comm_apdu_t const * const p_cmd_apdu,
uint8_t * p_raw_data,
uint16_t * const p_len);
/**
* @brief Function for decoding R-APDU.
*
* This function decodes buffer with encoded R-APDU and stores results in the R-APDU descriptor.
*
* @param[out] p_resp_apdu Pointer to the R-APDU descriptor.
* @param[in] p_raw_data Pointer to the buffer with encoded R-APDU.
* @param[in] len Size of of the buffer with encoded R-APDU.
*
* @retval NRF_SUCCESS If R-APDU was encoded successfully.
* @retval NRF_ERROR_INVALID_LENGTH If the buffer is too small to hold a valid R-APDU.
* @retval NRF_ERROR_NULL If any passed argument is NULL.
*/
ret_code_t nfc_t4t_resp_apdu_decode(nfc_t4t_resp_apdu_t * const p_resp_apdu,
uint8_t const * const p_raw_data,
uint16_t len);
/**
* @brief Function for printing a R-APDU descriptor.
*
* This function prints a R-APDU descriptor.
*
* @param[in] p_resp_apdu Pointer to the R-APDU descriptor.
*/
void nfc_t4t_resp_apdu_printout(nfc_t4t_resp_apdu_t * p_resp_apdu);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nfc_t4t_comm_apdu_clear(nfc_t4t_comm_apdu_t * const p_cmd_apdu)
{
memset(p_cmd_apdu, 0, sizeof(nfc_t4t_comm_apdu_t));
}
__STATIC_INLINE void nfc_t4t_resp_apdu_clear(nfc_t4t_resp_apdu_t * const p_resp_apdu)
{
memset(p_resp_apdu, 0, sizeof(nfc_t4t_resp_apdu_t));
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NFC_T4T_APDU_H__ */

View File

@@ -0,0 +1,266 @@
/**
* 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_config.h"
#if NFC_T4T_CC_FILE_PARSER_ENABLED
#include <string.h>
#include "nfc_t4t_cc_file.h"
#include "sdk_macros.h"
#include "nordic_common.h"
#include "app_util.h"
#define NRF_LOG_MODULE_NAME nfc_t4t_cc_file_parser
#if NFC_T4T_CC_FILE_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL NFC_T4T_CC_FILE_PARSER_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NFC_T4T_CC_FILE_PARSER_INFO_COLOR
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_T4T_CC_FILE_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "nrf_log.h"
#endif // NFC_T4T_CC_FILE_PARSER_LOG_ENABLED
/**
* @brief Valid value range for CCLEN field.
*/
#define CC_LEN_MIN_VALUE 0x000F
#define CC_LEN_MAX_VALUE 0xFFFE
/**
* @brief Valid major versions of Type 4 Tag specification.
*/
#define NFC_T4T_EXTENDED_MAJOR_VER 0x03 ///< Major version number allowing first TLV block to be Extended NDEF File Control TLV
#define NFC_T4T_REGULAR_MAJOR_VER 0x02 ///< Major version number allowing first TLV block to be NDEF File Control TLV
/**
* @brief Valid value range for MLe field.
*/
#define MLE_LEN_MIN_VALUE 0x000F
#define MLE_LEN_MAX_VALUE 0xFFFF
/**
* @brief Valid value range for MLc field.
*/
#define MLC_LEN_MIN_VALUE 0x0001
#define MLC_LEN_MAX_VALUE 0xFFFF
/**
* @brief Field sizes that are present in CC file.
*/
#define CC_LEN_FIELD_SIZE 2U
#define MAP_VER_FIELD_SIZE 1U
#define MLE_FIELD_SIZE 2U
#define MLC_FIELD_SIZE 2U
/// 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 validating arguments used by CC file parsing procedure.
*/
__STATIC_INLINE ret_code_t nfc_t4t_cc_args_validate(nfc_t4t_capability_container_t * p_t4t_cc_file,
uint8_t * p_raw_data,
uint16_t len)
{
if ( (p_t4t_cc_file == NULL)
|| (p_t4t_cc_file->p_tlv_block_array == NULL)
|| (p_raw_data == NULL) )
{
return NRF_ERROR_NULL;
}
if ( (len < CC_LEN_MIN_VALUE) || (len > CC_LEN_MAX_VALUE) )
{
return NRF_ERROR_INVALID_LENGTH;
}
if (p_t4t_cc_file->max_tlv_blocks == 0)
{
return NRF_ERROR_NO_MEM;
}
return NRF_SUCCESS;
}
/**
* @brief Function for validating CC file descriptor content.
*/
__STATIC_INLINE ret_code_t nfc_t4t_cc_file_validate(nfc_t4t_capability_container_t * p_t4t_cc_file)
{
uint16_t type = p_t4t_cc_file->p_tlv_block_array[0].type;
if ( (p_t4t_cc_file->major_version == NFC_T4T_EXTENDED_MAJOR_VER
&& type == EXTENDED_NDEF_FILE_CONTROL_TLV) ||
(p_t4t_cc_file->major_version == NFC_T4T_REGULAR_MAJOR_VER
&& type == NDEF_FILE_CONTROL_TLV) )
{
return NRF_SUCCESS;
}
return NRF_ERROR_INVALID_DATA;
}
/**
* @brief Function for clearing all TLV blocks from CC file descriptor.
*/
__STATIC_INLINE void nfc_t4t_cc_file_clear(nfc_t4t_capability_container_t * p_t4t_cc_file)
{
p_t4t_cc_file->tlv_count = 0;
}
/**
* @brief Function for adding a TLV block to the CC file descriptor.
*/
static ret_code_t nfc_t4t_tlv_block_insert(nfc_t4t_capability_container_t * p_t4t_cc_file,
nfc_t4t_tlv_block_t * p_tlv_block)
{
if (p_t4t_cc_file->tlv_count == p_t4t_cc_file->max_tlv_blocks)
{
return NRF_ERROR_NO_MEM;
}
// Copy contents of the source block.
p_t4t_cc_file->p_tlv_block_array[p_t4t_cc_file->tlv_count] = *p_tlv_block;
p_t4t_cc_file->tlv_count++;
return NRF_SUCCESS;
}
ret_code_t nfc_t4t_cc_file_parse(nfc_t4t_capability_container_t * p_t4t_cc_file,
uint8_t * p_raw_data,
uint16_t len)
{
ret_code_t err_code = nfc_t4t_cc_args_validate(p_t4t_cc_file, p_raw_data, len);
VERIFY_SUCCESS(err_code);
uint8_t * p_offset = p_raw_data;
nfc_t4t_cc_file_clear(p_t4t_cc_file);
p_t4t_cc_file->len = uint16_big_decode(p_offset);
p_offset += CC_LEN_FIELD_SIZE;
p_t4t_cc_file->major_version = MSN_GET(*p_offset);
p_t4t_cc_file->minor_version = LSN_GET(*p_offset);
p_offset += MAP_VER_FIELD_SIZE;
p_t4t_cc_file->max_rapdu_size = uint16_big_decode(p_offset);
p_offset += MLE_FIELD_SIZE;
p_t4t_cc_file->max_capdu_size = uint16_big_decode(p_offset);
p_offset += MLC_FIELD_SIZE;
nfc_t4t_tlv_block_t new_block;
len -= (p_offset - p_raw_data);
while (len > 0)
{
uint16_t tlv_len = len;
err_code = nfc_t4t_file_control_tlv_parse(&new_block, p_offset, &tlv_len);
VERIFY_SUCCESS(err_code);
p_offset += tlv_len;
len -= tlv_len;
err_code = nfc_t4t_tlv_block_insert(p_t4t_cc_file, &new_block);
VERIFY_SUCCESS(err_code);
}
return nfc_t4t_cc_file_validate(p_t4t_cc_file);
}
nfc_t4t_tlv_block_t * nfc_t4t_file_content_get(nfc_t4t_capability_container_t * p_t4t_cc_file,
uint16_t file_id)
{
nfc_t4t_tlv_block_t * p_tlv_array = p_t4t_cc_file->p_tlv_block_array;
for (uint8_t i = 0; i < p_t4t_cc_file->tlv_count; i++)
{
nfc_t4t_file_control_val_t * p_tlv_value = &p_tlv_array[i].value;
if (p_tlv_value->file_id == file_id)
{
return (p_tlv_array + i);
}
}
return NULL;
}
ret_code_t nfc_t4t_file_content_set(nfc_t4t_capability_container_t * p_t4t_cc_file,
nfc_t4t_file_t file,
uint16_t file_id)
{
nfc_t4t_tlv_block_t * p_tlv_block;
p_tlv_block = nfc_t4t_file_content_get(p_t4t_cc_file, file_id);
if (p_tlv_block != NULL)
{
p_tlv_block->value.file = file;
return NRF_SUCCESS;
}
return NRF_ERROR_NOT_FOUND;
}
void nfc_t4t_cc_file_printout(nfc_t4t_capability_container_t * p_t4t_cc_file)
{
NRF_LOG_INFO("Capability Container File content: ")
NRF_LOG_INFO("CCLEN: %d ", p_t4t_cc_file->len);
NRF_LOG_INFO("Mapping Version: %d.%d ",
p_t4t_cc_file->major_version,
p_t4t_cc_file->minor_version);
NRF_LOG_INFO("MLe: %d ", p_t4t_cc_file->max_rapdu_size)
NRF_LOG_INFO("MLc: %d ", p_t4t_cc_file->max_capdu_size)
NRF_LOG_INFO("Capability Container File contains %d File Control TLV block(s).",
p_t4t_cc_file->tlv_count);
for (uint8_t i = 0; i < p_t4t_cc_file->tlv_count; i++)
{
nfc_t4t_file_control_tlv_printout(i, &p_t4t_cc_file->p_tlv_block_array[i]);
}
}
#endif // NFC_T4T_CC_FILE_PARSER_ENABLED

View File

@@ -0,0 +1,177 @@
/**
* 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_T4T_CC_FILE_H__
#define NFC_T4T_CC_FILE_H__
/**@file
*
* @defgroup nfc_t4t_cc_file CC file parser
* @{
* @ingroup nfc_t4t_parser
*
* @brief Capability Container file parser for Type 4 Tag.
*
*/
#include <stdint.h>
#include "sdk_errors.h"
#include "nfc_t4t_tlv_block.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Descriptor for the Capability Container (CC) file of Type 4 Tag.
*/
typedef struct
{
nfc_t4t_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 4 Tag.
uint16_t const max_tlv_blocks; ///< Maximum number of TLV blocks.
uint16_t len; ///< Size (bytes) of a Capability Container including this field.
uint16_t max_rapdu_size; ///< MLe field - maximum R-APDU data size (bytes).
uint16_t max_capdu_size; ///< MLc field - maximum C-APDU data size (bytes).
uint8_t major_version; ///< Major version of the supported Type 4 Tag specification.
uint8_t minor_version; ///< Minor version of the supported Type 4 Tag specification.
} nfc_t4t_capability_container_t;
/**
* @brief Macro for creating and initializing a Type 4 Tag Capability Container descriptor.
*
* This macro creates and initializes a static instance of a @ref nfc_t4t_capability_container_t
* structure and an array of @ref nfc_t4t_tlv_block_t descriptors.
*
* Use the macro @ref NFC_T4T_CC_DESC to access the Type 4 Tag descriptor instance.
*
* @param[in] NAME Name of the created descriptor instance.
* @param[in] MAX_BLOCKS Maximum number of @ref nfc_t4t_tlv_block_t descriptors that can be
* stored in the array.
*
*/
#define NFC_T4T_CC_DESC_DEF(NAME, MAX_BLOCKS) \
static nfc_t4t_tlv_block_t NAME##_tlv_block_array[MAX_BLOCKS]; \
static nfc_t4t_capability_container_t NAME##_type_4_tag = \
{ \
.max_tlv_blocks = MAX_BLOCKS, \
.p_tlv_block_array = NAME##_tlv_block_array, \
.tlv_count = 0 \
}
/**
* @brief Macro for accessing the @ref nfc_t4t_capability_container_t instance that was created
* with @ref NFC_T4T_CC_DESC_DEF.
*
* @param[in] NAME Name of the created descriptor instance.
*/
#define NFC_T4T_CC_DESC(NAME) (NAME##_type_4_tag)
/**
* @brief Function for parsing raw data of a CC file, read from a Type 4 Tag.
*
* This function parses raw data of a Capability Container file and stores the results in its
* descriptor.
*
* @param[in,out] p_t4t_cc_file Pointer to the CC file descriptor that will be filled with
* parsed data.
* @param[in] p_raw_data Pointer to the buffer with raw data.
* @param[in] len Buffer length.
*
* @retval NRF_SUCCESS If operation was successful.
* @retval NRF_ERROR_NULL If any of the provided pointer arguments is NULL.
* @retval NRF_ERROR_INVALID_LENGTH If provided buffer exceeds a valid CC file length range.
* @retval NRF_ERROR_INVALID_DATA If mapping version of Type 4 Tag specification is not a
* compatible CC file structure.
* @retval Other Other error codes might be returned depending on
* @ref nfc_t4t_file_control_tlv_parse function.
*/
ret_code_t nfc_t4t_cc_file_parse(nfc_t4t_capability_container_t * p_t4t_cc_file,
uint8_t * p_raw_data,
uint16_t len);
/**
* @brief Function for finding File Control TLV block within the CC file descriptor.
*
* This function finds File Control TLV block that matches
* the specified file ID within the CC file descriptor.
*
* @param[in] p_t4t_cc_file Pointer to the CC file descriptor.
* @param[in] file_id File identifier.
*
* @retval TLV Pointer to the File Control TLV.
* @retval NULL If TLV with the specified File ID was not found.
*/
nfc_t4t_tlv_block_t * nfc_t4t_file_content_get(nfc_t4t_capability_container_t * p_t4t_cc_file,
uint16_t file_id);
/**
* @brief Function for binding a file with its File Control TLV block.
*
* This function binds file content with its File Control TLV block, in which
* maximal file size and access conditions are stored.
*
* @param[in,out] p_t4t_cc_file Pointer to the CC file descriptor.
* @param[in] file File descriptor.
* @param[in] file_id File identifier.
*
* @retval NRF_SUCCESS If operation was successful.
* @retval NRF_ERROR_NOT_FOUND If the provided file ID does not match any ID stored in TLV blocks
* of the CC file.
*/
ret_code_t nfc_t4t_file_content_set(nfc_t4t_capability_container_t * p_t4t_cc_file,
nfc_t4t_file_t file,
uint16_t file_id);
/**
* @brief Function for printing the CC file descriptor.
*
* This function prints the CC file descriptor.
*
* @param[in] p_t4t_cc_file Pointer to the CC file.
*/
void nfc_t4t_cc_file_printout(nfc_t4t_capability_container_t * p_t4t_cc_file);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NFC_T4T_CC_FILE_H__ */

View File

@@ -0,0 +1,401 @@
/**
* 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_config.h"
#if NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED
#include "nfc_t4t_hl_detection_procedures.h"
#include "nfc_t4t_apdu.h"
#include "adafruit_pn532.h"
#include "sdk_macros.h"
#include "nordic_common.h"
#define NRF_LOG_MODULE_NAME nfc_t4t_hl_detection_procedures
#if NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED
#define NRF_LOG_LEVEL NFC_T4T_HL_DETECTION_PROCEDURES_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NFC_T4T_HL_DETECTION_PROCEDURES_INFO_COLOR
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "nrf_log.h"
#endif // NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED
#define CC_FILE_ID 0xE103 ///< File Identifier of Capability Container.
#define FILE_ID_SIZE 2 ///< Size of File Identifier field in CC file.
#define MIN_MAX_RAPDU_SIZE 0x0F ///< Minimal value of maximal RAPDU data field size.
#define NDEF_FILE_NLEN_FIELD_SIZE 2 ///< Size of NLEN field in NDEF file.
#define NDEF_APP_PROC_RESP_LEN 256 ///< Maximal size of RAPDU data in the NDEF Tag Application Select Procedure.
// Adafruit library limitations.
#define MAX_ADAFRUIT_RAPDU_SIZE 242 ///< Maximal value of RAPDU data field size
#define MAX_ADAFRUIT_CAPDU_SIZE 240 ///< Maximal value of CAPDU data field size
static uint8_t m_file_id[FILE_ID_SIZE]; ///< Buffer for selected EF ID storage.
static const uint8_t m_nfc_t4t_select_ndef_app_data[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}; ///< NDEF Tag Application name.
static const uint8_t m_nlen_update_value[] = {0x00, 0x00}; ///< NLEN value used in NDEF Update Procedure.
/**
* @brief Function for performing APDU exchanges with Adafruit library.
*/
static ret_code_t nfc_t4t_apdu_exchange(nfc_t4t_comm_apdu_t * const p_capdu,
nfc_t4t_resp_apdu_t * const p_rapdu,
uint8_t * const p_apdu_buff,
uint8_t resp_len)
{
if (resp_len > APDU_BUFF_SIZE)
{
return NRF_ERROR_NO_MEM;
}
uint16_t apdu_buff_len = APDU_BUFF_SIZE;
ret_code_t err_code = nfc_t4t_comm_apdu_encode(p_capdu,
p_apdu_buff,
&apdu_buff_len);
VERIFY_SUCCESS(err_code);
err_code = adafruit_pn532_in_data_exchange(p_apdu_buff, apdu_buff_len, p_apdu_buff, &resp_len);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_resp_apdu_decode(p_rapdu, p_apdu_buff, resp_len);
VERIFY_SUCCESS(err_code);
nfc_t4t_resp_apdu_printout(p_rapdu);
VERIFY_RAPDU_SUCCESS(p_rapdu);
return err_code;
}
/**
* @brief Function for performing APDU exchanges with Adafruit library with default response length.
*/
static ret_code_t nfc_t4t_apdu_default_exchange(nfc_t4t_comm_apdu_t * const p_capdu,
nfc_t4t_resp_apdu_t * const p_rapdu,
uint8_t * const p_apdu_buff)
{
if (p_capdu->resp_len + sizeof(p_rapdu->status) > UINT8_MAX)
{
return NRF_ERROR_NOT_SUPPORTED;
}
uint8_t resp_len = (uint8_t) (p_capdu->resp_len + sizeof(p_rapdu->status));
ret_code_t err_code = nfc_t4t_apdu_exchange(p_capdu, p_rapdu, p_apdu_buff, resp_len);
return err_code;
}
/**
* @brief Function for saving part of EF (contained in RAPDU) in storage buffer.
*/
static ret_code_t nfc_t4t_file_chunk_save(nfc_t4t_resp_apdu_t const * const p_rapdu,
uint8_t * const p_storage_buff,
uint16_t storage_buff_len,
uint16_t * const p_file_offset)
{
if (p_rapdu->data.p_buff == NULL)
{
return NRF_ERROR_NULL;
}
if ((*p_file_offset) + p_rapdu->data.len > storage_buff_len)
{
return NRF_ERROR_NO_MEM;
}
memcpy(p_storage_buff + (*p_file_offset), p_rapdu->data.p_buff, p_rapdu->data.len);
*p_file_offset += p_rapdu->data.len;
return NRF_SUCCESS;
}
/**
* @brief Function for updating the remaining length of the read file.
*/
static ret_code_t nfc_t4t_file_len_update(nfc_t4t_resp_apdu_t const * const p_rapdu,
uint16_t * const p_len)
{
if (*p_len < p_rapdu->data.len)
{
return NRF_ERROR_INVALID_DATA;
}
*p_len -= p_rapdu->data.len;
return NRF_SUCCESS;
}
ret_code_t nfc_t4t_ndef_tag_app_select(void)
{
ret_code_t err_code;
nfc_t4t_comm_apdu_t capdu;
nfc_t4t_resp_apdu_t rapdu;
uint8_t apdu_buff[APDU_BUFF_SIZE];
NRF_LOG_INFO("NDEF Tag Application Select Procedure ");
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_SELECT_INS;
capdu.parameter = SELECT_BY_NAME;
capdu.data.p_buff = (uint8_t *) m_nfc_t4t_select_ndef_app_data;
capdu.data.len = sizeof(m_nfc_t4t_select_ndef_app_data);
capdu.resp_len = NDEF_APP_PROC_RESP_LEN;
err_code = nfc_t4t_apdu_exchange(&capdu, &rapdu, apdu_buff, sizeof(rapdu.status));
NRF_LOG_RAW_INFO("\r\n");
return err_code;
}
ret_code_t nfc_t4t_file_select(uint16_t file_id)
{
ret_code_t err_code;
nfc_t4t_comm_apdu_t capdu;
nfc_t4t_resp_apdu_t rapdu;
uint8_t apdu_buff[APDU_BUFF_SIZE];
if (file_id != CC_FILE_ID)
{
NRF_LOG_INFO("File (ID = %4X) Select Procedure ", file_id);
}
UNUSED_RETURN_VALUE(uint16_big_encode(file_id, m_file_id));
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_SELECT_INS;
capdu.parameter = SELECT_BY_FILE_ID;
capdu.data.p_buff = m_file_id;
capdu.data.len = sizeof(m_file_id);
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
NRF_LOG_RAW_INFO("\r\n");
return err_code;
}
ret_code_t nfc_t4t_cc_select(void)
{
NRF_LOG_INFO("Capability Container Select Procedure ");
return nfc_t4t_file_select(CC_FILE_ID);
}
ret_code_t nfc_t4t_cc_read(nfc_t4t_capability_container_t * const p_cc_file)
{
ret_code_t err_code;
nfc_t4t_comm_apdu_t capdu;
nfc_t4t_resp_apdu_t rapdu;
uint16_t clen;
uint16_t file_offset = 0;
uint8_t storage_buff[CC_STORAGE_BUFF_SIZE];
uint8_t apdu_buff[APDU_BUFF_SIZE];
NRF_LOG_INFO("Capability Container Read Procedure ");
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_READ_INS;
capdu.parameter = file_offset;
capdu.resp_len = MIN_MAX_RAPDU_SIZE;
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_file_chunk_save(&rapdu, storage_buff, CC_STORAGE_BUFF_SIZE, &file_offset);
VERIFY_SUCCESS(err_code);
clen = uint16_big_decode(storage_buff);
err_code = nfc_t4t_file_len_update(&rapdu, &clen);
VERIFY_SUCCESS(err_code);
while (clen > 0)
{
capdu.parameter = file_offset;
capdu.resp_len = MIN(MIN_MAX_RAPDU_SIZE, MIN(clen, MAX_ADAFRUIT_RAPDU_SIZE));
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_file_chunk_save(&rapdu, storage_buff, CC_STORAGE_BUFF_SIZE, &file_offset);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_file_len_update(&rapdu, &clen);
VERIFY_SUCCESS(err_code);
}
err_code = nfc_t4t_cc_file_parse(p_cc_file, storage_buff, file_offset);
NRF_LOG_RAW_INFO("\r\n");
return err_code;
}
ret_code_t nfc_t4t_ndef_read(nfc_t4t_capability_container_t * const p_cc_file,
uint8_t * p_ndef_file_buff,
uint8_t ndef_file_buff_len)
{
ret_code_t err_code;
nfc_t4t_comm_apdu_t capdu;
nfc_t4t_resp_apdu_t rapdu;
uint16_t len;
uint16_t file_offset = 0;
uint8_t apdu_buff[APDU_BUFF_SIZE];
NRF_LOG_INFO("NDEF Read Procedure ");
// Read the NLEN (NDEF length) field of NDEF file.
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_READ_INS;
capdu.parameter = file_offset;
capdu.resp_len = NDEF_FILE_NLEN_FIELD_SIZE;
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_file_chunk_save(&rapdu, p_ndef_file_buff, ndef_file_buff_len, &file_offset);
VERIFY_SUCCESS(err_code);
len = uint16_big_decode(p_ndef_file_buff) + NDEF_FILE_NLEN_FIELD_SIZE;
err_code = nfc_t4t_file_len_update(&rapdu, &len);
VERIFY_SUCCESS(err_code);
// Read the NDEF message.
while (len > 0)
{
capdu.parameter = file_offset;
capdu.resp_len = MIN(len, MIN(p_cc_file->max_rapdu_size, MAX_ADAFRUIT_RAPDU_SIZE));
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_file_chunk_save(&rapdu, p_ndef_file_buff, ndef_file_buff_len, &file_offset);
VERIFY_SUCCESS(err_code);
err_code = nfc_t4t_file_len_update(&rapdu, &len);
VERIFY_SUCCESS(err_code);
}
// Bind NDEF File Control TLV with NDEF file.
nfc_t4t_file_t file =
{
.p_content = p_ndef_file_buff,
.len = file_offset
};
uint16_t file_id = uint16_big_decode(m_file_id);
err_code = nfc_t4t_file_content_set(p_cc_file, file, file_id);
NRF_LOG_RAW_INFO("\r\n");
return err_code;
}
ret_code_t nfc_t4t_ndef_update(nfc_t4t_capability_container_t * const p_cc_file,
uint8_t * p_ndef_file_buff,
uint8_t ndef_file_buff_len)
{
ret_code_t err_code;
nfc_t4t_comm_apdu_t capdu;
nfc_t4t_resp_apdu_t rapdu;
uint16_t len;
uint16_t file_offset = 0;
uint16_t file_id = uint16_big_decode(m_file_id);
uint8_t apdu_buff[APDU_BUFF_SIZE];
nfc_t4t_tlv_block_t * p_tlv_block;
NRF_LOG_INFO("NDEF Update Procedure ");
if (ndef_file_buff_len < NDEF_FILE_NLEN_FIELD_SIZE)
{
return NRF_ERROR_INVALID_DATA;
}
// Check if selected NDEF file is registered in CC file descriptor.
p_tlv_block = nfc_t4t_file_content_get(p_cc_file, file_id);
if (p_tlv_block == NULL)
{
return NRF_ERROR_NULL;
}
// Check NDEF file capacity before writing anything to it.
len = uint16_big_decode(p_ndef_file_buff);
if ((len + NDEF_FILE_NLEN_FIELD_SIZE != ndef_file_buff_len) ||
(ndef_file_buff_len > p_tlv_block->value.max_file_size))
{
return NRF_ERROR_INVALID_LENGTH;
}
// Write the value 0000h in the NLEN field.
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_UPDATE_INS;
capdu.parameter = file_offset;
capdu.data.p_buff = (uint8_t *) m_nlen_update_value;
capdu.data.len = NDEF_FILE_NLEN_FIELD_SIZE;
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
file_offset += NDEF_FILE_NLEN_FIELD_SIZE;
// Write the NDEF message in the NDEF message field.
while (len > 0)
{
capdu.parameter = file_offset;
capdu.data.p_buff = p_ndef_file_buff + file_offset;
capdu.data.len = MIN(len, MIN(p_cc_file->max_capdu_size, MAX_ADAFRUIT_CAPDU_SIZE));
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
file_offset += capdu.data.len;
len -= capdu.data.len;
}
// Write the length of the NDEF message in the NLEN field.
capdu.parameter = 0;
capdu.data.p_buff = p_ndef_file_buff;
capdu.data.len = NDEF_FILE_NLEN_FIELD_SIZE;
err_code = nfc_t4t_apdu_default_exchange(&capdu, &rapdu, apdu_buff);
VERIFY_SUCCESS(err_code);
NRF_LOG_RAW_INFO("\r\n");
return NRF_SUCCESS;
}
#endif // NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED

View File

@@ -0,0 +1,184 @@
/**
* 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_T4T_HL_DETECTION_PROCEDURES_H__
#define NFC_T4T_HL_DETECTION_PROCEDURES_H__
/**@file
*
* @defgroup nfc_t4t_parser NFC Type 4 Tag parser
* @ingroup nfc_t4t
* @brief Parser for Type 4 Tag data.
*
* @defgroup nfc_t4t_hl_detection_procedures High-level NDEF Detection Procedure
* @{
* @ingroup nfc_t4t_parser
*
* @brief High-level NDEF Detection Procedure for Type 4 Tag communication.
*
*/
#include <stdint.h>
#include "sdk_errors.h"
#include "nfc_t4t_cc_file.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Function for performing NDEF Tag Application Select Procedure.
*
* This function performs NDEF Tag Application Select Procedure according to "Type 4 Tag Operation"
* (Version 3.0 published on 2014-07-30) chapter 5.5.2.
*
* @retval NRF_SUCCESS If NDEF Tag Application was successfully selected.
* @retval NRF_ERROR_NOT_FOUND If NDEF Tag Application was not found.
* @retval NRF_ERROR_NO_MEM If the APDU buffer is too small.
* @retval Other Other error codes may be returned depending on function
* @ref adafruit_pn532_in_data_exchange and on @ref nfc_t4t_apdu
* module functions.
*/
ret_code_t nfc_t4t_ndef_tag_app_select(void);
/**
* @brief Function for performing Capability Container Select Procedure.
*
* This function performs Capability Container Select Procedure according to "Type 4 Tag Operation"
* (Version 3.0 published on 2014-07-30) chapter 5.5.3.
*
* @retval NRF_SUCCESS If the Capability Container file was successfully selected.
* @retval NRF_ERROR_NOT_FOUND If the Capability Container file was not found.
* @retval NRF_ERROR_NO_MEM If the APDU buffer is too small.
* @retval Other Other error codes might be returned depending on function
* @ref adafruit_pn532_in_data_exchange and on @ref nfc_t4t_apdu
* module functions.
*/
ret_code_t nfc_t4t_cc_select(void);
/**
* @brief Function for performing Capability Container Read Procedure.
*
* This function performs Capability Container Read Procedure according to "Type 4 Tag Operation"
* (Version 3.0 published on 2014-07-30) chapter 5.5.4.
*
* @param[out] p_cc_file Pointer to the Capability Container descriptor.
*
* @retval NRF_SUCCESS If Capability Container file was successfully read.
* @retval NRF_ERROR_NO_MEM If APDU buffer or CC file storage buffer is too small.
* @retval NRF_ERROR_NOT_SUPPORTED If the requested response length in C-APDU is too big.
* @retval NRF_ERROR_NULL If R-APDU did not return any data bytes.
* @retval NRF_ERROR_INVALID_DATA If CCLEN field is not coherent with R-APDU data length.
* @retval Other Other error codes may be returned depending on functions
* @ref adafruit_pn532_in_data_exchange, @ref nfc_t4t_cc_file_parse,
* and on @ref nfc_t4t_apdu module functions.
*/
ret_code_t nfc_t4t_cc_read(nfc_t4t_capability_container_t * const p_cc_file);
/**
* @brief Function for performing NDEF Select Procedure.
*
* This function performs NDEF Select Procedure according to "Type 4 Tag Operation"
* (Version 3.0 published on 2014-07-30) chapter 5.5.5.
*
* @param[in] file_id File Identifier to choose the correct file.
*
* @retval NRF_SUCCESS If NDEF file was successfully selected.
* @retval NRF_ERROR_NOT_FOUND If NDEF file was not found.
* @retval NRF_ERROR_NO_MEM If APDU buffer is too small.
* @retval Other Other error codes may be returned depending on function
* @ref adafruit_pn532_in_data_exchange and on @ref nfc_t4t_apdu
* module functions.
*/
ret_code_t nfc_t4t_file_select(uint16_t file_id);
/**
* @brief Function for performing NDEF Read Procedure.
*
* This function performs NDEF Read Procedure according to "Type 4 Tag Operation"
* (Version 3.0 published on 2014-07-30) chapter 5.5.6.
*
* @param[in,out] p_cc_file Pointer to the Capability Container descriptor.
* @param[out] p_ndef_file_buff Pointer to the buffer where the NDEF file will be stored.
* @param[in] ndef_file_buff_len Length of the provided NDEF file buffer.
*
* @retval NRF_SUCCESS If NDEF file was successfully read.
* @retval NRF_ERROR_NO_MEM If APDU buffer or NDEF file buffer is too small.
* @retval NRF_ERROR_NOT_SUPPORTED If requested response length in C-APDU is too big.
* @retval NRF_ERROR_NULL If R-APDU did not return any data bytes.
* @retval NRF_ERROR_INVALID_DATA If NLEN field is not coherent with R-APDU data length.
* @retval Other Other error codes may be returned depending on function
* @ref adafruit_pn532_in_data_exchange, @ref nfc_t4t_file_content_set,
* and on @ref nfc_t4t_apdu module functions.
*/
ret_code_t nfc_t4t_ndef_read(nfc_t4t_capability_container_t * const p_cc_file,
uint8_t * p_ndef_file_buff,
uint8_t ndef_file_buff_len);
/**
* @brief Function for performing NDEF Update Procedure.
*
* This function performs NDEF Update Procedure according to "Type 4 Tag Operation"
* (Version 3.0 published on 2014-07-30) chapter 5.5.7.
*
* @param[in] p_cc_file Pointer to the Capability Container descriptor.
* @param[in] p_ndef_file_buff Pointer to the buffer with NDEF file.
* @param[in] ndef_file_buff_len Length of the provided NDEF file.
*
* @retval NRF_SUCCESS If NDEF file was successfully updated.
* @retval NRF_ERROR_NO_MEM If APDU buffer or NDEF file buffer is too small.
* @retval NRF_ERROR_NOT_SUPPORTED If the requested response length in C-APDU is too big.
* @retval NRF_ERROR_INVALID_DATA If NDEF file buffer is smaller than NLEN field size.
* @retval NRF_ERROR_INVALID_LENGTH If NLEN value is not coherent with NDEF file buffer length
* or if buffer length is bigger than maximal file size.
* @retval Other Other error codes may be returned depending on function
* @ref adafruit_pn532_in_data_exchange, @ref nfc_t4t_file_content_get,
* and on @ref nfc_t4t_apdu module functions.
*/
ret_code_t nfc_t4t_ndef_update(nfc_t4t_capability_container_t * const p_cc_file,
uint8_t * p_ndef_file_buff,
uint8_t ndef_file_buff_len);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NFC_T4T_HL_DETECTION_PROCEDURES_H__ */

View File

@@ -0,0 +1,327 @@
/**
* 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_config.h"
#if NFC_T4T_TLV_BLOCK_PARSER_ENABLED
#include <string.h>
#include "nfc_t4t_tlv_block.h"
#include "app_util.h"
#include "sdk_macros.h"
#include "nordic_common.h"
#define NRF_LOG_MODULE_NAME nfc_t4t_tlv_block_parser
#if NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL NFC_T4T_TLV_BLOCK_PARSER_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NFC_T4T_TLV_BLOCK_PARSER_INFO_COLOR
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#else // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#include "nrf_log.h"
#endif // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
#define TLV_TYPE_FIELD_LEN 1U ///< Length of a type field.
/**
* @brief TLV length field related defines.
*/
#define TLV_LEN_SHORT_FIELD_LEN 1U ///< Length of a short length field.
#define TLV_LEN_LONG_FIELD_LEN 3U ///< Length of an extended length field.
#define TLV_LEN_LONG_FORMAT_TOKEN 0xFF ///< Value indicating the use of an extended length field.
#define TLV_LEN_LONG_FORMAT_TOKEN_SIZE 1U ///< Size of long format token.
#define TLV_LEN_LONG_FORMAT_MIN_VALUE 0xFF ///< The minimal value of length field that can be used in long format.
/**
* @brief Possible sizes of TLV block.
*/
#define TLV_MIN_TL_FIELD_LEN (TLV_TYPE_FIELD_LEN + TLV_LEN_SHORT_FIELD_LEN)
#define TLV_MIN_LONG_FORMAT_TL_FIELD_LEN (TLV_TYPE_FIELD_LEN + TLV_LEN_LONG_FIELD_LEN)
#define TLV_MIN_VALUE_FIELD_SIZE 6U
/**
* @brief Field sizes that are present in TLV block.
*/
#define FILE_CONTROL_FILE_ID_FIELD_SIZE 2U
#define FILE_CONTROL_READ_ACCESS_FIELD_SIZE 1U
#define FILE_CONTROL_WRITE_ACCESS_FIELD_SIZE 1U
#define FILE_CONTROL_COMMON_FIELDS_SIZE (FILE_CONTROL_FILE_ID_FIELD_SIZE \
+ FILE_CONTROL_READ_ACCESS_FIELD_SIZE \
+ FILE_CONTROL_WRITE_ACCESS_FIELD_SIZE)
/**
* @brief Invalid values for File Identifier field.
*/
#define FILE_ID_INVALID_VALUE_0 0x0000
#define FILE_ID_INVALID_VALUE_1 0xE102
#define FILE_ID_INVALID_VALUE_2 0xE103
#define FILE_ID_INVALID_VALUE_3 0x3F00
#define FILE_ID_INVALID_VALUE_4 0x3FFF
#define FILE_ID_INVALID_VALUE_5 0xFFFF
/**
* @brief NDEF file related defines.
*/
#define NDEF_FILE_MAX_SIZE_FIELD_SIZE 2U
#define NDEF_FILE_MAX_SIZE_MIN_VAL 0x0005
#define NDEF_FILE_MAX_SIZE_MAX_VAL 0xFFFE
#define NDEF_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \
+ NDEF_FILE_MAX_SIZE_FIELD_SIZE)
/**
* @brief Proprietary file related defines.
*/
#define PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE 2U
#define PROPRIETARY_FILE_MAX_SIZE_MIN_VAL 0x0003
#define PROPRIETARY_FILE_MAX_SIZE_MAX_VAL 0xFFFE
#define PROPRIETARY_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \
+ PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE)
/**
* @brief Extended NDEF file related defines.
*/
#define EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE 4U
#define EXTENDED_NDEF_FILE_MAX_SIZE_MIN_VAL 0x0000FFFF
#define EXTENDED_NDEF_FILE_MAX_SIZE_MAX_VAL 0xFFFFFFFE
#define EXTENDED_NDEF_FILE_CONTROL_TLV_LEN (FILE_CONTROL_COMMON_FIELDS_SIZE \
+ EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE)
/**
* @brief Validates maximum file size field range. This field is present in every File Control TLV.
*/
#define NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(VALUE, MIN, MAX) \
if ( ( (VALUE) < (MIN) ) || ( (VALUE) > (MAX) ) ) \
{ \
return NRF_ERROR_INVALID_DATA; \
}
/**
* @brief Function for validating all possible types of File Control TLV.
*/
__STATIC_INLINE ret_code_t nfc_t4t_file_control_tl_validate(nfc_t4t_tlv_block_t * p_file_control_tlv)
{
switch (p_file_control_tlv->type)
{
case NDEF_FILE_CONTROL_TLV:
VERIFY_TRUE(p_file_control_tlv->length == NDEF_FILE_CONTROL_TLV_LEN,
NRF_ERROR_INVALID_DATA);
return NRF_SUCCESS;
case PROPRIETARY_FILE_CONTROL_TLV:
VERIFY_TRUE(p_file_control_tlv->length == PROPRIETARY_FILE_CONTROL_TLV_LEN,
NRF_ERROR_INVALID_DATA);
return NRF_SUCCESS;
case EXTENDED_NDEF_FILE_CONTROL_TLV:
VERIFY_TRUE(p_file_control_tlv->length == EXTENDED_NDEF_FILE_CONTROL_TLV_LEN,
NRF_ERROR_INVALID_DATA);
return NRF_SUCCESS;
default:
return NRF_ERROR_INVALID_DATA;
}
}
/**
* @brief Function for parsing value field of File Control TLV.
*/
static ret_code_t nfc_t4t_file_control_value_parse(nfc_t4t_tlv_block_t * p_file_control_tlv,
uint8_t * p_value_buff)
{
nfc_t4t_file_control_val_t * p_control_tlv_val;
// Handle File Identifier field.
p_control_tlv_val = &p_file_control_tlv->value;
p_control_tlv_val->file_id = uint16_big_decode(p_value_buff);
p_value_buff += FILE_CONTROL_FILE_ID_FIELD_SIZE;
switch (p_control_tlv_val->file_id)
{
case FILE_ID_INVALID_VALUE_0:
case FILE_ID_INVALID_VALUE_1:
case FILE_ID_INVALID_VALUE_2:
case FILE_ID_INVALID_VALUE_3:
case FILE_ID_INVALID_VALUE_4:
case FILE_ID_INVALID_VALUE_5:
return NRF_ERROR_INVALID_DATA;
default:
break;
}
// Handle Max file size field.
switch (p_file_control_tlv->type)
{
case NDEF_FILE_CONTROL_TLV:
p_control_tlv_val->max_file_size = uint16_big_decode(p_value_buff);
p_value_buff += NDEF_FILE_MAX_SIZE_FIELD_SIZE;
NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size,
NDEF_FILE_MAX_SIZE_MIN_VAL,
NDEF_FILE_MAX_SIZE_MAX_VAL);
break;
case PROPRIETARY_FILE_CONTROL_TLV:
p_control_tlv_val->max_file_size = uint16_big_decode(p_value_buff);
p_value_buff += PROPRIETARY_FILE_MAX_SIZE_FIELD_SIZE;
NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size,
PROPRIETARY_FILE_MAX_SIZE_MIN_VAL,
PROPRIETARY_FILE_MAX_SIZE_MAX_VAL);
break;
case EXTENDED_NDEF_FILE_CONTROL_TLV:
p_control_tlv_val->max_file_size = uint32_big_decode(p_value_buff);
p_value_buff += EXTENDED_NDEF_FILE_MAX_SIZE_FIELD_SIZE;
NFC_T4T_FILE_CONTROL_MAX_SIZE_FIELD_RANGE_VERIFY(p_control_tlv_val->max_file_size,
EXTENDED_NDEF_FILE_MAX_SIZE_MIN_VAL,
EXTENDED_NDEF_FILE_MAX_SIZE_MAX_VAL);
break;
}
// Handle read access condition field.
p_control_tlv_val->read_access = *p_value_buff;
p_value_buff += FILE_CONTROL_READ_ACCESS_FIELD_SIZE;
// Handle write access condition field.
p_control_tlv_val->write_access = *p_value_buff;
return NRF_SUCCESS;
}
ret_code_t nfc_t4t_file_control_tlv_parse(nfc_t4t_tlv_block_t * p_file_control_tlv,
uint8_t * p_raw_data,
uint16_t * p_len)
{
ret_code_t err_code;
uint8_t * p_offset = p_raw_data;
if (*p_len < TLV_MIN_TL_FIELD_LEN)
{
return NRF_ERROR_INVALID_LENGTH;
}
memset(p_file_control_tlv, 0, sizeof(nfc_t4t_tlv_block_t));
// Handle type field of TLV block.
p_file_control_tlv->type = *p_offset;
p_offset += TLV_TYPE_FIELD_LEN;
// Handle length field of TLV block.
if (*p_offset == TLV_LEN_LONG_FORMAT_TOKEN)
{
if (*p_len < TLV_MIN_LONG_FORMAT_TL_FIELD_LEN)
{
return NRF_ERROR_INVALID_LENGTH;
}
p_file_control_tlv->length = uint16_big_decode(p_offset + TLV_LEN_LONG_FORMAT_TOKEN_SIZE);
p_offset += TLV_LEN_LONG_FIELD_LEN;
if (p_file_control_tlv->length < TLV_LEN_LONG_FORMAT_MIN_VALUE)
{
return NRF_ERROR_INVALID_DATA;
}
}
else
{
p_file_control_tlv->length = *p_offset;
p_offset += TLV_LEN_SHORT_FIELD_LEN;
}
// Calculate the total TLV block size.
uint16_t tlv_block_len = (p_offset - p_raw_data) + p_file_control_tlv->length;
if (*p_len < tlv_block_len)
{
return NRF_ERROR_INVALID_LENGTH;
}
*p_len = tlv_block_len;
// Validate if type and length fields contain values supported by Type 4 Tag.
err_code = nfc_t4t_file_control_tl_validate(p_file_control_tlv);
VERIFY_SUCCESS(err_code);
// Handle value field of TLV block.
err_code = nfc_t4t_file_control_value_parse(p_file_control_tlv, p_offset);
return err_code;
}
void nfc_t4t_file_control_tlv_printout(uint8_t num, nfc_t4t_tlv_block_t * p_t4t_tlv_block)
{
NRF_LOG_INFO("%d file Control TLV", num);
switch (p_t4t_tlv_block->type)
{
case NDEF_FILE_CONTROL_TLV:
NRF_LOG_INFO("Type: NDEF File Control (0x%02x)", p_t4t_tlv_block->type);
break;
case PROPRIETARY_FILE_CONTROL_TLV:
NRF_LOG_INFO("Type: Proprietary File Control (0x%02x)", p_t4t_tlv_block->type);
break;
case EXTENDED_NDEF_FILE_CONTROL_TLV:
NRF_LOG_INFO("Type: Extended NDEF File Control (0x%02x)", p_t4t_tlv_block->type);
break;
default:
NRF_LOG_INFO("Type: Unknown (0x%02x)", p_t4t_tlv_block->type);
}
NRF_LOG_INFO("Length (in bytes): %d", p_t4t_tlv_block->length);
nfc_t4t_file_control_val_t * p_tlv_val = &p_t4t_tlv_block->value;
NRF_LOG_INFO("File Identifier: 0x%04X ", p_tlv_val->file_id);
NRF_LOG_INFO("Maximum file size: %d ", p_tlv_val->max_file_size);
NRF_LOG_INFO("Read access condition: 0x%02X ", p_tlv_val->read_access);
NRF_LOG_INFO("Write access condition: 0x%02x ", p_tlv_val->write_access);
if (p_tlv_val->file.p_content != NULL)
{
NRF_LOG_INFO("NDEF file content present. Length: %d ", p_tlv_val->file.len);
NRF_LOG_HEXDUMP_INFO(p_tlv_val->file.p_content, p_tlv_val->file.len);
}
else
{
NRF_LOG_INFO("NDEF file content is not present ");
}
}
#endif // NFC_T4T_TLV_BLOCK_PARSER_ENABLED

View File

@@ -0,0 +1,147 @@
/**
* 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_T4T_TLV_BLOCK_H__
#define NFC_T4T_TLV_BLOCK_H__
/**@file
*
* @defgroup nfc_t4t_tlv_block File Control TLV block parser for Type 4 Tag.
* @{
* @ingroup nfc_t4t_cc_file
*
* @brief File Control TLV block parser for Type 4 Tag (T4T).
*
*/
#include <stdint.h>
#include "sdk_errors.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CONTROL_FILE_READ_ACCESS_GRANTED 0x00 ///< Read access granted without any security.
/**
* @name Possible values of file write access condition field.
* @{
*/
#define CONTROL_FILE_WRITE_ACCESS_GRANTED 0x00 ///< Write access granted without any security.
#define CONTROL_FILE_WRITE_ACCESS_DISABLED 0xFF ///< No write access granted without any security (read-only).
/** @} */
/**
* @brief Possible types of File Control TLV for Type 4 Tag.
*/
typedef enum
{
NDEF_FILE_CONTROL_TLV = 0x04, ///< Control information concerning the EF file with short NDEF message.
PROPRIETARY_FILE_CONTROL_TLV = 0x05, ///< Control information concerning the Proprietary file with proprietary data.
EXTENDED_NDEF_FILE_CONTROL_TLV = 0x06 ///< Control information concerning the EF file with long NDEF message.
} nfc_t4t_tlv_block_types_t;
/**
* @brief File content descriptor.
*/
typedef struct
{
uint8_t * p_content; ///< Pointer to the file content.
uint16_t len; ///< Length of file content.
} nfc_t4t_file_t;
/**
* @brief Extended NDEF/NDEF/Proprietary File Control Value descriptor.
*/
typedef struct
{
nfc_t4t_file_t file; ///< Pointer to the described file content.
uint32_t max_file_size; ///< Maximum size (in bytes) of the file.
uint16_t file_id; ///< File identifier.
uint8_t read_access; ///< File read access condition.
uint8_t write_access; ///< File write access condition.
} nfc_t4t_file_control_val_t;
/**
* @brief File Control TLV block descriptor.
*/
typedef struct
{
nfc_t4t_file_control_val_t value; ///< Value field descriptor.
uint16_t length; ///< Length of the value field.
uint8_t type; ///< Type of the TLV block.
} nfc_t4t_tlv_block_t;
/**
* @brief Function for parsing raw data of File Control TLV, read from a Type 4 Tag.
*
* This function parses raw data of File Control TLV and stores the results in its
* descriptor.
*
* @param[in,out] p_file_control_tlv Pointer to the File Control TLV that will be filled with
* parsed data.
* @param[in] p_raw_data Pointer to the buffer with raw TLV data.
* @param[in,out] p_len In: Buffer length with TLV blocks.
* Out: Total length of first identified TLV within the buffer.
*
* @retval NRF_SUCCESS If operation was successful.
* @retval NRF_ERROR_INVALID_LENGTH If provided buffer length is too small for TLV block.
* @retval NRF_ERROR_INVALID_DATA If any TLV block field contains invalid data.
*/
ret_code_t nfc_t4t_file_control_tlv_parse(nfc_t4t_tlv_block_t * p_file_control_tlv,
uint8_t * p_raw_data,
uint16_t * p_len);
/**
* @brief Function for printing TLV block descriptor.
*
* This function prints TLV block descriptor.
*
* @param[in] num TLV block number.
* @param[in] p_t4t_tlv_block Pointer to the TLV block descriptor.
*/
void nfc_t4t_file_control_tlv_printout(uint8_t num, nfc_t4t_tlv_block_t * p_t4t_tlv_block);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NFC_T4T_TLV_BLOCK_H__ */