preface

NFC this word believe that we are now no stranger to the metro, shopping malls and so on in major cities to support NFC payment once became the hot spot of the headlines. In fact, there have been TWO-DIMENSIONAL code and NFC long ago, but because of the low cost of two-dimensional code and relatively low technical threshold, two-dimensional code quickly seized the mobile payment market, but at the same time, the development of NFC has not stopped.


In fact, the development of NFC on Android has been very rapid, but our Apple dad refused to take us to play NFC. Finally, at WWDC last year, Apple announced that it was “opening up” its NFC interface, which opens up more possibilities for NFC application development in the future.


About the NFC

Near Field Communication (NFC) is a technology that enables information exchange between two devices when they are close to each other.


Devices using NFC, such as mobile phones, can exchange data in close proximity to each other. It evolved from the integration of contactless radio frequency identification (RFID) and interconnectivity. By integrating inductive card readers, inductive cards, and point-to-point communication on a single chip, Using mobile terminals to achieve mobile payment, electronic ticketing, access control, mobile identity identification, anti-counterfeiting and other applications. Currently, Apple’s CoreNFC has limited support for NFC formats, and currently supports only NDEF formats.


About NDEF

NDEF (NFC Data Exchange Format) is a Data Format that enables information Exchange between NFC devices or labels. The NDEF format consists of various NDEF Messages and NDEF Records. The NDEF format uses an easy-to-understand format to store and exchange information such as URIs, plain text, and so on.


NFC tags, like Mifare Classic cards, can be configured as NDEF tags, and data written through one NFC device can be accessed by other NDEF-compliant devices. NDEF messages can also be used to exchange data between two active NFC devices in “point-to-point” mode.



NDEF Messages

NDEF Messages is the basis of the NDEF Records exchange mechanism, with each message containing one or more Records.


NDEF Records

NDEF Records contains a specific payload and has the following structure to indicate the content and record size:

Record Header

The record header contains a lot of important information. It takes three bits to identify the type of record that follows the TNF protocol. These three bits are used to indicate the type of record.


TNF: Type Name Format field

The type name of an NDEF record is a three-bit number that describes the type of the record and can be used to set expectations for the rest of the structure and content of the record. Simply put, these three bits can not only represent the type of the record, but also determine the data structure of the record to a certain extent. Possible record names are listed below:

TNF Value



Record Type

0x00

Empty Record indicates that the Record has no type, ID, or valid payload. This record type is typically used on newly formatted NDEF cards because the NDEF tag must have at least one NDEF record.

0x01

Well-known Record Indicates that the Record type field is in the FORMAT of RTD type name. This Type name uses a Record Type Definition (RTD) to store any specified Type, such as storing RTD text, RTD URIs, and so on. At the same time, this is one of the more common and useful record types.

0x02

The MIME Media Record indicates that payload is the middle or last chunk of the NDEF Record.

0x03

Absolute URI Record indicates that the type field of the Record must contain a URI field.

0x04

External Record indicates that the type field of the Record contains an External field in RTD format.

0x05

Unknown Record Indicates that the type of payload is Unknown.

0x06

The Unchanged MIME Media Record was the same as the Unchanged MIME Media Record.


IL: indicates the ID Length field

IL is the ID Length flag bit, used to indicate whether the following ID Length field is omitted. If this bit is set to 0, the ID Length is omitted from the record.


SR: indicates a Short Record bit

The short record flag bit is set to 1 if the PAYLOAD LENGTH field below is less than or equal to one byte.


CF: the Chunk Flag

A block identification bit that identifies whether the current block is the first or the middle block.


ME: the Message to the End

The end flag bit that identifies whether the current record is the last record of the current Message.


MB: Message Begin

The start flag bit that identifies whether the current record is the first record of the current Message.


Type Length

Represents the length of a type field. For some of the values in the TNF field description above, this field is always 0.


Payload Length

Indicates the length of the payload field of the record. If the above SR field is set to 1, the field will be 1 byte long, but if the SR field is set to 0, the field will have 32 bits and be 4 bytes long.


ID Length

Indicates the length of the RECORD ID. The field is omitted only if the IL position above is 1.


Record Type

Represents the type of record, and the value of this field must be determined based on the TNF bit setting.


Record ID

Indicates the ID of the record. When the IL bit is 0, this field is omitted.


Payload

Indicates the payload of the record. The Length of this field must be consistent with that of the payload Length field.


About Well-known Records and URI Records


Well Known Records (TNF Record Type 0x01) is the most commonly used and most useful NFC Record Type. It is written in the three bits of the TNF field mentioned above. It describes the overall Type of the current NDEF Record. It’s an overall architectural decision.


