Trouble generating NFC T4T messages in Zephyr

I'm attempting to create an NFC type 4 message to allow certain information to be read using a phone or other NFC reader.  I've studied a number of examples, but none that does exactly what I want, i.e. Type 4 text records.  The nearest I've found is the writable_ndef_msg example, but this uses file-based records, which I don't need, and I can't see the proper way to create records programatically without using the filesystem.

I've made some headway by scanning another known-good type 4 device using an ACR122 USB reader and a script tool to dump the raw data, and then I've crafted a packet that exactly matches this.

However, when I attempt to read using a phone I can't get any response at all.

I'm not an expert on NFC.  I suspect that there's something in the preamble of the protocol (i.e. something that the NFC script tool doesn't show me) that's not right, but I can't see anything in the NFC API that would allow me to experiment.

I've included below the code I'm using, if you're able to offer any advice on what I should try or how I should be going about it, I would be most grateful to hear.

Cheers,

  Frog


#include <zephyr.h>
#include <sys/reboot.h>
#include <stdbool.h>
#include <nfc_t4t_lib.h>
#include <stdio.h>

#include <nfc/ndef/msg.h>
#include <nfc/t4t/ndef_file.h>

#include "mac_addr.h"
#include "logger.h"
#include "meas.h"
#include "nfc.h"

#define NFC_BUF_SIZE 256
static uint8_t ndef_msg_buf[NFC_BUF_SIZE]; /**< Buffer for NDEF file. */

/**
 * @brief Callback function for handling NFC events.
 */
static void nfc_callback(void *context,
             nfc_t4t_event_t event,
             const uint8_t *data,
             size_t data_length,
             uint32_t flags)
{
    ARG_UNUSED(context);
    ARG_UNUSED(data);
    ARG_UNUSED(flags);

    switch (event) {
    case NFC_T4T_EVENT_FIELD_ON:
        break;

    case NFC_T4T_EVENT_FIELD_OFF:
        break;

    case NFC_T4T_EVENT_NDEF_READ:
        logger_dbg("NFC read\n");
        break;

    case NFC_T4T_EVENT_NDEF_UPDATED:
        logger_dbg("NFC write\n");
        if (data_length > 0)
        {
        }
        break;

    default:
        logger_dbg("NFC unknown\n");
        break;
    }
}

void append_text_record(uint8_t *dest, uint8_t * code, uint8_t * text, int8_t flags)
{
    int initial_len = dest[1] + dest[0] * 256;
    int idx = initial_len + 2;
    int id_length = strlen(code);
    int text_length = strlen(text);
    int rec_length = text_length + 3;

    dest[idx++] = flags;
    dest[idx++] = 1; // type length

    dest[idx++] = rec_length>>24; // record length
    dest[idx++] = rec_length>>16;
    dest[idx++] = rec_length>>8;
    dest[idx++] = rec_length;

    dest[idx++] = id_length;

    dest[idx++] = 'T'; // text record

    strcpy(&dest[idx], code);
    idx += id_length;

    dest[idx++] = 2;
    dest[idx++] = 'e';
    dest[idx++] = 'n';

    strcpy(&dest[idx], text);
    idx += rec_length;
    idx -= 5;

    dest[0] = idx / 256;
    dest[1] = idx % 256;
}


/**
 * @brief   Function for application main entry.
 */
int nfc_init(void)
{
    /* Set up NFC */
    int err = nfc_t4t_setup(nfc_callback, NULL);

    if (err < 0)
    {
        printk("Cannot setup t4t library!\n");
    }
    /* Run Read-Write mode for Type 4 Tag platform */

    nfc_update();

    int len = ndef_msg_buf[1] + ndef_msg_buf[0]*256;

    if (nfc_t4t_ndef_rwpayload_set(ndef_msg_buf, len) < 0)
    {
        printk("Cannot set payload!\n");
    }

    /* Start sensing NFC field */
    if (nfc_t4t_emulation_start() < 0)
    {
        printk("Cannot start emulation!\n");
    }

    return 0;
}
/** @} */

void nfc_update(void)
{
    char content[20];

    memset(ndef_msg_buf, 0, sizeof(ndef_msg_buf));

    uint8_t * pMac = mac_addr_get();
    sprintf(content, "%02x%02x%02x%02x%02x%02x", pMac[5],pMac[4],pMac[3],pMac[2],pMac[1],pMac[0]);
    append_text_record(ndef_msg_buf, "ID", content, 0x89);
    sprintf(content, "%02x:%02x:%02x:%02x:%02x:%02x", pMac[5],pMac[4],pMac[3],pMac[2],pMac[1],pMac[0]);
    append_text_record(ndef_msg_buf, "MAC", content, 0x09);
    sprintf(content, "%d%%", meas_get_battery_percent());
    append_text_record(ndef_msg_buf, "BAT", content, 0x09);
    sprintf(content, "%4.2fC", 0.01f * (float)meas_get_temperature_hundredths_celsius());
    append_text_record(ndef_msg_buf, "TEMP", content, 0x09);
    sprintf(content, "%dmlx", meas_get_light_millilux());
    append_text_record(ndef_msg_buf, "MLUX", content, 0x49);
}
Parents
  • Further update: I've resolved this; it turns out that calling

    nfc_t4t_ndef_rwpayload_set()

    with a buffer_length that's not at least a few bytes more than the actual length of the NDEF message causes the problem.  I haven't got to the bottom of exactly how many bytes extra are needed, but with a message of about 120 bytes I have found that specifying 256 bytes (in my case the size of the available buffer rather than the content) is successful.

Reply
  • Further update: I've resolved this; it turns out that calling

    nfc_t4t_ndef_rwpayload_set()

    with a buffer_length that's not at least a few bytes more than the actual length of the NDEF message causes the problem.  I haven't got to the bottom of exactly how many bytes extra are needed, but with a message of about 120 bytes I have found that specifying 256 bytes (in my case the size of the available buffer rather than the content) is successful.

Children
No Data
Related