How do you read the memory of a Type 2 tag page by page?
With the READ command, 0x30 followed by a page number, which returns sixteen bytes: four pages of four bytes each. Pages 0 to 2 hold the identifier and the static lock bytes, page 3 holds the capability container, and content starts at page 4. What follows the data area depends on the chip.
READ returns four pages
Type 2 memory is counted in pages of four bytes. READ, command 0x30 followed by the number of the first page, returns sixteen bytes, that page and the three after it. WRITE, 0xA2 followed by a page number and four bytes, writes a single page. Both values are in the definitions of Android's open source NFC stack; the normative text is the NFC Forum Type 2 Tag specification, which the Forum sells.
On Android, MifareUltralight.readPages() sends the READ and writePage() the WRITE. The class is optional, and a phone that lacks it still lists NfcA for the same tag, whose transceive() sends the same command. On iOS, a tag of the Ultralight family arrives as NFCMiFareTag, and the command goes through sendMiFareCommand, with the CRC that Apple's reference asks for.
The last pages need care. According to the MifareUltralight reference, a READ that runs past the last readable page returns pages wrapped back to the first: on an original MIFARE Ultralight, reading from page 0x0E returns pages 0x0E, 0x0F, 0x00 and 0x01. Code that reads the end of memory keeps only the pages it asked for.
The first four pages
The first sixteen bytes describe the tag. Pages 0 to 2 hold the identifier and internal bytes, and the last two bytes of page 2 are the static lock bytes, whose bits make pages read only for good. Page 3 is the capability container, described in general on the capability container page:
| Byte | Holds | Values in the Android stack |
|---|---|---|
| 0 | NDEF magic number | 0xE1 |
| 1 | Version of the mapping | 0x10, 0x11 or 0x12 |
| 2 | Size of the data area, divided by 8 | 0x12 announces 144 bytes |
| 3 | Access to the data area | 0x00 read and write, 0x0F read only |
A tag whose byte 0 is anything other than 0xE1 is not formatted for NDEF. Byte 3 matters as much as the lock bits: the Android stack refuses to write NDEF when it does not grant write access, whatever the lock bits say.
Finding the NDEF message
From page 4, the data area holds a sequence of TLV blocks: a type byte, a length, then the value. The types are few:
| Type | Block |
|---|---|
0x00 | NULL, padding that readers skip |
0x01 | Lock Control, which describes the lock bytes |
0x02 | Memory Control, which marks reserved areas |
0x03 | The NDEF message |
0xFD | Proprietary information |
0xFE | Terminator, the last block of the data area |
The length takes one byte up to 254, and three bytes from 255: 0xFF, then the length on two bytes. Code walks the blocks from page 4, skips those it does not need, and reads the message where the 0x03 block says it is. It does not assume the message starts at page 4, since a Lock Control or Memory Control block can come first.
Byte 2 of the capability container bounds the walk. Beyond 64 bytes, the size the Android stack treats as the static layout, a tag has dynamic lock bytes as well, and a Lock Control block, where present, tells where they are.
Where the chip takes over
What follows the data area belongs to the chip: dynamic lock bytes, configuration, counters, the password. An NTAG213 has 45 pages, its dynamic lock bytes in page 40 and its configuration in pages 41 to 44, according to its fiche on wakdev.com; an NTAG215 has 135 pages and keeps the same settings in pages 130 to 134. Code reads these pages from the fiche of the chip in hand, never from a page number that worked on another.
Reading can itself change something. A chip with a read counter increments it on the first read after the tag enters the field, as the NTAG213 fiche describes, and a chip whose password protects reading refuses READ on the protected pages until the code authenticates, as the authentication page explains.
Frequently asked questions
Can I read a Type 2 tag without the MifareUltralight class?
Yes. Every such tag also reports NfcA, whose transceive method sends the same READ command, 0x30 followed by the page number.
Why do the last bytes I read repeat the first pages?
The read ran past the end of memory and wrapped around, as the MifareUltralight reference describes. Keep only the pages you asked for.
Where does the NDEF message start?
Where the TLV block of type 0x03 says, found by walking the blocks from page 4. Other blocks can come before it.
Does reading a tag change it?
Not its content. On a chip with a read counter, the first read after the tag enters the field increments the counter.