Custom messages

Use the Custom NDEF messages and Custom NDEF records modules to create standardized messages and records that are not covered by other modules, or to create your own custom messages.

To generate a custom NDEF message, start by creating the records that make up the message. Next, generate an empty message of the required length and add the records to the message. Finally, encode and create the message.

By default, NDEF messages are encoded for the Type 2 Tag platform. See NDEF message and record format for a description of the format. You can choose to encode the message for the Type 4 Tag platform by setting CONFIG_NFC_NDEF_MSG_WITH_NLEN to y. In this case, an additional field is added in front of an NDEF message.

You can also encapsulate a message as payload for a record. For example, a Handover Request message contains several Alternative Carrier records. These records themselves are full messages that contain information about alternative carriers that can be used for further communication.

Creating a record descriptor

You can provide the payload of the record in binary format or in a different format that is then converted into binary format. The content of the record is defined in a record descriptor.

Use the NFC_NDEF_RECORD_BIN_DATA_DEF macro for binary data or the NFC_NDEF_GENERIC_RECORD_DESC_DEF macro for other data to create the record descriptor. You must provide header information for the record (for example, ID and type) and the payload data to the macro. For generic data that is not in binary format, you must also provide a payload constructor. This constructor converts the payload data to the needed format. For binary data, the module provides this constructor.

The following code example shows how to generate a record descriptor:

int err;
u32_t length;

/// Declare record descriptor by macro - create and initialize an instance of
///   nfc_ndef_record_desc_t.
NFC_NDEF_GENERIC_RECORD_DESC_DEF( record,
                                  3,
                                  id_string,
                                  sizeof(id_string),
                                  type_string,
                                  sizeof(type_string),
                                  payload_constructor, // implementation provided by user
                                  &payload_constructor_data // structure depends on user implementation
                                );

// If required, get the record size to length variable.
err = nfc_ndef_record_encode( &NFC_NDEF_GENERIC_RECORD_DESC_DEF(record),
                                     NDEF_MIDDLE_RECORD,
                                     NULL,
                                     &length);

Creating a message

A message consists of one or more records. Accordingly, a message descriptor (that holds the content of the message) contains an array of pointers to record descriptors.

Use the NFC_NDEF_MSG_DEF macro to create the message descriptor and the array of pointers. When creating the message descriptor, you specify how many records the message will contain, but you do not specify the actual records yet.

To add the records, use the nfc_ndef_msg_record_add() function.

After adding all records, call nfc_ndef_msg_encode() to actually create the message from the message descriptor. nfc_ndef_msg_encode() internally calls nfc_ndef_record_encode() to encode each record. The NDEF records are always encoded in long format. If no ID field is specified, a record without ID field is generated.

The following code example shows how to create two messages:

int err;
u8_t buffer_for_message[512];
u8_t buffer_for_message_2[128];
u32_t length;

// Declare message descriptor by macro - create and initialize an instance of
//   nfc_ndef_msg_desc_t and an array of pointers to nfc_ndef_record_desc_t.
// The declared message can contain up to 2 records.
NFC_NDEF_MSG_DEF(my_message, 2);

// Add record_1 and record_2 to the message.
// record_1 and record_2 are record descriptors as created in the previous
//   code example.
err = nfc_ndef_msg_record_add( &NFC_NDEF_MSG(my_message), record_1);
err = nfc_ndef_msg_record_add( &NFC_NDEF_MSG(my_message), record_2);

// Get the message size to the length variable.
err_t = nfc_ndef_msg_encode( &NFC_NDEF_MSG(my_message),
                                    NULL,
                                    &length);

// Encode the message to buffer_for_message.
ASSERT(length <= 512); // make sure the message fits into the buffer
err_t = nfc_ndef_msg_encode( &NFC_NDEF_MSG(my_message),
                                    buffer_for_message,
                                    &length);

// Clear the message description.
nfc_ndef_msg_clear( &NFC_NDEF_MSG(my_message));

// Add record_3 to the message.
// record_3 is a record descriptors as created in the previous code example.
err = nfc_ndef_msg_record_add( &NFC_NDEF_MSG(my_message), record_3);

// Encode another message to buffer_for_message_2.
length = 128; // amount of memory available for message
err_t = nfc_ndef_msg_encode( &NFC_NDEF_MSG(my_message),
                                    buffer_for_message_2,
                                    &length);

