Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce NFC driver with RFAL middleware #4566

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

kopecdav
Copy link

@kopecdav kopecdav commented Jan 31, 2025

This PR Introduce NFC driver with RFAL middleware to control ST25R3916.

RFAL is a ST middleware which provides a low level control of the ST25R3916 + an extra layer to support several different NFC standards.

PR also introduce prodtests to READ, EMULATE and WRITE to NFC card.

@kopecdav kopecdav added the T3W1 label Jan 31, 2025
@kopecdav kopecdav requested review from TychoVrahe and cepetr January 31, 2025 12:42
@kopecdav kopecdav self-assigned this Jan 31, 2025
@kopecdav kopecdav requested a review from prusnak as a code owner January 31, 2025 12:42
@TychoVrahe TychoVrahe removed the request for review from prusnak January 31, 2025 15:06
@kopecdav kopecdav force-pushed the kopecdav/T3W1/NFC_driver branch from 2e6bf04 to 4c189eb Compare January 31, 2025 15:47
Copy link

github-actions bot commented Jan 31, 2025

core UI changes device test click test persistence test
T2T1 Model T test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
T3B1 Safe 3 test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
T3T1 Safe 5 test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
All main(screens)

@kopecdav kopecdav force-pushed the kopecdav/T3W1/NFC_driver branch from 4c189eb to 606d8c9 Compare February 3, 2025 08:56
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.c Outdated Show resolved Hide resolved
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Show resolved Hide resolved
*/
0x00, 0x00}; /* RD */

static ReturnCode nfc_transcieve_blocking(uint8_t *txBuf, uint16_t txBufSize,
Copy link
Contributor

Choose a reason for hiding this comment

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

In new code, we prefer camelCase over snake_case. camelCase is also used in other parts of the file.

Copy link
Contributor

Choose a reason for hiding this comment

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

wait do we? i am confused now, i believe snake_case is almost exclusively used in our C code

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, I flipped it:-)

Copy link
Author

Choose a reason for hiding this comment

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

I changed the return type to the nfc_status_t but in rest of the code I have everything in snake_case i think. Unfortunatelly the RFAL is written in camelCase so the code looks bit wierd :/. But I dont think we can do anything about it.

Copy link
Contributor

Choose a reason for hiding this comment

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

There are still some places that use camelCase (e.g., txBuf, txBufSize, rcvLen). Of course, we should not change the rfal source code.

core/embed/io/nfc/st25r3916b/ndef.h Outdated Show resolved Hide resolved
core/embed/projects/prodtest/cmd/prodtest_nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
@kopecdav kopecdav force-pushed the kopecdav/T3W1/NFC_driver branch from 09828c9 to d0ecd9f Compare February 6, 2025 19:17
core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc.c Outdated Show resolved Hide resolved
core/embed/projects/prodtest/cmd/prodtest_nfc.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.c Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.c Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.c Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/card_emulation.h Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/ndef.h Show resolved Hide resolved
0x00U /*!<NFC-F PAD0 */

/* P2P communication data */
static uint8_t NFCID3[] = {0x01, 0xFE, 0x03, 0x04, 0x05,
Copy link
Contributor

Choose a reason for hiding this comment

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

sure static const is even better

core/embed/io/nfc/st25r3916b/nfc.c Show resolved Hide resolved
*/
0x00, 0x00}; /* RD */

static ReturnCode nfc_transcieve_blocking(uint8_t *txBuf, uint16_t txBufSize,
Copy link
Contributor

Choose a reason for hiding this comment

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

wait do we? i am confused now, i believe snake_case is almost exclusively used in our C code

core/embed/io/nfc/inc/io/nfc.h Outdated Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc_internal.h Show resolved Hide resolved
core/embed/io/nfc/st25r3916b/nfc_internal.h Outdated Show resolved Hide resolved
@kopecdav kopecdav force-pushed the kopecdav/T3W1/NFC_driver branch from 4c6eec4 to d962d63 Compare February 10, 2025 14:48

*buffer = 0xFE; // TLV termination

return uri_len + 7; // return buffer len
Copy link
Contributor

@cepetr cepetr Feb 13, 2025

Choose a reason for hiding this comment

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

The constant 7 corresponds to NDEF_MESSAGE_URI_OVERHEAD.

The code looks fine, but I would personally simplify it a bit - it’s up to you. If we have more code like this - and it looks like we have, it might be preferable to create a small helper function for buffer reading/writing. That would simplify the code and make it safer.

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
  }

  uint8_t* p = buffer;
  *p++ = 0x3;  // TLV header
  *p++ = uri_len + 5;  // uri + record header
  *p++ = 0xD1;  // NDEF record Header
  *p++ = 0x1;  // Type length
  *p++ = uri_len;  // Payload length
  *p++ = 0x55;  // URI type
  *p = 0x1;  // URI abreviation
  memcpy(p, uri, uri_len);
  p += uri_len;
  *p++ = 0xFE;  // TLV termination

  return dst - buffer;
}

return NDEF_OK;
}

uint16_t ndef_create_uri(const char *uri, uint8_t *buffer, size_t buffer_size) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You are mixing size_t and uint16_t. The strlen() function returns a size_t. Perhaps we should consistently use size_t for buffer sizes and possibly for buffer indices as well. This also applies to ndef_parse_message(), where there is a mix of uint16_t and int16_t.

status = HAL_SPI_Init(&drv->hspi);

if (status != HAL_OK) {
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

Here, false is returned, and a few lines later, NFC_ERROR is returned.

return NFC_OK;
}

nfc_status_t nfc_deinit(void) {
Copy link
Contributor

Choose a reason for hiding this comment

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

xxx_deinit() functions should not return error codes. They are called in situations where errors are not expected or cannot be handled. Therefore, the xxx_deinit() function should be designed to succeed in all cases. Ideally, even if the driver is only partially initialized, xxx_deinit() can still be called from the xxx_init() routine.

rfalNfcDefaultDiscParams(&drv->disc_params);

if (ret != RFAL_ERR_NONE) {
return NFC_ERROR;
Copy link
Contributor

Choose a reason for hiding this comment

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

If we return from the _init() function in this way, we leave the driver partially initialized. I know we don’t do it consistently in our code base, but a good approach is to use a goto/cleanup pattern and call the _deinit() routine in the cleanup section.


nfc_status_t nfc_dev_deactivate(void) {

st25r3916b_driver_t drv = g_st25r3916b_driver;
Copy link
Contributor

Choose a reason for hiding this comment

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

st25r3916b_driver_t *drv = ...


#define NDEF_MESSAGE_URI_OVERHEAD 7

ndef_status_t ndef_parse_message(const uint8_t *buffer, uint16_t buffer_len,
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be better to maintain consistency with variable names (e.g., buffer_len,len, buffer_size).


while (1) {

ndef_parse_record(buffer, remaining_len,
Copy link
Contributor

Choose a reason for hiding this comment

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

ndef_parse_record() returns an error code, but it's not checked here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: 🏃‍♀️ In progress
Development

Successfully merging this pull request may close these issues.

3 participants