The URI Records (0x55/ ‘U’) is a useful data Type. It is written in a byte (8 bits) of the Recode Type field above. It describes the Type of data information that the NDEF record carries.


This type can be used to store useful information such as phone numbers, web addresses, and links to various protocols. Its structure is defined as follows:

The first byte represents the identifier of the type. This identifier is used to shorten the length of the URI. The valid values are shown in the following table:

The next N bytes are used to represent the rest of a URI after the identifier is removed. For example: For example, if we want to write https://www.mob.com, in the first byte we want to write 0x02, which means https://www. 0x6D 0x6F 0x62 0x2E 0x63 0x6F 0x6D (for details, see the ASCII code mapping table http://ascii.911cha.com/)


All of the above content is about the NDEF data format in detail, so here is also unfortunate to tell you, we usually directly from a treasure, east or xyz to buy NFC cards (commonly known as: white cards) will not be NDEF format, so…


Use Mifare Classic Cards as the NDEF tag


Mifare Classic 1K and 4K cards can be initialized to NFC’s NDEF format label. Mifare Classic can be configured as an NDEF tag compatible with the NFC forum, but only if the data in it is organized in a certain way. For specific requirements, please refer to the following information:


AN1304 – NFC Type MIFARE Classic Tag Operation

https://www.nxp.com/docs/en/application-note/AN1304.pdf


While the above is an authoritative source of user manuals, here’s a quick overview of the key concepts involved in using Mifare Classic Cards as an NDEF tag.


1. Mifare Application Directory (MAD)

The directory of the Mifare application, which exists to establish a relationship between the sector memory of the Mifare Classic card and a single NDEF record. MAD indicates which sector contains which NDEF record. The authoritative sources of information about the Mifare application directory are:


AN10787 – MIFARE Application Directory (MAD)

https://www.nxp.com/docs/en/application-note/AN10787.pdf


For compatibility purposes, two types of MAD are officially defined according to the size of the card’s memory. To explain the difference briefly, MAD1 can be used on any card, while MAD2 can only be used on cards with more than 1K bytes of memory.


2. Store NDEF Messages

In order to store NDEF messages on a Mifare Classic card, the messages need to be encapsulated in something called a TLV block. The basic structure of the TLV block is described as follows:

TLV is an abbreviation for three different dimensions: T: Tag Field L: Length Field Length V: Value Field Value


A TLV block consists of one or more bytes, depending on the presence of the above three dimensions, but at least one byte, since the T field is mandatory in each case.


Tag Field

The label field is a unique mandatory field that uses a single byte to identify the type of the TLV block. Valid values are as follows:


Length Field

The length field contains the length (in bytes) of the numeric field, which can be represented in one or three bytes: a byte format is a simple one-byte numeric value from 0x00 to 0xFF; The three-byte format consists of the following:

Value Field

The value field exists only when the length field exists and is not equal to 0x00. This field is the storage location of payload.


Terminator TLV

The terminator, the last TLV block in the data area, is a fixed single byte: 0xFE. This TLV block is also mandatory.


3. A memory example of a Mifare Classic card with an NDEF record

The example above contains two NDEF records in sector 1:


The first record is the first two bytes of sector 1 block 4: As described above, each record starts with a TLV block, and the first byte of the TLV block (value 0x00) indicates that this is an empty block type. The second byte is the length field and is also 0x00. Therefore, the record has no payload and the value field of the TLV block does not exist. This record is typically inserted when the Mifare Classic card is first formatted to ensure that at least one record exists.


The second record starts at the third byte of block 4 in sector 1 and ends at the sixth byte of block 5:

Similarly, for the first two bytes, according to the DESCRIPTION of the TLV block, the first byte 0x03 means that this is an NDEF Message type, and the second byte 0x11 means that the data length of the block is 17 bytes. The analysis of the next 17 bytes is shown in the following table:


Byte(s)

Value

Description

04:04

0xD1

The record header of the NDEF record. refer to the NDEF record Description section above for a detailed explanation. Bit allocation is as follows:

TNF = 0x01 indicates that the record is of well-known type

IL = 0 indicates that there is no ID field

SR = 1 means this is a short record

CF = 0 means that this block is not the first block

ME = 1 indicates that the current record is the last record

MB = 1 indicates the start of Message

04:05

0x01

NDEF The length of the record type, 1 byte, because the following record type value is 0x55

04:06

0x0D

Indicates the length of payload, which is 13 bytes

04:07

0x55

NDEF Indicates the type of the record. 0x55 indicates the URI type

04:08

0x01

Payload begins, followed by the contents of the payload

04:09.. 05:04

.

Payload Specifies the hexadecimal data

The last byte, 0xFE, is the terminator of the TLV block. It means the end of the block


Related reference links:

• Official website of NXP

https://www.nxp.com/

• NFC BBS