Encapsulating a message

To encapsulate a message in a record so that it can be added to another message, use the NFC_NDEF_NESTED_NDEF_MSG_RECORD_DEF macro to create the record descriptor. This record descriptor uses nfc_ndef_msg_encode() as payload constructor. You can then add this record descriptor to a message like any other record descriptor.

The following code example shows how to encapsulate a message as payload for a record:

// nested_message_desc is a message descriptor

// declare a record descriptor with an NDEF message nested in payload
// create and initialize instance of nfc_ndef_record_desc_t
NFC_NDEF_NESTED_NDEF_MSG_RECORD_DEF( compound_record,
                                     3,
                                     sizeof(id_string),
                                     id_string,
                                     type_string,
                                     sizeof(type_string),
                                     &nested_message_desc );

// add compound record to a message like any other record
err = nfc_ndef_msg_record_add( &NFC_NDEF_MSG(my_message), &NFC_NDEF_NESTED_NDEF_MSG_RECORD(compound_record));

API documentation

Custom NDEF messages

Header file: include/nfc_ndef_msg.h
Source file: subsys/nfc/ndef/nfc_ndef_msg.c
group nfc_ndef_msg

Generation of NFC NDEF messages for the NFC tag.

Defines

NLEN_FIELD_SIZE

Size of NLEN field, used to encode NDEF message for Type 4 Tag.

NFC_NDEF_MSG_DEF(name, max_record_cnt)

Macro for creating and initializing an NFC NDEF message descriptor.

This macro creates and initializes an instance of type nfc_ndef_msg_desc and an array of pointers to record descriptors (nfc_ndef_record_desc) used by the message.

Use the macro NFC_NDEF_MSG to access the NDEF message descriptor instance.

Note
The message descriptor is declared as automatic variable, which implies that the NDEF message encoding must be done in the same variable scope.
Parameters
  • name: Name of the related instance.
  • max_record_cnt: Maximal count of records in the message.

NFC_NDEF_MSG(name)

Macro for accessing the NFC NDEF message descriptor instance that you created with NFC_NDEF_MSG_DEF.

NFC_NDEF_NESTED_NDEF_MSG_RECORD_DEF(name, tnf_arg, id_arg, id_len, type_arg, type_len, nested_message)

Macro for creating and initializing an NFC NDEF record descriptor with an encapsulated NDEF message. This macro creates and initializes an instance of type nfc_ndef_record_desc that contains an encapsulated NDEF message as payload. nfc_ndef_msg_encode is used as payload constructor to encode the message. The encoded message is then used as payload for the record.

Use the macro NFC_NDEF_NESTED_NDEF_MSG_RECORD to access the NDEF record descriptor instance.

Note
The message descriptor is declared as automatic variable, which implies that the NDEF message encoding must be done in the same variable scope.
Parameters
  • name: Name of the created record descriptor instance.
  • tnf_arg: Type Name Format (TNF) value for the record.
  • id_arg: Pointer to the ID string.
  • id_len: Length of the ID string.
  • type_arg: Pointer to the type string.
  • type_len: Length of the type string.
  • nested_message: Pointer to the message descriptor to encapsulate as the record’s payload.

NFC_NDEF_NESTED_NDEF_MSG_RECORD(name)

Macro for accessing the NFC NDEF record descriptor instance that you created with NFC_NDEF_NESTED_NDEF_MSG_RECORD_DEF.

Functions

int nfc_ndef_msg_encode(struct nfc_ndef_msg_desc const *ndef_msg_desc, u8_t *msg_buffer, u32_t *msg_len)

Encode an NDEF message.

This function encodes an NDEF message according to the provided message descriptor.

Note
The way of encoding an NDEF message may vary depending on tag’s platform. Set CONFIG_NFC_NDEF_MSG_WITH_NLEN=y if you want to use Type 4 Tag in application’s configuration prj.conf file.
Parameters
  • ndef_msg_desc: Pointer to the message descriptor.
  • msg_buffer: Pointer to the message destination. If NULL, function will calculate the expected size of the message.
  • msg_len: Size of the available memory for the message as input. Size of the generated message as output.
Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

