Blame view

PN532/examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.pde 6.66 KB
1a2e5ee4   henyxia   Big revision
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  /**************************************************************************/
  /*! 
      This examples attempts to take a Mifare Classic 1K card that has been
      formatted for NDEF messages using mifareclassic_formatndef, and resets
      the authentication keys back to the Mifare Classic defaults
  
      To enable debug message, define DEBUG in PN532/PN532_debug.h
  */
  /**************************************************************************/
  
  #include <SPI.h>
  #include <PN532_SPI.h>
  #include "PN532.h"
  
  PN532_SPI pn532spi(SPI, 10);
  PN532 nfc(pn532spi);
  
  
  #define NR_SHORTSECTOR          (32)    // Number of short sectors on Mifare 1K/4K
  #define NR_LONGSECTOR           (8)     // Number of long sectors on Mifare 4K
  #define NR_BLOCK_OF_SHORTSECTOR (4)     // Number of blocks in a short sector
  #define NR_BLOCK_OF_LONGSECTOR  (16)    // Number of blocks in a long sector
  
  // Determine the sector trailer block based on sector number
  #define BLOCK_NUMBER_OF_SECTOR_TRAILER(sector) (((sector)<NR_SHORTSECTOR)? \
    ((sector)*NR_BLOCK_OF_SHORTSECTOR + NR_BLOCK_OF_SHORTSECTOR-1):\
    (NR_SHORTSECTOR*NR_BLOCK_OF_SHORTSECTOR + (sector-NR_SHORTSECTOR)*NR_BLOCK_OF_LONGSECTOR + NR_BLOCK_OF_LONGSECTOR-1))
  
  // Determine the sector's first block based on the sector number
  #define BLOCK_NUMBER_OF_SECTOR_1ST_BLOCK(sector) (((sector)<NR_SHORTSECTOR)? \
    ((sector)*NR_BLOCK_OF_SHORTSECTOR):\
    (NR_SHORTSECTOR*NR_BLOCK_OF_SHORTSECTOR + (sector-NR_SHORTSECTOR)*NR_BLOCK_OF_LONGSECTOR))
  
  // The default Mifare Classic key
  static const uint8_t KEY_DEFAULT_KEYAB[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  
  void setup(void) {
    Serial.begin(115200);
    Serial.println("Looking for PN532...");
  
    nfc.begin();
  
    uint32_t versiondata = nfc.getFirmwareVersion();
    if (! versiondata) {
      Serial.print("Didn't find PN53x board");
      while (1); // halt
    }
    
    // Got ok data, print it out!
    Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
    Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
    Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
    
    // configure board to read RFID tags
    nfc.SAMConfig();
  }
  
  void loop(void) {
    uint8_t success;                          // Flag to check if there was an error with the PN532
    uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
    uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
    bool authenticated = false;               // Flag to indicate if the sector is authenticated
    uint8_t blockBuffer[16];                  // Buffer to store block contents
    uint8_t blankAccessBits[3] = { 0xff, 0x07, 0x80 };
    uint8_t idx = 0;
    uint8_t numOfSector = 16;                 // Assume Mifare Classic 1K for now (16 4-block sectors)
    
    Serial.println("Place your NDEF formatted Mifare Classic 1K card on the reader");
    Serial.println("and press any key to continue ...");
    
    // Wait for user input before proceeding
    while (!Serial.available());
    while (Serial.available()) Serial.read();
      
    // Wait for an ISO14443A type card (Mifare, etc.).  When one is found
    // 'uid' will be populated with the UID, and uidLength will indicate
    // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
    success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  
    if (success) 
    {
      // We seem to have a tag ...
      // Display some basic information about it
      Serial.println("Found an ISO14443A card/tag");
      Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
      Serial.print("  UID Value: ");
      nfc.PrintHex(uid, uidLength);
      Serial.println("");
      
      // Make sure this is a Mifare Classic card
      if (uidLength != 4)
      {
        Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 
        return;
      }    
      
      Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
      Serial.println("");
      Serial.println("Reformatting card for Mifare Classic (please don't touch it!) ... ");
  
      // Now run through the card sector by sector
      for (idx = 0; idx < numOfSector; idx++)
      {
        // Step 1: Authenticate the current sector using key B 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
        success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), 1, (uint8_t *)KEY_DEFAULT_KEYAB);
        if (!success)
        {
          Serial.print("Authentication failed for sector "); Serial.println(numOfSector);
          return;
        }
        
        // Step 2: Write to the other blocks
        if (idx == 16)
        {
          memset(blockBuffer, 0, sizeof(blockBuffer));
          if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer)))
          {
            Serial.print("Unable to write to sector "); Serial.println(numOfSector);
            return;
          }
        }
        if ((idx == 0) || (idx == 16))
        {
          memset(blockBuffer, 0, sizeof(blockBuffer));
          if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer)))
          {
            Serial.print("Unable to write to sector "); Serial.println(numOfSector);
            return;
          }
        }
        else
        {
          memset(blockBuffer, 0, sizeof(blockBuffer));
          if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer)))
          {
            Serial.print("Unable to write to sector "); Serial.println(numOfSector);
            return;
          }
          if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer)))
          {
            Serial.print("Unable to write to sector "); Serial.println(numOfSector);
            return;
          }
        }
        memset(blockBuffer, 0, sizeof(blockBuffer));
        if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, blockBuffer)))
        {
          Serial.print("Unable to write to sector "); Serial.println(numOfSector);
          return;
        }
        
        // Step 3: Reset both keys to 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
        memcpy(blockBuffer, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB));
        memcpy(blockBuffer + 6, blankAccessBits, sizeof(blankAccessBits));
        blockBuffer[9] = 0x69;
        memcpy(blockBuffer + 10, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB));
  
        // Step 4: Write the trailer block
        if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), blockBuffer)))
        {
          Serial.print("Unable to write trailer block of sector "); Serial.println(numOfSector);
          return;
        }
      }
    }
    
    // Wait a bit before trying again
    Serial.println("\n\nDone!");
    delay(1000);
    Serial.flush();
    while(Serial.available()) Serial.read();
  }