جستجو
منو بسته
خبرخوان

نوشته های بلاگ برچسب خورده با  "mifare"

Rfid MIFARE card memory layout

اصطلاحات

UID = Unique ID   کد یونیک
PICC = short for Proximity Integrated Circuit Card (RFID Tag itself) actually your code header explains this. تگ آر اف آی دی

PCD = (Proximity Coupling Device): NXP MFRC522 Contactless Reader IC کارت خوان

 Block 0 = is read only manufacturer data  شماره کارت و اطلاعات کارخانه

یادگیری ساختار حافظه کارتهای RFID

کارتهای Mifare Classic Card در واقع یک حافظه قابل خواندن و نوشتن هستند .

این کارتها از تعدادی سکتور تشکیل شده اند که هر سکتور خود به چهار بلوک تقسیم می شود و  هر بلوک 16 بایت ظرفیت دارد .

مثلا هر کارت یک کیلو بایتی از 16 سکتور * چهار بلوک * 16 بایت تشکیل شده که جمعا 1024 بایت را تشکیل میدهد  . تصویر اول

 

هر سکتور توسط یک کلید محافظت میشود و بلوک چهارم از هر سکتور شامل کلید دسترسی به آن سکتور است . تصویر دوم

Understanding the memory structure of MIFARE Classic cards

The MIFARE Classic card is a memory storage device. The memory is divided into sectors, which are also divided into blocks of 16 bytes.

The MIFARE Classic 1K card has 16 sectors, each of which are divided into four blocks. If we do the math, we can figure out how the memory structure would be like: 16 bytes (1 block) * 4 blocks * 16 sectors = 1024 bytes.

Mifare Card Memory Layout

 

 

کارت های 4 کیلوبایتی دارای 40 سکتور هستند که 32 سکتور آن به بلوکهای  چهارتایی تقسیم شده اند و هشت سکتور آخر نیز به بلوکهای هشت تایی تقسیم شده اند .

32 سکتور * 4 بلوک * 16 بایت

+

8 سکتور * 16 بلوک * 16 بایت

=4096 بایت

The MIFARE Classic 4K card has 40 sectors, 32 of which are divided into four blocks and the remaining 8 are divided into 16 blocks. 16 bytes (1 block) * 4 blocks * 32 sectors + 16 bytes (1 block) * 16 blocks * 8 sectors = 4096 bytes. The memory structure is as follows:

 

Answer to Request

 

With the Answer to Request sequence the MIFARE® RWD (Read Write Device) requests allMIFARE® cards in the antenna field. When a card is in the operating range of a RWD, theRWD continues communication with the appropriate protocol.

Anticollision loop

In the Anticollision loop the serial number of the card is read. If there are several cards in theoperating range of a RWD they can be distinguished by their different serial numbers and onecan be selected (Select card) for further transactions. The unselected cards return to thestandby mode and wait for a new Answer to Request and Anticollision loop.

 

 

Select Card

With the Select Card command the RWD selects one individual card for further authenticationand memory related operations. The card returns the Answer to Select (ATS) code, whichdetermines the individual type of the selected card.

 

 

Access Specification

After identification and selection of one card the RWD specifies the memory location of the following access.

Three Pass Authentication

The appropriate access key for the previously specified access is used for 3 Pass Authentication. Any communication after authentication is automatically encrypted at the sender and decrypted by the receiver.

Read/Write

After authentication any of the following operations may be performed:

READ          reads one block

WRITE        writes one block

DECREMENT    decrements the contents of one block and stores the result

              in the data-register

INCREMENT    increments the contents of one block and stores the result

              in the data-register

TRANSFER     writes the contents of the data-register to one block

RESTORE      stores the contents of one block in the data-register

 

 

The MF1ICS50 IC of a Mifare Classic has integrated a 8192 Bit EEPROM which is split into 16 sectors with 4 blocks.One block consists of 16 bytes (1 Byte = 8 Bit).

 

 

Manufacturer Code (Block 0 of Sector 0)

The first block of the memory is reserved for manufacturer data like 32 bit serial number. This is a read only block. In many documents it is named "Block 0".

Data Block (Block 0 to 3 except "Block 0")

 

Access conditions for the Data Blocks are defined in the Sector Trailers. According to these conditions data can be read, written, incremented, decremented, transferred or restored either with Key A, Key B or never.

 

 

 

 

 بلوک چهارم از هر سکتور به نام سکتور تریلر شناخته میشود که مانند شکلهای بالا شامل کلید

A کلید B

و چهار بایت قواعد دسترسی می باشد .

 

 

 

 

وضعیت بایتهای 6-7-8 در کارتهای تحویل شده از کارخانه

 

 

