diff --git a/.editorconfig b/.editorconfig index cf375163a6..aaa22ea26c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -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 diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index b08d2d6201..93d0a3d5ce 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -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', diff --git a/core/embed/io/nfc/inc/io/nfc.h b/core/embed/io/nfc/inc/io/nfc.h index 51953a963d..736e07f7d7 100644 --- a/core/embed/io/nfc/inc/io/nfc.h +++ b/core/embed/io/nfc/inc/io/nfc.h @@ -17,23 +17,37 @@ * along with this program. If not, see . */ -#ifndef TREZORHAL_NFC_H -#define TREZORHAL_NFC_H +#pragma once -#include -#include +#include + +#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); diff --git a/core/embed/io/nfc/st25r3916b/card_emulation.c b/core/embed/io/nfc/st25r3916b/card_emulation.c new file mode 100644 index 0000000000..11aa173b3a --- /dev/null +++ b/core/embed/io/nfc/st25r3916b/card_emulation.c @@ -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
+ * T4T_VNo : Indicates the Mapping Version
+ * MLe high : Max R-APDU size
+ * MLc high : Max C-APDU size
+ * NDEF FCI T: Indicates the NDEF-File_Ctrl_TLV
+ * NDEF FCI L: The length of the V-field
+ * NDEF FCI V1: NDEF File Identifier
+ * NDEF FCI V2: NDEF File size
+ * NDEF FCI V3: NDEF Read AC
+ * NDEF FCI V4: NDEF Write AC
+ */ +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
+ * NDEF Header: MB,ME,SR,Well known Type
+ * NDEF type length
+ * NDEF payload length
+ * NDEF Type : URI
+ * NDEF URI abreviation field : http://www.
+ * NDEF URI string : st.com/st25-demo
+ */ +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
+ * Nbr : Indicates the number of blocks that can be read
+ * Nbw : Indicates the number of blocks that can be written
+ * NmaxB : Indicates the maximum number of blocks available for NDEF data
+ * WriteFlag : Indicates whether a previous NDEF write procedure has finished or + * not
RWFlag : Indicates data can be updated or not
Ln : Is the size + * of the actual stored NDEF data in bytes
Checksum : allows the + * Reader/Writer to check whether the Attribute Data are correct
+ */ +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****/ diff --git a/core/embed/io/nfc/st25r3916b/card_emulation.h b/core/embed/io/nfc/st25r3916b/card_emulation.h new file mode 100644 index 0000000000..eebcb393c5 --- /dev/null +++ b/core/embed/io/nfc/st25r3916b/card_emulation.h @@ -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 + +/** @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****/ diff --git a/core/embed/io/nfc/st25r3916b/ndef.c b/core/embed/io/nfc/st25r3916b/ndef.c index ee10eb45b4..83004ab7df 100644 --- a/core/embed/io/nfc/st25r3916b/ndef.c +++ b/core/embed/io/nfc/st25r3916b/ndef.c @@ -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 . + */ - -#include -#include #include "ndef.h" +#include -// 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 +} diff --git a/core/embed/io/nfc/st25r3916b/ndef.h b/core/embed/io/nfc/st25r3916b/ndef.h index c5e78438a5..91be63ee2f 100644 --- a/core/embed/io/nfc/st25r3916b/ndef.h +++ b/core/embed/io/nfc/st25r3916b/ndef.h @@ -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 . + */ +#pragma once + +#include #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); diff --git a/core/embed/io/nfc/st25r3916b/nfc.c b/core/embed/io/nfc/st25r3916b/nfc.c index 5223503e71..44352779a9 100644 --- a/core/embed/io/nfc/st25r3916b/nfc.c +++ b/core/embed/io/nfc/st25r3916b/nfc.c @@ -1,32 +1,60 @@ +/* + * 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 . + */ -#include -#include #include #include -#include "../inc/io/nfc.h" -#include "nfc_internal.h" -#include "rfal_platform.h" +#include +#include +#include +#include + +#include "card_emulation.h" #include "ndef.h" +#include "nfc_internal.h" +#include "rfal_isoDep.h" +#include "rfal_nfc.h" +#include "rfal_nfca.h" +#include "rfal_platform.h" +#include "rfal_rf.h" +#include "rfal_t2t.h" +#include "rfal_utils.h" -#include "../rfal/include/rfal_isoDep.h" -#include "../rfal/include/rfal_nfc.h" -#include "../rfal/include/rfal_nfca.h" -#include "../rfal/include/rfal_rf.h" -#include "../rfal/include/rfal_t2t.h" -#include "../rfal/include/rfal_utils.h" -#include "prodtest_common.h" +// NFC-A SEL_RES configured for Type 4A Tag Platform +#define LM_SEL_RES 0x20U -#include "stm32u5xx_hal.h" +// NFC-F SENSF_RES configured for Type 3 Tag Platform +#define LM_NFCID2_BYTE1 0x02U -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" +// NFC-F System Code byte 1 +#define LM_SC_BYTE1 0x12U -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" +// NFC-F System Code byte 2 +#define LM_SC_BYTE2 0xFCU -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +// NFC-F PAD0 +#define LM_PAD0 0x00U + +typedef enum { + NFC_STATE_ACTIVE, + NFC_STATE_NOT_ACTIVE, +} nfc_state_t; typedef struct { bool initialized; @@ -35,218 +63,68 @@ typedef struct { // NFC IRQ pin callback void (*nfc_irq_callback)(void); EXTI_HandleTypeDef hEXTI; - rfalNfcDiscoverParam disc_params; + bool rfal_initialized; + nfc_state_t last_nfc_state; } st25r3916b_driver_t; static st25r3916b_driver_t g_st25r3916b_driver = { .initialized = false, + .rfal_initialized = false, }; -static void parse_tag_header(uint8_t *data, uint16_t dataLen); - -/* Definition of possible states the demo state machine could have */ -#define DEMO_ST_CE_NOTINIT 0 /*!< Demo State: Not initialized */ -#define DEMO_ST_CE_START_DISCOVERY 1 /*!< Demo State: Start Discovery */ -#define DEMO_ST_CE_DISCOVERY 2 /*!< Demo State: Discovery */ -#define DEMO_ST_CE_TAG_OPERATION 3 /*!< Demo State: Discovery */ - -/* Definition of possible states the demo state machine could have */ -#define DEMO_ST_NOTINIT 0 /*!< Demo State: Not initialized */ -#define DEMO_ST_START_DISCOVERY 1 /*!< Demo State: Start Discovery */ -#define DEMO_ST_DISCOVERY 2 /*!< Demo State: Discovery */ - -#define DEMO_NFCV_BLOCK_LEN 4 /*!< NFCV Block len */ -#define DEMO_NFCV_USE_SELECT_MODE \ - false /*!< NFCV demonstrate select mode */ - -/* -****************************************************************************** -* GLOBAL DEFINES -****************************************************************************** -*/ - - - -/* Definition of possible states the demo state machine could have */ -#define DEMO_ST_NOTINIT 0 /*!< Demo State: Not initialized | Stopped */ -#define DEMO_ST_START_DISCOVERY 1 /*!< Demo State: Start Discovery */ -#define DEMO_ST_DISCOVERY 2 /*!< Demo State: Discovery */ - -#define DEMO_NFCV_BLOCK_LEN 4 /*!< NFCV Block len */ - -#define DEMO_NFCV_USE_SELECT_MODE \ - false /*!< NFCV demonstrate select mode */ -#define DEMO_NFCV_WRITE_TAG false /*!< NFCV demonstrate Write Single Block */ - -/* Definition of various Listen Mode constants */ -#if defined(DEMO_LISTEN_MODE_TARGET) -#define DEMO_LM_SEL_RES \ - 0x40U /*!> 4) & 0xF]; - *pout++ = hex[(*pin++) & 0xF]; - } - *pout++ = hex[(*pin >> 4) & 0xF]; - *pout++ = hex[(*pin) & 0xF]; - *pout = 0; - } - - hexStrIdx++; - hexStrIdx %= MAX_HEX_STR; - - return hexStr[idx]; - } -} - -typedef struct{ +typedef struct { uint8_t UID[7]; uint8_t BCC[1]; uint8_t SYSTEM_AREA[2]; - union{ + union { uint8_t CC[4]; - struct{ + struct { uint8_t CC_MAGIC_NUMBER; uint8_t CC_VERSION; uint8_t CC_SIZE; uint8_t CC_ACCESS_CONDITION; }; }; -} type2_header_t; +} nfc_device_header_t2t_t; + +// P2P communication data +static const uint8_t nfcid3[] = {0x01, 0xFE, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A}; +static const uint8_t gb[] = {0x46, 0x66, 0x6d, 0x01, 0x01, 0x11, 0x02, + 0x02, 0x07, 0x80, 0x03, 0x02, 0x00, 0x03, + 0x04, 0x01, 0x32, 0x07, 0x01, 0x03}; + +// NFC-A CE config +// 4-byte UIDs with first byte 0x08 would need random number for the subsequent +// 3 bytes. 4-byte UIDs with first byte 0x*F are Fixed number, not unique, use +// for this demo 7-byte UIDs need a manufacturer ID and need to assure +// uniqueness of the rest. +static const uint8_t ce_nfca_nfcid[] = { + 0x1, 0x2, 0x3, 0x4}; // =_STM, 5F 53 54 4D NFCID1 / UID (4 bytes) +static const uint8_t ce_nfca_sens_res[] = { + 0x02, 0x00}; // SENS_RES / ATQA for 4-byte UID +static const uint8_t ce_nfca_sel_res = LM_SEL_RES; // SEL_RES / SAK + +static const uint8_t ce_nfcf_nfcid2[] = { + LM_NFCID2_BYTE1, 0xFE, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + +// NFC-F CE config +static const uint8_t ce_nfcf_sc[] = {LM_SC_BYTE1, LM_SC_BYTE2}; +static uint8_t ce_nfcf_sensf_res[] = { + 0x01, // SENSF_RES + 0x02, 0xFE, 0x11, 0x22, + 0x33, 0x44, 0x55, 0x66, // NFCID2 + LM_PAD0, LM_PAD0, 0x00, 0x00, + 0x00, 0x7F, 0x7F, 0x00, // PAD0, PAD1, MRTIcheck, MRTIupdate, PAD2 + 0x00, 0x00}; // RD + +static nfc_status_t nfc_transcieve_blocking(uint8_t *tx_buf, + uint16_t tx_buf_size, + uint8_t **rx_buf, + uint16_t **rcv_len, uint32_t fwt); + +static void nfc_card_emulator_loop(rfalNfcDevice *nfc_dev); nfc_status_t nfc_init() { st25r3916b_driver_t *drv = &g_st25r3916b_driver; @@ -255,37 +133,41 @@ nfc_status_t nfc_init() { return NFC_OK; } + memset(drv, 0, sizeof(st25r3916b_driver_t)); + // Enable clock of relevant peripherals // SPI + GPIO ports - SPI_INSTANCE_3_CLK_EN(); - SPI_INSTANCE_3_MISO_CLK_EN(); - SPI_INSTANCE_3_MOSI_CLK_EN(); - SPI_INSTANCE_3_SCK_CLK_EN(); - SPI_INSTANCE_3_NSS_CLK_EN(); + NFC_SPI_FORCE_RESET(); + NFC_SPI_RELEASE_RESET(); + NFC_SPI_CLK_EN(); + NFC_SPI_MISO_CLK_EN(); + NFC_SPI_MOSI_CLK_EN(); + NFC_SPI_SCK_CLK_EN(); + NFC_SPI_NSS_CLK_EN(); // SPI peripheral pin config GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = SPI_INSTANCE_3_PIN_AF; + GPIO_InitStruct.Alternate = NFC_SPI_PIN_AF; - GPIO_InitStruct.Pin = SPI_INSTANCE_3_MISO_PIN; - HAL_GPIO_Init(SPI_INSTANCE_3_MISO_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = NFC_SPI_MISO_PIN; + HAL_GPIO_Init(NFC_SPI_MISO_PORT, &GPIO_InitStruct); - GPIO_InitStruct.Pin = SPI_INSTANCE_3_MOSI_PIN; - HAL_GPIO_Init(SPI_INSTANCE_3_MOSI_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = NFC_SPI_MOSI_PIN; + HAL_GPIO_Init(NFC_SPI_MOSI_PORT, &GPIO_InitStruct); - GPIO_InitStruct.Pin = SPI_INSTANCE_3_SCK_PIN; - HAL_GPIO_Init(SPI_INSTANCE_3_SCK_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = NFC_SPI_SCK_PIN; + HAL_GPIO_Init(NFC_SPI_SCK_PORT, &GPIO_InitStruct); - // NSS pin controled by software, set as classical GPIO + // NSS pin controlled by software, set as classical GPIO GPIO_InitTypeDef GPIO_InitStruct_nss = {0}; GPIO_InitStruct_nss.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct_nss.Pull = GPIO_NOPULL; GPIO_InitStruct_nss.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct_nss.Pin = SPI_INSTANCE_3_NSS_PIN; - HAL_GPIO_Init(SPI_INSTANCE_3_NSS_PORT, &GPIO_InitStruct_nss); + GPIO_InitStruct_nss.Pin = NFC_SPI_NSS_PIN; + HAL_GPIO_Init(NFC_SPI_NSS_PORT, &GPIO_InitStruct_nss); // NFC IRQ pin GPIO_InitTypeDef GPIO_InitStructure_int = {0}; @@ -295,9 +177,9 @@ nfc_status_t nfc_init() { GPIO_InitStructure_int.Pin = NFC_INT_PIN; HAL_GPIO_Init(NFC_INT_PORT, &GPIO_InitStructure_int); - memset(&(drv->hspi), 0, sizeof(drv->hspi)); + memset(&drv->hspi, 0, sizeof(drv->hspi)); - drv->hspi.Instance = SPI_INSTANCE_3; + drv->hspi.Instance = NFC_SPI_INSTANCE; drv->hspi.Init.Mode = SPI_MODE_MASTER; drv->hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; // TODO: Calculate frequency precisly. @@ -309,22 +191,11 @@ nfc_status_t nfc_init() { drv->hspi.Init.NSSPolarity = SPI_NSS_POLARITY_LOW; drv->hspi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; - EXTI_ConfigTypeDef EXTI_Config = {0}; - EXTI_Config.GPIOSel = NFC_EXTI_INTERRUPT_GPIOSEL; - EXTI_Config.Line = NFC_EXTI_INTERRUPT_LINE; - EXTI_Config.Mode = EXTI_MODE_INTERRUPT; - EXTI_Config.Trigger = EXTI_TRIGGER_RISING; - HAL_EXTI_SetConfigLine(&drv->hEXTI, &EXTI_Config); - NVIC_SetPriority(NFC_EXTI_INTERRUPT_NUM, IRQ_PRI_NORMAL); - __HAL_GPIO_EXTI_CLEAR_FLAG(NFC_INT_PIN); - NVIC_EnableIRQ(NFC_EXTI_INTERRUPT_NUM); - HAL_StatusTypeDef status; - - status = HAL_SPI_Init(&(drv->hspi)); + status = HAL_SPI_Init(&drv->hspi); if (status != HAL_OK) { - return false; + goto cleanup; } ReturnCode ret; @@ -334,124 +205,146 @@ nfc_status_t nfc_init() { rfalNfcDefaultDiscParams(&drv->disc_params); if (ret != RFAL_ERR_NONE) { - return NFC_ERROR; + goto cleanup; } + drv->rfal_initialized = true; + + // Initialize EXTI for NFC IRQ pin + EXTI_ConfigTypeDef EXTI_Config = {0}; + EXTI_Config.GPIOSel = NFC_EXTI_INTERRUPT_GPIOSEL; + EXTI_Config.Line = NFC_EXTI_INTERRUPT_LINE; + EXTI_Config.Mode = EXTI_MODE_INTERRUPT; + EXTI_Config.Trigger = EXTI_TRIGGER_RISING; + status = HAL_EXTI_SetConfigLine(&drv->hEXTI, &EXTI_Config); + + if (status != HAL_OK) { + goto cleanup; + } + + NVIC_SetPriority(NFC_EXTI_INTERRUPT_NUM, IRQ_PRI_NORMAL); + __HAL_GPIO_EXTI_CLEAR_FLAG(NFC_INT_PIN); + NVIC_ClearPendingIRQ(NFC_EXTI_INTERRUPT_NUM); + NVIC_EnableIRQ(NFC_EXTI_INTERRUPT_NUM); + drv->initialized = true; + drv->last_nfc_state = NFC_STATE_NOT_ACTIVE; return NFC_OK; + +cleanup: + nfc_deinit(); + return NFC_ERROR; } -nfc_status_t nfc_deinit() { +void nfc_deinit(void) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; - if (!drv->initialized) { - return NFC_OK; - } - - // Deactivate rfal STM. - rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_IDLE); - while (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { - rfalNfcWorker(); + if (drv->rfal_initialized) { + // Deactivate rfal STM (Disconnects active devices) + rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_IDLE); + while (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { + rfalNfcWorker(); + } } HAL_EXTI_ClearConfigLine(&drv->hEXTI); NVIC_DisableIRQ(NFC_EXTI_INTERRUPT_NUM); - ReturnCode ret_code = rfalDeinitialize(); + if (drv->rfal_initialized) { + rfalDeinitialize(); + drv->rfal_initialized = false; + } - if (ret_code != RFAL_ERR_NONE) { + HAL_SPI_DeInit(&drv->hspi); + + HAL_GPIO_DeInit(NFC_SPI_MISO_PORT, NFC_SPI_MISO_PIN); + HAL_GPIO_DeInit(NFC_SPI_MOSI_PORT, NFC_SPI_MOSI_PIN); + HAL_GPIO_DeInit(NFC_SPI_SCK_PORT, NFC_SPI_SCK_PIN); + HAL_GPIO_DeInit(NFC_SPI_NSS_PORT, NFC_SPI_NSS_PIN); + HAL_GPIO_DeInit(NFC_INT_PORT, NFC_INT_PIN); + + memset(&drv, 0, sizeof(st25r3916b_driver_t)); +} + +nfc_status_t nfc_register_tech(const nfc_tech_t tech) { + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + + if (drv->initialized == false) { + return NFC_NOT_INITIALIZED; + } + + drv->disc_params.devLimit = 1; + memcpy(&drv->disc_params.nfcid3, nfcid3, sizeof(nfcid3)); + memcpy(&drv->disc_params.GB, gb, sizeof(gb)); + drv->disc_params.GBLen = sizeof(gb); + drv->disc_params.p2pNfcaPrio = true; + drv->disc_params.totalDuration = 1000U; + + if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { return NFC_ERROR; } - HAL_SPI_DeInit(&(drv->hspi)); - - HAL_GPIO_DeInit(SPI_INSTANCE_3_MISO_PORT, SPI_INSTANCE_3_MISO_PIN); - HAL_GPIO_DeInit(SPI_INSTANCE_3_MOSI_PORT, SPI_INSTANCE_3_MOSI_PIN); - HAL_GPIO_DeInit(SPI_INSTANCE_3_SCK_PORT, SPI_INSTANCE_3_SCK_PIN); - HAL_GPIO_DeInit(SPI_INSTANCE_3_NSS_PORT, SPI_INSTANCE_3_NSS_PIN); - HAL_GPIO_DeInit(NFC_INT_PORT, NFC_INT_PIN); - - drv->initialized = false; - - return NFC_OK; -} - -nfc_status_t nfc_register_card_emu(nfc_card_emul_tech_t tech) { - st25r3916b_driver_t *drv = &g_st25r3916b_driver; - - // In case the NFC state machine is active, deactivate to idle before - // registering a new card emulation technology. - if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { - rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_IDLE); - do { - rfalNfcWorker(); - } while (rfalNfcGetState() != RFAL_NFC_STATE_IDLE); + // Set general discovery parameters. + if (tech & NFC_POLLER_TECH_A) { + drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_A; } - drv->disc_params.devLimit = 1; - memcpy(&drv->disc_params.nfcid3, NFCID3, sizeof(NFCID3)); - memcpy(&drv->disc_params.GB, GB, sizeof(GB)); - drv->disc_params.GBLen = sizeof(GB); - drv->disc_params.p2pNfcaPrio = true; - drv->disc_params.totalDuration = 1000U; + if (tech & NFC_POLLER_TECH_B) { + drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_B; + } - switch (tech) { - case NFC_CARD_EMU_TECH_A: - memcpy(drv->disc_params.lmConfigPA.SENS_RES, ceNFCA_SENS_RES, - RFAL_LM_SENS_RES_LEN); /* Set SENS_RES / ATQA */ - memcpy(drv->disc_params.lmConfigPA.nfcid, ceNFCA_NFCID, - RFAL_LM_NFCID_LEN_04); /* Set NFCID / UID */ - drv->disc_params.lmConfigPA.nfcidLen = - RFAL_LM_NFCID_LEN_04; /* Set NFCID length to 4 bytes */ - drv->disc_params.lmConfigPA.SEL_RES = - ceNFCA_SEL_RES; /* Set SEL_RES / SAK */ - drv->disc_params.techs2Find |= RFAL_NFC_LISTEN_TECH_A; - break; - case NFC_CARD_EMU_TECH_V: - drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_V; - break; - default: - return NFC_ERROR; + if (tech & NFC_POLLER_TECH_F) { + drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_F; + } + + if (tech & NFC_POLLER_TECH_V) { + drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_V; + } + + if (tech & NFC_CARD_EMU_TECH_A) { + card_emulation_init(ce_nfcf_nfcid2); + + // Set SENS_RES / ATQA + memcpy(drv->disc_params.lmConfigPA.SENS_RES, ce_nfca_sens_res, + RFAL_LM_SENS_RES_LEN); + + // Set NFCID / UID + memcpy(drv->disc_params.lmConfigPA.nfcid, ce_nfca_nfcid, + RFAL_LM_NFCID_LEN_04); + + // Set NFCID length to 4 bytes + drv->disc_params.lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_04; + + // Set SEL_RES / SAK + drv->disc_params.lmConfigPA.SEL_RES = ce_nfca_sel_res; + drv->disc_params.techs2Find |= RFAL_NFC_LISTEN_TECH_A; + } + + if (tech & NFC_CARD_EMU_TECH_F) { + // Set configuration for NFC-F CE + memcpy(drv->disc_params.lmConfigPF.SC, ce_nfcf_sc, + RFAL_LM_SENSF_SC_LEN); // Set System Code + + // Load NFCID2 on SENSF_RES + memcpy(&ce_nfcf_sensf_res[RFAL_NFCF_CMD_LEN], ce_nfcf_nfcid2, + RFAL_NFCID2_LEN); + + // Set SENSF_RES / Poll Response + memcpy(drv->disc_params.lmConfigPF.SENSF_RES, ce_nfcf_sensf_res, + RFAL_LM_SENSF_RES_LEN); + + drv->disc_params.techs2Find |= RFAL_NFC_LISTEN_TECH_F; } return NFC_OK; } -nfc_status_t nfc_register_poller(nfc_poller_tech_t tech) { +nfc_status_t nfc_activate_stm(void) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; - // In case the NFC state machine is active, deactivate to idle before - // registering a new card emulation technology. - if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { - rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_IDLE); - do { - rfalNfcWorker(); - } while (rfalNfcGetState() != RFAL_NFC_STATE_IDLE); - } - - drv->disc_params.devLimit = 1; - memcpy(&drv->disc_params.nfcid3, NFCID3, sizeof(NFCID3)); - memcpy(&drv->disc_params.GB, GB, sizeof(GB)); - drv->disc_params.GBLen = sizeof(GB); - drv->disc_params.p2pNfcaPrio = true; - drv->disc_params.totalDuration = 1000U; - - switch (tech) { - case NFC_POLLER_TECH_A: - drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_A; - break; - case NFC_POLLER_TECH_B: - drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_B; - break; - case NFC_POLLER_TECH_F: - drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_F; - break; - case NFC_POLLER_TECH_V: - drv->disc_params.techs2Find |= RFAL_NFC_POLL_TECH_V; - break; - default: - return NFC_ERROR; + if (!drv->initialized) { + return NFC_NOT_INITIALIZED; } ReturnCode err; @@ -463,219 +356,248 @@ nfc_status_t nfc_register_poller(nfc_poller_tech_t tech) { return NFC_OK; } -nfc_status_t nfc_run_worker() { - static rfalNfcDevice *nfcDevice; +nfc_status_t nfc_deactivate_stm(void) { + st25r3916b_driver_t *drv = &g_st25r3916b_driver; - rfalNfcWorker(); /* Run RFAL worker periodically */ - - if (rfalNfcIsDevActivated(rfalNfcGetState())) { - rfalNfcGetActiveDevice(&nfcDevice); - - switch (nfcDevice->type) { - /*******************************************************************************/ - case RFAL_NFC_LISTEN_TYPE_NFCA: - - switch (nfcDevice->dev.nfca.type) { - case RFAL_NFCA_T1T: - vcp_println("ISO14443A/Topaz (NFC-A T1T) TAG found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - - break; - - case RFAL_NFCA_T4T: - vcp_println("NFCA Passive ISO-DEP device found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - - break; - - case RFAL_NFCA_T4T_NFCDEP: - case RFAL_NFCA_NFCDEP: - break; - default: - vcp_println("ISO14443A/NFC-A card found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - - ReturnCode err; - uint16_t rcvLen; - uint8_t blockNum = 0; - uint8_t rxBuf[16]; - - vcp_println("Tag ID len: %d", nfcDevice->nfcidLen); - - // Read first 16 bytes (1st block) - err = rfalT2TPollerRead(0, rxBuf, sizeof(rxBuf), &rcvLen); - parse_tag_header(rxBuf, sizeof(rxBuf)); - - uint8_t memory_area_data[160] = {0}; - for (uint8_t i = 0; i < 10; i++) { - err = rfalT2TPollerRead(4+i*4, memory_area_data+i*16, 16 , &rcvLen); - } - - ndef_record_t record; - parse_ndef_record(memory_area_data+2, 160, &record); - vcp_println("Record payload: %s", record.payload); - - - - - - - break; - } - - /*******************************************************************************/ - case RFAL_NFC_LISTEN_TYPE_NFCB: - - vcp_println("NFC TYPE B card found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - - break; - - /*******************************************************************************/ - case RFAL_NFC_LISTEN_TYPE_NFCF: - - vcp_println("NFC TYPE F card found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - - break; - - /*******************************************************************************/ - case RFAL_NFC_LISTEN_TYPE_NFCV: - - vcp_println("NFC TYPE V card found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - - break; - - /*******************************************************************************/ - case RFAL_NFC_LISTEN_TYPE_ST25TB: - - vcp_println("ST25TB card found. UID: %s\r\n", - hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); - break; - - /*******************************************************************************/ - case RFAL_NFC_LISTEN_TYPE_AP2P: - case RFAL_NFC_POLL_TYPE_AP2P: - break; - - /*******************************************************************************/ - case RFAL_NFC_POLL_TYPE_NFCA: - break; - case RFAL_NFC_POLL_TYPE_NFCF: - break; - /*******************************************************************************/ - default: - break; - } - - rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY); + if (!drv->initialized) { + return NFC_OK; + } + // In case the NFC state machine is active, deactivate to idle before + // registering a new card emulation technology. + if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { + rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_IDLE); + do { + rfalNfcWorker(); + } while (rfalNfcGetState() != RFAL_NFC_STATE_IDLE); } return NFC_OK; } +nfc_status_t nfc_get_event(nfc_event_t *event) { + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + *event = NFC_NO_EVENT; -static void parse_tag_header(uint8_t *data, uint16_t dataLen){ - - type2_header_t hdr; - - memcpy(hdr.UID, data, 3); - hdr.BCC[0] = data[3]; - memcpy(hdr.UID + 3, data+4, 4); - memcpy(hdr.SYSTEM_AREA, data+8, 2); - memcpy(hdr.CC, data+12, 4); - - vcp_println("UID: %s", hex2Str(hdr.UID, sizeof(hdr.UID))); - vcp_println("BCC: %s (%s)", hex2Str(hdr.BCC, sizeof(hdr.BCC)), (0x88 == (hdr.UID[0] ^ hdr.UID[1] ^ hdr.UID[2] ^ hdr.BCC[0]))? " CHECKSUM PASSED" : "CHECKSUM FAILED"); - vcp_println("SYSTEM_AREA: %s", hex2Str(hdr.SYSTEM_AREA, sizeof(hdr.SYSTEM_AREA))); - vcp_println("CC: %s", hex2Str(hdr.CC, sizeof(hdr.CC))); - vcp_println(" -> CC_MAGIC_NUMBER: %02X", hdr.CC_MAGIC_NUMBER); - vcp_println(" -> CC_VERSION: %02X", hdr.CC_VERSION); - vcp_println(" -> CC_SIZE: %02X (%d bytes)", hdr.CC_SIZE, hdr.CC_SIZE*8); - vcp_println(" -> CC_ACCESS_CONDITION: %02X", hdr.CC_ACCESS_CONDITION); - -} - - -/*! - ***************************************************************************** - * \brief Demo Blocking Transceive - * - * Helper function to send data in a blocking manner via the rfalNfc module - * - * \warning A protocol transceive handles long timeouts (several seconds), - * transmission errors and retransmissions which may lead to a long period of - * time where the MCU/CPU is blocked in this method. - * This is a demo implementation, for a non-blocking usage example please - * refer to the Examples available with RFAL - * - * \param[in] txBuf : data to be transmitted - * \param[in] txBufSize : size of the data to be transmited - * \param[out] rxData : location where the received data has been placed - * \param[out] rcvLen : number of data bytes received - * \param[in] fwt : FWT to be used (only for RF frame interface, - * otherwise use RFAL_FWT_NONE) - * - * \return RFAL_ERR_PARAM : Invalid parameters - * \return RFAL_ERR_TIMEOUT : Timeout error - * \return RFAL_ERR_FRAMING : Framing error detected - * \return RFAL_ERR_PROTO : Protocol error detected - * \return RFAL_ERR_NONE : No error, activation successful - * - ***************************************************************************** - */ -ReturnCode demoTransceiveBlocking(uint8_t *txBuf, uint16_t txBufSize, - uint8_t **rxData, uint16_t **rcvLen, - uint32_t fwt) { - ReturnCode err; - - err = rfalNfcDataExchangeStart(txBuf, txBufSize, rxData, rcvLen, fwt); - if (err == RFAL_ERR_NONE) { - do { - rfalNfcWorker(); - err = rfalNfcDataExchangeGetStatus(); - } while (err == RFAL_ERR_BUSY); + if (!drv->initialized) { + return NFC_NOT_INITIALIZED; } - return err; + + rfalNfcDevice *nfc_device; + + // Run RFAL worker periodically + rfalNfcWorker(); + + rfalNfcState rfal_state = rfalNfcGetState(); + + nfc_state_t cur_nfc_state = NFC_STATE_NOT_ACTIVE; + + if (rfalNfcIsDevActivated(rfal_state)) { + cur_nfc_state = NFC_STATE_ACTIVE; + } + + if (cur_nfc_state != drv->last_nfc_state) { + switch (cur_nfc_state) { + case NFC_STATE_ACTIVE: + *event = NFC_EVENT_ACTIVATED; + break; + + case NFC_STATE_NOT_ACTIVE: + *event = NFC_EVENT_DEACTIVATED; + break; + + default: + *event = NFC_NO_EVENT; + } + + drv->last_nfc_state = cur_nfc_state; + } + + if (cur_nfc_state == NFC_STATE_ACTIVE) { + rfalNfcGetActiveDevice(&nfc_device); + + // Perform immediate mandatory actions for certain technology (Placeholder) + switch (nfc_device->type) { + case RFAL_NFC_LISTEN_TYPE_NFCA: + + switch (nfc_device->dev.nfca.type) { + case RFAL_NFCA_T1T: + break; + case RFAL_NFCA_T4T: + break; + case RFAL_NFCA_T4T_NFCDEP: + break; + case RFAL_NFCA_NFCDEP: + break; + default: + break; + } + + case RFAL_NFC_LISTEN_TYPE_NFCB: + break; + + case RFAL_NFC_LISTEN_TYPE_NFCF: + break; + + case RFAL_NFC_LISTEN_TYPE_NFCV: + break; + + case RFAL_NFC_LISTEN_TYPE_ST25TB: + break; + + case RFAL_NFC_LISTEN_TYPE_AP2P: + case RFAL_NFC_POLL_TYPE_AP2P: + break; + + // Card emulators must respond to reader commands promptly. Once + // activated, the RFAL worker is called multiple times until back-to-back + // communication with the reader finishes. This can prolong the + // nfc_get_event() service time compared to standard reader mode. + case RFAL_NFC_POLL_TYPE_NFCA: + case RFAL_NFC_POLL_TYPE_NFCF: + + if (nfc_device->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) { + // not supported yet + } else { + nfc_card_emulator_loop(nfc_device); + rfalNfcDeactivate( + RFAL_NFC_DEACTIVATE_DISCOVERY); // Automatically deactivate + } + + // No event in CE mode, activation/deactivation handled automatically + *event = NFC_NO_EVENT; + + break; + + default: + break; + } + } + + return NFC_OK; } -HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData, - uint8_t *rxData, uint16_t length) { +nfc_status_t nfc_dev_deactivate(void) { + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + + if (!drv->initialized) { + return NFC_NOT_INITIALIZED; + } + + rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY); + + return NFC_OK; +} + +nfc_status_t nfc_transceive(const uint8_t *tx_data, uint16_t tx_data_len, + uint8_t *rx_data, uint16_t *rx_data_len) { + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + + if (drv->initialized == false) { + return NFC_NOT_INITIALIZED; + } + + if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { + return NFC_ERROR; + } + + ReturnCode err; + err = nfc_transcieve_blocking((uint8_t *)tx_data, tx_data_len, &rx_data, + &rx_data_len, RFAL_FWT_NONE); + + if (err != RFAL_ERR_NONE) { + return NFC_ERROR; + } + + return NFC_OK; +} + +nfc_status_t nfc_dev_write_ndef_uri(void) { + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + + if (!drv->initialized) { + return NFC_NOT_INITIALIZED; + } + + // NDEF message + uint8_t ndef_message[128] = {0}; + + uint16_t buffer_len = + ndef_create_uri("trezor.io/", ndef_message, sizeof(ndef_message)); + + for (uint8_t i = 0; i < buffer_len / 4; i++) { + rfalT2TPollerWrite(4 + i, ndef_message + i * 4); + } + + return NFC_OK; +} + +nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info) { + if (rfalNfcIsDevActivated(rfalNfcGetState())) { + rfalNfcDevice *nfc_device; + rfalNfcGetActiveDevice(&nfc_device); + + // Resolve device type + switch (nfc_device->type) { + case RFAL_NFC_LISTEN_TYPE_NFCA: + dev_info->type = NFC_DEV_TYPE_A; + break; + case RFAL_NFC_LISTEN_TYPE_NFCB: + dev_info->type = NFC_DEV_TYPE_B; + break; + case RFAL_NFC_LISTEN_TYPE_NFCF: + dev_info->type = NFC_DEV_TYPE_F; + break; + case RFAL_NFC_LISTEN_TYPE_NFCV: + dev_info->type = NFC_DEV_TYPE_V; + break; + case RFAL_NFC_LISTEN_TYPE_ST25TB: + dev_info->type = NFC_DEV_TYPE_ST25TB; + break; + case RFAL_NFC_LISTEN_TYPE_AP2P: + dev_info->type = NFC_DEV_TYPE_AP2P; + break; + default: + dev_info->type = NFC_DEV_TYPE_UNKNOWN; + break; + } + + dev_info->uid_len = nfc_device->nfcidLen; + + if (nfc_device->nfcidLen > NFC_MAX_UID_LEN) { + return NFC_ERROR; + } + + // Copy the hex UID in printable string + cstr_encode_hex(dev_info->uid, NFC_MAX_UID_BUF_SIZE, nfc_device->nfcid, + nfc_device->nfcidLen); + + } else { + // No device activated + return NFC_ERROR; + } + + return NFC_OK; +} + +HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *tx_data, + uint8_t *rx_data, uint16_t length) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; HAL_StatusTypeDef status; - if ((txData != NULL) && (rxData == NULL)) { - status = HAL_SPI_Transmit(&(drv->hspi), (uint8_t *)txData, length, 1000); - } else if ((txData == NULL) && (rxData != NULL)) { - status = HAL_SPI_Receive(&(drv->hspi), rxData, length, 1000); + if ((tx_data != NULL) && (rx_data == NULL)) { + status = HAL_SPI_Transmit(&drv->hspi, (uint8_t *)tx_data, length, 1000); + } else if ((tx_data == NULL) && (rx_data != NULL)) { + status = HAL_SPI_Receive(&drv->hspi, rx_data, length, 1000); } else { - status = HAL_SPI_TransmitReceive(&(drv->hspi), (uint8_t *)txData, rxData, + status = HAL_SPI_TransmitReceive(&drv->hspi, (uint8_t *)tx_data, rx_data, length, 1000); } return status; } -uint32_t nfc_create_timer(uint16_t time) { return (systick_ms() + time); } - -bool nfc_timer_is_expired(uint32_t timer) { - uint32_t u_diff; - int32_t s_diff; - - u_diff = (timer - systick_ms()); // Calculate the diff between the timers - s_diff = u_diff; // Convert the diff to a signed var - - // Check if the given timer has expired already - if (s_diff < 0) { - return true; - } - - return false; -} - void nfc_ext_irq_set_callback(void (*cb)(void)) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; drv->nfc_irq_callback = cb; @@ -690,3 +612,62 @@ void NFC_EXTI_INTERRUPT_HANDLER(void) { drv->nfc_irq_callback(); } } + +static void nfc_card_emulator_loop(rfalNfcDevice *nfc_dev) { + ReturnCode err = RFAL_ERR_INTERNAL; + uint8_t *rx_buf; + uint16_t *rcv_len; + uint8_t tx_buf[150]; + uint16_t tx_len; + + do { + rfalNfcWorker(); + + switch (rfalNfcGetState()) { + case RFAL_NFC_STATE_ACTIVATED: + err = nfc_transcieve_blocking(NULL, 0, &rx_buf, &rcv_len, 0); + break; + + case RFAL_NFC_STATE_DATAEXCHANGE: + case RFAL_NFC_STATE_DATAEXCHANGE_DONE: + + tx_len = + ((nfc_dev->type == RFAL_NFC_POLL_TYPE_NFCA) + ? card_emulation_t4t(rx_buf, *rcv_len, tx_buf, sizeof(tx_buf)) + : rfalConvBytesToBits( + card_emulation_t3t(rx_buf, rfalConvBitsToBytes(*rcv_len), + tx_buf, sizeof(rx_buf)))); + + err = nfc_transcieve_blocking(tx_buf, tx_len, &rx_buf, &rcv_len, + RFAL_FWT_NONE); + break; + + case RFAL_NFC_STATE_START_DISCOVERY: + return; + + case RFAL_NFC_STATE_LISTEN_SLEEP: + default: + break; + } + } while ((err == RFAL_ERR_NONE) || (err == RFAL_ERR_SLEEP_REQ)); +} + +static nfc_status_t nfc_transcieve_blocking(uint8_t *tx_buf, + uint16_t tx_buf_size, + uint8_t **rx_buf, + uint16_t **rcv_len, uint32_t fwt) { + ReturnCode err; + err = rfalNfcDataExchangeStart(tx_buf, tx_buf_size, rx_buf, rcv_len, fwt); + if (err == RFAL_ERR_NONE) { + do { + rfalNfcWorker(); + err = rfalNfcDataExchangeGetStatus(); + } while (err == RFAL_ERR_BUSY); + } + + if (err != RFAL_ERR_NONE) { + return NFC_ERROR; + } else { + return NFC_OK; + } +} diff --git a/core/embed/io/nfc/st25r3916b/nfc_internal.h b/core/embed/io/nfc/st25r3916b/nfc_internal.h index 579a786efa..ce1ed90413 100644 --- a/core/embed/io/nfc/st25r3916b/nfc_internal.h +++ b/core/embed/io/nfc/st25r3916b/nfc_internal.h @@ -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 . + */ -#include +#pragma once -#ifndef TREZORHAL_NFC_INTERNAL_H -#define TREZORHAL_NFC_INTERNAL_H +#include -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 diff --git a/core/embed/io/nfc/st25r3916b/rfal_platform.h b/core/embed/io/nfc/st25r3916b/rfal_platform.h index d410e93001..a848e773f7 100644 --- a/core/embed/io/nfc/st25r3916b/rfal_platform.h +++ b/core/embed/io/nfc/st25r3916b/rfal_platform.h @@ -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 -#include "stm32u5xx_hal.h" - -#include -#include -#include -#include -#include -#include - -#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 . + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include + +#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 diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h index f925495484..64330ac3a2 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h @@ -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 diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h index 1317a58954..7d08569ba3 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h @@ -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_ diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md index 23d589f891..be5c2fa267 100644 --- a/core/embed/projects/prodtest/README.md +++ b/core/embed/projects/prodtest/README.md @@ -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 +# NFC activated in reader mode for 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 +# Emulation started for +# 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 +# NFC reader on, put the card on the reader (timeout s) +# Writting URI to NFC tag 7AF403 +OK +``` diff --git a/core/embed/projects/prodtest/cmd/prodtest_nfc.c b/core/embed/projects/prodtest/cmd/prodtest_nfc.c new file mode 100644 index 0000000000..023a9185c3 --- /dev/null +++ b/core/embed/projects/prodtest/cmd/prodtest_nfc.c @@ -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 . + */ + +#ifdef USE_NFC + +#include + +#include +#include +#include + +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 = "" +); + +PRODTEST_CLI_CMD( + .name = "nfc-emulate-card", + .func = prodtest_nfc_emulate_card, + .info = "Activate NFC in card emulation (CE) mode", + .args = "" +); + +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 = "" +); + +#endif // USE_NFC diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py index 39200aaa6f..4a9a8f17d7 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py @@ -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"] diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py index 46f4033575..b0c92b24f9 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py @@ -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"] diff --git a/tools/style.c.exclude b/tools/style.c.exclude index 6487231786..8d9ca1e4ca 100644 --- a/tools/style.c.exclude +++ b/tools/style.c.exclude @@ -10,3 +10,4 @@ ^\./crypto/sha3 ^\./legacy/vendor ^\./core/embed/sys/systemview/stm32 +^\./core/embed/io/nfc/rfal