NFC Forum

•Mifare Classic S50

http://www.cnblogs.com/SCPlatform/p/5116180.html


iOS CoreNFC

The following is a simple example of how to use Apple Dad’s CoreNFC, which can only be used to read NDEF information stored on a card.


To this end, I used the STM32F407 microcontroller to pair with the Adafruit PN532 ShieldNFC read and write the information to the card in NDEF format. In this article, I won’t record how to format regular Mifare Classic cards into NDEF format cards and how to write data to NDEF cards (CoreNFC for iOS does not support writing for the time being).


In order for our app to use NFC, we must authorize the application: First, we need to create a certificate that supports NFC, and open the NFC Tag Reading, as shown in the picture below:

After importing the certificate, we need to perform the info.plist configuration for privacy-nfc Scan Usage Description permission, as shown in the figure below:

To implement NFC, we need to import corenfc. framework first and import its header file #import CoreNFC is not supported in the iOS emulator.

1. Initialize the Session

Similar to qr code scanning, NFC also has a Session for information interaction, and this Session should be held during the use of the Session, so the initialization of the Session code is as follows:

@interface NFCTableViewController ()<NFCNDEFReaderSessionDelegate>/** NFC Session */@property (nonatomic, strong) NFCNDEFReaderSession *nfcSession; /** founded NFC Messages */@property (nonatomic, strong) NSMutableArray<NSArray<NFCNDEFMessage *> *> *nfcMessages; @end@implementation NFCTableViewController#pragma mark - initializeNFC- (void)initializeNFCSession {// Create a Session self.nfcSession = [[NFCNDEFReaderSession alloc] initWithDelegate:self queue:dispatch_get_main_queue() invalidateAfterFirstRead:NO]; / / set the Session information prompts the self. The nfcSession. AlertMessage = @"You can scan NFC-tags by holding them behind the top of your iPhone.";
}@endCopy the code

2. Start the Session

If you have a Session, you can start listening. The example code is as follows:

- (IBAction)startSearchBtnClick:(UIBarButtonItem *)sender {    NSLog(@"%s", __func__); // Start Session [self.nfcSession beginSession]; }Copy the code

When the Session starts, the scan panel of the system will be automatically brought up, as shown in the figure below:

3. Listen for agent callbacks

After the Session is started in the above way, the device will automatically start scanning for NDEF format label information. When the scanned label information or any exception occurs, the device will call back through the proxy method, so we need to listen for Session callback information, as shown in the following example:

#pragma mark - NFCNDEFReaderSessionDelegate/*! * @method readerSession:didInvalidateWithError: * * @param session The session object that is invalidated. * @param error The error indicates the invalidation reason. *  * @discussion Gets called when a session becomes invalid. At this point the client is expected to discard * the *//** Callback when an error occurs in the session read by NFC or the session expires. In this case, the client discards the returned session. That is, the session cannot be reused. @param session error session @param error error message */- (void)readerSession:(NFCNDEFReaderSession *)session didInvalidateWithError:(NSError *)error { if (error)
    {        NSLog(@"NFC-Session invalidated: %@", error);
    }    if(self.nfcsession) {// Close the current session [self.nfcsession invalidateSession]; self.nfcSession = nil; } // Re-initialize a new session [self initializeNFCSession]; } / *! * @method readerSession:didDetectNDEFs: * * @param session The session object usedfor tag detection. * @param messages  Array of @link NFCNDEFMessage @link/ objects. The order of the discovery on the tag is maintained. * * @discussion      Gets called when the reader detects NFC tag(s) with NDEF messages in the polling sequence.  Polling *                  is automatically restarted once the detected tag is removed from the reader*//** When the NFC Session reads the NDEF information in the polling queue, the polling will automatically restart once again to check whether the NFC label is out of the read range. @param session read session @param messages read messages */- (void)readerSession:(NFCNDEFReaderSession *)session didDetectNDEFs:(NSArray
      
        *)messages { NSLog(@"New NFC Messages %zd detected:", messages.count); for (NFCNDEFMessage *message in messages) { NSLog(@"- %zd Records:", message.records.count); for (NFCNDEFPayload *record in message.records) { NSLog(@"\t- TNF(TypeNameFormat): %@", [self formattedTypeNameFormat:record.typeNameFormat]); NSLog(@"\t- Payload: %@", [[NSString alloc] initWithData:record.payload encoding:NSUTF8StringEncoding]); NSLog(@"\t- Type: %@", [[NSString alloc] initWithData:record.type encoding:NSUTF8StringEncoding]); NSLog(@"\t- Identifier: %@", [[NSString alloc] initWithData:record.identifier encoding:NSUTF8StringEncoding]); } } [self.nfcMessages addObject:messages]; dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; }); }
      Copy the code