copy project from century 2in6 esl project

This commit is contained in:
muyuchl
2025-04-26 13:14:26 +08:00
commit 2c9b333b97
1507 changed files with 460409 additions and 0 deletions

View File

@@ -0,0 +1,260 @@
/**
* Copyright (c) 2016 - 2017, 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
#else // NFC_T4T_APDU_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // NFC_T4T_APDU_LOG_ENABLED
#include "nrf_log.h"
/**
* @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 \r\n", p_resp_apdu->status);
if (p_resp_apdu->data.p_buff != NULL)
{
NRF_LOG_INFO("R-APDU data: \r\n");
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.\r\n");
}
}
#endif // NFC_T4T_APDU_ENABLED

View File

@@ -0,0 +1,222 @@
/**
* Copyright (c) 2016 - 2017, 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 - 2017, 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
#else // NFC_T4T_CC_FILE_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // NFC_T4T_CC_FILE_PARSER_LOG_ENABLED
#include "nrf_log.h"
/**
* @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: \r\n")
NRF_LOG_INFO("CCLEN: %d \r\n", p_t4t_cc_file->len);
NRF_LOG_INFO("Mapping Version: %d.%d \r\n",
p_t4t_cc_file->major_version,
p_t4t_cc_file->minor_version);
NRF_LOG_INFO("MLe: %d \r\n", p_t4t_cc_file->max_rapdu_size)
NRF_LOG_INFO("MLc: %d \r\n\r\n", p_t4t_cc_file->max_capdu_size)
NRF_LOG_INFO("Capability Container File contains %d File Control TLV block(s).\r\n",
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]);
}
NRF_LOG_RAW_INFO("\r\n");
}
#endif // NFC_T4T_CC_FILE_PARSER_ENABLED

View File

@@ -0,0 +1,178 @@
/**
* Copyright (c) 2016 - 2017, 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,399 @@
/**
* Copyright (c) 2016 - 2017, 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
#else // NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED
#include "nrf_log.h"
#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 56 ///< 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 \r\n");
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 \r\n", 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 \r\n");
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 \r\n");
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 \r\n");
// 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 \r\n");
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,185 @@
/**
* Copyright (c) 2016 - 2017, 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,326 @@
/**
* Copyright (c) 2016 - 2017, 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
#else // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED
#include "nrf_log.h"
#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\r\n", num);
switch (p_t4t_tlv_block->type)
{
case NDEF_FILE_CONTROL_TLV:
NRF_LOG_INFO("Type: NDEF File Control (0x%02x)\r\n", p_t4t_tlv_block->type);
break;
case PROPRIETARY_FILE_CONTROL_TLV:
NRF_LOG_INFO("Type: Proprietary File Control (0x%02x)\r\n", p_t4t_tlv_block->type);
break;
case EXTENDED_NDEF_FILE_CONTROL_TLV:
NRF_LOG_INFO("Type: Extended NDEF File Control (0x%02x)\r\n", p_t4t_tlv_block->type);
break;
default:
NRF_LOG_INFO("Type: Unknown (0x%02x)\r\n", p_t4t_tlv_block->type);
}
NRF_LOG_INFO("Length (in bytes): %d\r\n", 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 \r\n", p_tlv_val->file_id);
NRF_LOG_INFO("Maximum file size: %d \r\n", p_tlv_val->max_file_size);
NRF_LOG_INFO("Read access condition: 0x%02X \r\n", p_tlv_val->read_access);
NRF_LOG_INFO("Write access condition: 0x%02x \r\n\r\n", p_tlv_val->write_access);
if (p_tlv_val->file.p_content != NULL)
{
NRF_LOG_INFO("NDEF file content present. Length: %d \r\n", 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 \r\n");
}
NRF_LOG_RAW_INFO("\r\n");
}
#endif // NFC_T4T_TLV_BLOCK_PARSER_ENABLED

View File

@@ -0,0 +1,148 @@
/**
* Copyright (c) 2016 - 2017, 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__ */