void nfc_ndef_msg_clear(struct nfc_ndef_msg_desc *msg)

Clear an NDEF message.

This function clears an NDEF message descriptor, thus empties the NDEF message.

Parameters
  • msg: Pointer to the message descriptor.

int nfc_ndef_msg_record_add(struct nfc_ndef_msg_desc *msg, struct nfc_ndef_record_desc const *record)

Add a record to an NDEF message.

Parameters
  • record: Pointer to the record descriptor.
  • msg: Pointer to the message descriptor.
Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

struct nfc_ndef_msg_desc
#include <nfc_ndef_msg.h>

NDEF message descriptor.

Public Members

struct nfc_ndef_record_desc const **record

Pointer to an array of pointers to NDEF record descriptors.

u32_t max_record_count

Number of elements in the allocated record array, which defines the maximum number of records within the NDEF message.

u32_t record_count

Number of records in the NDEF message.

Custom NDEF records

Header file: include/nfc_ndef_record.h
Source file: subsys/nfc/ndef/nfc_ndef_record.c
group nfc_ndef_record

Generation of NFC NDEF records for NFC messages.

Defines

NDEF_RECORD_IL_MASK

Mask of the ID field presence bit in the flags byte of an NDEF record.

NDEF_RECORD_TNF_MASK

Mask of the TNF value field in the first byte of an NDEF record.

NDEF_RECORD_SR_MASK

Mask of the SR flag. If set, this flag indicates that the PAYLOAD_LENGTH field has a size of 1 byte. Otherwise, PAYLOAD_LENGTH has 4 bytes.

NDEF_RECORD_PAYLOAD_LEN_LONG_SIZE

Size of the Payload Length field in a long NDEF record.

NDEF_RECORD_PAYLOAD_LEN_SHORT_SIZE

Size of the Payload Length field in a short NDEF record.

NDEF_RECORD_ID_LEN_SIZE
NDEF_RECORD_LOCATION_MASK

Mask of the Record Location bits in the NDEF record’s flags byte.

NFC_NDEF_GENERIC_RECORD_DESC_DEF(name, tnf_arg, id_arg, id_len, type_arg, type_len, payload_constructor_arg, payload_descriptor_arg)

Macro for creating and initializing an NFC NDEF record descriptor for a generic record.

This macro creates and initializes an instance of type nfc_ndef_record_desc.

Use the macro NFC_NDEF_GENERIC_RECORD_DESC to access the NDEF record descriptor instance.

Note
The record descriptor is declared as automatic variable, which implies that the NDEF record encoding must be done in the same variable scope.
Parameters
  • name: Name of the created descriptor instance.
  • tnf_arg: Type Name Format (TNF) value for the record.
  • id_arg: Pointer to the ID string.
  • id_len: Length of the ID string.
  • type_arg: Pointer to the type string.
  • type_len: Length of the type string.
  • payload_constructor_arg: Pointer to the payload constructor function. The constructor must be of type payload_constructor_t.
  • payload_descriptor_arg: Pointer to the data for the payload constructor.

NFC_NDEF_GENERIC_RECORD_DESC(name)

Macro for accessing the NFC NDEF record descriptor instance that you created with NFC_NDEF_GENERIC_RECORD_DESC_DEF.

NFC_NDEF_RECORD_BIN_DATA_DEF(name, tnf_arg, id_arg, id_len, type_arg, type_len, payload_arg, payload_len)

Macro for creating and initializing an NFC NDEF record descriptor for a record with binary payload.

This macro creates and initializes an instance of type nfc_ndef_record_desc and a binary data descriptor containing the payload data.

Use the macro NFC_NDEF_RECORD_BIN_DATA to access the NDEF record descriptor instance.

Note
The record descriptor is declared as automatic variable, which implies that the NDEF record encoding must be done in the same variable scope.
Parameters
  • name: Name of the created descriptor instance.
  • tnf_arg: Type Name Format (TNF) value for the record.
  • id_arg: Pointer to the ID string.
  • id_len: Length of the ID string.
  • type_arg: Pointer to the type string.
  • type_len: Length of the type string.
  • payload_arg: Pointer to the payload data that will be copied to the payload field.
  • payload_len: Length of the payload.

NFC_NDEF_RECORD_BIN_DATA(name)

