diff --git a/core/embed/io/nfc/inc/io/nfc.h b/core/embed/io/nfc/inc/io/nfc.h index d516a12fff..72bed61937 100644 --- a/core/embed/io/nfc/inc/io/nfc.h +++ b/core/embed/io/nfc/inc/io/nfc.h @@ -17,12 +17,10 @@ * along with this program. If not, see . */ -#ifndef TREZORHAL_NFC_H -#define TREZORHAL_NFC_H -#include -#include -#include "ndef.h" +#pragma once + +#include "trezor_types.h" #define NFC_MAX_UID_LEN 10 @@ -46,7 +44,7 @@ typedef enum { } nfc_dev_type_t; typedef enum { - NFC_STATE_IDLE, + NFC_NO_EVENT, NFC_STATE_ACTIVATED, } nfc_event_t; @@ -60,45 +58,40 @@ typedef enum { typedef struct { uint8_t type; - char uid[NFC_MAX_UID_LEN]; + char uid[NFC_MAX_UID_LEN + 1]; // Plus one for string termination uint8_t uid_len; } nfc_dev_info_t; -// Initialize NFC driver including supportive RFAL middlewere -nfc_status_t nfc_init(); +// Initialize NFC driver including supportive RFAL middleware +nfc_status_t nfc_init(void); -// Deinitialize NFC drive -nfc_status_t nfc_deinit(); +// Deinitialize NFC driver +nfc_status_t nfc_deinit(void); // 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(nfc_tech_t tech); +nfc_status_t nfc_register_tech(const nfc_tech_t tech); -// Register event callbacks to be called with state machine, this function is -// used when user need to further interact (read/write) with the connected NFC -// device -nfc_status_t nfc_register_event_callback(nfc_event_t event_type, - void (*cb_fn)(void)); - -// Activate the NFC RFAL state machine which will explore the registered -// technologies State machine handles the low level NFC protocols of registered -// technologies and provide the user with the activated device information. With -// activated, user have to constantly run NFC workerwith nfc_feed_worker() to -// activly loop the state machine. -nfc_status_t nfc_activate_stm(); +// 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); // Deactivate the NFC RFAL state machine (put in IDLE state). -nfc_status_t nfc_deactivate_stm(); +nfc_status_t nfc_deactivate_stm(void); -// Calls NFC RFAL worker which service the NFC statemachine exploring the -// registered technologies. this function has to be actively called in loop -// (main NFC poll function). -nfc_status_t nfc_feed_worker(); +// 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_event_t nfc_get_event(void); + +// 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 NDFE message with the trezor.io URI to the activated NFC device. -nfc_status_t nfc_def_write_ndef_uri(); - -#endif // TREZORHAL_NFC_H +// 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/rfal/LOCAL_CHANGES.md b/core/embed/io/nfc/rfal/LOCAL_CHANGES.md new file mode 100644 index 0000000000..394d73e6a0 --- /dev/null +++ b/core/embed/io/nfc/rfal/LOCAL_CHANGES.md @@ -0,0 +1,8 @@ + +RFAL middleware was imported into trezor-firmware to support a low level NFC operations of st25r3916b from +https://www.st.com/en/embedded-software/stsw-st25r-lib.html#overview (version 1.7.0) + +# Local changes + +1. rfalIsoDepInfo structure defined in include/rfal_isoDep.h and rfalNfcDepInfo include/rfal_nfcDep.h contains variable DSI which colide with the DSI macro in +STM32 HAL drivers. To resolve this, variale in RFAL library was refactored to DSI_ID. \ No newline at end of file diff --git a/core/embed/io/nfc/st25r3916b/card_emulation.c b/core/embed/io/nfc/st25r3916b/card_emulation.c index 983ee1737b..cb92e73010 100644 --- a/core/embed/io/nfc/st25r3916b/card_emulation.c +++ b/core/embed/io/nfc/st25r3916b/card_emulation.c @@ -529,7 +529,7 @@ static uint16_t card_emulation_t3t_update(uint8_t *cmdData, uint8_t *rspData) { * @return None ***************************************************************************** */ -void card_emulation_init(uint8_t *nfcfNfcid) { +void card_emulation_init(const uint8_t *nfcfNfcid) { if (nfcfNfcid != NULL) { memcpy(gNfcfNfcid, nfcfNfcid, RFAL_NFCF_NFCID2_LEN); } diff --git a/core/embed/io/nfc/st25r3916b/card_emulation.h b/core/embed/io/nfc/st25r3916b/card_emulation.h index d747d0b37a..f175e3ab4c 100644 --- a/core/embed/io/nfc/st25r3916b/card_emulation.h +++ b/core/embed/io/nfc/st25r3916b/card_emulation.h @@ -16,16 +16,14 @@ */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef DEMO_CE_H -#define DEMO_CE_H +#pragma once #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ -#include -#include +#include /** @addtogroup X-CUBE-NFC6_Applications * @brief Sample applications for X-NUCLEO-NFC06A1 STM32 expansion boards. @@ -74,7 +72,7 @@ extern "C" { /** @defgroup CE_CardEmul_Exported_functions * @{ */ -void card_emulation_init(uint8_t *nfcfNfcid); +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, @@ -100,6 +98,4 @@ uint16_t card_emulation_t4t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf, } #endif -#endif /* DEMO_CE_H */ - /******************* (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 d656fcc282..0a30342f55 100644 --- a/core/embed/io/nfc/st25r3916b/ndef.c +++ b/core/embed/io/nfc/st25r3916b/ndef.c @@ -1,12 +1,28 @@ +/* + * 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 "ndef.h" -#include -#include // ndef_status_t create_ndef_record_uri(uint8_t *bytearray, ) -ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len, +ndef_status_t ndef_parse_message(const uint8_t *buffer, uint16_t buffer_len, ndef_message_t *message) { memset(message, 0, sizeof(ndef_message_t)); @@ -34,7 +50,7 @@ ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len, remaining_len = message->message_total_len; while (1) { - parse_ndef_record(buffer, remaining_len, + ndef_parse_record(buffer, remaining_len, &(message->records[message->records_cnt])); buffer += message->records[message->records_cnt].record_total_len; remaining_len -= message->records[message->records_cnt].record_total_len; @@ -57,7 +73,7 @@ ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len, return NDEF_OK; } -ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len, +ndef_status_t ndef_parse_record(const uint8_t *buffer, uint16_t len, ndef_record_t *rec) { uint8_t bp = 0; @@ -119,7 +135,7 @@ ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len, return NDEF_OK; } -uint16_t create_ndef_uri(const char *uri, uint8_t *buffer) { +uint16_t ndef_create_uri(const char *uri, uint8_t *buffer) { *buffer = 0x3; // TLV header buffer++; @@ -129,15 +145,6 @@ uint16_t create_ndef_uri(const char *uri, uint8_t *buffer) { *buffer = uri_len + 5; // uri + record header; buffer++; - // ndef_record_header_t hdr = { - // .tnf = 0x01, - // .il = 0, - // .sr = 1, - // .cf = 0, - // .me = 1, - // .mb = 1, - // }; - *buffer = 0xD1; // NDEF record Header buffer++; @@ -158,8 +165,6 @@ uint16_t create_ndef_uri(const char *uri, uint8_t *buffer) { buffer++; } - // memcpy(buffer, uri, uri_len); - *buffer = 0xFE; // TLV termination return uri_len + 7; // return buffer len diff --git a/core/embed/io/nfc/st25r3916b/ndef.h b/core/embed/io/nfc/st25r3916b/ndef.h index f68f6eeff7..cef1899580 100644 --- a/core/embed/io/nfc/st25r3916b/ndef.h +++ b/core/embed/io/nfc/st25r3916b/ndef.h @@ -1,7 +1,6 @@ -#include +#pragma once -#ifndef NDEF_H -#define NDEF_H +#include #define NDEF_MAX_RECORDS 3 #define NDEF_MAX_RECORD_PAYLOAD_BYTES 50 @@ -37,10 +36,9 @@ typedef struct { ndef_record_t records[NDEF_MAX_RECORDS]; } ndef_message_t; -ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len, +ndef_status_t ndef_parse_message(const uint8_t *buffer, uint16_t buffer_len, ndef_message_t *message); -ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len, +ndef_status_t ndef_parse_record(const uint8_t *buffer, uint16_t len, ndef_record_t *rec); -uint16_t create_ndef_uri(const char *uri, uint8_t *buffer); +uint16_t ndef_create_uri(const char *uri, uint8_t *buffer); -#endif diff --git a/core/embed/io/nfc/st25r3916b/nfc.c b/core/embed/io/nfc/st25r3916b/nfc.c index 4ecdffa954..7bd708bebb 100644 --- a/core/embed/io/nfc/st25r3916b/nfc.c +++ b/core/embed/io/nfc/st25r3916b/nfc.c @@ -1,23 +1,52 @@ +/* + * 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 +#include +#include + +#include "io/nfc.h" +#include "rfal_isoDep.h" +#include "rfal_nfc.h" +#include "rfal_nfca.h" +#include "rfal_rf.h" +#include "rfal_t2t.h" +#include "rfal_utils.h" #include "card_emulation.h" #include "ndef.h" #include "nfc_internal.h" #include "rfal_platform.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 "stm32u5xx_hal.h" +#define LM_SEL_RES \ + 0x20U /*!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. @@ -204,7 +213,7 @@ nfc_status_t nfc_init() { return NFC_OK; } -nfc_status_t nfc_deinit() { +nfc_status_t nfc_deinit(void) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; if (!drv->initialized) { @@ -228,40 +237,25 @@ nfc_status_t nfc_deinit() { 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_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); drv->initialized = false; return NFC_OK; + } -void rfal_callback(rfalNfcState st) { + +nfc_status_t nfc_register_tech(const nfc_tech_t tech) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; - switch (st) { - case RFAL_NFC_STATE_IDLE: - if (drv->nfc_state_idle_cb != NULL) { - drv->nfc_state_idle_cb(); - } - break; - - case RFAL_NFC_STATE_ACTIVATED: - if (drv->nfc_state_activated_cb != NULL) { - drv->nfc_state_activated_cb(); - } - break; - default: - // State not reported - break; + if (drv->initialized == false) { + return NFC_NOT_INITIALIZED; } -} - -nfc_status_t nfc_register_tech(nfc_tech_t tech) { - st25r3916b_driver_t *drv = &g_st25r3916b_driver; drv->disc_params.devLimit = 1; memcpy(&drv->disc_params.nfcid3, NFCID3, sizeof(NFCID3)); @@ -269,11 +263,6 @@ nfc_status_t nfc_register_tech(nfc_tech_t tech) { drv->disc_params.GBLen = sizeof(GB); drv->disc_params.p2pNfcaPrio = true; drv->disc_params.totalDuration = 1000U; - drv->disc_params.notifyCb = rfal_callback; - - if (drv->initialized == false) { - return NFC_NOT_INITIALIZED; - } if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) { return NFC_ERROR; @@ -324,34 +313,13 @@ nfc_status_t nfc_register_tech(nfc_tech_t tech) { return NFC_OK; } -nfc_status_t nfc_register_event_callback(nfc_event_t event_type, - void (*cb_fn)(void)) { +nfc_status_t nfc_activate_stm(void) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; - switch (event_type) { - case NFC_STATE_IDLE: - drv->nfc_state_idle_cb = cb_fn; - break; - case NFC_STATE_ACTIVATED: - drv->nfc_state_activated_cb = cb_fn; - break; - default: - return NFC_ERROR; + if(!drv->initialized) { + return NFC_NOT_INITIALIZED; } - return NFC_OK; -} - -nfc_status_t nfc_unregister_event_callback() { - st25r3916b_driver_t *drv = &g_st25r3916b_driver; - drv->disc_params.notifyCb = NULL; - - return NFC_OK; -} - -nfc_status_t nfc_activate_stm() { - st25r3916b_driver_t *drv = &g_st25r3916b_driver; - ReturnCode err; err = rfalNfcDiscover(&(drv->disc_params)); if (err != RFAL_ERR_NONE) { @@ -361,7 +329,14 @@ nfc_status_t nfc_activate_stm() { return NFC_OK; } -nfc_status_t nfc_deactivate_stm() { +nfc_status_t nfc_deactivate_stm(void) { + + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + + 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) { @@ -374,61 +349,60 @@ nfc_status_t nfc_deactivate_stm() { return NFC_OK; } -nfc_status_t nfc_feed_worker() { +nfc_event_t nfc_get_event(void) { + + st25r3916b_driver_t *drv = &g_st25r3916b_driver; + + if(!drv->initialized) { + return NFC_NOT_INITIALIZED; + } + static rfalNfcDevice *nfcDevice; rfalNfcWorker(); /* Run RFAL worker periodically */ - if (rfalNfcIsDevActivated(rfalNfcGetState())) { + if(rfalNfcIsDevActivated(rfalNfcGetState())) { + rfalNfcGetActiveDevice(&nfcDevice); + // Perform immediate mandatory actions for certain technology (Placeholder) switch (nfcDevice->type) { - /*******************************************************************************/ + case RFAL_NFC_LISTEN_TYPE_NFCA: switch (nfcDevice->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 need to promptly respond to the reader commands, so when - // activated rfal worker is called seveal times untill back to back - // communication with the reader is completed. This may prolong the - // run_feed_worker service time compared to standard reader mode. + // 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: @@ -436,59 +410,35 @@ nfc_status_t nfc_feed_worker() { // not supported yet } else { nfc_card_emulator_loop(nfcDevice); + rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY); // Automatically deactivate } - break; + + return NFC_NO_EVENT; break; - break; - /*******************************************************************************/ default: break; } - rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY); + return NFC_STATE_ACTIVATED; + } - return NFC_OK; + return NFC_NO_EVENT; } -static void nfc_card_emulator_loop(rfalNfcDevice *nfcDev) { - ReturnCode err = RFAL_ERR_INTERNAL; - uint8_t *rxData; - uint16_t *rcvLen; - uint8_t txBuf[150]; - uint16_t txLen; +nfc_status_t nfc_dev_deactivate(void) { - do { - rfalNfcWorker(); + st25r3916b_driver_t drv = g_st25r3916b_driver; - switch (rfalNfcGetState()) { - case RFAL_NFC_STATE_ACTIVATED: - err = nfc_transcieve_blocking(NULL, 0, &rxData, &rcvLen, 0); - break; + if (!drv.initialized) { + return NFC_NOT_INITIALIZED; + } - case RFAL_NFC_STATE_DATAEXCHANGE: - case RFAL_NFC_STATE_DATAEXCHANGE_DONE: + rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY); - txLen = ((nfcDev->type == RFAL_NFC_POLL_TYPE_NFCA) - ? card_emulation_t4t(rxData, *rcvLen, txBuf, sizeof(txBuf)) - : rfalConvBytesToBits(card_emulation_t3t( - rxData, rfalConvBitsToBytes(*rcvLen), txBuf, - sizeof(txBuf)))); - - err = nfc_transcieve_blocking(txBuf, txLen, &rxData, &rcvLen, - 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)); + return NFC_OK; } nfc_status_t nfc_transceive(const uint8_t *txData, uint16_t txDataLen, @@ -514,11 +464,18 @@ nfc_status_t nfc_transceive(const uint8_t *txData, uint16_t txDataLen, return NFC_OK; } -nfc_status_t nfc_def_write_ndef_uri() { +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 = create_ndef_uri("trezor.io/", ndef_message); + uint16_t buffer_len = ndef_create_uri("trezor.io/", ndef_message); for (uint8_t i = 0; i < buffer_len / 4; i++) { rfalT2TPollerWrite(4 + i, ndef_message + i * 4); @@ -564,8 +521,12 @@ nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info) { return NFC_ERROR; } - char *uid_str = hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen); - memcpy(dev_info->uid, uid_str, nfcDevice->nfcidLen); + if (nfcDevice->nfcidLen <= NFC_MAX_UID_LEN) { + return NFC_ERROR; + } + + // Copy the hex UID in printable string + cstr_encode_hex(dev_info->uid, NFC_MAX_UID_LEN, nfcDevice->nfcid, nfcDevice->nfcidLen); } else { // No device activated @@ -575,58 +536,6 @@ nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info) { return NFC_OK; } -// static void parse_tag_header(uint8_t *data, uint16_t dataLen) { -// nfc_device_header_t2t_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); - -// } - -static ReturnCode nfc_transcieve_blocking(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); - } - return err; -} - -static char *hex2Str(unsigned char *data, size_t dataLen) { - { - unsigned char *pin = data; - const char *hex = "0123456789ABCDEF"; - char *pout = hexStr[hexStrIdx]; - uint8_t i = 0; - uint8_t idx = hexStrIdx; - if (dataLen == 0) { - pout[0] = 0; - } else { - for (; i < dataLen - 1; ++i) { - *pout++ = hex[(*pin >> 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]; - } -} - HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData, uint8_t *rxData, uint16_t length) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; @@ -644,22 +553,9 @@ HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData, return status; } -uint32_t nfc_create_timer(uint16_t time) { return (systick_ms() + time); } +uint32_t nfc_create_timer(uint16_t time) { return ticks_timeout(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; -} +bool nfc_timer_is_expired(uint32_t timer) { return ticks_expired(timer); } void nfc_ext_irq_set_callback(void (*cb)(void)) { st25r3916b_driver_t *drv = &g_st25r3916b_driver; @@ -675,3 +571,58 @@ void NFC_EXTI_INTERRUPT_HANDLER(void) { drv->nfc_irq_callback(); } } + + +static void nfc_card_emulator_loop(rfalNfcDevice *nfcDev) { + + ReturnCode err = RFAL_ERR_INTERNAL; + uint8_t *rxBuf; + uint16_t *rcvLen; + uint8_t txBuf[150]; + uint16_t txLen; + + do { + rfalNfcWorker(); + + switch (rfalNfcGetState()) { + case RFAL_NFC_STATE_ACTIVATED: + err = nfc_transcieve_blocking(NULL, 0, &rxBuf, &rcvLen, 0); + break; + + case RFAL_NFC_STATE_DATAEXCHANGE: + case RFAL_NFC_STATE_DATAEXCHANGE_DONE: + + txLen = ((nfcDev->type == RFAL_NFC_POLL_TYPE_NFCA) + ? card_emulation_t4t(rxBuf, *rcvLen, txBuf, sizeof(txBuf)) + : rfalConvBytesToBits(card_emulation_t3t( + rxBuf, rfalConvBitsToBytes(*rcvLen), txBuf, + sizeof(txBuf)))); + + err = nfc_transcieve_blocking(txBuf, txLen, &rxBuf, &rcvLen, + 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 ReturnCode nfc_transcieve_blocking(uint8_t *txBuf, uint16_t txBufSize, + uint8_t **rxBuf, uint16_t **rcvLen, + uint32_t fwt) { + ReturnCode err; + + err = rfalNfcDataExchangeStart(txBuf, txBufSize, rxBuf, rcvLen, fwt); + if (err == RFAL_ERR_NONE) { + do { + rfalNfcWorker(); + err = rfalNfcDataExchangeGetStatus(); + } while (err == RFAL_ERR_BUSY); + } + return err; +} \ No newline at end of file diff --git a/core/embed/io/nfc/st25r3916b/nfc_internal.h b/core/embed/io/nfc/st25r3916b/nfc_internal.h index 579a786efa..7dd5e1bdb9 100644 --- a/core/embed/io/nfc/st25r3916b/nfc_internal.h +++ b/core/embed/io/nfc/st25r3916b/nfc_internal.h @@ -1,9 +1,8 @@ +#pragma once + #include -#ifndef TREZORHAL_NFC_INTERNAL_H -#define TREZORHAL_NFC_INTERNAL_H - HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData, uint8_t *rxData, uint16_t length); @@ -13,4 +12,3 @@ bool nfc_timer_is_expired(uint32_t timer); 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..8995a7e427 100644 --- a/core/embed/io/nfc/st25r3916b/rfal_platform.h +++ b/core/embed/io/nfc/st25r3916b/rfal_platform.h @@ -20,8 +20,7 @@ * */ -#ifndef RFAL_PLATFORM_H -#define RFAL_PLATFORM_H +#pragma once #ifdef __cplusplus extern "C" { @@ -34,16 +33,13 @@ extern "C" { */ #include -#include "stm32u5xx_hal.h" - +#include #include #include -#include -#include -#include -#include +#include #include "io/nfc.h" + #include "nfc_internal.h" /* @@ -56,10 +52,10 @@ extern "C" { #define ST25R3916B // GPIO pin used for ST25R SPI SS -#define ST25R_SS_PIN SPI_INSTANCE_3_NSS_PIN +#define ST25R_SS_PIN NFC_SPI_NSS_PIN // GPIO port used for ST25R SPI SS port -#define ST25R_SS_PORT SPI_INSTANCE_3_NSS_PORT +#define ST25R_SS_PORT NFC_SPI_NSS_PORT // GPIO pin used for ST25R External Interrupt #define ST25R_INT_PIN NFC_INT_PIN @@ -73,12 +69,10 @@ extern "C" { ****************************************************************************** */ #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) + NVIC_DisableIRQ(NFC_EXTI_INTERRUPT_NUM) #define platformUnprotectST25RComm() \ - NVIC_EnableIRQ(EXTI10_IRQn) // TODO: Use macro here / + NVIC_EnableIRQ(NFC_EXTI_INTERRUPT_NUM) #define platformProtectST25RIrqStatus() \ platformProtectST25RComm() /*!< Protect unique access to IRQ status var - \ @@ -292,5 +286,3 @@ extern uint8_t globalCommProtectCnt; /* Global Protection Counter provided per #ifdef __cplusplus } #endif - -#endif /* RFAL_PLATFORM_H */ diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h index c30a55d4e3..8745d8f906 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h @@ -166,22 +166,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 63f522633d..d2f0af4138 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h @@ -166,22 +166,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/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md index c3ee5202d6..e5f6c0b468 100644 --- a/core/embed/projects/prodtest/README.md +++ b/core/embed/projects/prodtest/README.md @@ -545,3 +545,48 @@ Example: optiga-counter-read OK 0E ``` + + +### 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 index 05201d5dd8..56176fdfba 100644 --- a/core/embed/projects/prodtest/cmd/prodtest_nfc.c +++ b/core/embed/projects/prodtest/cmd/prodtest_nfc.c @@ -25,21 +25,8 @@ #include #include -static bool nfc_dev_activated = false; static nfc_dev_info_t dev_info = {0}; -static void nfc_activated_callback() { - nfc_dev_read_info(&dev_info); - nfc_dev_activated = true; -} - -static void nfc_write_tag_callback() { - nfc_dev_info_t dev_info; - nfc_dev_read_info(&dev_info); - - nfc_dev_activated = true; -} - static void prodtest_nfc_read_card(cli_t* cli) { uint32_t timeout = 0; memset(&dev_info, 0, sizeof(dev_info)); @@ -55,31 +42,41 @@ static void prodtest_nfc_read_card(cli_t* cli) { return; } - nfc_dev_activated = false; - nfc_status_t ret = nfc_init(); if (ret != NFC_OK) { cli_error(cli, CLI_ERROR_FATAL, "NFC init failed"); } else { - cli_trace(cli, "NFC activated in reader mode for %d seconds.", timeout); + 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_register_event_callback(NFC_STATE_ACTIVATED, nfc_activated_callback); nfc_activate_stm(); - uint32_t tick = systick_ms(); + nfc_event_t nfc_event = NFC_NO_EVENT; - while (!nfc_dev_activated) { // Todo, while timeout or device found + uint32_t expire_time = ticks_timeout(timeout); - if ((systick_ms() - tick) > (timeout * 1000)) { + while (true) { + + if (ticks_expired(expire_time)) { nfc_deinit(); cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout"); return; } - nfc_feed_worker(); + nfc_event = nfc_get_event(); + + if(nfc_event == NFC_STATE_ACTIVATED) { + nfc_dev_read_info(&dev_info); + nfc_dev_deactivate(); + break; + } + + if (cli_aborted(cli)) { + return; + } + } cli_trace(cli, "NFC card detected."); @@ -136,16 +133,21 @@ static void prodtest_nfc_emulate_card(cli_t* cli) { if (ret != NFC_OK) { cli_error(cli, CLI_ERROR_FATAL, "NFC init failed"); } else { - cli_trace(cli, "Emulation started for %d seconds", timeout); + cli_trace(cli, "Emulation started for %d ms", timeout); } nfc_register_tech(NFC_CARD_EMU_TECH_A); nfc_activate_stm(); - uint32_t tick = systick_ms(); + uint32_t expire_time = ticks_timeout(timeout); + + while (!ticks_expired(expire_time)) { + nfc_get_event(); + + if (cli_aborted(cli)) { + return; + } - while ((systick_ms() - tick) < (timeout * 1000)) { - nfc_feed_worker(); } cli_trace(cli, "Emulation over"); @@ -170,41 +172,52 @@ static void prodtest_nfc_write_card(cli_t* cli) { return; } - nfc_dev_activated = false; - nfc_status_t ret = nfc_init(); if (ret != NFC_OK) { cli_error(cli, CLI_ERROR_FATAL, "NFC init failed"); } else { - cli_trace(cli, "NFC reader on put the card on the reader (timeout %d s)", + cli_trace(cli, "NFC reader on, put the card on the reader (timeout %d ms)", timeout); } nfc_register_tech(NFC_POLLER_TECH_A); - nfc_register_event_callback(NFC_STATE_ACTIVATED, nfc_write_tag_callback); nfc_activate_stm(); - uint32_t tick = systick_ms(); + nfc_event_t nfc_event = NFC_NO_EVENT; + uint32_t expire_time = ticks_timeout(timeout); - while (!nfc_dev_activated) { // Todo, while timeout or device found + while (true) { - if ((systick_ms() - tick) > timeout * 1000) { + if (ticks_expired(expire_time)) { nfc_deinit(); cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout"); return; } - nfc_feed_worker(); - } + nfc_event = nfc_get_event(); + if (nfc_event == NFC_STATE_ACTIVATED) { - if (dev_info.type != NFC_DEV_TYPE_A) { - cli_error(cli, CLI_ERROR, "Only NFC type A cards supported"); - return; - } + nfc_dev_read_info(&dev_info); - cli_trace(cli, "Writting URI to NFC tag %s", dev_info.uid); - nfc_def_write_ndef_uri(); + if (dev_info.type != NFC_DEV_TYPE_A) { + cli_error(cli, CLI_ERROR, "Only NFC type A cards supported"); + return; + } + + 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)) { + return; + } + + } nfc_deinit();