mirror of
https://gitee.com/muyuchl/nrf51_2in13_epd.git
synced 2025-12-15 02:08:12 +08:00
copy project from century 2in6 esl project
This commit is contained in:
260
COMPONENTS/nfc/t4t_parser/apdu/nfc_t4t_apdu.c
Normal file
260
COMPONENTS/nfc/t4t_parser/apdu/nfc_t4t_apdu.c
Normal 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
|
||||
|
||||
222
COMPONENTS/nfc/t4t_parser/apdu/nfc_t4t_apdu.h
Normal file
222
COMPONENTS/nfc/t4t_parser/apdu/nfc_t4t_apdu.h
Normal 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__ */
|
||||
266
COMPONENTS/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.c
Normal file
266
COMPONENTS/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.c
Normal 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
|
||||
|
||||
178
COMPONENTS/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.h
Normal file
178
COMPONENTS/nfc/t4t_parser/cc_file/nfc_t4t_cc_file.h
Normal 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__ */
|
||||
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
326
COMPONENTS/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.c
Normal file
326
COMPONENTS/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.c
Normal 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
|
||||
|
||||
148
COMPONENTS/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.h
Normal file
148
COMPONENTS/nfc/t4t_parser/tlv/nfc_t4t_tlv_block.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user