If Key B may be read in the corresponding Sector Trailer it cannot serve for authentication (all grey marked lines inprevious table). Consequences: If the RWD tries to authenticate any block of a sector with key B using grey marked

access conditions, the card will refuse any subsequent memory access after authentication

 

 

The described memory organization makes it possible to appoint different sectors to different applications and to prevent data corruption by using application specific secret keys. Keys can only be altered by a RWD which has stored the actual Key A or Key B if this is allowed according to access conditions. Otherwise the actual key cannot be changed any more.

Before the execution of a command the correct format of the Access Conditions is checked by the Card-IC. Thus , when programming the Sector Trailer the card needs to be fixed within the operating range of a RWD's antenna to prevent interruption of the write operation because any unsuccessful write operation may lead to blocking the whole sector.

 

 

 

Example of a New Mifare Classic 1K Card

The follow memory dump illustrates the structure of a 1K Mifare Classic Card, where the data and Sector Trailer blocks can be clearly seen:

برای مشاهده بلوکهای حافظه از نرم افزارهای اندروید زیر استفاده نمایید

MifareClassicTool-2.0.7.apk

MifareClassicTool-2.0.7.apk

دانلود از گوگل پلی استور

------------------------------------------------------------------------------------------------

 

nfctaginfo.apk

دانلود از گوگل پلی استور

نمونه ای از حافظه یک کارت خالی تریلر بلوک شامل کلیدهای آ و بی و قواعد دسترسی به بلوکها کاملا مشخص هستند

 

[--------------------------Start of Memory Dump--------------------------]
------------------------Sector 0-------------------------
Block 0  8E 02 6F 66 85 08 04 00 62 63 64 65 66 67 68 69  ?.of?...bcdefghi
Block 1  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 2  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 3  00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 1-------------------------
Block 4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 5  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 6  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 7  00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 2-------------------------
Block 8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 9  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 11 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 3-------------------------
Block 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 15 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 4-------------------------
Block 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 19 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 5-------------------------
Block 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 23 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 6-------------------------
Block 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 27 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 7-------------------------
Block 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 31 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 8-------------------------
Block 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 35 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 9-------------------------
Block 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 39 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 10-------------------------
Block 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 43 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 11-------------------------
Block 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 47 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 12-------------------------
Block 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 51 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 13-------------------------
Block 52 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 55 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 14-------------------------
Block 56 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 58 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 59 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
------------------------Sector 15-------------------------
Block 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Block 63 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF  ......ÿ.?iÿÿÿÿÿÿ
[---------------------------End of Memory Dump---------------------------]

 

 

 

 

MFRC522.h – A Library to use ARDUINO RFID MODULE KIT 13.56 MHZ BY COOQROBOT.

 

There are three hardware components involved:

 

1) The micro controller: An Arduino

2) The PCD (Proximity Coupling Device): NXP MFRC522 Contactless Reader IC

3) The PICC (short for Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.

 

 

MIFARE Classic 1K (MF1S503x):

 

Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes. The blocks are numbered 0-63.

 

Block 3 in each sector is the Sector Trailer.

*                         Bytes 0-5:   Key A

*                         Bytes 6-8:   Access Bits

*                         Bytes 9:     User data

*                         Bytes 10-15: Key B (or user data)

 

Block 0 is read only manufacturer data.

 

To access a block, an authentication using a key from the block's sector must be performed first.

 

Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11).

 

All keys are set to FFFFFFFFFFFFh at chip delivery.

 

Warning: Please read section 8.7 "Memory Access". It includes this text: if the PICC detects a format violation the whole sector is irreversibly blocked.

  "value block" برای کاربردها تیکتینگ استفاده می شود

To use a block in "value block" mode (for Increment/Decrement operations) you need to change the sector trailer. Use PICC_SetAccessBits() to calculate the bit patterns.

 

Commands sent to the PICC.

 

The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)

 

 

PICC_CMD_REQA = 0x26,    

REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.

PICC_CMD_WUPA = 0x52,           

Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.

PICC_CMD_CT  = 0x88,            

Cascade Tag. Not really a command, but used during anti collision.

PICC_CMD_SEL_CL1    = 0x93,            

Anti collision/Select, Cascade Level 1

PICC_CMD_SEL_CL2    = 0x95,            

Anti collision/Select, Cascade Level 2

PICC_CMD_SEL_CL3    = 0x97,            

Anti collision/Select, Cascade Level 3

PICC_CMD_HLTA = 0x50,           

HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.

 

 

The commands used for MIFARE Classic

Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.

The read/write commands can also be used for MIFARE Ultralight.

 

 

PICC_CMD_MF_AUTH_KEY_A    = 0x60,            

Perform authentication with Key A

PICC_CMD_MF_AUTH_KEY_B    = 0x61,            

