mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-04-10 12:25:55 +00:00
feat(core): Introduce nfc commands in prodtest & update NFC library [no changelog]
This commit is contained in:
parent
fc2cf1535e
commit
bdc8dbffe3
@ -16,3 +16,9 @@ charset = utf-8
|
||||
end_of_line = unset
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
# Ignore rfal nfc library
|
||||
[/core/embed/io/nfc/rfal/**]
|
||||
end_of_line = unset
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
|
@ -106,6 +106,7 @@ SOURCE_PRODTEST = [
|
||||
'embed/projects/prodtest/cmd/prodtest_get_cpuid.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_haptic.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_help.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_nfc.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_optiga.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_otp_batch.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_otp_variant.c',
|
||||
|
@ -17,23 +17,37 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_NFC_H
|
||||
#define TREZORHAL_NFC_H
|
||||
#pragma once
|
||||
|
||||
#include <trezor_bsp.h>
|
||||
#include <trezor_rtl.h>
|
||||
#include <trezor_types.h>
|
||||
|
||||
#define NFC_MAX_UID_LEN 10
|
||||
#define NFC_MAX_UID_BUF_SIZE ((NFC_MAX_UID_LEN + 1) * 2)
|
||||
|
||||
typedef enum {
|
||||
NFC_CARD_EMU_TECH_A,
|
||||
NFC_CARD_EMU_TECH_V,
|
||||
} nfc_card_emul_tech_t;
|
||||
NFC_POLLER_TECH_A = 0x1,
|
||||
NFC_POLLER_TECH_B = 0x1 << 1,
|
||||
NFC_POLLER_TECH_F = 0x1 << 2,
|
||||
NFC_POLLER_TECH_V = 0x1 << 3,
|
||||
NFC_CARD_EMU_TECH_A = 0x1 << 4,
|
||||
NFC_CARD_EMU_TECH_F = 0x1 << 5,
|
||||
} nfc_tech_t;
|
||||
|
||||
typedef enum {
|
||||
NFC_POLLER_TECH_A,
|
||||
NFC_POLLER_TECH_B,
|
||||
NFC_POLLER_TECH_F,
|
||||
NFC_POLLER_TECH_V,
|
||||
} nfc_poller_tech_t;
|
||||
NFC_DEV_TYPE_A,
|
||||
NFC_DEV_TYPE_B,
|
||||
NFC_DEV_TYPE_F,
|
||||
NFC_DEV_TYPE_V,
|
||||
NFC_DEV_TYPE_ST25TB,
|
||||
NFC_DEV_TYPE_AP2P,
|
||||
NFC_DEV_TYPE_UNKNOWN,
|
||||
} nfc_dev_type_t;
|
||||
|
||||
typedef enum {
|
||||
NFC_NO_EVENT,
|
||||
NFC_EVENT_DEACTIVATED,
|
||||
NFC_EVENT_ACTIVATED,
|
||||
} nfc_event_t;
|
||||
|
||||
typedef enum {
|
||||
NFC_OK,
|
||||
@ -43,14 +57,43 @@ typedef enum {
|
||||
NFC_INITIALIZATION_FAILED,
|
||||
} nfc_status_t;
|
||||
|
||||
nfc_status_t nfc_init();
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
char uid[NFC_MAX_UID_BUF_SIZE]; // Plus one for string termination
|
||||
uint8_t uid_len;
|
||||
} nfc_dev_info_t;
|
||||
|
||||
nfc_status_t nfc_deinit();
|
||||
// Initialize NFC driver including supportive RFAL middleware
|
||||
nfc_status_t nfc_init(void);
|
||||
|
||||
nfc_status_t nfc_register_card_emu(nfc_card_emul_tech_t tech);
|
||||
// Deinitialize NFC driver
|
||||
void nfc_deinit(void);
|
||||
|
||||
nfc_status_t nfc_register_poller(nfc_poller_tech_t tech);
|
||||
// Register NFC technology (or several) to be explored by NFC state machine
|
||||
// use this function before activating the state machine with nfc_activate_stm()
|
||||
nfc_status_t nfc_register_tech(const nfc_tech_t tech);
|
||||
|
||||
nfc_status_t nfc_run_worker();
|
||||
// Activates the NFC RFAL state machine to explore the previously registered
|
||||
// technologies. The RFAL handles low-level NFC protocols and provides
|
||||
// information about the activated device. This function only starts the
|
||||
// exploration; you must regularly call nfc_get_event() to continue processing
|
||||
// NFC operations.
|
||||
nfc_status_t nfc_activate_stm(void);
|
||||
|
||||
#endif // TREZORHAL_NFC_H
|
||||
// Deactivate the NFC RFAL state machine (put in IDLE state).
|
||||
nfc_status_t nfc_deactivate_stm(void);
|
||||
|
||||
// Calls NFC RFAL worker to service the NFC state machine and expolore
|
||||
// registered technologies. This function has to be actively called in loop
|
||||
// (main NFC poll function), returns nfc event.
|
||||
nfc_status_t nfc_get_event(nfc_event_t *event);
|
||||
|
||||
// Deactivate the currently activated NFC device and put RFAL state machine back
|
||||
// to discovary state.
|
||||
nfc_status_t nfc_dev_deactivate(void);
|
||||
|
||||
// Read the general device information of the activated NFC device.
|
||||
nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info);
|
||||
|
||||
// Write the NDEF message with the trezor.io URI to the activated NFC device.
|
||||
nfc_status_t nfc_dev_write_ndef_uri(void);
|
||||
|
653
core/embed/io/nfc/st25r3916b/card_emulation.c
Normal file
653
core/embed/io/nfc/st25r3916b/card_emulation.c
Normal file
@ -0,0 +1,653 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file card_emulation.c
|
||||
* @author MMY Application Team
|
||||
* @brief Body function to manage card emul mode
|
||||
******************************************************************************
|
||||
** This notice applies to any and all portions of this file
|
||||
* that are not between comment pairs USER CODE BEGIN and
|
||||
* USER CODE END. Other portions of this file, whether
|
||||
* inserted by the user or by software development tools
|
||||
* are owned by their respective copyright owners.
|
||||
*
|
||||
* COPYRIGHT(c) 2018 STMicroelectronics
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "card_emulation.h"
|
||||
#include "rfal_nfca.h"
|
||||
#include "rfal_nfcf.h"
|
||||
#include "rfal_rf.h"
|
||||
|
||||
/** @addtogroup X-CUBE-NFC6_Applications
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup CardEmulation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup CE_CardEmul
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/** @defgroup CE_CardEmul_Private_Typedef
|
||||
* @{
|
||||
*/
|
||||
enum States {
|
||||
STATE_IDLE = 0, /*!< Emulated Tag state idle */
|
||||
STATE_APP_SELECTED = 1, /*!< Emulated Tag state application selected */
|
||||
STATE_CC_SELECTED = 2, /*!< Emulated Tag state CCFile selected */
|
||||
STATE_FID_SELECTED = 3, /*!< Emulated Tag state FileID selected */
|
||||
};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup CE_CardEmul_Private_Define
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NDEF_SIZE 2048 /*!< Max NDEF size emulated. Range: 0005h - 7FFFh */
|
||||
#define T4T_CLA_00 0x00 /*!< CLA value for type 4 command */
|
||||
#define T4T_INS_SELECT \
|
||||
0xA4 /*!< INS value for select command */
|
||||
#define T4T_INS_READ \
|
||||
0xB0 /*!< INS value for reabbinary command */
|
||||
#define T4T_INS_UPDATE \
|
||||
0xD6 /*!< INS value for update command */
|
||||
#define FID_CC 0xE103 /*!< File ID number for CCFile */
|
||||
#define FID_NDEF 0x0001 /*!< File ID number for NDEF file */
|
||||
#define T3T_BLOCK_SIZE \
|
||||
0x10 /*!< Block size in Type 3 Tag */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup CE_CardEmul_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
static uint8_t gNfcfNfcid[RFAL_NFCF_NFCID2_LEN];
|
||||
static uint8_t ndefFile[NDEF_SIZE]; /*!< Buffer to store NDEF File */
|
||||
static int8_t nState = STATE_IDLE; /*!< Type 4 tag emulation status */
|
||||
static int32_t nSelectedIdx = -1; /*!< current file selected */
|
||||
static int32_t nFiles = 2; /*!< Number of file emulated */
|
||||
|
||||
/**
|
||||
* CCLEN : Indicates the size of this CC File <BR>
|
||||
* T4T_VNo : Indicates the Mapping Version <BR>
|
||||
* MLe high : Max R-APDU size <BR>
|
||||
* MLc high : Max C-APDU size <BR>
|
||||
* NDEF FCI T: Indicates the NDEF-File_Ctrl_TLV <BR>
|
||||
* NDEF FCI L: The length of the V-field <BR>
|
||||
* NDEF FCI V1: NDEF File Identifier <BR>
|
||||
* NDEF FCI V2: NDEF File size <BR>
|
||||
* NDEF FCI V3: NDEF Read AC <BR>
|
||||
* NDEF FCI V4: NDEF Write AC <BR>
|
||||
*/
|
||||
static uint8_t ccfile[] = {
|
||||
0x00,
|
||||
0x0F, /* CCLEN */
|
||||
0x20, /* T4T_VNo */
|
||||
0x00,
|
||||
0x7F, /* MLe */
|
||||
0x00,
|
||||
0x7F, /* MLc */
|
||||
0x04, /* T */
|
||||
0x06, /* L */
|
||||
(FID_NDEF & 0xFF00) >> 8,
|
||||
(FID_NDEF & 0x00FF), /* V1 */
|
||||
(NDEF_SIZE & 0xFF00) >> 8,
|
||||
(NDEF_SIZE & 0x00FF), /* V2 */
|
||||
0x00, /* V3 */
|
||||
0x00 /* V4 */
|
||||
};
|
||||
|
||||
static uint32_t pdwFileSize[] = {sizeof(ccfile),
|
||||
NDEF_SIZE}; /*!< Current emulated files size */
|
||||
|
||||
/**
|
||||
* NDEF length <BR>
|
||||
* NDEF Header: MB,ME,SR,Well known Type <BR>
|
||||
* NDEF type length <BR>
|
||||
* NDEF payload length <BR>
|
||||
* NDEF Type : URI <BR>
|
||||
* NDEF URI abreviation field : http://www. <BR>
|
||||
* NDEF URI string : st.com/st25-demo <BR>
|
||||
*/
|
||||
static const uint8_t ndef_uri[] = {
|
||||
0x00, 0x15, /* NDEF length */
|
||||
0xD1, /* NDEF Header */
|
||||
0x01, /* NDEF type length */
|
||||
0x11, /* NDEF payload length */
|
||||
0x55, /* NDEF Type */
|
||||
0x01, /* NDEF URI abreviation field */
|
||||
0x74, 0x72, 0x65, 0x7A, 0x6F, 0x72, 0x2E, 0x69, 0x6F}; /* NDEF URI string */
|
||||
|
||||
__WEAK const uint8_t *NdefFile = ndef_uri;
|
||||
__WEAK uint32_t NdefFileLen = sizeof(ndef_uri);
|
||||
|
||||
/**
|
||||
* Ver : Indicates the NDEF mapping version <BR>
|
||||
* Nbr : Indicates the number of blocks that can be read <BR>
|
||||
* Nbw : Indicates the number of blocks that can be written <BR>
|
||||
* NmaxB : Indicates the maximum number of blocks available for NDEF data <BR>
|
||||
* WriteFlag : Indicates whether a previous NDEF write procedure has finished or
|
||||
* not <BR> RWFlag : Indicates data can be updated or not <BR> Ln : Is the size
|
||||
* of the actual stored NDEF data in bytes <BR> Checksum : allows the
|
||||
* Reader/Writer to check whether the Attribute Data are correct <BR>
|
||||
*/
|
||||
static uint8_t InformationBlock[] = {
|
||||
0x10, /* Ver */
|
||||
0x08, /* Nbr */
|
||||
0x08, /* Nbw */
|
||||
0x00, 0x0F, /* NmaxB */
|
||||
0x00, 0x00, 0x00, 0x00, /* RFU */
|
||||
0x00, /* WriteFlag */
|
||||
0x01, /* RWFlag */
|
||||
0x00, 0x00, 0x15, /* Ln */
|
||||
0x00, 0x45 /* Checksum */
|
||||
};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup CE_CardEmul_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Compare 2 commands supplied in parameters
|
||||
*
|
||||
* @param[in] cmd : pointer to the received command.
|
||||
* @param[in] find : pointer to the avalaible command.
|
||||
* @param[in] len : length of the available command.
|
||||
*
|
||||
* @retval True : Same command.
|
||||
* @retval False : Different command.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static bool cmd_compare(uint8_t *cmd, uint8_t *find, uint16_t len) {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (!memcmp(&cmd[i], find, len)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Manage the T4T Select answer to the reader
|
||||
*
|
||||
* @param[in] cmdData : pointer to the received command.
|
||||
* @param[out] rspData : pointer to the answer to send.
|
||||
*
|
||||
* @return Answer size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static uint16_t card_emulation_t4t_select(uint8_t *cmdData, uint8_t *rspData) {
|
||||
bool success = false;
|
||||
/*
|
||||
* Cmd: CLA(1) | INS(1) | P1(1) | P2(1) | Lc(1) | Data(n) | [Le(1)]
|
||||
* Rsp: [FCI(n)] | SW12
|
||||
*
|
||||
* Select App by Name NDEF: 00 A4 04 00 07 D2 76 00 00 85 01 01 00
|
||||
* Select App by Name NDEF 4 ST: 00 A4 04 00 07 A0 00 00 00 03 00 00 00
|
||||
* Select CC FID: 00 A4 00 0C 02 xx xx
|
||||
* Select NDEF FID: 00 A4 00 0C 02 xx xx
|
||||
*/
|
||||
|
||||
uint8_t aid[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
|
||||
uint8_t fidCC[] = {FID_CC >> 8, FID_CC & 0xFF};
|
||||
uint8_t fidNDEF[] = {FID_NDEF >> 8, FID_NDEF & 0xFF};
|
||||
uint8_t selectFileId[] = {0xA4, 0x00, 0x0C, 0x02, 0x00, 0x01};
|
||||
|
||||
if (cmd_compare(cmdData, aid, sizeof(aid))) { /* Select Appli */
|
||||
nState = STATE_APP_SELECTED;
|
||||
success = true;
|
||||
} else if ((nState >= STATE_APP_SELECTED) &&
|
||||
cmd_compare(cmdData, fidCC, sizeof(fidCC))) { /* Select CC */
|
||||
nState = STATE_CC_SELECTED;
|
||||
nSelectedIdx = 0;
|
||||
success = true;
|
||||
} else if ((nState >= STATE_APP_SELECTED) &&
|
||||
(cmd_compare(cmdData, fidNDEF, sizeof(fidNDEF)) ||
|
||||
cmd_compare(cmdData, selectFileId,
|
||||
sizeof(selectFileId)))) { /* Select NDEF */
|
||||
nState = STATE_FID_SELECTED;
|
||||
nSelectedIdx = 1;
|
||||
success = true;
|
||||
} else {
|
||||
nState = STATE_IDLE;
|
||||
}
|
||||
|
||||
rspData[0] = (success ? (char)0x90 : 0x6A);
|
||||
rspData[1] = (success ? (char)0x00 : 0x82);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Manage the T4T Read answer to the reader
|
||||
*
|
||||
* @param[in] cmdData : pointer to the received command.
|
||||
* @param[out] rspData : pointer to the answer to send.
|
||||
* @param[in] rspDataLen : size of the answer buffer.
|
||||
*
|
||||
* @return Answer size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static uint16_t card_emulation_t4t_read(uint8_t *cmdData, uint8_t *rspData,
|
||||
uint16_t rspDataLen) {
|
||||
/*
|
||||
* Cmd: CLA(1) | INS(1) | P1(1).. offset inside file high | P2(1).. offset
|
||||
* inside file high | Le(1).. nBytes to read Rsp: BytesRead | SW12
|
||||
*/
|
||||
unsigned short offset = (cmdData[2] << 8) | cmdData[3];
|
||||
unsigned short toRead = cmdData[4];
|
||||
uint8_t *ppbMemory;
|
||||
|
||||
if (rspDataLen < 2) {
|
||||
// platformErrorHandle(); /* Must ensure appropriate buffer */
|
||||
}
|
||||
|
||||
/* Any file selected */
|
||||
if (nSelectedIdx < 0 || nSelectedIdx >= nFiles) {
|
||||
rspData[0] = ((char)0x6A);
|
||||
rspData[1] = ((char)0x82);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* offset + length exceed file size */
|
||||
if ((unsigned long)(offset + toRead) > pdwFileSize[nSelectedIdx]) {
|
||||
toRead = pdwFileSize[nSelectedIdx] - offset;
|
||||
}
|
||||
|
||||
if (rspDataLen < (toRead + 2)) {
|
||||
rspData[0] = ((char)0x6F);
|
||||
rspData[1] = ((char)0x00);
|
||||
return 2;
|
||||
}
|
||||
|
||||
ppbMemory = (nSelectedIdx == 0 ? ccfile : ndefFile);
|
||||
/* read data */
|
||||
memcpy(rspData, &ppbMemory[offset], toRead);
|
||||
|
||||
rspData[toRead] = ((char)0x90);
|
||||
rspData[toRead + 1] = ((char)0x00);
|
||||
return toRead + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Manage the T4T Update answer to the reader
|
||||
*
|
||||
* @param[in] cmdData : pointer to the received command.
|
||||
* @param[in] rspData : pointer to the answer to send.
|
||||
*
|
||||
* @return Answer size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static uint16_t card_emulation_t4t_update(uint8_t *cmdData, uint8_t *rspData) {
|
||||
uint32_t offset = (cmdData[2] << 8) | cmdData[3];
|
||||
uint32_t length = cmdData[4];
|
||||
|
||||
if (nSelectedIdx != 1) {
|
||||
rspData[0] = ((char)0x6A);
|
||||
rspData[1] = ((char)0x82);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ((unsigned long)(offset + length) > pdwFileSize[nSelectedIdx]) {
|
||||
rspData[0] = ((char)0x62);
|
||||
rspData[1] = ((char)0x82);
|
||||
return 2;
|
||||
}
|
||||
|
||||
memcpy((ndefFile + offset), &cmdData[5], length);
|
||||
|
||||
rspData[0] = ((char)0x90);
|
||||
rspData[1] = ((char)0x00);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Manage the T4T Read answer to the reader
|
||||
*
|
||||
* @param[in] cmdData : pointer to the received command.
|
||||
* @param[out] rspData : pointer to the answer to send.
|
||||
* @param[in] rspDataLen : size of the answer buffer.
|
||||
*
|
||||
* @return Answer size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static uint16_t card_emulation_t3t_check(uint8_t *cmdData, uint8_t *rspData,
|
||||
uint16_t rspDataLen) {
|
||||
/*
|
||||
* Cmd: cmd | NFCID2 | NoS | Service code list | NoB | Block list
|
||||
* Rsp: rsp | NFCID2 | Status Flag 1 | Status Flag 2 | NoB | Block Data
|
||||
*/
|
||||
uint8_t *block;
|
||||
uint16_t blocknb[256];
|
||||
uint32_t idx = 0;
|
||||
uint32_t cnt = 0;
|
||||
uint32_t nbmax = 0;
|
||||
|
||||
/* Command response */
|
||||
rspData[idx++] = RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION + 1;
|
||||
|
||||
/* NFCID 2 bytes */
|
||||
if (memcmp(gNfcfNfcid, &cmdData[RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN],
|
||||
RFAL_NFCF_NFCID2_LEN) == 0) {
|
||||
memcpy(&rspData[idx], &gNfcfNfcid, RFAL_NFCF_NFCID2_LEN);
|
||||
idx += RFAL_NFCF_NFCID2_LEN;
|
||||
} else {
|
||||
/* If NFCID2 in command is different, no answer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for command errors */
|
||||
if ((cmdData[10] != 1) || ((cmdData[11] != 0x09) && (cmdData[11] != 0x0B)) ||
|
||||
(cmdData[13] == 0) || (cmdData[13] > InformationBlock[1])) {
|
||||
rspData[idx++] = 0xFF;
|
||||
rspData[idx++] = 0xFF;
|
||||
return idx;
|
||||
} else {
|
||||
rspData[idx++] = 0x00;
|
||||
rspData[idx++] = 0x00;
|
||||
}
|
||||
|
||||
/* Verify CHECK response length */
|
||||
if (rspDataLen < (11 + (cmdData[13] * T3T_BLOCK_SIZE))) {
|
||||
// platformErrorHandle(); /* Must ensure appropriate buffer */
|
||||
}
|
||||
|
||||
/* Nob */
|
||||
rspData[idx++] = cmdData[13];
|
||||
|
||||
/* Retrieving block to read */
|
||||
block = &cmdData[14];
|
||||
for (cnt = 0; cnt < cmdData[13]; cnt++) {
|
||||
/* TS T3T 5.6.1.5 Service Code List Order value SHALL be between 0 and NoS-1
|
||||
*/
|
||||
if (((*block) & 0x0F) >= cmdData[10]) {
|
||||
rspData[idx - 3] = 0xFF;
|
||||
rspData[idx - 2] = 0x80; /* TS T3T table 13 - proprietary value to
|
||||
indicate specific error conditions.*/
|
||||
return (idx - 1);
|
||||
}
|
||||
/* Check block list element size */
|
||||
if (*block & 0x80) {
|
||||
/* 2-byte Block List element */
|
||||
blocknb[cnt] = *(block + 1);
|
||||
block += 2;
|
||||
} else {
|
||||
/* 3-byte Block List element */
|
||||
blocknb[cnt] = *(block + 2); /* Little Endian Format */
|
||||
blocknb[cnt] <<= 8;
|
||||
blocknb[cnt] |= *(block + 1);
|
||||
block += 3;
|
||||
}
|
||||
|
||||
/* Return error if Blocknb > NmaxB */
|
||||
nbmax = InformationBlock[3];
|
||||
nbmax = (nbmax << 8) | InformationBlock[4];
|
||||
if (blocknb[cnt] > nbmax) {
|
||||
rspData[idx - 3] = 0xFF;
|
||||
rspData[idx - 2] = 0x70;
|
||||
return (idx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < cmdData[13]; cnt++) {
|
||||
if (blocknb[cnt] == 0x0000) {
|
||||
/* Read information block */
|
||||
memcpy(&rspData[idx], InformationBlock, sizeof(InformationBlock));
|
||||
idx += sizeof(InformationBlock);
|
||||
} else {
|
||||
/* Read ndef block */
|
||||
memcpy(&rspData[idx],
|
||||
&ndefFile[2 + ((blocknb[cnt] - 1) * T3T_BLOCK_SIZE)],
|
||||
T3T_BLOCK_SIZE);
|
||||
idx += T3T_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Manage the T3T Update answer to the reader
|
||||
*
|
||||
* @param[in] cmdData : pointer to the received command.
|
||||
* @param[in] rspData : pointer to the answer to send.
|
||||
*
|
||||
* @return Answer size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
static uint16_t card_emulation_t3t_update(uint8_t *cmdData, uint8_t *rspData) {
|
||||
/*
|
||||
* Cmd: cmd | NFCID2 | NoS | Service code list | NoB | Block list | Block Data
|
||||
* Rsp: rsp | NFCID2 | Status Flag 1 | Status Flag 2
|
||||
*/
|
||||
uint8_t *block;
|
||||
uint16_t blocknb[256];
|
||||
uint32_t idx = 0;
|
||||
uint32_t cnt = 0;
|
||||
uint32_t nbmax = 0;
|
||||
|
||||
/* Command response */
|
||||
rspData[idx++] = RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION + 1;
|
||||
|
||||
/* NFCID 2 bytes */
|
||||
if (memcmp(gNfcfNfcid, &cmdData[RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN],
|
||||
RFAL_NFCF_NFCID2_LEN) == 0) {
|
||||
memcpy(&rspData[idx], gNfcfNfcid, RFAL_NFCF_NFCID2_LEN);
|
||||
idx += RFAL_NFCF_NFCID2_LEN;
|
||||
} else {
|
||||
/* If NFCID2 in command is different, no answer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for command errors */
|
||||
if ((cmdData[10] != 1) || (cmdData[11] != 0x09) || (cmdData[13] == 0) ||
|
||||
(cmdData[13] > InformationBlock[2])) {
|
||||
rspData[idx++] = 0xFF;
|
||||
rspData[idx++] = 0xFF;
|
||||
return idx;
|
||||
} else {
|
||||
rspData[idx++] = 0x00;
|
||||
rspData[idx++] = 0x00;
|
||||
}
|
||||
|
||||
/* Retrieving block to read */
|
||||
block = &cmdData[14];
|
||||
for (cnt = 0; cnt < cmdData[13]; cnt++) {
|
||||
/* Check block list element size */
|
||||
if (*block & 0x80) {
|
||||
/* 2-byte Block List element */
|
||||
blocknb[cnt] = *(block + 1);
|
||||
block += 2;
|
||||
} else {
|
||||
/* 3-byte Block List element */
|
||||
blocknb[cnt] = *(block + 2); /* Little Endian Format */
|
||||
blocknb[cnt] <<= 8;
|
||||
blocknb[cnt] |= *(block + 1);
|
||||
block += 3;
|
||||
}
|
||||
/* Return error if Blocknb > NmaxB */
|
||||
nbmax = InformationBlock[3];
|
||||
nbmax = (nbmax << 8) | InformationBlock[4];
|
||||
if (blocknb[cnt] > nbmax) {
|
||||
rspData[idx - 2] = 0xFF;
|
||||
rspData[idx - 1] = 0x70;
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < cmdData[13]; cnt++) {
|
||||
if (blocknb[cnt] == 0x0000) {
|
||||
/* Write information block */
|
||||
memcpy(InformationBlock, block, T3T_BLOCK_SIZE);
|
||||
block += T3T_BLOCK_SIZE;
|
||||
} else {
|
||||
/* Read ndef block */
|
||||
memcpy(&ndefFile[2 + ((blocknb[cnt] - 1) * T3T_BLOCK_SIZE)], block,
|
||||
T3T_BLOCK_SIZE);
|
||||
block += T3T_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Status flag answer */
|
||||
rspData[idx++] = 0x00;
|
||||
rspData[idx++] = 0x00;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief card emulation initialize
|
||||
*
|
||||
* Initializes the CE mode
|
||||
*
|
||||
* @param[in] nfcfNfcid : The NFCID to be used in T3T CE.
|
||||
*
|
||||
* @return None
|
||||
*****************************************************************************
|
||||
*/
|
||||
void card_emulation_init(const uint8_t *nfcfNfcid) {
|
||||
if (nfcfNfcid != NULL) {
|
||||
memcpy(gNfcfNfcid, nfcfNfcid, RFAL_NFCF_NFCID2_LEN);
|
||||
}
|
||||
|
||||
memcpy(ndefFile, (uint8_t *)NdefFile, NdefFileLen);
|
||||
|
||||
/* Update AIB Ln with actual NDEF length */
|
||||
InformationBlock[12] = NdefFile[0];
|
||||
InformationBlock[13] = NdefFile[1];
|
||||
uint16_t checksum = 0;
|
||||
for (int i = 0; i < 14; i++) {
|
||||
checksum += InformationBlock[i];
|
||||
}
|
||||
InformationBlock[14] = checksum >> 8;
|
||||
InformationBlock[15] = checksum & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Demo CE T4T
|
||||
*
|
||||
* Parses the received command and computes the response to be sent back to
|
||||
* the Reader
|
||||
*
|
||||
* @param[in] rxData : pointer to the received command.
|
||||
* @param[in] rxDataLen : length of the received command.
|
||||
* @param[in] txBuf : pointer to where the response will be placed.
|
||||
* @param[in] txBufLen : size of txBuf.
|
||||
*
|
||||
* @return Response size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
uint16_t card_emulation_t4t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
|
||||
uint16_t txBufLen) {
|
||||
if ((txBuf == NULL) || (txBufLen < 2)) {
|
||||
// platformErrorHandle(); /* Must ensure appropriate buffer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((rxData != NULL) && (rxDataLen >= 4)) {
|
||||
if (rxData[0] == T4T_CLA_00) {
|
||||
switch (rxData[1]) {
|
||||
case T4T_INS_SELECT:
|
||||
return card_emulation_t4t_select(rxData, txBuf);
|
||||
|
||||
case T4T_INS_READ:
|
||||
return card_emulation_t4t_read(rxData, txBuf, txBufLen);
|
||||
|
||||
case T4T_INS_UPDATE:
|
||||
return card_emulation_t4t_update(rxData, txBuf);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function not supported ... */
|
||||
txBuf[0] = ((char)0x68);
|
||||
txBuf[1] = ((char)0x00);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @brief Demo CE T3T
|
||||
*
|
||||
* Parses the received command and computes the response to be sent back to
|
||||
* the Reader
|
||||
*
|
||||
* @param[in] rxData : pointer to the received command.
|
||||
* @param[in] rxDataLen : length of the received command.
|
||||
* @param[in] txBuf : pointer to where the response will be placed.
|
||||
* @param[in] txBufLen : size of txBuf.
|
||||
*
|
||||
* @return Response size.
|
||||
*****************************************************************************
|
||||
*/
|
||||
uint16_t card_emulation_t3t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
|
||||
uint16_t txBufLen) {
|
||||
if ((txBuf == NULL) || (txBufLen < 11)) {
|
||||
// platformErrorHandle(); /* Must ensure appropriate buffer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((rxData != NULL) && (rxDataLen >= 4)) {
|
||||
switch (rxData[1]) {
|
||||
case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION:
|
||||
return card_emulation_t3t_check(rxData, txBuf, txBufLen);
|
||||
|
||||
case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION:
|
||||
return card_emulation_t3t_update(rxData, txBuf);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function not supported ... */
|
||||
txBuf[0] = ((char)0xFF);
|
||||
txBuf[1] = ((char)0xFF);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
101
core/embed/io/nfc/st25r3916b/card_emulation.h
Normal file
101
core/embed/io/nfc/st25r3916b/card_emulation.h
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file card_emulation.h
|
||||
* @author MMY Application Team
|
||||
* @brief Implementation of Common CardEmulation parts
|
||||
******************************************************************************
|
||||
** This notice applies to any and all portions of this file
|
||||
* that are not between comment pairs USER CODE BEGIN and
|
||||
* USER CODE END. Other portions of this file, whether
|
||||
* inserted by the user or by software development tools
|
||||
* are owned by their respective copyright owners.
|
||||
*
|
||||
* COPYRIGHT(c) 2018 STMicroelectronics
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <trezor_bsp.h>
|
||||
|
||||
/** @addtogroup X-CUBE-NFC6_Applications
|
||||
* @brief Sample applications for X-NUCLEO-NFC06A1 STM32 expansion boards.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup CardEmulation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CE_CardEmul
|
||||
* @brief Card Emulation management functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* T3T Information Block Bytes offset */
|
||||
#define T3T_INFBLK_VER_OFFSET 0
|
||||
#define T3T_INFBLK_NBR_OFFSET 1
|
||||
#define T3T_INFBLK_NBW_OFFSET 2
|
||||
#define T3T_INFBLK_NMAXB_OFFSET 3
|
||||
#define T3T_INFBLK_WRITEFLAG_OFFSET 9
|
||||
#define T3T_INFBLK_RWFLAG_OFFSET 10
|
||||
#define T3T_INFBLK_LN_OFFSET 11
|
||||
#define T3T_INFBCK_CHECKSUM_OFFSET 14
|
||||
|
||||
/* T3T Information Block WriteFlag values */
|
||||
#define T3T_WRITEFLAG_OFF 0x00
|
||||
#define T3T_WRITEFLAG_ON 0x0F
|
||||
|
||||
/* T3T COMMAND OFFSET */
|
||||
#define T3T_CHECK_RESP_CMD_OFFSET 0
|
||||
#define T3T_CHECK_RESP_NFCID2_OFFSET 1
|
||||
#define T3T_CHECK_RESP_SF1_OFFSET 9
|
||||
#define T3T_CHECK_RESP_SF2_OFFSET 10
|
||||
#define T3T_CHECK_RESP_NOB_OFFSET 11
|
||||
#define T3T_CHECK_RESP_DATA_OFFSET 12
|
||||
#define T3T_UPDATE_RESP_CMD_OFFSET 0
|
||||
#define T3T_UPDATE_RESP_NFCID2_OFFSET 1
|
||||
#define T3T_UPDATE_RESP_SF1_OFFSET 9
|
||||
#define T3T_UPDATE_RESP_SF2_OFFSET 10
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @defgroup CE_CardEmul_Exported_functions
|
||||
* @{
|
||||
*/
|
||||
void card_emulation_init(const uint8_t *nfcfNfcid);
|
||||
uint16_t card_emulation_t3t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
|
||||
uint16_t txBufLen);
|
||||
uint16_t card_emulation_t4t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
|
||||
uint16_t txBufLen);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************* (C) COPYRIGHT 2018 STMicroelectronics *****END OF FILE****/
|
@ -1,92 +1,202 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "ndef.h"
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
// ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len ,ndef_message_t *message){
|
||||
#define NDEF_MESSAGE_URI_OVERHEAD 7
|
||||
|
||||
// memset(message, 0, sizeof(ndef_message_t));
|
||||
ndef_status_t ndef_parse_message(const uint8_t *buffer, size_t buffer_size,
|
||||
ndef_message_t *message) {
|
||||
memset(message, 0, sizeof(ndef_message_t));
|
||||
|
||||
// uint16_t offset = 0;
|
||||
// uint16_t remainin_len = buffer_len
|
||||
size_t remaining_len = buffer_size;
|
||||
|
||||
// while(1){
|
||||
if (remaining_len <= 0) {
|
||||
return NDEF_ERROR;
|
||||
}
|
||||
|
||||
// ndef_record_t record;
|
||||
// parse_ndef_record(buffer + offset, remainin_len , &record);
|
||||
// offset += record.payload_length;
|
||||
// Indicate TLV header
|
||||
if (*buffer == 0x3) {
|
||||
buffer++;
|
||||
remaining_len--;
|
||||
} else {
|
||||
return NDEF_ERROR; // Not a valid TLV structure
|
||||
}
|
||||
|
||||
// message->records_cnt++;
|
||||
// if(message->records_cnt >= NDEF_MAX_RECORDS){
|
||||
// break; // Max records reached
|
||||
// }
|
||||
// }
|
||||
if (remaining_len <= 0) {
|
||||
return NDEF_ERROR;
|
||||
}
|
||||
|
||||
// return NDEF_OK;
|
||||
// }
|
||||
// TLV length
|
||||
if (*buffer == 0xFF) {
|
||||
// TLV 3 byte length format
|
||||
buffer++;
|
||||
remaining_len--;
|
||||
|
||||
ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len, ndef_record_t *rec){
|
||||
if (remaining_len < 2) {
|
||||
return NDEF_ERROR;
|
||||
}
|
||||
message->message_total_len = (int16_t)(buffer[0] << 8 | buffer[1]);
|
||||
buffer = buffer + 2;
|
||||
remaining_len = remaining_len - 2;
|
||||
|
||||
} else {
|
||||
message->message_total_len = *buffer;
|
||||
buffer++;
|
||||
remaining_len--;
|
||||
}
|
||||
|
||||
if (message->message_total_len > remaining_len) {
|
||||
return NDEF_ERROR; // Not enough room to cover while message
|
||||
}
|
||||
remaining_len = message->message_total_len;
|
||||
|
||||
ndef_status_t status;
|
||||
while (1) {
|
||||
status = ndef_parse_record(buffer, remaining_len,
|
||||
&message->records[message->records_cnt]);
|
||||
|
||||
if (status != NDEF_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
buffer += message->records[message->records_cnt].record_total_len;
|
||||
remaining_len -= message->records[message->records_cnt].record_total_len;
|
||||
message->records_cnt++;
|
||||
|
||||
if (message->records_cnt >= NDEF_MAX_RECORDS) {
|
||||
break; // Max records reached
|
||||
}
|
||||
|
||||
if (remaining_len == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check TLV termination character
|
||||
if (*buffer != 0xFE) {
|
||||
return NDEF_ERROR; // Not a valid TLV structure
|
||||
}
|
||||
|
||||
return NDEF_OK;
|
||||
}
|
||||
|
||||
ndef_status_t ndef_parse_record(const uint8_t *buffer, size_t buffer_size,
|
||||
ndef_record_t *rec) {
|
||||
uint8_t bp = 0;
|
||||
|
||||
// Check if there is enough items to cover first part of the header revelaing record length
|
||||
if(len < 3){
|
||||
return NDEF_ERROR; // Not enough data to parse
|
||||
// Check if there is enough items to cover first part of the header revelaing
|
||||
// record length
|
||||
if (buffer_size < 3) {
|
||||
return NDEF_ERROR; // Not enough data to parse
|
||||
}
|
||||
|
||||
// Look at first byte, parse header
|
||||
memcpy(&(rec->header), buffer, 1);
|
||||
bp++;
|
||||
rec->header.byte = buffer[bp++];
|
||||
|
||||
if(rec->header.tnf == 0x00 || rec->header.tnf > 0x06){
|
||||
return NDEF_ERROR; // Empty or non-existing record
|
||||
if (rec->header.tnf == 0x00 || rec->header.tnf > 0x06) {
|
||||
return NDEF_ERROR; // Empty or non-existing record
|
||||
}
|
||||
|
||||
rec->type_length = buffer[bp++];
|
||||
|
||||
if(rec->header.sr){
|
||||
if (rec->header.sr) {
|
||||
rec->payload_length = buffer[bp++];
|
||||
}else{
|
||||
memcpy(&(rec->payload_length), buffer + bp, 4);
|
||||
} else {
|
||||
rec->payload_length = (uint32_t)buffer[bp];
|
||||
bp += 4;
|
||||
}
|
||||
|
||||
if(rec->header.il){
|
||||
if (rec->header.il) {
|
||||
rec->id_length = buffer[bp++];
|
||||
}else{
|
||||
} else {
|
||||
// ID length ommited
|
||||
rec->id_length = 0;
|
||||
}
|
||||
|
||||
if(rec->type_length > 0){
|
||||
memcpy(&(rec->type), buffer + bp, rec->type_length);
|
||||
if (rec->type_length > 0) {
|
||||
rec->type = buffer[bp];
|
||||
bp += rec->type_length;
|
||||
}else{
|
||||
} else {
|
||||
// Type length ommited
|
||||
rec->type = 0;
|
||||
}
|
||||
|
||||
if(rec->id_length > 0){
|
||||
memcpy(&(rec->id), buffer + bp, rec->id_length);
|
||||
bp += rec->id_length;
|
||||
}else{
|
||||
// ID length ommited
|
||||
if (rec->id_length == 0) {
|
||||
// ID ommited
|
||||
rec->id = 0;
|
||||
} else {
|
||||
rec->id = buffer[bp++];
|
||||
}
|
||||
|
||||
if(rec->payload_length > 0){
|
||||
if (rec->payload_length > 0) {
|
||||
if (rec->payload_length > NDEF_MAX_RECORD_PAYLOAD_BYTES) {
|
||||
return NDEF_ERROR; // Payload too long
|
||||
}
|
||||
|
||||
memcpy(rec->payload, buffer + bp, rec->payload_length);
|
||||
bp += rec->payload_length;
|
||||
}else{
|
||||
} else {
|
||||
// Payload length ommited;
|
||||
}
|
||||
|
||||
rec->record_total_len = bp;
|
||||
|
||||
return NDEF_OK;
|
||||
|
||||
}
|
||||
|
||||
size_t ndef_create_uri(const char *uri, uint8_t *buffer, size_t buffer_size) {
|
||||
size_t uri_len = strlen(uri);
|
||||
|
||||
if (buffer_size < (uri_len + NDEF_MESSAGE_URI_OVERHEAD)) {
|
||||
return 0; // Not enough room to create URI
|
||||
}
|
||||
|
||||
*buffer = 0x3; // TLV header
|
||||
buffer++;
|
||||
|
||||
// NDEF message length
|
||||
*buffer = uri_len + 5; // uri + record header;
|
||||
buffer++;
|
||||
|
||||
*buffer = 0xD1; // NDEF record Header
|
||||
buffer++;
|
||||
|
||||
*buffer = 0x1; // Type length
|
||||
buffer++;
|
||||
|
||||
*buffer = uri_len; // Payload length
|
||||
buffer++;
|
||||
|
||||
*buffer = 0x55; // URI type
|
||||
buffer++;
|
||||
|
||||
*buffer = 0x1; // URI abreviation
|
||||
buffer++;
|
||||
|
||||
for (uint8_t i = 0; i < uri_len; i++) {
|
||||
*buffer = uri[i];
|
||||
buffer++;
|
||||
}
|
||||
|
||||
*buffer = 0xFE; // TLV termination
|
||||
|
||||
return uri_len + NDEF_MESSAGE_URI_OVERHEAD; // return buffer len
|
||||
}
|
||||
|
@ -1,23 +1,49 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <trezor_types.h>
|
||||
|
||||
#define NDEF_MAX_RECORDS 3
|
||||
#define NDEF_MAX_RECORD_PAYLOAD_BYTES 50
|
||||
|
||||
typedef enum{
|
||||
NDEF_OK = 0,
|
||||
NDEF_ERROR = 1,
|
||||
typedef enum {
|
||||
NDEF_OK = 0,
|
||||
NDEF_ERROR = 1,
|
||||
} ndef_status_t;
|
||||
|
||||
typedef struct{
|
||||
uint8_t tnf : 3;
|
||||
uint8_t il : 1;
|
||||
uint8_t sr : 1;
|
||||
uint8_t cf : 1;
|
||||
uint8_t me : 1;
|
||||
uint8_t mb : 1;
|
||||
}ndef_record_header_t;
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t mb : 1;
|
||||
uint8_t me : 1;
|
||||
uint8_t cf : 1;
|
||||
uint8_t sr : 1;
|
||||
uint8_t il : 1;
|
||||
uint8_t tnf : 3;
|
||||
};
|
||||
uint8_t byte;
|
||||
};
|
||||
} ndef_record_header_t;
|
||||
|
||||
typedef struct{
|
||||
typedef struct {
|
||||
ndef_record_header_t header;
|
||||
uint8_t type_length;
|
||||
uint32_t payload_length;
|
||||
@ -26,13 +52,24 @@ typedef struct{
|
||||
uint8_t id;
|
||||
uint8_t payload[NDEF_MAX_RECORD_PAYLOAD_BYTES];
|
||||
uint16_t record_total_len;
|
||||
}ndef_record_t;
|
||||
} ndef_record_t;
|
||||
|
||||
typedef struct{
|
||||
uint8_t records_cnt;
|
||||
ndef_record_t records[NDEF_MAX_RECORDS];
|
||||
typedef struct {
|
||||
uint32_t message_total_len;
|
||||
uint8_t records_cnt;
|
||||
ndef_record_t records[NDEF_MAX_RECORDS];
|
||||
} ndef_message_t;
|
||||
|
||||
// ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len ,ndef_message_t *message);
|
||||
ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len, ndef_record_t *rec);
|
||||
// Parse the NDEF message from the byte buffer
|
||||
// Returns NDEF_OK if the message is parsed successfully
|
||||
ndef_status_t ndef_parse_message(const uint8_t *buffer, size_t buffer_size,
|
||||
ndef_message_t *message);
|
||||
|
||||
// Parse the NDEF record from the byte buffer
|
||||
// Returns NDEF_OK if the record is parsed successfully
|
||||
ndef_status_t ndef_parse_record(const uint8_t *buffer, size_t buffer_size,
|
||||
ndef_record_t *rec);
|
||||
|
||||
// Write the NDEF message with single URI record into the byte buffer
|
||||
// Returns the size of the byte buffer.
|
||||
size_t ndef_create_uri(const char *uri, uint8_t *buffer, size_t buffer_size);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,27 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <trezor_bsp.h>
|
||||
#pragma once
|
||||
|
||||
#ifndef TREZORHAL_NFC_INTERNAL_H
|
||||
#define TREZORHAL_NFC_INTERNAL_H
|
||||
#include <trezor_types.h>
|
||||
|
||||
HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData,
|
||||
uint8_t *rxData, uint16_t length);
|
||||
|
||||
uint32_t nfc_create_timer(uint16_t time);
|
||||
|
||||
bool nfc_timer_is_expired(uint32_t timer);
|
||||
HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *tx_data,
|
||||
uint8_t *rx_data, uint16_t length);
|
||||
|
||||
void nfc_ext_irq_set_callback(void (*cb)(void));
|
||||
|
||||
#endif
|
||||
|
@ -1,296 +1,256 @@
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* COPYRIGHT 2018 STMicroelectronics, all rights reserved
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/*! \file
|
||||
*
|
||||
* \author
|
||||
*
|
||||
* \brief Platform header file. Defining platform independent functionality.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RFAL_PLATFORM_H
|
||||
#define RFAL_PLATFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*ReturnCode
|
||||
******************************************************************************
|
||||
* INCLUDES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <trezor_bsp.h>
|
||||
#include "stm32u5xx_hal.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/systimer.h>
|
||||
|
||||
#include "io/nfc.h"
|
||||
#include "nfc_internal.h"
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* GLOBAL DEFINES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
// Device type definition
|
||||
#define ST25R3916B
|
||||
|
||||
// GPIO pin used for ST25R SPI SS
|
||||
#define ST25R_SS_PIN SPI_INSTANCE_3_NSS_PIN
|
||||
|
||||
// GPIO port used for ST25R SPI SS port
|
||||
#define ST25R_SS_PORT SPI_INSTANCE_3_NSS_PORT
|
||||
|
||||
// GPIO pin used for ST25R External Interrupt
|
||||
#define ST25R_INT_PIN NFC_INT_PIN
|
||||
|
||||
// GPIO port used for ST25R External Interrupt
|
||||
#define ST25R_INT_PORT NFC_INT_PORT
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* GLOBAL MACROS
|
||||
******************************************************************************
|
||||
*/
|
||||
#define platformProtectST25RComm() \
|
||||
NVIC_DisableIRQ(EXTI10_IRQn) // TODO: PRobably should be irq_lock instead //
|
||||
// Protect the unique access to communication
|
||||
// channel (disable IRQ on single thread)
|
||||
|
||||
#define platformUnprotectST25RComm() \
|
||||
NVIC_EnableIRQ(EXTI10_IRQn) // TODO: Use macro here /
|
||||
|
||||
#define platformProtectST25RIrqStatus() \
|
||||
platformProtectST25RComm() /*!< Protect unique access to IRQ status var - \
|
||||
IRQ disable on single thread environment (MCU) \
|
||||
; Mutex lock on a multi thread environment */
|
||||
#define platformUnprotectST25RIrqStatus() \
|
||||
platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable \
|
||||
on a single thread environment (MCU) ; Mutex \
|
||||
unlock on a multi thread environment */
|
||||
|
||||
// Turns the given GPIO High
|
||||
#define platformGpioSet(port, pin) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET)
|
||||
|
||||
// Turns the given GPIO Low
|
||||
#define platformGpioClear(port, pin) \
|
||||
HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET)
|
||||
|
||||
// Toggles the given GPIO
|
||||
#define platformGpioToggle(port, pin) HAL_GPIO_TogglePin(port, pin)
|
||||
|
||||
// Checks if the given LED is High
|
||||
#define platformGpioIsHigh(port, pin) \
|
||||
(HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET)
|
||||
|
||||
// Checks if the given LED is Low
|
||||
#define platformGpioIsLow(port, pin) (!platformGpioIsHigh(port, pin))
|
||||
|
||||
// Create a timer with the given time (ms)
|
||||
#define platformTimerCreate(t) nfc_create_timer(t)
|
||||
|
||||
// Checks if the given timer is expired
|
||||
#define platformTimerIsExpired(timer) nfc_timer_is_expired(timer)
|
||||
|
||||
// Performs a delay for the given time (ms)
|
||||
#define platformDelay(t) HAL_Delay(t)
|
||||
|
||||
// Get System Tick ( 1 tick = 1 ms)
|
||||
#define platformGetSysTick() HAL_GetTick()
|
||||
|
||||
// Asserts whether the given expression is true
|
||||
#define platformAssert(exp) assert_param(exp)
|
||||
|
||||
#define platformErrorHandle() //_Error_Handler(__FILE__, __LINE__) /*!< Global
|
||||
// error handle\trap */
|
||||
|
||||
#define platformIrqST25RSetCallback(cb) nfc_ext_irq_set_callback(cb)
|
||||
|
||||
// SPI SS\CS: Chip|Slave Select
|
||||
#define platformSpiSelect() \
|
||||
HAL_GPIO_WritePin(ST25R_SS_PORT, ST25R_SS_PIN, GPIO_PIN_RESET)
|
||||
|
||||
// SPI SS\CS: Chip|Slave Deselect
|
||||
#define platformSpiDeselect() \
|
||||
HAL_GPIO_WritePin(ST25R_SS_PORT, ST25R_SS_PIN, GPIO_PIN_SET)
|
||||
|
||||
// SPI transceive
|
||||
#define platformSpiTxRx(txBuf, rxBuf, len) \
|
||||
nfc_spi_transmit_receive(txBuf, rxBuf, len)
|
||||
|
||||
// Log method
|
||||
#define platformLog(...) // logUsart(__VA_ARGS__)
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
******************************************************************************
|
||||
*/
|
||||
extern uint8_t globalCommProtectCnt; /* Global Protection Counter provided per
|
||||
platform - instantiated in main.c */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* RFAL FEATURES CONFIGURATION
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#define RFAL_FEATURE_LISTEN_MODE \
|
||||
true /*!< Enable/Disable RFAL support for Listen Mode */
|
||||
#define RFAL_FEATURE_WAKEUP_MODE \
|
||||
true /*!< Enable/Disable RFAL support for the Wake-Up mode */
|
||||
#define RFAL_FEATURE_LOWPOWER_MODE \
|
||||
false /*!< Enable/Disable RFAL support for the Low Power mode */
|
||||
#define RFAL_FEATURE_NFCA \
|
||||
true /*!< Enable/Disable RFAL support for NFC-A (ISO14443A) */
|
||||
#define RFAL_FEATURE_NFCB \
|
||||
true /*!< Enable/Disable RFAL support for NFC-B (ISO14443B) */
|
||||
#define RFAL_FEATURE_NFCF \
|
||||
true /*!< Enable/Disable RFAL support for NFC-F (FeliCa) */
|
||||
#define RFAL_FEATURE_NFCV \
|
||||
true /*!< Enable/Disable RFAL support for NFC-V (ISO15693) */
|
||||
#define RFAL_FEATURE_T1T \
|
||||
true /*!< Enable/Disable RFAL support for T1T (Topaz) */
|
||||
#define RFAL_FEATURE_T2T true /*!< Enable/Disable RFAL support for T2T */
|
||||
#define RFAL_FEATURE_T4T true /*!< Enable/Disable RFAL support for T4T */
|
||||
#define RFAL_FEATURE_ST25TB \
|
||||
true /*!< Enable/Disable RFAL support for ST25TB \
|
||||
*/
|
||||
#define RFAL_FEATURE_ST25xV \
|
||||
true /*!< Enable/Disable RFAL support for ST25TV/ST25DV */
|
||||
#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG \
|
||||
false /*!< Enable/Disable Analog Configs to be dynamically updated (RAM) */
|
||||
#define RFAL_FEATURE_DPO \
|
||||
true /*!< Enable/Disable RFAL Dynamic Power Output support */
|
||||
#define RFAL_FEATURE_ISO_DEP \
|
||||
true /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4) */
|
||||
#define RFAL_FEATURE_ISO_DEP_POLL \
|
||||
true /*!< Enable/Disable RFAL support for Poller mode (PCD) ISO-DEP \
|
||||
(ISO14443-4) */
|
||||
#define RFAL_FEATURE_ISO_DEP_LISTEN \
|
||||
true /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP \
|
||||
(ISO14443-4) */
|
||||
#define RFAL_FEATURE_NFC_DEP \
|
||||
true /*!< Enable/Disable RFAL support for NFC-DEP (NFCIP1/P2P) */
|
||||
|
||||
#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN \
|
||||
256U /*!< ISO-DEP I-Block max length. Please use values as defined by \
|
||||
rfalIsoDepFSx */
|
||||
#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN \
|
||||
254U /*!< NFC-DEP Block/Payload length. Allowed values: 64, 128, 192, 254 */
|
||||
#define RFAL_FEATURE_NFC_RF_BUF_LEN \
|
||||
258U /*!< RF buffer length used by RFAL NFC layer */
|
||||
|
||||
#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN \
|
||||
512U /*!< ISO-DEP APDU max length. Please use multiples of I-Block max \
|
||||
length */
|
||||
#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN 512U /*!< NFC-DEP PDU max length. */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* RFAL CUSTOM SETTINGS
|
||||
******************************************************************************
|
||||
Custom analog configs are used to cope with Automatic Antenna Tuning (AAT)
|
||||
that are optimized differently for each board.
|
||||
*/
|
||||
// #define RFAL_ANALOG_CONFIG_CUSTOM /*!< Use Custom
|
||||
// Analog Configs when defined */
|
||||
|
||||
#ifndef platformProtectST25RIrqStatus
|
||||
#define platformProtectST25RIrqStatus() /*!< Protect unique access to IRQ \
|
||||
status var - IRQ disable on single \
|
||||
thread environment (MCU) ; Mutex \
|
||||
lock on a multi thread environment \
|
||||
*/
|
||||
#endif /* platformProtectST25RIrqStatus */
|
||||
|
||||
#ifndef platformUnprotectST25RIrqStatus
|
||||
#define platformUnprotectST25RIrqStatus() /*!< Unprotect the IRQ status var - \
|
||||
IRQ enable on a single thread \
|
||||
environment (MCU) ; Mutex unlock \
|
||||
on a multi thread environment */
|
||||
#endif /* platformUnprotectST25RIrqStatus */
|
||||
|
||||
#ifndef platformProtectWorker
|
||||
#define platformProtectWorker() /* Protect RFAL Worker/Task/Process from \
|
||||
concurrent execution on multi thread \
|
||||
platforms */
|
||||
#endif /* platformProtectWorker */
|
||||
|
||||
#ifndef platformUnprotectWorker
|
||||
#define platformUnprotectWorker() /* Unprotect RFAL Worker/Task/Process from \
|
||||
concurrent execution on multi thread \
|
||||
platforms */
|
||||
#endif /* platformUnprotectWorker */
|
||||
|
||||
#ifndef platformIrqST25RPinInitialize
|
||||
#define platformIrqST25RPinInitialize() /*!< Initializes ST25R IRQ pin */
|
||||
#endif /* platformIrqST25RPinInitialize */
|
||||
|
||||
#ifndef platformIrqST25RSetCallback
|
||||
#define platformIrqST25RSetCallback(cb) /*!< Sets ST25R ISR callback */
|
||||
#endif /* platformIrqST25RSetCallback */
|
||||
|
||||
#ifndef platformLedsInitialize
|
||||
#define platformLedsInitialize() /*!< Initializes the pins used as LEDs to \
|
||||
outputs */
|
||||
#endif /* platformLedsInitialize */
|
||||
|
||||
#ifndef platformLedOff
|
||||
#define platformLedOff(port, pin) /*!< Turns the given LED Off */
|
||||
#endif /* platformLedOff */
|
||||
|
||||
#ifndef platformLedOn
|
||||
#define platformLedOn(port, pin) /*!< Turns the given LED On */
|
||||
#endif /* platformLedOn */
|
||||
|
||||
#ifndef platformLedToggle
|
||||
#define platformLedToggle(port, pin) /*!< Toggles the given LED */
|
||||
#endif /* platformLedToggle */
|
||||
|
||||
#ifndef platformGetSysTick
|
||||
#define platformGetSysTick() /*!< Get System Tick ( 1 tick = 1 ms) */
|
||||
#endif /* platformGetSysTick */
|
||||
|
||||
#ifndef platformTimerDestroy
|
||||
#define platformTimerDestroy(timer) /*!< Stops and released the given timer */
|
||||
#endif /* platformTimerDestroy */
|
||||
|
||||
#ifndef platformLog
|
||||
#define platformLog(...) /*!< Log method */
|
||||
#endif /* platformLog */
|
||||
|
||||
#ifndef platformAssert
|
||||
#define platformAssert(exp) /*!< Asserts whether the given expression is true \
|
||||
*/
|
||||
#endif /* platformAssert */
|
||||
|
||||
#ifndef platformErrorHandle
|
||||
#define platformErrorHandle() /*!< Global error handler or trap */
|
||||
#endif /* platformErrorHandle */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RFAL_PLATFORM_H */
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <trezor_bsp.h>
|
||||
#include <trezor_types.h>
|
||||
|
||||
#include <sys/systick.h>
|
||||
|
||||
#include "io/nfc.h"
|
||||
|
||||
#include "nfc_internal.h"
|
||||
|
||||
// Device type definition
|
||||
#define ST25R3916B
|
||||
|
||||
// GPIO pin used for ST25R SPI SS
|
||||
#define ST25R_SS_PIN NFC_SPI_NSS_PIN
|
||||
|
||||
// GPIO port used for ST25R SPI SS port
|
||||
#define ST25R_SS_PORT NFC_SPI_NSS_PORT
|
||||
|
||||
// GPIO pin used for ST25R External Interrupt
|
||||
#define ST25R_INT_PIN NFC_INT_PIN
|
||||
|
||||
// GPIO port used for ST25R External Interrupt
|
||||
#define ST25R_INT_PORT NFC_INT_PORT
|
||||
|
||||
#define platformProtectST25RComm() NVIC_DisableIRQ(NFC_EXTI_INTERRUPT_NUM)
|
||||
|
||||
#define platformUnprotectST25RComm() NVIC_EnableIRQ(NFC_EXTI_INTERRUPT_NUM)
|
||||
|
||||
#define platformProtectST25RIrqStatus() \
|
||||
platformProtectST25RComm() /*!< Protect unique access to IRQ status var - \
|
||||
IRQ disable on single thread environment (MCU) \
|
||||
; Mutex lock on a multi thread environment */
|
||||
#define platformUnprotectST25RIrqStatus() \
|
||||
platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable \
|
||||
on a single thread environment (MCU) ; Mutex \
|
||||
unlock on a multi thread environment */
|
||||
|
||||
// Turns the given GPIO High
|
||||
#define platformGpioSet(port, pin) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET)
|
||||
|
||||
// Turns the given GPIO Low
|
||||
#define platformGpioClear(port, pin) \
|
||||
HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET)
|
||||
|
||||
// Toggles the given GPIO
|
||||
#define platformGpioToggle(port, pin) HAL_GPIO_TogglePin(port, pin)
|
||||
|
||||
// Checks if the given LED is High
|
||||
#define platformGpioIsHigh(port, pin) \
|
||||
(HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET)
|
||||
|
||||
// Checks if the given LED is Low
|
||||
#define platformGpioIsLow(port, pin) (!platformGpioIsHigh(port, pin))
|
||||
|
||||
// Create a timer with the given time (ms)
|
||||
#define platformTimerCreate(t) ticks_timeout(t)
|
||||
|
||||
// Checks if the given timer is expired
|
||||
#define platformTimerIsExpired(timer) ticks_expired(timer)
|
||||
|
||||
// Performs a delay for the given time (ms)
|
||||
#define platformDelay(t) HAL_Delay(t)
|
||||
|
||||
// Get System Tick ( 1 tick = 1 ms)
|
||||
#define platformGetSysTick() HAL_GetTick()
|
||||
|
||||
// Asserts whether the given expression is true
|
||||
#define platformAssert(exp) assert_param(exp)
|
||||
|
||||
#define platformErrorHandle() //_Error_Handler(__FILE__, __LINE__) /*!< Global
|
||||
// error handle\trap */
|
||||
|
||||
#define platformIrqST25RSetCallback(cb) nfc_ext_irq_set_callback(cb)
|
||||
|
||||
// SPI SS\CS: Chip|Slave Select
|
||||
#define platformSpiSelect() \
|
||||
HAL_GPIO_WritePin(ST25R_SS_PORT, ST25R_SS_PIN, GPIO_PIN_RESET)
|
||||
|
||||
// SPI SS\CS: Chip|Slave Deselect
|
||||
#define platformSpiDeselect() \
|
||||
HAL_GPIO_WritePin(ST25R_SS_PORT, ST25R_SS_PIN, GPIO_PIN_SET)
|
||||
|
||||
// SPI transceive
|
||||
#define platformSpiTxRx(txBuf, rxBuf, len) \
|
||||
nfc_spi_transmit_receive(txBuf, rxBuf, len)
|
||||
|
||||
// Log method
|
||||
#define platformLog(...) // logUsart(__VA_ARGS__)
|
||||
|
||||
extern uint8_t globalCommProtectCnt; /* Global Protection Counter provided per
|
||||
platform - instantiated in main.c */
|
||||
|
||||
#define RFAL_FEATURE_LISTEN_MODE \
|
||||
true /*!< Enable/Disable RFAL support for Listen Mode */
|
||||
#define RFAL_FEATURE_WAKEUP_MODE \
|
||||
true /*!< Enable/Disable RFAL support for the Wake-Up mode */
|
||||
#define RFAL_FEATURE_LOWPOWER_MODE \
|
||||
false /*!< Enable/Disable RFAL support for the Low Power mode */
|
||||
#define RFAL_FEATURE_NFCA \
|
||||
true /*!< Enable/Disable RFAL support for NFC-A (ISO14443A) */
|
||||
#define RFAL_FEATURE_NFCB \
|
||||
true /*!< Enable/Disable RFAL support for NFC-B (ISO14443B) */
|
||||
#define RFAL_FEATURE_NFCF \
|
||||
true /*!< Enable/Disable RFAL support for NFC-F (FeliCa) */
|
||||
#define RFAL_FEATURE_NFCV \
|
||||
true /*!< Enable/Disable RFAL support for NFC-V (ISO15693) */
|
||||
#define RFAL_FEATURE_T1T \
|
||||
true /*!< Enable/Disable RFAL support for T1T (Topaz) */
|
||||
#define RFAL_FEATURE_T2T true /*!< Enable/Disable RFAL support for T2T */
|
||||
#define RFAL_FEATURE_T4T true /*!< Enable/Disable RFAL support for T4T */
|
||||
#define RFAL_FEATURE_ST25TB \
|
||||
true /*!< Enable/Disable RFAL support for ST25TB \
|
||||
*/
|
||||
#define RFAL_FEATURE_ST25xV \
|
||||
true /*!< Enable/Disable RFAL support for ST25TV/ST25DV */
|
||||
#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG \
|
||||
false /*!< Enable/Disable Analog Configs to be dynamically updated (RAM) */
|
||||
#define RFAL_FEATURE_DPO \
|
||||
true /*!< Enable/Disable RFAL Dynamic Power Output support */
|
||||
#define RFAL_FEATURE_ISO_DEP \
|
||||
true /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4) */
|
||||
#define RFAL_FEATURE_ISO_DEP_POLL \
|
||||
true /*!< Enable/Disable RFAL support for Poller mode (PCD) ISO-DEP \
|
||||
(ISO14443-4) */
|
||||
#define RFAL_FEATURE_ISO_DEP_LISTEN \
|
||||
true /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP \
|
||||
(ISO14443-4) */
|
||||
#define RFAL_FEATURE_NFC_DEP \
|
||||
true /*!< Enable/Disable RFAL support for NFC-DEP (NFCIP1/P2P) */
|
||||
|
||||
#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN \
|
||||
256U /*!< ISO-DEP I-Block max length. Please use values as defined by \
|
||||
rfalIsoDepFSx */
|
||||
#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN \
|
||||
254U /*!< NFC-DEP Block/Payload length. Allowed values: 64, 128, 192, 254 */
|
||||
#define RFAL_FEATURE_NFC_RF_BUF_LEN \
|
||||
258U /*!< RF buffer length used by RFAL NFC layer */
|
||||
|
||||
#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN \
|
||||
512U /*!< ISO-DEP APDU max length. Please use multiples of I-Block max \
|
||||
length */
|
||||
#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN 512U /*!< NFC-DEP PDU max length. */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* RFAL CUSTOM SETTINGS
|
||||
******************************************************************************
|
||||
Custom analog configs are used to cope with Automatic Antenna Tuning (AAT)
|
||||
that are optimized differently for each board.
|
||||
*/
|
||||
// #define RFAL_ANALOG_CONFIG_CUSTOM /*!< Use Custom
|
||||
// Analog Configs when defined */
|
||||
|
||||
#ifndef platformProtectST25RIrqStatus
|
||||
#define platformProtectST25RIrqStatus() /*!< Protect unique access to IRQ \
|
||||
status var - IRQ disable on single \
|
||||
thread environment (MCU) ; Mutex \
|
||||
lock on a multi thread environment \
|
||||
*/
|
||||
#endif /* platformProtectST25RIrqStatus */
|
||||
|
||||
#ifndef platformUnprotectST25RIrqStatus
|
||||
#define platformUnprotectST25RIrqStatus() /*!< Unprotect the IRQ status var - \
|
||||
IRQ enable on a single thread \
|
||||
environment (MCU) ; Mutex unlock \
|
||||
on a multi thread environment */
|
||||
#endif /* platformUnprotectST25RIrqStatus */
|
||||
|
||||
#ifndef platformProtectWorker
|
||||
#define platformProtectWorker() /* Protect RFAL Worker/Task/Process from \
|
||||
concurrent execution on multi thread \
|
||||
platforms */
|
||||
#endif /* platformProtectWorker */
|
||||
|
||||
#ifndef platformUnprotectWorker
|
||||
#define platformUnprotectWorker() /* Unprotect RFAL Worker/Task/Process from \
|
||||
concurrent execution on multi thread \
|
||||
platforms */
|
||||
#endif /* platformUnprotectWorker */
|
||||
|
||||
#ifndef platformIrqST25RPinInitialize
|
||||
#define platformIrqST25RPinInitialize() /*!< Initializes ST25R IRQ pin */
|
||||
#endif /* platformIrqST25RPinInitialize */
|
||||
|
||||
#ifndef platformIrqST25RSetCallback
|
||||
#define platformIrqST25RSetCallback(cb) /*!< Sets ST25R ISR callback */
|
||||
#endif /* platformIrqST25RSetCallback */
|
||||
|
||||
#ifndef platformLedsInitialize
|
||||
#define platformLedsInitialize() /*!< Initializes the pins used as LEDs to \
|
||||
outputs */
|
||||
#endif /* platformLedsInitialize */
|
||||
|
||||
#ifndef platformLedOff
|
||||
#define platformLedOff(port, pin) /*!< Turns the given LED Off */
|
||||
#endif /* platformLedOff */
|
||||
|
||||
#ifndef platformLedOn
|
||||
#define platformLedOn(port, pin) /*!< Turns the given LED On */
|
||||
#endif /* platformLedOn */
|
||||
|
||||
#ifndef platformLedToggle
|
||||
#define platformLedToggle(port, pin) /*!< Toggles the given LED */
|
||||
#endif /* platformLedToggle */
|
||||
|
||||
#ifndef platformGetSysTick
|
||||
#define platformGetSysTick() /*!< Get System Tick ( 1 tick = 1 ms) */
|
||||
#endif /* platformGetSysTick */
|
||||
|
||||
#ifndef platformTimerDestroy
|
||||
#define platformTimerDestroy(timer) /*!< Stops and released the given timer */
|
||||
#endif /* platformTimerDestroy */
|
||||
|
||||
#ifndef platformLog
|
||||
#define platformLog(...) /*!< Log method */
|
||||
#endif /* platformLog */
|
||||
|
||||
#ifndef platformAssert
|
||||
#define platformAssert(exp) /*!< Asserts whether the given expression is true \
|
||||
*/
|
||||
#endif /* platformAssert */
|
||||
|
||||
#ifndef platformErrorHandle
|
||||
#define platformErrorHandle() /*!< Global error handler or trap */
|
||||
#endif /* platformErrorHandle */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -160,22 +160,24 @@
|
||||
#define NRF_OUT_FW_RUNNING_PORT GPIOE
|
||||
#define NRF_OUT_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
|
||||
|
||||
#define SPI_INSTANCE_3 SPI3
|
||||
#define SPI_INSTANCE_3_PIN_AF GPIO_AF6_SPI3
|
||||
#define SPI_INSTANCE_3_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
|
||||
#define SPI_INSTANCE_3_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
|
||||
#define SPI_INSTANCE_3_MISO_PORT GPIOB
|
||||
#define SPI_INSTANCE_3_MISO_PIN GPIO_PIN_4
|
||||
#define SPI_INSTANCE_3_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define SPI_INSTANCE_3_MOSI_PORT GPIOB
|
||||
#define SPI_INSTANCE_3_MOSI_PIN GPIO_PIN_5
|
||||
#define SPI_INSTANCE_3_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define SPI_INSTANCE_3_SCK_PORT GPIOG
|
||||
#define SPI_INSTANCE_3_SCK_PIN GPIO_PIN_9
|
||||
#define SPI_INSTANCE_3_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
#define SPI_INSTANCE_3_NSS_PORT GPIOG
|
||||
#define SPI_INSTANCE_3_NSS_PIN GPIO_PIN_12
|
||||
#define SPI_INSTANCE_3_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
#define NFC_SPI_INSTANCE SPI3
|
||||
#define NFC_SPI_PIN_AF GPIO_AF6_SPI3
|
||||
#define NFC_SPI_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
|
||||
#define NFC_SPI_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
|
||||
#define NFC_SPI_FORCE_RESET __HAL_RCC_SPI3_FORCE_RESET
|
||||
#define NFC_SPI_RELEASE_RESET __HAL_RCC_SPI3_RELEASE_RESET
|
||||
#define NFC_SPI_MISO_PORT GPIOB
|
||||
#define NFC_SPI_MISO_PIN GPIO_PIN_4
|
||||
#define NFC_SPI_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define NFC_SPI_MOSI_PORT GPIOB
|
||||
#define NFC_SPI_MOSI_PIN GPIO_PIN_5
|
||||
#define NFC_SPI_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define NFC_SPI_SCK_PORT GPIOG
|
||||
#define NFC_SPI_SCK_PIN GPIO_PIN_9
|
||||
#define NFC_SPI_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
#define NFC_SPI_NSS_PORT GPIOG
|
||||
#define NFC_SPI_NSS_PIN GPIO_PIN_12
|
||||
#define NFC_SPI_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
|
||||
#define NFC_INT_PIN GPIO_PIN_10
|
||||
#define NFC_INT_PORT GPIOG
|
||||
|
@ -160,4 +160,31 @@
|
||||
#define NRF_OUT_FW_RUNNING_PORT GPIOE
|
||||
#define NRF_OUT_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
|
||||
|
||||
#define NFC_SPI_INSTANCE SPI3
|
||||
#define NFC_SPI_PIN_AF GPIO_AF6_SPI3
|
||||
#define NFC_SPI_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
|
||||
#define NFC_SPI_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
|
||||
#define NFC_SPI_FORCE_RESET __HAL_RCC_SPI3_FORCE_RESET
|
||||
#define NFC_SPI_RELEASE_RESET __HAL_RCC_SPI3_RELEASE_RESET
|
||||
#define NFC_SPI_MISO_PORT GPIOB
|
||||
#define NFC_SPI_MISO_PIN GPIO_PIN_4
|
||||
#define NFC_SPI_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define NFC_SPI_MOSI_PORT GPIOB
|
||||
#define NFC_SPI_MOSI_PIN GPIO_PIN_5
|
||||
#define NFC_SPI_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define NFC_SPI_SCK_PORT GPIOG
|
||||
#define NFC_SPI_SCK_PIN GPIO_PIN_9
|
||||
#define NFC_SPI_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
#define NFC_SPI_NSS_PORT GPIOG
|
||||
#define NFC_SPI_NSS_PIN GPIO_PIN_12
|
||||
#define NFC_SPI_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
|
||||
#define NFC_INT_PIN GPIO_PIN_10
|
||||
#define NFC_INT_PORT GPIOG
|
||||
#define NFC_INT_PIN_CLK_ENA __HAL_RCC_GPIOG_CLK_ENABLE
|
||||
#define NFC_EXTI_INTERRUPT_GPIOSEL EXTI_GPIOG
|
||||
#define NFC_EXTI_INTERRUPT_LINE EXTI_LINE_10
|
||||
#define NFC_EXTI_INTERRUPT_NUM EXTI10_IRQn
|
||||
#define NFC_EXTI_INTERRUPT_HANDLER EXTI10_IRQHandler
|
||||
|
||||
#endif // TREZOR_T3W1_REVA_H_
|
||||
|
@ -771,3 +771,38 @@ wpc-update
|
||||
# Updating STWLC38...
|
||||
# WPC update completed 800 ms
|
||||
```
|
||||
|
||||
### nfc-read-card
|
||||
Activate the NFC in reader mode for a given time. Read general information from firstly discovered NFC tag or exits on timeout.
|
||||
|
||||
Example:
|
||||
```
|
||||
nfc-read-card <timeout_seconds>
|
||||
# NFC activated in reader mode for <timeout_seconds> seconds.
|
||||
# NFC card detected.
|
||||
# NFC Type A: UID: %s
|
||||
OK
|
||||
```
|
||||
|
||||
|
||||
### nfc-emulate-card
|
||||
Activate NFC in Card Emulator mode for given time.
|
||||
|
||||
Example:
|
||||
```
|
||||
nfc-emulate-card <timeout_seconds>
|
||||
# Emulation started for <timeout_seconds>
|
||||
# Emulation over
|
||||
OK
|
||||
```
|
||||
|
||||
### nfc-write-card
|
||||
Activates the NFC reader for given time. Writes the NDEF URI message into the first discovered NFC tag type A or exits on timeout.
|
||||
|
||||
Example:
|
||||
```
|
||||
nfc-write_card <timeout_seconds>
|
||||
# NFC reader on, put the card on the reader (timeout <timeout_seconds> s)
|
||||
# Writting URI to NFC tag 7AF403
|
||||
OK
|
||||
```
|
||||
|
266
core/embed/projects/prodtest/cmd/prodtest_nfc.c
Normal file
266
core/embed/projects/prodtest/cmd/prodtest_nfc.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_NFC
|
||||
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <io/nfc.h>
|
||||
#include <rtl/cli.h>
|
||||
#include <sys/systick.h>
|
||||
|
||||
static nfc_dev_info_t dev_info = {0};
|
||||
|
||||
static void prodtest_nfc_read_card(cli_t* cli) {
|
||||
uint32_t timeout = 0;
|
||||
memset(&dev_info, 0, sizeof(dev_info));
|
||||
|
||||
if (cli_has_arg(cli, "timeout") &&
|
||||
!cli_arg_uint32(cli, "timeout", &timeout)) {
|
||||
cli_error_arg(cli, "Expecting timeout argument.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 1) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
nfc_status_t ret = nfc_init();
|
||||
|
||||
if (ret != NFC_OK) {
|
||||
cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
|
||||
goto cleanup;
|
||||
} else {
|
||||
cli_trace(cli, "NFC activated in reader mode for %d ms.", timeout);
|
||||
}
|
||||
|
||||
nfc_register_tech(NFC_POLLER_TECH_A | NFC_POLLER_TECH_B | NFC_POLLER_TECH_F |
|
||||
NFC_POLLER_TECH_V);
|
||||
nfc_activate_stm();
|
||||
|
||||
nfc_event_t nfc_event;
|
||||
uint32_t expire_time = ticks_timeout(timeout);
|
||||
|
||||
while (true) {
|
||||
if (ticks_expired(expire_time)) {
|
||||
cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
nfc_status_t nfc_status = nfc_get_event(&nfc_event);
|
||||
|
||||
if (nfc_status != NFC_OK) {
|
||||
cli_error(cli, CLI_ERROR, "NFC error");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (nfc_event == NFC_EVENT_ACTIVATED) {
|
||||
nfc_dev_read_info(&dev_info);
|
||||
nfc_dev_deactivate();
|
||||
break;
|
||||
}
|
||||
|
||||
if (cli_aborted(cli)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cli_trace(cli, "NFC card detected.");
|
||||
|
||||
switch (dev_info.type) {
|
||||
case NFC_DEV_TYPE_A:
|
||||
cli_trace(cli, "NFC Type A: UID: %s", dev_info.uid);
|
||||
break;
|
||||
case NFC_DEV_TYPE_B:
|
||||
cli_trace(cli, "NFC Type B: UID: %s", dev_info.uid);
|
||||
break;
|
||||
case NFC_DEV_TYPE_F:
|
||||
cli_trace(cli, "NFC Type F: UID: %s", dev_info.uid);
|
||||
break;
|
||||
case NFC_DEV_TYPE_V:
|
||||
cli_trace(cli, "NFC Type V: UID: %s", dev_info.uid);
|
||||
break;
|
||||
case NFC_DEV_TYPE_ST25TB:
|
||||
cli_trace(cli, "NFC Type ST25TB: UID: %s", dev_info.uid);
|
||||
break;
|
||||
case NFC_DEV_TYPE_AP2P:
|
||||
cli_trace(cli, "NFC Type AP2P: UID: %s", dev_info.uid);
|
||||
break;
|
||||
case NFC_DEV_TYPE_UNKNOWN:
|
||||
cli_error(cli, CLI_ERROR_ABORT, "NFC Type UNKNOWN");
|
||||
goto cleanup;
|
||||
return;
|
||||
|
||||
default:
|
||||
cli_error(cli, CLI_ERROR_ABORT, "NFC Type UNKNOWN");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
|
||||
cleanup:
|
||||
nfc_deinit();
|
||||
}
|
||||
|
||||
static void prodtest_nfc_emulate_card(cli_t* cli) {
|
||||
uint32_t timeout = 0;
|
||||
|
||||
if (cli_has_arg(cli, "timeout") &&
|
||||
!cli_arg_uint32(cli, "timeout", &timeout)) {
|
||||
cli_error_arg(cli, "Expecting timeout argument.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 1) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
nfc_status_t ret = nfc_init();
|
||||
|
||||
if (ret != NFC_OK) {
|
||||
cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
|
||||
goto cleanup;
|
||||
} else {
|
||||
cli_trace(cli, "Emulation started for %d ms", timeout);
|
||||
}
|
||||
|
||||
nfc_register_tech(NFC_CARD_EMU_TECH_A);
|
||||
nfc_activate_stm();
|
||||
|
||||
uint32_t expire_time = ticks_timeout(timeout);
|
||||
nfc_event_t nfc_event;
|
||||
|
||||
while (!ticks_expired(expire_time)) {
|
||||
nfc_status_t nfc_status = nfc_get_event(&nfc_event);
|
||||
|
||||
if (nfc_status != NFC_OK) {
|
||||
cli_error(cli, CLI_ERROR, "NFC error");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (cli_aborted(cli)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cli_trace(cli, "Emulation over");
|
||||
|
||||
cli_ok(cli, "");
|
||||
|
||||
cleanup:
|
||||
nfc_deinit();
|
||||
}
|
||||
|
||||
static void prodtest_nfc_write_card(cli_t* cli) {
|
||||
uint32_t timeout = 0;
|
||||
memset(&dev_info, 0, sizeof(dev_info));
|
||||
|
||||
if (cli_has_arg(cli, "timeout") &&
|
||||
!cli_arg_uint32(cli, "timeout", &timeout)) {
|
||||
cli_error_arg(cli, "Expecting timeout argument.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 1) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
nfc_status_t ret = nfc_init();
|
||||
|
||||
if (ret != NFC_OK) {
|
||||
cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
|
||||
goto cleanup;
|
||||
} else {
|
||||
cli_trace(cli, "NFC reader on, put the card on the reader (timeout %d ms)",
|
||||
timeout);
|
||||
}
|
||||
|
||||
nfc_register_tech(NFC_POLLER_TECH_A | NFC_POLLER_TECH_B | NFC_POLLER_TECH_F |
|
||||
NFC_POLLER_TECH_V);
|
||||
nfc_activate_stm();
|
||||
|
||||
nfc_event_t nfc_event;
|
||||
uint32_t expire_time = ticks_timeout(timeout);
|
||||
|
||||
while (true) {
|
||||
if (ticks_expired(expire_time)) {
|
||||
cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
nfc_status_t nfc_status = nfc_get_event(&nfc_event);
|
||||
|
||||
if (nfc_status != NFC_OK) {
|
||||
cli_error(cli, CLI_ERROR_FATAL, "NFC error");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (nfc_event == NFC_EVENT_ACTIVATED) {
|
||||
nfc_dev_read_info(&dev_info);
|
||||
|
||||
if (dev_info.type != NFC_DEV_TYPE_A) {
|
||||
cli_error(cli, CLI_ERROR_ABORT, "Only NFC type A cards supported");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Writting URI to NFC tag %s", dev_info.uid);
|
||||
nfc_dev_write_ndef_uri();
|
||||
|
||||
nfc_dev_deactivate();
|
||||
break;
|
||||
}
|
||||
|
||||
if (cli_aborted(cli)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
|
||||
cleanup:
|
||||
nfc_deinit();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "nfc-read-card",
|
||||
.func = prodtest_nfc_read_card,
|
||||
.info = "Activate NFC in reader mode",
|
||||
.args = "<timeout>"
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "nfc-emulate-card",
|
||||
.func = prodtest_nfc_emulate_card,
|
||||
.info = "Activate NFC in card emulation (CE) mode",
|
||||
.args = "<timeout>"
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "nfc-write-card",
|
||||
.func = prodtest_nfc_write_card,
|
||||
.info = "Activate NFC in reader mode and write a URI to the attached card",
|
||||
.args = "<timeout>"
|
||||
);
|
||||
|
||||
#endif // USE_NFC
|
@ -94,6 +94,7 @@ def configure(
|
||||
if "nfc" in features_wanted:
|
||||
sources += ["embed/io/nfc/st25r3916b/nfc.c"]
|
||||
sources += ["embed/io/nfc/st25r3916b/ndef.c"]
|
||||
sources += ["embed/io/nfc/st25r3916b/card_emulation.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/st25r3916/rfal_rfst25r3916.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_analogConfig.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfc.c"]
|
||||
|
@ -91,6 +91,35 @@ def configure(
|
||||
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_uart_ex.c",
|
||||
]
|
||||
|
||||
if "nfc" in features_wanted:
|
||||
sources += ["embed/io/nfc/st25r3916b/nfc.c"]
|
||||
sources += ["embed/io/nfc/st25r3916b/ndef.c"]
|
||||
sources += ["embed/io/nfc/st25r3916b/card_emulation.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/st25r3916/rfal_rfst25r3916.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_analogConfig.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfc.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfca.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfcb.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfcf.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfcv.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_isoDep.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_nfcDep.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_st25tb.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_t1t.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_t2t.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_iso15693_2.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/rfal_crc.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916_com.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916_led.c"]
|
||||
sources += ["embed/io/nfc/rfal/source/st25r3916/st25r3916_irq.c"]
|
||||
paths += ["embed/io/nfc/inc/"]
|
||||
paths += ["embed/io/nfc/st25r3916b/"]
|
||||
paths += ["embed/io/nfc/rfal/source"]
|
||||
paths += ["embed/io/nfc/rfal/source/st25r3916"]
|
||||
paths += ["embed/io/nfc/rfal/include/"]
|
||||
defines += [("USE_NFC", "1")]
|
||||
|
||||
if "optiga" in features_wanted:
|
||||
sources += ["embed/sec/optiga/stm32/optiga_hal.c"]
|
||||
sources += ["embed/sec/optiga/optiga.c"]
|
||||
|
@ -10,3 +10,4 @@
|
||||
^\./crypto/sha3
|
||||
^\./legacy/vendor
|
||||
^\./core/embed/sys/systemview/stm32
|
||||
^\./core/embed/io/nfc/rfal
|
||||
|
Loading…
Reference in New Issue
Block a user