Skip to content

Conversation

@kopecdav
Copy link
Contributor

This PR brings support for ST25TV tag.

Implementation details

New driver exclusive for ST25TV tag was implemented in parallel to current NFC driver. Old NFC driver provides general support for many kinds technologies and implementing a driver for ST25TV (as a proprietary technology) would add another layer on the top of the already many layer driver. NFC driver would then work only as a trampoline, which did not make sense.

Both drivers are attached to same SPI peripheral, so user can select which driver to use, but should not use both simultaneously.

Driver provide functions to initiate a connections with the tag, read out basic system information, read and write to the tag memory, wipe the memory, but do not provide any complex memory handling operations which will be implemented in the upper level.

Event loop

Compared to general NFC driver, ST25TV driver do not require to poll for RfalWorker function when running NFC discover. Instead, RfalWorker was embedded to event loop poll and user could react to incoming events.

Prodtest

Implementation was extended with several prodtest commands allowing to test basic driver operations.

@kopecdav kopecdav self-assigned this Nov 19, 2025
@kopecdav kopecdav requested a review from obrusvit as a code owner November 19, 2025 13:53
@kopecdav kopecdav added the T3W1 Trezor Safe 7 label Nov 19, 2025
@github-project-automation github-project-automation bot moved this to 🔎 Needs review in Firmware Nov 19, 2025
@kopecdav kopecdav requested review from bleska and Copilot November 19, 2025 13:53
@github-actions
Copy link

Looks like you changed Cargo.lock. Please make sure to review the dependencies and update internal version list.

Copilot finished reviewing on behalf of kopecdav November 19, 2025 13:55
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new dedicated driver for ST25TV NFC tags, operating in parallel with the existing general NFC driver. The implementation provides core operations (initialization, connection management, read/write, wipe) via a new syscall interface, integrates an event-based polling mechanism into the system event loop, and extends prodtest with comprehensive testing commands.

Key changes:

  • New NFC backup driver with dedicated API (nfc_backup.h) and syscall interface
  • Refactored SPI handling to share hardware between NFC and NFC backup drivers
  • Event-driven architecture using system event polling rather than manual worker polling
  • Comprehensive prodtest commands for testing all driver operations

Reviewed Changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
core/site_scons/models/T3W1/trezor_t3w1_revC.py Adds new source files for NFC backup driver to build configuration
core/embed/sys/task/inc/sys/sysevent.h Adds SYSHANDLE_NFC_BACKUP event handle for event loop integration
core/embed/sys/syscall/stm32/syscall_verifiers.h Declares syscall verifier functions for NFC backup operations
core/embed/sys/syscall/stm32/syscall_verifiers.c Implements memory access validation for NFC backup syscalls
core/embed/sys/syscall/stm32/syscall_stubs.c Implements userspace syscall stubs for NFC backup API
core/embed/sys/syscall/stm32/syscall_dispatch.c Routes NFC backup syscalls to kernel implementations
core/embed/sys/syscall/inc/sys/syscall_numbers.h Defines syscall numbers for NFC backup operations
core/embed/rust/src/ui/ui_prodtest.rs Adds UI trait method for NFC tag connection visualization
core/embed/rust/src/ui/layout_eckhart/prodtest/mod.rs Implements NFC tag connection screen with visual feedback
core/embed/rust/src/ui/api/prodtest_c.rs Exposes Rust UI function to C code
core/embed/rust/rust_ui_prodtest.h Declares C interface for NFC prodtest UI
core/embed/projects/prodtest/main.c Includes NFC backup header for prodtest usage
core/embed/projects/prodtest/cmd/prodtest_nfc.c Implements 8 prodtest commands for NFC backup testing
core/embed/projects/prodtest/README.md Documents all new prodtest commands with examples
core/embed/io/nfc/st25r3916b/rfal_platform.h Removes circular include dependency
core/embed/io/nfc/st25r3916b/nfc_spi.c Extracts SPI handling into shared module
core/embed/io/nfc/st25r3916b/nfc_internal.h Declares shared SPI functions for both drivers
core/embed/io/nfc/st25r3916b/nfc_backup_poll.h Declares event polling functions for NFC backup
core/embed/io/nfc/st25r3916b/nfc_backup_poll.c Implements event-based polling for NFC backup
core/embed/io/nfc/st25r3916b/nfc_backup.c Core NFC backup driver implementation
core/embed/io/nfc/st25r3916b/nfc.c Refactored to use shared SPI module
core/embed/io/nfc/inc/io/nfc_backup.h Public API header for NFC backup driver
Comments suppressed due to low confidence (1)

core/embed/io/nfc/st25r3916b/nfc_backup.c:1

  • Corrected spelling of 'precisly' to 'precisely'.