Perform authentication with Key B

PICC_CMD_MF_READ           = 0x30,            

Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.

PICC_CMD_MF_WRITE          = 0xA0,            

Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.

PICC_CMD_MF_DECREMENT     = 0xC0,            

Decrements the contents of a block and stores the result in the internal data register.

PICC_CMD_MF_INCREMENT     = 0xC1,            

Increments the contents of a block and stores the result in the internal data register.

PICC_CMD_MF_RESTORE        = 0xC2,            

Reads the contents of a block into the internal data register.

PICC_CMD_MF_TRANSFER      = 0xB0,            

Writes the contents of the internal data register to a block.

 

 

 

List of the functions in the library

 

Functions for setting up the Arduino

 

MFRC522(byte chipSelectPin, byte resetPowerDownPin);

void setSPIConfig();

 

Basic interface functions for communicating with the MFRC522

 

void PCD_WriteRegister(byte reg, byte value);

void PCD_WriteRegister(byte reg, byte count, byte *values);

byte PCD_ReadRegister(byte reg);

void PCD_ReadRegister(byte reg, byte count, byte *values, byte rxAlign = 0);

void setBitMask(unsigned char reg, unsigned char mask);

void PCD_SetRegisterBitMask(byte reg, byte mask);

void PCD_ClearRegisterBitMask(byte reg, byte mask);

byte PCD_CalculateCRC(byte *data, byte length, byte *result);

 

Functions for manipulating the MFRC522

 

void PCD_Init();

void PCD_Reset();

void PCD_AntennaOn();

 

Functions for communicating with PICCs

 

byte PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);

 

 

byte PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);

 

byte PICC_RequestA(byte *bufferATQA, byte *bufferSize);

byte PICC_WakeupA(byte *bufferATQA, byte *bufferSize);

byte PICC_REQA_or_WUPA(   byte command, byte *bufferATQA, byte *bufferSize); 

byte PICC_Select(Uid *uid, byte validBits = 0);

byte PICC_HaltA(); 

 

Functions for communicating with MIFARE PICCs

 

byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);

void PCD_StopCrypto1();

byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);

byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);

byte MIFARE_Decrement(byte blockAddr, long delta);

byte MIFARE_Increment(byte blockAddr, long delta);

byte MIFARE_Restore(byte blockAddr);

byte MIFARE_Transfer(byte blockAddr);

byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);

      

Support functions

 

byte PCD_MIFARE_Transceive(      byte *sendData, byte sendLen, bool acceptTimeout = false);

const char *GetStatusCodeName(byte code);

byte PICC_GetType(byte sak);

const char *PICC_GetTypeName(byte type);

void PICC_DumpToSerial(Uid *uid);

void PICC_DumpMifareClassicToSerial(Uid *uid, byte piccType, MIFARE_Key *key);

void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);

void PICC_DumpMifareUltralightToSerial();

void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);

 

 

Convenience functions - does not add extra functionality

 

bool PICC_IsNewCardPresent();

bool PICC_ReadCardSerial();     

 

Detailed documentation – enum and structures

 

PICC types we can detect. Remember to update PICC_GetTypeName() if you add more.

 

enum PICC_Type

 

Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.

 

enum StatusCode

 

A struct used for passing the UID of a PICC.

 

typedef struct {

       byte          size;        Number of bytes in the UID. 4, 7 or 10.

       byte          uidByte[10];

       byte          sak;          The SAK (Select acknowledge) byte returned

                                  from the PICC after successful selection.

       } Uid

 

A struct used for passing a MIFARE Crypto1 key

 

typedef struct {

       byte          keyByte[MF_KEY_SIZE];

       } MIFARE_Key;

 

Example:

// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.

MFRC522::MIFARE_Key key;

for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

 

Member variables

 

       Uid uid;            Used by PICC_ReadCardSerial().

 

Detailed documentation – functions

 

+Create object instance

MFRC522(

byte chipSelectPin,       Arduino pin used for SPI chip select

byte resetPowerDownPin    Arduino pin used for SPI reset

);

Example:

#include <SPI.h>

#include <MFRC522.h>

#define SS_PIN 10   //Arduino Uno

#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN);       // Create MFRC522 instance.

 

+Initializes the MFRC522 chip.

void MFRC522::PCD_Init()

Example:

void setup() {

       Serial.begin(9600);       // Init serial communications with PC

       SPI.begin();               // Init SPI bus

       mfrc522.PCD_Init();       // Init MFRC522 card

}

 

+Set SPI bus to work with MFRC522 chip.

 

Please call this function if you have changed the SPI config since the MFRC522 constructor was run.

 

void MFRC522::setSPIConfig()

 