Macro for accessing the NFC NDEF record descriptor instance that you created with NFC_NDEF_RECORD_BIN_DATA_DEF.

NFC_NDEF_BIN_PAYLOAD_DESC(name)

Macro for accessing the binary data descriptor that contains the payload of the record that you created with NFC_NDEF_RECORD_BIN_DATA_DEF.

Typedefs

typedef int (*payload_constructor_t)(void *payload_descriptor, u8_t *buffer, u32_t *len)

Payload constructor type.

A payload constructor is a function for constructing the payload of an NDEF record.

Parameters
  • payload_descriptor: Pointer to the input data for the constructor.
  • buffer: Pointer to the payload destination. If NULL, function will calculate the expected size of the record payload. *
  • len: Size of the available memory to write as input. Size of the generated record payload as output. The implementation must check if the payload will fit in the provided buffer. This must be checked by the caller function.
Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

Enums

enum nfc_ndef_record_tnf

Type Name Format (TNF) Field Values.

Values to specify the TNF of a record.

Values:

TNF_EMPTY = 0x00

The value indicates that there is no type or payload associated with this record.

TNF_WELL_KNOWN = 0x01

NFC Forum well-known type [NFC RTD].

TNF_MEDIA_TYPE = 0x02

Media-type as defined in RFC 2046 [RFC 2046].

TNF_ABSOLUTE_URI = 0x03

Absolute URI as defined in RFC 3986 [RFC 3986].

TNF_EXTERNAL_TYPE = 0x04

NFC Forum external type [NFC RTD].

TNF_UNKNOWN_TYPE = 0x05

The value indicates that there is no type associated with this record.

TNF_UNCHANGED = 0x06

The value is used for the record chunks used in chunked payload.

TNF_RESERVED = 0x07

The value is reserved for future use.

enum nfc_ndef_record_location

Record position within the NDEF message.

Values to specify the location of a record within the NDEF message.

Values:

NDEF_FIRST_RECORD = 0x80

First record.

NDEF_MIDDLE_RECORD = 0x00

Middle record.

NDEF_LAST_RECORD = 0x40

Last record.

NDEF_LONE_RECORD = 0xC0

Only one record in the message.

Functions

int nfc_ndef_record_encode(struct nfc_ndef_record_desc const *ndef_record_desc, enum nfc_ndef_record_location const record_location, u8_t *record_buffer, u32_t *record_len)

Encode an NDEF record.

This function encodes an NDEF record according to the provided record descriptor.

Parameters
  • ndef_record_desc: Pointer to the record descriptor.
  • record_location: Location of the record within the NDEF message.
  • record_buffer: Pointer to the record destination. If NULL, function will calculate the expected size of the record.
  • record_len: Size of the available memory for the record as input. Size of the generated record as output.
Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

int nfc_ndef_bin_payload_memcopy(struct nfc_ndef_bin_payload_desc *payload_descriptor, u8_t *buffer, u32_t *len)

Construct the payload for an NFC NDEF record from binary data.

This function copies data from a binary buffer to the payload field of the NFC NDEF record.

Parameters
  • payload_descriptor: Pointer to the descriptor of the binary data location and size.
  • buffer: Pointer to the payload destination. If NULL, function will calculate the expected size of the record payload.
  • len: Size of the available memory for the payload as input. Size of the copied payload as output.
Return Value
  • 0: If the operation was successful. Otherwise, a (negative) error code is returned.

struct nfc_ndef_record_desc
#include <nfc_ndef_record.h>

NDEF record descriptor.

Public Members

nfc_ndef_record_tnf tnf

Value of the Type Name Format (TNF) field.

u8_t id_length

Length of the ID field. If 0, a record format without ID field is assumed.

u8_t const *id

Pointer to the ID field data. Not relevant if id_length is 0.

u8_t type_length

Length of the type field.

u8_t const *type

Pointer to the type field data. Not relevant if type_length is 0.

payload_constructor_t payload_constructor

Pointer to the payload constructor function.

void *payload_descriptor

Pointer to the data for the payload constructor function.

struct nfc_ndef_bin_payload_desc
#include <nfc_ndef_record.h>

Binary data descriptor containing the payload for the record.

Public Members

u8_t const *payload

Pointer to the buffer with the data.

u32_t payload_length

Length of data in bytes.