1
0
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:
kopecdav 2025-01-31 10:15:00 +01:00 committed by kopecdav
parent fc2cf1535e
commit bdc8dbffe3
17 changed files with 2190 additions and 926 deletions

View File

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

View File

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

View File

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

View 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****/

View 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****/

View 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
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

@ -10,3 +10,4 @@
^\./crypto/sha3
^\./legacy/vendor
^\./core/embed/sys/systemview/stm32
^\./core/embed/io/nfc/rfal