+Performs a soft reset on the MFRC522 chip and waits for it to be ready again.

void MFRC522::PCD_Reset()

 

+Turns the antenna on by enabling pins TX1 and TX2.

After a reset these pins are disabled.

void MFRC522::PCD_AntennaOn()

 

+Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.

Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::PICC_RequestA(

byte *bufferATQA,   The buffer to store the ATQA (Answer to request) in

byte *bufferSize    Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.

 

 

+Transmits a Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.

Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::PICC_WakeupA(     

byte *bufferATQA,   The buffer to store the ATQA (Answer to request) in

byte *bufferSize    Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.

 

 

+Transmits SELECT/ANTICOLLISION commands to select a single PICC.

Before calling this function the PICCs must be placed in the READY(*) state by calling PICC_RequestA() or PICC_WakeupA().

On success:

 

-The chosen PICC is in state ACTIVE(*) and all other PICCs have returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.)

-The UID size and value of the chosen PICC is returned in *uid along with the SAK.

 

 

A PICC UID consists of 4, 7 or 10 bytes.

Only 4 bytes can be specified in a SELECT command, so for the longer UIDs two or three iterations are used:

 

UID size     Number of UID bytes        Cascade levels      Example of PICC

========     ===================        ==============      ===============

single              4                    1                    MIFARE Classic

double              7                    2                    MIFARE Ultralight

triple              10                  3                    Not currently in use?

 

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::PICC_Select(

Uid *uid,                  Pointer to Uid struct. Normally output, but can also

                           be used to supply a known UID.

 

byte validBits             The number of known UID bits supplied in *uid.

 

                           Normally 0. If set you must also supply uid->size.

 

Description of buffer structure:

 

Byte 0: SEL         Indicates the Cascade Level: PICC_CMD_SEL_CL1, PICC_CMD_SEL_CL2 or PICC_CMD_SEL_CL3

Byte 1: NVB                Number of Valid Bits (in complete command, not just the UID): High nibble: complete bytes, Low nibble: Extra bits.

Byte 2: UID-data or CT    See explanation below. CT means Cascade Tag.

Byte 3: UID-data

Byte 4: UID-data

Byte 5: UID-data

Byte 6: BCC                Block Check Character - XOR of bytes 2-5

Byte 7: CRC_A

Byte 8: CRC_A

 

The BCC and CRC_A is only transmitted if we know all the UID bits of the current Cascade Level.

Description of bytes 2-5: (Section 6.5.4 of the ISO/IEC 14443-3 draft: UID contents and cascade levels)

 

UID size     Cascade levelByte2  Byte3  Byte4  Byte5

========     ==================  =====  =====  =====

4 bytes             1             uid0   uid1   uid2   uid3

7 bytes             1             CT     uid0   uid1   uid2

                     2             uid3   uid4   uid5   uid6

10 bytes            1             CT     uid0   uid1   uid2

                     2             CT     uid3   uid4   uid5

 

 

 

+Instructs a PICC in state ACTIVE(*) to go to state HALT.

return STATUS_OK on success, STATUS_??? otherwise.

byte PICC_HaltA();

Example:

// Halt PICC

mfrc522.PICC_HaltA();

 

 

+Executes the MFRC522 MFAuthent command.

This command manages MIFARE authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card.

The authentication is described in the MFRC522 datasheet section 10.3.1.9 and http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1. for use with MIFARE Classic PICCs.

The PICC must be selected - ie in state ACTIVE(*) - before calling this function.

Remember to call PCD_StopCrypto1() at the end of communication with the authenticated PICC - otherwise no new communications can start.

All keys are set to FFFFFFFFFFFFh at chip delivery.

return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you supply the wrong key.

byte MFRC522::PCD_AuthenticateI(

byte command,       PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B

byte blockAddr,            The block number. See numbering in the comments in

                          the .h file.

MIFARE_Key *key,           Pointer to the Crypto1 key to use (6 bytes)

Uid *uid                   Pointer to Uid struct. The first 4 bytes of the UID

                           is used.

)

Example:

MFRC522::MIFARE_Key key;

for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

byte trailerBlock   = 7;

byte status;

if ( ! mfrc522.PICC_ReadCardSerial()) return;

status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));

if (status != MFRC522::STATUS_OK) {

   Serial.print("PCD_Authenticate() failed: ");

   Serial.println(mfrc522.GetStatusCodeName(status));

   return;

}

 

+Used to exit the PCD from its authenticated state.

Remember to call PCD_StopCrypto1() at the end of communication with the authenticated PICC - otherwise no new communications can start.

void MFRC522::PCD_StopCrypto1()

Example:

// Stop encryption on PCD

mfrc522.PCD_StopCrypto1();                           

 

+Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC.

