Tag NDEF Exchange Protocol for NFC Tag Device

The Tag NDEF Exchange Protocol (TNEP) is an application-level protocol for sending or retrieving application data units between a Poller Device and an NFC Tag Device.

The data units take the form of NFC Data Exchange Format (NDEF) messages. The protocol operates between the NDEF application layer and the Tag Device, that is a device that supports at least one communication protocol for NDEF. The Poller is an NFC device in the Poll mode, in which it sends commands and receives responses.

The NFC Tag Device supports all tag types from Type 2 Tag to Type 5 Tag. The Poller communicates with the type of tag corresponding to the NFC Tag Device type. The communication occurs through Poller’s Reader/Writer role.

Initialization

Before using the TNEP library in a Tag Device application, configure the NDEF message buffers and define the TNEP Services.

Configuring the NDEF message buffers

The TNEP library communicates with the Tag Device using the NDEF message buffers. The buffers are initialized all at the same time by nfc_tnep_tag_tx_msg_buffer_register().

To use the NDEF message buffers, you must configure the following elements: * Provide a pointer to two TX buffers: one TX buffer for emulating the NDEF message and one for encoding the new NDEF message. * Set a maximum buffer size in bytes, which is valid for both buffers.

The buffers must be linked with the Tag Device layer in the application.

When the NFC Poller device writes a new NDEF Message inside the tag buffer, the application must inform the TNEP library by calling nfc_tnep_tag_rx_msg_indicate().

Defining TNEP Services

The TNEP Services are capabilities and features provided to the adjacent upper layer. They must be defined for the TNEP library in order to create the Initial NDEF message. At least one TNEP Service must be defined for the message to be created.

To create a TNEP Service, use the NFC_TNEP_TAG_SERVICE_DEF macro.

After defining the Services, create a table that lists all of them. You can use NFC_TNEP_TAG_SERVICE to get the names of the Services created.

The Service table is given to the nfc_tnep_tag_initial_msg_create() function and the Service Parameter record of each Service is inserted into the Initial TNEP message. A Service Parameter record contains parameters for communicating with the Service.

See the following code for an example of Service definition and TNEP initialization:

#define NFC_TNEP_TAG_SERVICE_DEF(service_name, uri, uri_length, mode, t_wait, n_wait, mac_msg_size
                                                         select_cb, deselect_cb message_cb, timeout_cb, error_cb)

NFC_NDEF_MSG_DEF(ndef_msg, 16);

static struct nfc_tnep_tag_service services[] = {
        NFC_TNEP_TAG_SERVICE(service_name),
};

nfc_tnep_tx_msg_buffer_register(buffer, swap_buffer, buffer_length);

nfc_tnep_init(event, event_cnt, &NFC_NDEF_MSG(ndef_msg),
              nfc_txt_rw_payload_set);

nfc_tXt_setup();

nfc_tnep_tag_initial_msg_create(services, ARRAY_SIZE(services), NULL, 0);

nfc_tXt_emulation_start();

Configuration

After initialization, the TNEP library is in the Service Ready state and the NDEF message buffer contains Service Parameter records provided with the Initial TNEP message.

The Initial TNEP message can also include optional NDEF records that can interact with the NFC Poller device that does not support the protocol.

Make sure to call the nfc_tnep_tag_process() function in infinite loop in the application.

Receiving new messages

When a new NDEF message appears in the buffer and it contains a Service Select record, the application can select this Service. To do this, the application should indicate the service and inform the TNEP library by calling nfc_tnep_tag_rx_msg_indicate(). The TNEP library will change its state to Service Selected. At that point moving forward, the Service decryption message will not longer be provided.

After the successful Service selection, the select callback function of the Service will be called. If the TNEP library was already in the Service Selected state at the moment of receiving the NDEF message with the Service Select record, the deselect callback of the previous service will be called before the select callback of the new service.

