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