For MIFARE Classic the sector containing the block must be authenticated before calling this function.

For MIFARE Ultralight only addresses 00h to 0Fh are decoded.

* The MF0ICU1 returns a NAK for higher addresses.

* The MF0ICU1 responds to the READ command by sending 16 bytes starting from

      the page address defined by the command argument.

* For example; if blockAddr is 03h then pages 03h, 04h, 05h, 06h are returned.

* A roll-back is implemented: If blockAddr is 0Eh, then the contents of pages 0Eh, 0Fh, 00h and 01h are returned.

The buffer must be at least 18 bytes because a CRC_A is also returned.

Checks the CRC_A before returning STATUS_OK.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_Read(

byte blockAddr,     MIFARE Classic: The block (0-0xff) number.

                     MIFARE Ultralight: The first page to return data from.

byte *buffer,The buffer to store the data in

 

byte *bufferSize    Buffer size, at least 18 bytes. Also number of bytes returned

                    if STATUS_OK.

Example:

byte valueBlockA   = 4; byte buffer[18]; byte size = sizeof(buffer);

byte status = mfrc522.MIFARE_Read(valueBlockA, buffer, &size);

 

+Writes 16 bytes to the active PICC.

For MIFARE Classic the sector containing the block must be authenticated before calling this function.

For MIFARE Ultralight the operation is called "COMPATIBILITY WRITE".

Even though 16 bytes are transferred to the Ultralight PICC, only the least significant 4 bytes (bytes 0 to 3)are written to the specified address. It is recommended to set the remaining bytes 04h to 0Fh to all logic 0.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_Write(     

byte blockAddr,

                     MIFARE Classic: The block (0-0xff) number.

                     MIFARE Ultralight: The page (2-15) to write to.

byte *buffer,The 16 bytes to write to the PICC

byte bufferSize     Buffer size, must be at least 16 bytes. Exactly 16 bytes are

                     written.

Example:

byte valueBlockA   = 4;

byte value1Block[] = { 1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16};

status = mfrc522.MIFARE_Write(valueBlockA, value1Block, 16);

if (status != MFRC522::STATUS_OK) {

   Serial.print("MIFARE_Write() failed: ");

   Serial.println(mfrc522.GetStatusCodeName(status));

}

                                        

 

+MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.

For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.

Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].

Use MIFARE_Transfer() to store the result in a block.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_Decrement(

byte blockAddr,     The block (0-0xff) number.

long delta          This number is subtracted from the value of block blockAddr.

 

             

+MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.

For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.

Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].

Use MIFARE_Transfer() to store the result in a block.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_Increment( 

byte blockAddr,     The block (0-0xff) number.

long delta          This number is added to the value of block blockAddr.            

Example:

// Add 1 to the value of valueBlockA and store the result in valueBlockA.

byte valueBlockA    = 5;

Serial.print("Adding 1 to value of block "); Serial.println(valueBlockA);

byte status = mfrc522.MIFARE_Increment(valueBlockA, 1);

if (status != MFRC522::STATUS_OK) {

       Serial.print("MIFARE_Increment() failed: ");

       Serial.println(mfrc522.GetStatusCodeName(status));

       return;

}

status = mfrc522.MIFARE_Transfer(valueBlockA);

if (status != MFRC522::STATUS_OK) {

       Serial.print("MIFARE_Transfer() failed: ");

       Serial.println(mfrc522.GetStatusCodeName(status));

       return;

}

                          

 

+MIFARE Restore copies the value of the addressed block into a volatile memory.

For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.

Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].

Use MIFARE_Transfer() to store the result in a block.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_Restore(   

byte blockAddr      The block (0-0xff) number.

The datasheet describes Restore as a two step operation, but does not explain what data to transfer in step 2.Doing only a single step does not work, so I chose to transfer 0L in step two.

 

+Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_TwoStepHelper(   

byte command,The command to use

byte blockAddr,     The block (0-0xff) number.

long data           The data to transfer in step 2

                                                              )

 

+MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.

For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.

Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].

return STATUS_OK on success, STATUS_??? otherwise.

byte MFRC522::MIFARE_Transfer(  

byte blockAddr      The block (0-0xff) number.

                                               

 

+Returns a string pointer to a status code name.

const char *MFRC522::GetStatusCodeName(

byte code    One of the StatusCode enums.

                                                      

       code values         return values

       STATUS_OK:                "Success."

       STATUS_ERROR:             "Error in communication."

       STATUS_COLLISION:  "Collision detected."

       STATUS_TIMEOUT:           "Timeout in communication."

       STATUS_NO_ROOM:           "A buffer is not big enough."

       STATUS_INTERNAL_ERROR:   "Internal error in the code. Should not happen."

       STATUS_INVALID:           "Invalid argument."

       STATUS_CRC_WRONG:  "The CRC_A does not match."

       STATUS_MIFARE_NACK:      "A MIFARE PICC responded with NAK."

       default:                  "Unknown error"

      

Example:

Serial.println(mfrc522.GetStatusCodeName(status));

 

+Translates the SAK (Select Acknowledge) to a PICC type.

return PICC_Type

byte MFRC522::PICC_GetType(

byte sak            The SAK byte returned from PICC_Select().

 

                    

sak                 return value

sak & 0x04          PICC_TYPE_NOT_COMPLETE

0x09                PICC_TYPE_MIFARE_MINI

0x08                PICC_TYPE_MIFARE_1K

0x18                PICC_TYPE_MIFARE_4K

0x00                PICC_TYPE_MIFARE_UL

0x10 or 0x11PICC_TYPE_MIFARE_PLUS

0x01                PICC_TYPE_TNP3XXX

sak & 0x20          PICC_TYPE_ISO_14443_4

sak & 0x40          PICC_TYPE_ISO_18092

else                PICC_TYPE_UNKNOWN

 

+Returns a string pointer to the PICC type name.

const char *MFRC522::PICC_GetTypeName(

byte piccTypeOne of the PICC_Type enums.

 

 

piccType                   return value

PICC_TYPE_ISO_14443_4     "PICC compliant with ISO/IEC 14443-4"

PICC_TYPE_ISO_18092:      "PICC compliant with ISO/IEC 18092 (NFC)"

PICC_TYPE_MIFARE_MINI     "MIFARE Mini, 320 bytes"

PICC_TYPE_MIFARE_1K"MIFARE 1KB"

PICC_TYPE_MIFARE_4K"MIFARE 4KB"

PICC_TYPE_MIFARE_UL"MIFARE Ultralight or Ultralight C"

PICC_TYPE_MIFARE_PLUS     "MIFARE Plus"

 

PICC_TYPE_TNP3XXX          "MIFARE TNP3XXX"

PICC_TYPE_NOT_COMPLETE    "SAK indicates UID is not complete."

PICC_TYPE_UNKNOWN          "Unknown type”

Example:

Serial.println(mfrc522.PICC_GetTypeName(piccType));

 

+Dumps debug info about the selected PICC to Serial.

On success the PICC is halted after dumping the data.

For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.

void MFRC522::PICC_DumpToSerial(

Uid *uid     Pointer to Uid struct returned from a successful PICC_Select().

Example:

mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

 

+Dumps memory contents of a sector of a MIFARE Classic PICC.

Uses PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1.

Always uses PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer access bits.

void MFRC522::PICC_DumpMifareClassicSectorToSerial(

Uid *uid,           Pointer to Uid struct returned from a successful PICC_Select()

MIFARE_Key *key,    Key A for the sector.

byte sector         The sector to dump, 0..39.

 

+Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).

void MFRC522::MIFARE_SetAccessBits(   

byte *accessBitBuffer,    Pointer to byte 6, 7 and 8 in the sector trailer.

                          Bytes [0..2] will be set.

 

byte g0,                   Access bits [C1 C2 C3] for block 0

                           (for sectors 0-31) or blocks 0-4 (for sectors 32-39)

 

byte g1,                   Access bits C1 C2 C3] for block 1 (for sectors 0-31)

                           or blocks 5-9 (for sectors 32-39)

 

byte g2,                   Access bits C1 C2 C3] for block 2 (for sectors 0-31)

                           or blocks 10-14 (for sectors 32-39)

 

byte g3                    Access bits C1 C2 C3] for the sector trailer, block 3

                           (for sectors 0-31) or block 15 (for sectors 32-39)

 

The access bits are stored in a peculiar fashion.

There are four groups:

 

g[3]   Access bits for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)

 

g[2]   Access bits for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)

g[1]   Access bits for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)

g[0]   Access bits for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)

 