When TNEP is in the Service Selected state, the Service’s new message callback will be called after successfully processing the new message. Application data can be added to the reply message with nfc_tnep_tag_tx_msg_app_data(). This function can be called from the Service Selected callback or from any other context, for example a different thread.

If the Tag Device application has no more data, it will reply by using nfc_tnep_tag_tx_msg_no_app_data(). If the application does not reply before the expiration on the time period specified by the Service’s initialization parameters, the Service will be deselected by the Reader/Writer device.

The following code demonstrates how to exchange the NDEF messages using the TNEP library after initialization:

static void training_service_selected(void)
{
        /* service selection function body */
        nfc_tnep_tag_tx_msg_app_data(app_records, records_cnt);

        return 0;
}

static void training_service_deselected(void)
{
        /* service deselection function body */
}

static void training_service_new_message(void)
{
        /* new application data function body */

        /* Add application data reply*/
        nfc_tnep_tx_msg_app_data(app_record);
}

tag_x_tag_handler()
{
        nfc_tnep_tag_rx_msg_indicate();
}

main()
{
        /*initialization code, application code*/
        while (1) {
                nfc_tnep_tag_process();
        }
}

API documentation

Header file: include/tnep/tag.h
Source file: subsys/tnep/tag.c
group nfc_tnep_tag

TAG NDEF Exchange Protocol for the NFC Tag Device.

Defines

NFC_TNEP_EVENTS_NUMBER

NFC TNEP library event count.

NFC_TNEP_TAG_MAX_WAIT_TIME

Maximum Service Waiting Time.

NFC_TNEP_TAG_MAX_N_WAIT_TIME

Maximum Waiting Time extension.

NFC_TNEP_TAG_SERVICE_DEF(_name, _uri, _uri_length, _mode, _t_wait, _n_wait, _max_msg_size, _select_cb, _deselect_cb, _message_cb, _error_cb)

Macro to define TNEP service.

TNEP Service instance contains information about Services Parameter and callback s for NDEF application. The Service Parameter contains the Service Name URI of the Service and the TNEP parameters used to communicate with the Service. The Reader/Writer will configure the TNEP communication according to the announced parameter in the Service Parameter record.

Parameters
  • [in] _name: Service instance name used in code. Use NFC_TNEP_TAG_SERVICE to get service by name.

  • [in] _uri: Service Name URI.

  • [in] _uri_length: Service Name URI length in bytes.

  • [in] _mode: Service mode - TNEP Communication Mode: Single Response or Service specific

  • [in] _t_wait: Minimum Waiting Time measured between the end of the last write command of an NDEF Write Procedure and the start of the first command of the first NDEF Read Procedure following the NDEF Write Procedures. T_wait has a value between 0 and 63 and is converted to time units using protocol specified formula.

  • [in] _n_wait: Maximum Number of Waiting Time Extensions is the maximum number of requested waiting time extensions n_wait for a specific Service. N_wait can vary between 0 and 15 repetitions.

  • [in] _max_msg_size: Maximum NDEF message size in bytes.

  • [in] _select_cb: Callback function, called by protocol library when service is selected by the Reader/Writer.

  • [in] _deselect_cb: Callback function, called by protocol library when service is deselected by the Reader/Writer.

  • [in] _message_cb: Callback function, called by protocol library when new message is received from the Reader/Writer. [in] _error_cb Callback function, called by protocol library when an internal error occurred.

NFC_TNEP_TAG_SERVICE(_name)

macro for accessing the TNEP Service.

Typedefs

typedef int (*nfc_payload_set_t)(u8_t *, size_t)

Functions

int nfc_tnep_tag_tx_msg_buffer_register(u8_t *tx_buff, u8_t *tx_swap_buff, size_t len)

Register TNEP message buffer.

TNEP Tag Device needs two buffers one for current NDEF message and seconds for new message.

Parameters
  • [in] tx_buff: Pointer to NDEF message buffer.

  • [in] tx_swap_buff: Pointer to swap NDEF message buffer.

  • [in] len: Length of NDEF message buffers.

Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