/*

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +423 to +429
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
SYSCALL_NFC_BACKUP_READ_DATA);
}

bool nfc_backup_write_data(uint16_t block_number, const uint8_t *data,
size_t data_size) {
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function parameters are block_number, data, and data_size, but the syscall is invoked with undefined variables start_block and num_blocks. This should be syscall_invoke3(block_number, (uint32_t)data, data_size, ...) to match the function signature.

Suggested change
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
SYSCALL_NFC_BACKUP_READ_DATA);
}
bool nfc_backup_write_data(uint16_t block_number, const uint8_t *data,
size_t data_size) {
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
return (bool)syscall_invoke3(block_number, (uint32_t)data, data_size,
SYSCALL_NFC_BACKUP_READ_DATA);
}
bool nfc_backup_write_data(uint16_t block_number, const uint8_t *data,
size_t data_size) {
return (bool)syscall_invoke3(block_number, (uint32_t)data, data_size,

Copilot uses AI. Check for mistakes.
Comment on lines +423 to +429
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
SYSCALL_NFC_BACKUP_READ_DATA);
}

bool nfc_backup_write_data(uint16_t block_number, const uint8_t *data,
size_t data_size) {
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function parameters are block_number, data, and data_size, but the syscall is invoked with undefined variables start_block and num_blocks. This should be syscall_invoke3(block_number, (uint32_t)data, data_size, ...) to match the function signature.

Suggested change
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
SYSCALL_NFC_BACKUP_READ_DATA);
}
bool nfc_backup_write_data(uint16_t block_number, const uint8_t *data,
size_t data_size) {
return (bool)syscall_invoke3(start_block, (uint32_t)data, num_blocks,
return (bool)syscall_invoke3(block_number, (uint32_t)data, data_size,
SYSCALL_NFC_BACKUP_READ_DATA);
}
bool nfc_backup_write_data(uint16_t block_number, const uint8_t *data,
size_t data_size) {
return (bool)syscall_invoke3(block_number, (uint32_t)data, data_size,

Copilot uses AI. Check for mistakes.
```

### nfc-backup-store-secret
Activates NFC reader and store the secret phrese on the connected tag.
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'phrese' to 'phrase'.

Copilot uses AI. Check for mistakes.
```

### nfc-backup-read-secret
Activates NFC reader and read the secret phrese from the connected tag.
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'phrese' to 'phrase'.

Copilot uses AI. Check for mistakes.
}

uint8_t data_buffer[1] = {0};
uint8_t recieved_buf[7] = {0};
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'recieved' to 'received'.

Copilot uses AI. Check for mistakes.
response, sizeof(response), &received_length);

if (received_length != 3) {
return RFAL_ERR_PROTO;
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function return type is bool but returns RFAL_ERR_PROTO (likely an enum/int). This should return false to match the function signature.

Suggested change
return RFAL_ERR_PROTO;
return false;

Copilot uses AI. Check for mistakes.
if (enable) {
data[2] = 0x05; // Boot to silent mode regardless of DS_STS
} else {
data[2] = 0x00; // Disbale silent mode
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'Disbale' to 'Disable'.

Suggested change
data[2] = 0x00; // Disbale silent mode
data[2] = 0x00; // Disable silent mode

Copilot uses AI. Check for mistakes.
Comment on lines +374 to +375
system_info->mem_block_count = response[12] + 1; // Block size in bytes
system_info->mem_block_size = response[13] + 1; // Number of blocks
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments appear to be swapped. Line 374 assigns to mem_block_count but the comment says 'Block size in bytes', while line 375 assigns to mem_block_size but the comment says 'Number of blocks'. The comments should be swapped to match the variables.

Suggested change
system_info->mem_block_count = response[12] + 1; // Block size in bytes
system_info->mem_block_size = response[13] + 1; // Number of blocks
system_info->mem_block_count = response[12] + 1; // Number of blocks
system_info->mem_block_size = response[13] + 1; // Block size in bytes

Copilot uses AI. Check for mistakes.
.func = prodtest_nfc_backup_store_secret,
.info = "Store secret data to NFC backup tag",
.args = "<secret>"
);
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace after closing parenthesis should be removed.

Suggested change
);
);

Copilot uses AI. Check for mistakes.
.func = prodtest_nfc_backup_wipe_memory,
.info = "Wipe NFC backup memory",
.args = ""
)
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon after closing parenthesis. Should be ); to match the pattern used in other command definitions.

Suggested change
)
);

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

en main(all)

model device_test click_test persistence_test
T2T1 test(all) main(all) test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all) test(all) main(all)

Latest CI run: 19503676208

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T3W1 Trezor Safe 7

Projects

Status: 🔎 Needs review

Development

Successfully merging this pull request may close these issues.

2 participants