Each group has access bits [C1 C2 C3]. In this code C1 is MSB and C3 is LSB.

The four CX bits are stored together in a nibble cx and an inverted nibble cx_.

Example:

// Sector trailer that defines blocks 5 and 6 as Value Blocks and enables key B.

byte trailerBuffer[] = {255,255,255,255,255,255,0,0,0,0, 255,255,255,255,255,255};

// Keep default keys.

// g1=6(i.e.110) => block 5 value block. Key B write&increment, A or B decrement.

// g2=6 => Same thing for block 6.

// g3=3 => Key B must be used to modify the Sector Trailer. Key B becomes valid.

mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3);

 

+Check if a card is present

bool MFRC522::PICC_IsNewCardPresent()

Returns true if a PICC responds to PICC_CMD_REQA.

Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored.

Example:

// Look for new cards

if ( ! mfrc522.PICC_IsNewCardPresent()) return;

 

 

+Read Card Serial

bool MFRC522::PICC_ReadCardSerial()

Simple wrapper around PICC_Select.

Returns true if a UID could be read.The read UID is available in the class variable uid.

Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or PICC_WakeupA() first.

return true if one selected

Now a card is selected. The UID and SAK is in mfrc522.uid.

Example:

Serial.print("Card UID:");

for (byte i = 0; i < mfrc522.uid.size; i++) {

   Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");

   Serial.print(mfrc522.uid.uidByte[i], HEX);

}