int nfc_tnep_tag_init(struct k_poll_event *events, u8_t event_cnt, struct nfc_ndef_msg_desc *msg, nfc_payload_set_t payload_set)

Start communication using TNEP.

Parameters
  • [out] events: TNEP Tag Events.

  • [in] cnt: Event count. This library needs 2 events.

  • [inout] Pointer: to NDEF message structure. It is used to create TNEP NDEF message.

  • [in] payload_set: Function for setting NDEF data for NFC TNEP Tag Device. This library use it internally to set raw NDEF message to the Tag NDEF file. This function is called from atomic context, so sleeping or anyhow delaying is not allowed there.

Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

int nfc_tnep_tag_initial_msg_create(const struct nfc_tnep_tag_service *svc, size_t svc_cnt, const struct nfc_ndef_record_desc *records, size_t records_cnt)

Create the initial TNEP NDEF message.

This function create the Initial TNEP message. Initial NDEF message has to contain at least one service parameters record. It can contain also optional NDEF Records which can be used by NFC Poller Device which does not support TNEP Protocol.

Parameters
  • [in] svc: Pointer to the first service information structure.

  • [in] svc_cnt: Number of provided services for application.

  • [in] records: Pointer to the first no TNEP NDEF Records structure.

  • [in] records_cnt: Number of privided NDEF Records.

Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

void nfc_tnep_tag_process(void)

Waiting for a signals to execute protocol logic.

This function must be called periodically from thread to process the TNEP Tag Device.

Note

This function cannot be called before nfc_tnep_init.

void nfc_tnep_tag_rx_msg_indicate(const u8_t *rx_buffer, size_t len)

Indicate about new TNEP message available in buffer.

The NFC Tag Device concludes that the NDEF Write Procedure is finished when, after a write command of the NDEF Write Procedure, an NDEF message is available in the data area. If, after the write command of the NDEF Write Procedure, no NDEF message is available in the data area, the NFC Tag Device concludes that the actual NDEF Write Procedure is ongoing.

Parameters
  • [in] rx_buffer: Pointer to NDEF message buffer.

  • [in] len: Length of NDEF message buffer.

int nfc_tnep_tag_tx_msg_app_data(const struct nfc_ndef_record_desc *record, size_t cnt, enum nfc_tnep_status_value status)

Add application data record to next message.

Use this function to set application data after the service selection to set service application data and use it also during service data exchange with the NFC Polling Device. To indicate that application has no more data use .

Parameters
  • [in] record: Pointer to application data records.

  • [in] cnt: Records count.

  • [in] status: TNEP App data message status.

Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

int nfc_tnep_tag_tx_msg_no_app_data(void)

Respond with no more application data.

If the NDEF application on the NFC Tag Device has finished, and therefore the NFC Tag Device has no more application data available for the Reader/Writer, then the NFC Tag Device SHALL provide a Status message containing a single record that is a TNEP Status record indicating success.

Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

void nfc_tnep_tag_on_selected(void)

Handle NFC Tag selected event.

If data exchange with poller starts again, NFC TNEP Tag device shall provide TNEP Initial message.

struct nfc_tnep_tag_service_cb
#include <tag.h>

Public Members

void (*selected)(void)

Function called when service was selected.

void (*deselected)(void)

Function called when service deselected.

void (*message_received)(const u8_t *data, size_t len)

Function called when new message was received.

Parameters
  • [in] data: Pointer to received data.

  • [in] len: Received data length.

void (*error_detected)(int err)

Function called when an internal error in TNEP detected.

Parameters
  • err: Detected error code.

struct nfc_tnep_tag_service
#include <tag.h>

Service structure.

This structure contains all information about user service. It contains service parameters, service parameters record and services callbacks. It is used by tnep_init function.

Public Members

struct nfc_ndef_tnep_rec_svc_param *parameters

Services parameters.

struct nfc_ndef_record_desc *ndef_record

NDEF records data.

const struct nfc_tnep_tag_service_cb *callbacks

Callbacks structure.