// Dump PICC type

byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);

Serial.print("PICC type: ");

Serial.println(mfrc522.PICC_GetTypeName(piccType));

if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI

     && piccType != MFRC522::PICC_TYPE_MIFARE_1K

     &&       piccType != MFRC522::PICC_TYPE_MIFARE_4K) {

     Serial.println("This sample only works with MIFARE Classic cards.");

     return;

}

 

How to convert a normal block into a value block

Usually a normal block has 000 access bits, while a value block has 110 access bits

Example:

byte valueBlockA    = 5;

byte valueBlockB    = 6;

byte trailerBlock   = 7;

// We need a sector trailer with blocks 5 and 6 as Value Blocks and enables key B.

byte trailerBuffer[] = { 255,255,255,255,255,255,

                          0,0,0,0,255,255,255,255,255,255}; // Keep default keys.

// g1=6 => block 5 as value block. Key B to write&increment, A or B for decrement.

// g2=6 => Same thing for block 6.

// g3=3 => Key B must be used to modify the Sector Trailer. Key B becomes valid.

mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3);

byte status = mfrc522.MIFARE_Write(trailerBlock, trailerBuffer, 16);

if (status != MFRC522::STATUS_OK) {

       Serial.print("MIFARE_Write() failed: ");

       Serial.println(mfrc522.GetStatusCodeName(status));

       return;

}     

 

How to setup a Value Block with a value set to zero

Example:

byte blockAddr=5;

byte valueBlock[] = {0,0,0,0, 255,255,255,255, 0,0,0,0,                                                           blockAddr,~blockAddr,blockAddr,~blockAddr };

byte status = mfrc522.MIFARE_Write(blockAddr, valueBlock, 16);

if (status != MFRC522::STATUS_OK) {

       Serial.print("MIFARE_Write() failed: ");

       Serial.println(mfrc522.GetStatusCodeName(status));

}

 

 

 

 

تغییر کلیدهای A و B مایفر
برای تغییر کلیدهای A و B کارتهای مایفر باید در تریلر بلوک هر سکتور اطلاعات را بنویسیم .
همانطور که قبلا گفته شد تریلر بلوک Trailer Block شامل 16 بایت است که 6 بایت کلید A و 4 بایت قواعد دسترسی و 6 بایت کلید B میباشد .
 
// In this sample we use the second sector,
    // that is: sector #1, covering block #4 up to and including block #7
    byte sector         = 1;
    byte valueBlockA    = 5;
    byte valueBlockB    = 6;
    byte trailerBlock   = 7;      //شماره تریلر بلوک در واقع بلوک 4 از سکتور 2
    MFRC522::StatusCode status;
    byte buffer[18];
    byte size = sizeof(buffer);
    long value;

    // Authenticate using key A تایید اعتبار با کلید آ
    Serial.println(F("Authenticating using key A..."));
    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
    if (status != MFRC522::STATUS_OK) {
        Serial.print(F("PCD_Authenticate() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
    }

    // Show the whole sector as it currently is
    Serial.println(F("Current data in sector:"));
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
    Serial.println();
    
    // We need a sector trailer that defines blocks 5 and 6 as Value Blocks and enables key B
    // The last block in a sector (block #3 for Mifare Classic 1K) is the Sector Trailer.
    // See http://www.nxp.com/documents/data_sheet/MF1S503x.pdf sections 8.6 and 8.7:
    //      Bytes 0-5:   Key A
    //      Bytes 6-8:   Access Bits
    //      Bytes 9:     User data
    //      Bytes 10-15: Key B (or user data)
   // ابتدا تریلر بلاک را به صورت یک آرایه از نوع بایت تعریف کرده و 6 بایت کلید آ و 6 بایت کلید ب را مینویسیم و 4 بایت قواعد دسترسی را صفر قرار میدهیم
   // البته میتوان از همان اول قواعد دسترسی را نوشت ولی راه درست استفاده از تابع اکسس بیت است
    byte trailerBuffer[] = {
        32, 33, 34, 35, 36, 37,       // Keep default key A
        0, 0, 0,
        0,
        42, 43, 44, 45, 46, 47};      // Keep default key B

    // The access bits are stored in a peculiar fashion.
    // There are four groups:
    //      g[0]    Access bits for block 0 (for sectors 0-31)  این پارامتر دسترسی به بلاک 0 در سکتورهای 0 تا31 است-نکته کارتهای 1 کیلوبایتی 16 و کارتهای 2 کیلوبایتی 32 سکتور دارند و کارتهای 4 کیلوبایتی 39 سکتور دارند .
    //              or blocks 0-4 (for sectors 32-39)
    //      g[1]    Access bits for block 1 (for sectors 0-31)  این پارامتر دسترسی به بلاک ۱ در سکتورهای 0 تا31 است
    //              or blocks 5-9 (for sectors 32-39)
    //      g[2]    Access bits for block 2 (for sectors 0-31) این پارامتر دسترسی به بلاک 2 در سکتورهای 0 تا31 است
    //              or blocks 10-14 (for sectors 32-39)
    //      g[3]    Access bits for the Sector Trailer: block 3 (for sectors 0-31) این پارامتر دسترسی به بلاک 3 یا تریلر بلوک در سکتورهای 0 تا31 است
    //              or block 15 (for sectors 32-39)
    // Each group has access bits [C1 C2 C3], in this code C1 is MSB and C3 is LSB.
    // Determine the bit pattern needed using MIFARE_SetAccessBits:
    //      g0=0    access bits for block 0 (of this sector) using [0 0 0] = 000b = 0
    //              which means key A|B have r/w for block 0 of this sector
    //              which (in this example) translates to block #4 within sector #1;
    //              this is the transport configuration (at factory delivery).
    //      g1=6    access bits for block 1 (of this sector) using [1 1 0] = 110b = 6
    //              which means block 1 (of this sector) is used as a value block,
    //              which (in this example) translates to block #5 within sector #1;
    //              where key A|B have r, key B has w, key B can increment,
    //              and key A|B can decrement, transfer, and restore.
    //      g2=6    same thing for block 2 (of this sector): set it to a value block;
    //              which (in this example) translates to block #6 within sector #1;
    //      g3=3    access bits for block 3 (of this sector): the Sector Trailer here;
    //              using [0 1 1] = 011b = 3 which means only key B has r/w access
    //              to the Sector Trailer (block 3 of this sector) from now on
    //              which (in this example) translates to block #7 within sector #1;
    Serial.println("=========================================");
    Serial.println(trailerBuffer[6]);
    Serial.println(trailerBuffer[7]);
    Serial.println(trailerBuffer[8]);
    Serial.println(trailerBuffer[9]);
    Serial.println("==========================================");
    mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3);
    Serial.println(trailerBuffer[6]);
    Serial.println(trailerBuffer[7]);
    Serial.println(trailerBuffer[8]);
    Serial.println(trailerBuffer[9]);
    Serial.println("===========================================");

    // Read the sector trailer as it is currently stored on the PICC
    Serial.println(F("Reading sector trailer..."));
    status = mfrc522.MIFARE_Read(trailerBlock, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
    }
    Serial.println(mfrc522.GetStatusCodeName(status));
    // Check if it matches the desired access pattern already;
    // because if it does, we don't need to write it again...
    Serial.println("===========>>>>>>KEY_A>>>>>>===========");
    Serial.println(buffer[0]);
    Serial.println(buffer[1]);
    Serial.println(buffer[2]);
    Serial.println(buffer[3]);
    Serial.println(buffer[4]);
    Serial.println(buffer[5]);
    Serial.println("===========>>>>>>ACCESS_CONDITIONS>>>>>>===========");
    Serial.println(buffer[6]);
    Serial.println(buffer[7]);
    Serial.println(buffer[8]);
    Serial.println(buffer[9]);
    Serial.println("=========>>>>>>KEY_B>>>>>>===========");
    Serial.println(buffer[10]);
    Serial.println(buffer[11]);
    Serial.println(buffer[12]);
    Serial.println(buffer[13]);
    Serial.println(buffer[14]);
    Serial.println(buffer[15]);
    Serial.println("============>>>>>>>>>>>>>>>>===========");
    if (    buffer[6] != trailerBuffer[6]
        &&  buffer[7] != trailerBuffer[7]
        &&  buffer[8] != trailerBuffer[8]) {
        // They don't match (yet), so write it to the PICC
        Serial.println(F("Writing new sector trailer..."));
        status = mfrc522.MIFARE_Write(trailerBlock, trailerBuffer, 16);
        if (status != MFRC522::STATUS_OK) {
            Serial.print(F("MIFARE_Write() failed: "));
            Serial.println(mfrc522.GetStatusCodeName(status));
            return;
        }
    }