
The mbed code for our second prototype
PN532/Adafruit_PN532.cpp@0:76b77ec0a86d, 2014-11-17 (annotated)
- Committer:
- smcqueen
- Date:
- Mon Nov 17 01:09:06 2014 +0000
- Revision:
- 0:76b77ec0a86d
Final code for prototype 2
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
smcqueen | 0:76b77ec0a86d | 1 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 2 | /*! |
smcqueen | 0:76b77ec0a86d | 3 | @file Adafruit_PN532.cpp |
smcqueen | 0:76b77ec0a86d | 4 | @author Adafruit Industries |
smcqueen | 0:76b77ec0a86d | 5 | @license BSD (see license.txt) |
smcqueen | 0:76b77ec0a86d | 6 | |
smcqueen | 0:76b77ec0a86d | 7 | SPI Driver for NXP's PN532 NFC/13.56MHz RFID Transceiver |
smcqueen | 0:76b77ec0a86d | 8 | |
smcqueen | 0:76b77ec0a86d | 9 | This is a library for the Adafruit PN532 NFC/RFID breakout boards |
smcqueen | 0:76b77ec0a86d | 10 | This library works with the Adafruit NFC breakout |
smcqueen | 0:76b77ec0a86d | 11 | ----> https://www.adafruit.com/products/364 |
smcqueen | 0:76b77ec0a86d | 12 | |
smcqueen | 0:76b77ec0a86d | 13 | Check out the links above for our tutorials and wiring diagrams |
smcqueen | 0:76b77ec0a86d | 14 | These chips use SPI to communicate, 4 required to interface |
smcqueen | 0:76b77ec0a86d | 15 | |
smcqueen | 0:76b77ec0a86d | 16 | Adafruit invests time and resources providing this open source code, |
smcqueen | 0:76b77ec0a86d | 17 | please support Adafruit and open-source hardware by purchasing |
smcqueen | 0:76b77ec0a86d | 18 | products from Adafruit! |
smcqueen | 0:76b77ec0a86d | 19 | |
smcqueen | 0:76b77ec0a86d | 20 | |
smcqueen | 0:76b77ec0a86d | 21 | @section HISTORY |
smcqueen | 0:76b77ec0a86d | 22 | |
smcqueen | 0:76b77ec0a86d | 23 | v1.4 - Added setPassiveActivationRetries() |
smcqueen | 0:76b77ec0a86d | 24 | |
smcqueen | 0:76b77ec0a86d | 25 | v1.2 - Added writeGPIO() |
smcqueen | 0:76b77ec0a86d | 26 | - Added readGPIO() |
smcqueen | 0:76b77ec0a86d | 27 | |
smcqueen | 0:76b77ec0a86d | 28 | v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes |
smcqueen | 0:76b77ec0a86d | 29 | - Added the following helper functions for text display |
smcqueen | 0:76b77ec0a86d | 30 | static void PrintHex(const uint8_t * data, const uint32_t numuint8_ts) |
smcqueen | 0:76b77ec0a86d | 31 | static void PrintHexChar(const uint8_t * pbtData, const uint32_t numuint8_ts) |
smcqueen | 0:76b77ec0a86d | 32 | - Added the following Mifare Classic functions: |
smcqueen | 0:76b77ec0a86d | 33 | bool mifareclassic_IsFirstBlock (uint32_t uiBlock) |
smcqueen | 0:76b77ec0a86d | 34 | bool mifareclassic_IsTrailerBlock (uint32_t uiBlock) |
smcqueen | 0:76b77ec0a86d | 35 | uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) |
smcqueen | 0:76b77ec0a86d | 36 | uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) |
smcqueen | 0:76b77ec0a86d | 37 | uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) |
smcqueen | 0:76b77ec0a86d | 38 | - Added the following Mifare Ultalight functions: |
smcqueen | 0:76b77ec0a86d | 39 | uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) |
smcqueen | 0:76b77ec0a86d | 40 | */ |
smcqueen | 0:76b77ec0a86d | 41 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 42 | |
smcqueen | 0:76b77ec0a86d | 43 | #include "Adafruit_PN532.h" |
smcqueen | 0:76b77ec0a86d | 44 | |
smcqueen | 0:76b77ec0a86d | 45 | uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00}; |
smcqueen | 0:76b77ec0a86d | 46 | uint8_t pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03}; |
smcqueen | 0:76b77ec0a86d | 47 | |
smcqueen | 0:76b77ec0a86d | 48 | // Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE related code |
smcqueen | 0:76b77ec0a86d | 49 | // #define PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 50 | // #define MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 51 | |
smcqueen | 0:76b77ec0a86d | 52 | Serial serial(USBTX, USBRX); |
smcqueen | 0:76b77ec0a86d | 53 | #define SERIAL_PRINT serial.printf |
smcqueen | 0:76b77ec0a86d | 54 | |
smcqueen | 0:76b77ec0a86d | 55 | #define _BV(bit) (1 << (bit)) |
smcqueen | 0:76b77ec0a86d | 56 | #define PN532_PACKBUFFSIZ 64 |
smcqueen | 0:76b77ec0a86d | 57 | uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ]; |
smcqueen | 0:76b77ec0a86d | 58 | |
smcqueen | 0:76b77ec0a86d | 59 | void delay(int delayInMS) { |
smcqueen | 0:76b77ec0a86d | 60 | wait(1.0 * delayInMS / 1000); |
smcqueen | 0:76b77ec0a86d | 61 | } |
smcqueen | 0:76b77ec0a86d | 62 | |
smcqueen | 0:76b77ec0a86d | 63 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 64 | /*! |
smcqueen | 0:76b77ec0a86d | 65 | @brief Instantiates a new PN532 class |
smcqueen | 0:76b77ec0a86d | 66 | |
smcqueen | 0:76b77ec0a86d | 67 | @param clk SPI clock pin (SCK) |
smcqueen | 0:76b77ec0a86d | 68 | @param miso SPI MISO pin |
smcqueen | 0:76b77ec0a86d | 69 | @param mosi SPI MOSI pin |
smcqueen | 0:76b77ec0a86d | 70 | @param ss SPI chip select pin (CS/SSEL) |
smcqueen | 0:76b77ec0a86d | 71 | */ |
smcqueen | 0:76b77ec0a86d | 72 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 73 | Adafruit_PN532::Adafruit_PN532(DigitalOut clk, DigitalIn miso, |
smcqueen | 0:76b77ec0a86d | 74 | DigitalOut mosi, DigitalOut ss) |
smcqueen | 0:76b77ec0a86d | 75 | : _clk(clk), _miso(miso), _mosi(mosi), _ss(ss) {} |
smcqueen | 0:76b77ec0a86d | 76 | |
smcqueen | 0:76b77ec0a86d | 77 | Adafruit_PN532::Adafruit_PN532(PinName clk_pin, PinName miso_pin, |
smcqueen | 0:76b77ec0a86d | 78 | PinName mosi_pin, PinName ss_pin) |
smcqueen | 0:76b77ec0a86d | 79 | : _clk(DigitalOut(clk_pin)), _miso(DigitalIn(miso_pin)), |
smcqueen | 0:76b77ec0a86d | 80 | _mosi(DigitalOut(mosi_pin)), _ss(DigitalOut(ss_pin)) {} |
smcqueen | 0:76b77ec0a86d | 81 | |
smcqueen | 0:76b77ec0a86d | 82 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 83 | /*! |
smcqueen | 0:76b77ec0a86d | 84 | @brief Setups the HW |
smcqueen | 0:76b77ec0a86d | 85 | */ |
smcqueen | 0:76b77ec0a86d | 86 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 87 | void Adafruit_PN532::begin() { |
smcqueen | 0:76b77ec0a86d | 88 | _ss = 0; |
smcqueen | 0:76b77ec0a86d | 89 | delay(1000); |
smcqueen | 0:76b77ec0a86d | 90 | |
smcqueen | 0:76b77ec0a86d | 91 | // not exactly sure why but we have to send a dummy command to get synced up |
smcqueen | 0:76b77ec0a86d | 92 | pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; |
smcqueen | 0:76b77ec0a86d | 93 | sendCommandCheckAck(pn532_packetbuffer, 1); |
smcqueen | 0:76b77ec0a86d | 94 | |
smcqueen | 0:76b77ec0a86d | 95 | // ignore response! |
smcqueen | 0:76b77ec0a86d | 96 | } |
smcqueen | 0:76b77ec0a86d | 97 | |
smcqueen | 0:76b77ec0a86d | 98 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 99 | /*! |
smcqueen | 0:76b77ec0a86d | 100 | @brief Prints a hexadecimal value in plain characters |
smcqueen | 0:76b77ec0a86d | 101 | |
smcqueen | 0:76b77ec0a86d | 102 | @param data Pointer to the uint8_t data |
smcqueen | 0:76b77ec0a86d | 103 | @param numuint8_ts Data length in uint8_ts |
smcqueen | 0:76b77ec0a86d | 104 | */ |
smcqueen | 0:76b77ec0a86d | 105 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 106 | void Adafruit_PN532::PrintHex(const uint8_t * data, const uint32_t numuint8_ts) |
smcqueen | 0:76b77ec0a86d | 107 | { |
smcqueen | 0:76b77ec0a86d | 108 | uint32_t szPos; |
smcqueen | 0:76b77ec0a86d | 109 | for (szPos=0; szPos < numuint8_ts; szPos++) |
smcqueen | 0:76b77ec0a86d | 110 | { |
smcqueen | 0:76b77ec0a86d | 111 | SERIAL_PRINT("0x"); |
smcqueen | 0:76b77ec0a86d | 112 | // Append leading 0 for small values |
smcqueen | 0:76b77ec0a86d | 113 | if (data[szPos] <= 0xF) |
smcqueen | 0:76b77ec0a86d | 114 | SERIAL_PRINT("0"); |
smcqueen | 0:76b77ec0a86d | 115 | SERIAL_PRINT("%d", data[szPos]); |
smcqueen | 0:76b77ec0a86d | 116 | if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1)) |
smcqueen | 0:76b77ec0a86d | 117 | { |
smcqueen | 0:76b77ec0a86d | 118 | SERIAL_PRINT(" "); |
smcqueen | 0:76b77ec0a86d | 119 | } |
smcqueen | 0:76b77ec0a86d | 120 | } |
smcqueen | 0:76b77ec0a86d | 121 | SERIAL_PRINT("\n"); |
smcqueen | 0:76b77ec0a86d | 122 | } |
smcqueen | 0:76b77ec0a86d | 123 | |
smcqueen | 0:76b77ec0a86d | 124 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 125 | /*! |
smcqueen | 0:76b77ec0a86d | 126 | @brief Prints a hexadecimal value in plain characters, along with |
smcqueen | 0:76b77ec0a86d | 127 | the char equivalents in the following format |
smcqueen | 0:76b77ec0a86d | 128 | |
smcqueen | 0:76b77ec0a86d | 129 | 00 00 00 00 00 00 ...... |
smcqueen | 0:76b77ec0a86d | 130 | |
smcqueen | 0:76b77ec0a86d | 131 | @param data Pointer to the uint8_t data |
smcqueen | 0:76b77ec0a86d | 132 | @param numuint8_ts Data length in uint8_ts |
smcqueen | 0:76b77ec0a86d | 133 | */ |
smcqueen | 0:76b77ec0a86d | 134 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 135 | void Adafruit_PN532::PrintHexChar(const uint8_t * data, const uint32_t numuint8_ts) |
smcqueen | 0:76b77ec0a86d | 136 | { |
smcqueen | 0:76b77ec0a86d | 137 | uint32_t szPos; |
smcqueen | 0:76b77ec0a86d | 138 | for (szPos=0; szPos < numuint8_ts; szPos++) |
smcqueen | 0:76b77ec0a86d | 139 | { |
smcqueen | 0:76b77ec0a86d | 140 | // Append leading 0 for small values |
smcqueen | 0:76b77ec0a86d | 141 | if (data[szPos] <= 0xF) |
smcqueen | 0:76b77ec0a86d | 142 | SERIAL_PRINT("0"); |
smcqueen | 0:76b77ec0a86d | 143 | SERIAL_PRINT("%x", data[szPos]); |
smcqueen | 0:76b77ec0a86d | 144 | if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1)) |
smcqueen | 0:76b77ec0a86d | 145 | { |
smcqueen | 0:76b77ec0a86d | 146 | SERIAL_PRINT(" "); |
smcqueen | 0:76b77ec0a86d | 147 | } |
smcqueen | 0:76b77ec0a86d | 148 | } |
smcqueen | 0:76b77ec0a86d | 149 | SERIAL_PRINT(" "); |
smcqueen | 0:76b77ec0a86d | 150 | for (szPos=0; szPos < numuint8_ts; szPos++) |
smcqueen | 0:76b77ec0a86d | 151 | { |
smcqueen | 0:76b77ec0a86d | 152 | if (data[szPos] <= 0x1F) |
smcqueen | 0:76b77ec0a86d | 153 | SERIAL_PRINT("."); |
smcqueen | 0:76b77ec0a86d | 154 | else |
smcqueen | 0:76b77ec0a86d | 155 | SERIAL_PRINT("%c", data[szPos]); |
smcqueen | 0:76b77ec0a86d | 156 | } |
smcqueen | 0:76b77ec0a86d | 157 | SERIAL_PRINT(""); |
smcqueen | 0:76b77ec0a86d | 158 | } |
smcqueen | 0:76b77ec0a86d | 159 | |
smcqueen | 0:76b77ec0a86d | 160 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 161 | /*! |
smcqueen | 0:76b77ec0a86d | 162 | @brief Checks the firmware version of the PN5xx chip |
smcqueen | 0:76b77ec0a86d | 163 | |
smcqueen | 0:76b77ec0a86d | 164 | @returns The chip's firmware version and ID |
smcqueen | 0:76b77ec0a86d | 165 | */ |
smcqueen | 0:76b77ec0a86d | 166 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 167 | uint32_t Adafruit_PN532::getFirmwareVersion(void) { |
smcqueen | 0:76b77ec0a86d | 168 | uint32_t response; |
smcqueen | 0:76b77ec0a86d | 169 | |
smcqueen | 0:76b77ec0a86d | 170 | pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; |
smcqueen | 0:76b77ec0a86d | 171 | |
smcqueen | 0:76b77ec0a86d | 172 | if (! sendCommandCheckAck(pn532_packetbuffer, 1)) |
smcqueen | 0:76b77ec0a86d | 173 | return 0; |
smcqueen | 0:76b77ec0a86d | 174 | |
smcqueen | 0:76b77ec0a86d | 175 | // read data packet |
smcqueen | 0:76b77ec0a86d | 176 | readspidata(pn532_packetbuffer, 12); |
smcqueen | 0:76b77ec0a86d | 177 | |
smcqueen | 0:76b77ec0a86d | 178 | // check some basic stuff |
smcqueen | 0:76b77ec0a86d | 179 | if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) { |
smcqueen | 0:76b77ec0a86d | 180 | return 0; |
smcqueen | 0:76b77ec0a86d | 181 | } |
smcqueen | 0:76b77ec0a86d | 182 | |
smcqueen | 0:76b77ec0a86d | 183 | response = pn532_packetbuffer[6]; |
smcqueen | 0:76b77ec0a86d | 184 | response <<= 8; |
smcqueen | 0:76b77ec0a86d | 185 | response |= pn532_packetbuffer[7]; |
smcqueen | 0:76b77ec0a86d | 186 | response <<= 8; |
smcqueen | 0:76b77ec0a86d | 187 | response |= pn532_packetbuffer[8]; |
smcqueen | 0:76b77ec0a86d | 188 | response <<= 8; |
smcqueen | 0:76b77ec0a86d | 189 | response |= pn532_packetbuffer[9]; |
smcqueen | 0:76b77ec0a86d | 190 | |
smcqueen | 0:76b77ec0a86d | 191 | return response; |
smcqueen | 0:76b77ec0a86d | 192 | } |
smcqueen | 0:76b77ec0a86d | 193 | |
smcqueen | 0:76b77ec0a86d | 194 | |
smcqueen | 0:76b77ec0a86d | 195 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 196 | /*! |
smcqueen | 0:76b77ec0a86d | 197 | @brief Sends a command and waits a specified period for the ACK |
smcqueen | 0:76b77ec0a86d | 198 | |
smcqueen | 0:76b77ec0a86d | 199 | @param cmd Pointer to the command buffer |
smcqueen | 0:76b77ec0a86d | 200 | @param cmdlen The size of the command in uint8_ts |
smcqueen | 0:76b77ec0a86d | 201 | @param timeout timeout before giving up |
smcqueen | 0:76b77ec0a86d | 202 | |
smcqueen | 0:76b77ec0a86d | 203 | @returns 1 if everything is OK, 0 if timeout occured before an |
smcqueen | 0:76b77ec0a86d | 204 | ACK was recieved |
smcqueen | 0:76b77ec0a86d | 205 | */ |
smcqueen | 0:76b77ec0a86d | 206 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 207 | // default timeout of one second |
smcqueen | 0:76b77ec0a86d | 208 | bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) { |
smcqueen | 0:76b77ec0a86d | 209 | uint16_t timer = 0; |
smcqueen | 0:76b77ec0a86d | 210 | |
smcqueen | 0:76b77ec0a86d | 211 | // write the command |
smcqueen | 0:76b77ec0a86d | 212 | spiwritecommand(cmd, cmdlen); |
smcqueen | 0:76b77ec0a86d | 213 | |
smcqueen | 0:76b77ec0a86d | 214 | // Wait for chip to say its ready! |
smcqueen | 0:76b77ec0a86d | 215 | while (readspistatus() != PN532_SPI_READY) { |
smcqueen | 0:76b77ec0a86d | 216 | if (timeout != 0) { |
smcqueen | 0:76b77ec0a86d | 217 | timer+=10; |
smcqueen | 0:76b77ec0a86d | 218 | if (timer > timeout) |
smcqueen | 0:76b77ec0a86d | 219 | return false; |
smcqueen | 0:76b77ec0a86d | 220 | } |
smcqueen | 0:76b77ec0a86d | 221 | delay(10); |
smcqueen | 0:76b77ec0a86d | 222 | } |
smcqueen | 0:76b77ec0a86d | 223 | |
smcqueen | 0:76b77ec0a86d | 224 | // read acknowledgement |
smcqueen | 0:76b77ec0a86d | 225 | if (!spi_readack()) { |
smcqueen | 0:76b77ec0a86d | 226 | return false; |
smcqueen | 0:76b77ec0a86d | 227 | } |
smcqueen | 0:76b77ec0a86d | 228 | |
smcqueen | 0:76b77ec0a86d | 229 | timer = 0; |
smcqueen | 0:76b77ec0a86d | 230 | // Wait for chip to say its ready! |
smcqueen | 0:76b77ec0a86d | 231 | while (readspistatus() != PN532_SPI_READY) { |
smcqueen | 0:76b77ec0a86d | 232 | if (timeout != 0) { |
smcqueen | 0:76b77ec0a86d | 233 | timer+=10; |
smcqueen | 0:76b77ec0a86d | 234 | if (timer > timeout) |
smcqueen | 0:76b77ec0a86d | 235 | return false; |
smcqueen | 0:76b77ec0a86d | 236 | } |
smcqueen | 0:76b77ec0a86d | 237 | delay(10); |
smcqueen | 0:76b77ec0a86d | 238 | } |
smcqueen | 0:76b77ec0a86d | 239 | |
smcqueen | 0:76b77ec0a86d | 240 | return true; // ack'd command |
smcqueen | 0:76b77ec0a86d | 241 | } |
smcqueen | 0:76b77ec0a86d | 242 | |
smcqueen | 0:76b77ec0a86d | 243 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 244 | /*! |
smcqueen | 0:76b77ec0a86d | 245 | Writes an 8-bit value that sets the state of the PN532's GPIO pins |
smcqueen | 0:76b77ec0a86d | 246 | |
smcqueen | 0:76b77ec0a86d | 247 | @warning This function is provided exclusively for board testing and |
smcqueen | 0:76b77ec0a86d | 248 | is dangerous since it will throw an error if any pin other |
smcqueen | 0:76b77ec0a86d | 249 | than the ones marked "Can be used as GPIO" are modified! All |
smcqueen | 0:76b77ec0a86d | 250 | pins that can not be used as GPIO should ALWAYS be left high |
smcqueen | 0:76b77ec0a86d | 251 | (value = 1) or the system will become unstable and a HW reset |
smcqueen | 0:76b77ec0a86d | 252 | will be required to recover the PN532. |
smcqueen | 0:76b77ec0a86d | 253 | |
smcqueen | 0:76b77ec0a86d | 254 | pinState[0] = P30 Can be used as GPIO |
smcqueen | 0:76b77ec0a86d | 255 | pinState[1] = P31 Can be used as GPIO |
smcqueen | 0:76b77ec0a86d | 256 | pinState[2] = P32 *** RESERVED (Must be 1!) *** |
smcqueen | 0:76b77ec0a86d | 257 | pinState[3] = P33 Can be used as GPIO |
smcqueen | 0:76b77ec0a86d | 258 | pinState[4] = P34 *** RESERVED (Must be 1!) *** |
smcqueen | 0:76b77ec0a86d | 259 | pinState[5] = P35 Can be used as GPIO |
smcqueen | 0:76b77ec0a86d | 260 | |
smcqueen | 0:76b77ec0a86d | 261 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 262 | */ |
smcqueen | 0:76b77ec0a86d | 263 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 264 | bool Adafruit_PN532::writeGPIO(uint8_t pinstate) { |
smcqueen | 0:76b77ec0a86d | 265 | // Make sure pinstate does not try to toggle P32 or P34 |
smcqueen | 0:76b77ec0a86d | 266 | pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); |
smcqueen | 0:76b77ec0a86d | 267 | |
smcqueen | 0:76b77ec0a86d | 268 | // Fill command buffer |
smcqueen | 0:76b77ec0a86d | 269 | pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; |
smcqueen | 0:76b77ec0a86d | 270 | pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins |
smcqueen | 0:76b77ec0a86d | 271 | pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by SPI) |
smcqueen | 0:76b77ec0a86d | 272 | |
smcqueen | 0:76b77ec0a86d | 273 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 274 | SERIAL_PRINT("Writing P3 GPIO: "); SERIAL_PRINTln(pn532_packetbuffer[1], HEX); |
smcqueen | 0:76b77ec0a86d | 275 | #endif |
smcqueen | 0:76b77ec0a86d | 276 | |
smcqueen | 0:76b77ec0a86d | 277 | // Send the WRITEGPIO command (0x0E) |
smcqueen | 0:76b77ec0a86d | 278 | if (! sendCommandCheckAck(pn532_packetbuffer, 3)) |
smcqueen | 0:76b77ec0a86d | 279 | return 0x0; |
smcqueen | 0:76b77ec0a86d | 280 | |
smcqueen | 0:76b77ec0a86d | 281 | // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 00) |
smcqueen | 0:76b77ec0a86d | 282 | readspidata(pn532_packetbuffer, 8); |
smcqueen | 0:76b77ec0a86d | 283 | |
smcqueen | 0:76b77ec0a86d | 284 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 285 | SERIAL_PRINT("Received: "); |
smcqueen | 0:76b77ec0a86d | 286 | PrintHex(pn532_packetbuffer, 8); |
smcqueen | 0:76b77ec0a86d | 287 | SERIAL_PRINTln(""); |
smcqueen | 0:76b77ec0a86d | 288 | #endif |
smcqueen | 0:76b77ec0a86d | 289 | |
smcqueen | 0:76b77ec0a86d | 290 | return (pn532_packetbuffer[5] == 0x0F); |
smcqueen | 0:76b77ec0a86d | 291 | } |
smcqueen | 0:76b77ec0a86d | 292 | |
smcqueen | 0:76b77ec0a86d | 293 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 294 | /*! |
smcqueen | 0:76b77ec0a86d | 295 | Reads the state of the PN532's GPIO pins |
smcqueen | 0:76b77ec0a86d | 296 | |
smcqueen | 0:76b77ec0a86d | 297 | @returns An 8-bit value containing the pin state where: |
smcqueen | 0:76b77ec0a86d | 298 | |
smcqueen | 0:76b77ec0a86d | 299 | pinState[0] = P30 |
smcqueen | 0:76b77ec0a86d | 300 | pinState[1] = P31 |
smcqueen | 0:76b77ec0a86d | 301 | pinState[2] = P32 |
smcqueen | 0:76b77ec0a86d | 302 | pinState[3] = P33 |
smcqueen | 0:76b77ec0a86d | 303 | pinState[4] = P34 |
smcqueen | 0:76b77ec0a86d | 304 | pinState[5] = P35 |
smcqueen | 0:76b77ec0a86d | 305 | */ |
smcqueen | 0:76b77ec0a86d | 306 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 307 | uint8_t Adafruit_PN532::readGPIO(void) { |
smcqueen | 0:76b77ec0a86d | 308 | pn532_packetbuffer[0] = PN532_COMMAND_READGPIO; |
smcqueen | 0:76b77ec0a86d | 309 | |
smcqueen | 0:76b77ec0a86d | 310 | // Send the READGPIO command (0x0C) |
smcqueen | 0:76b77ec0a86d | 311 | if (! sendCommandCheckAck(pn532_packetbuffer, 1)) |
smcqueen | 0:76b77ec0a86d | 312 | return 0x0; |
smcqueen | 0:76b77ec0a86d | 313 | |
smcqueen | 0:76b77ec0a86d | 314 | // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 DATACHECKSUM 00) |
smcqueen | 0:76b77ec0a86d | 315 | readspidata(pn532_packetbuffer, 11); |
smcqueen | 0:76b77ec0a86d | 316 | |
smcqueen | 0:76b77ec0a86d | 317 | /* READGPIO response should be in the following format: |
smcqueen | 0:76b77ec0a86d | 318 | |
smcqueen | 0:76b77ec0a86d | 319 | uint8_t Description |
smcqueen | 0:76b77ec0a86d | 320 | ------------- ------------------------------------------ |
smcqueen | 0:76b77ec0a86d | 321 | b0..5 Frame header and preamble |
smcqueen | 0:76b77ec0a86d | 322 | b6 P3 GPIO Pins |
smcqueen | 0:76b77ec0a86d | 323 | b7 P7 GPIO Pins (not used ... taken by SPI) |
smcqueen | 0:76b77ec0a86d | 324 | b8 Interface Mode Pins (not used ... bus select pins) |
smcqueen | 0:76b77ec0a86d | 325 | b9..10 checksum */ |
smcqueen | 0:76b77ec0a86d | 326 | |
smcqueen | 0:76b77ec0a86d | 327 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 328 | SERIAL_PRINT("Received: "); |
smcqueen | 0:76b77ec0a86d | 329 | PrintHex(pn532_packetbuffer, 11); |
smcqueen | 0:76b77ec0a86d | 330 | SERIAL_PRINTln(""); |
smcqueen | 0:76b77ec0a86d | 331 | SERIAL_PRINT("P3 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[6], HEX); |
smcqueen | 0:76b77ec0a86d | 332 | SERIAL_PRINT("P7 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[7], HEX); |
smcqueen | 0:76b77ec0a86d | 333 | SERIAL_PRINT("IO GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[8], HEX); |
smcqueen | 0:76b77ec0a86d | 334 | // Note: You can use the IO GPIO value to detect the serial bus being used |
smcqueen | 0:76b77ec0a86d | 335 | switch(pn532_packetbuffer[8]) |
smcqueen | 0:76b77ec0a86d | 336 | { |
smcqueen | 0:76b77ec0a86d | 337 | case 0x00: // Using UART |
smcqueen | 0:76b77ec0a86d | 338 | SERIAL_PRINTln("Using UART (IO = 0x00)"); |
smcqueen | 0:76b77ec0a86d | 339 | break; |
smcqueen | 0:76b77ec0a86d | 340 | case 0x01: // Using I2C |
smcqueen | 0:76b77ec0a86d | 341 | SERIAL_PRINTln("Using I2C (IO = 0x01)"); |
smcqueen | 0:76b77ec0a86d | 342 | break; |
smcqueen | 0:76b77ec0a86d | 343 | case 0x02: // Using SPI |
smcqueen | 0:76b77ec0a86d | 344 | SERIAL_PRINTln("Using SPI (IO = 0x02)"); |
smcqueen | 0:76b77ec0a86d | 345 | break; |
smcqueen | 0:76b77ec0a86d | 346 | } |
smcqueen | 0:76b77ec0a86d | 347 | #endif |
smcqueen | 0:76b77ec0a86d | 348 | |
smcqueen | 0:76b77ec0a86d | 349 | return pn532_packetbuffer[6]; |
smcqueen | 0:76b77ec0a86d | 350 | } |
smcqueen | 0:76b77ec0a86d | 351 | |
smcqueen | 0:76b77ec0a86d | 352 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 353 | /*! |
smcqueen | 0:76b77ec0a86d | 354 | @brief Configures the SAM (Secure Access Module) |
smcqueen | 0:76b77ec0a86d | 355 | */ |
smcqueen | 0:76b77ec0a86d | 356 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 357 | bool Adafruit_PN532::SAMConfig(void) { |
smcqueen | 0:76b77ec0a86d | 358 | pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; |
smcqueen | 0:76b77ec0a86d | 359 | pn532_packetbuffer[1] = 0x01; // normal mode; |
smcqueen | 0:76b77ec0a86d | 360 | pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second |
smcqueen | 0:76b77ec0a86d | 361 | pn532_packetbuffer[3] = 0x01; // use IRQ pin! |
smcqueen | 0:76b77ec0a86d | 362 | |
smcqueen | 0:76b77ec0a86d | 363 | if (! sendCommandCheckAck(pn532_packetbuffer, 4)) |
smcqueen | 0:76b77ec0a86d | 364 | return false; |
smcqueen | 0:76b77ec0a86d | 365 | |
smcqueen | 0:76b77ec0a86d | 366 | // read data packet |
smcqueen | 0:76b77ec0a86d | 367 | readspidata(pn532_packetbuffer, 8); |
smcqueen | 0:76b77ec0a86d | 368 | |
smcqueen | 0:76b77ec0a86d | 369 | return (pn532_packetbuffer[5] == 0x15); |
smcqueen | 0:76b77ec0a86d | 370 | } |
smcqueen | 0:76b77ec0a86d | 371 | |
smcqueen | 0:76b77ec0a86d | 372 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 373 | /*! |
smcqueen | 0:76b77ec0a86d | 374 | Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register |
smcqueen | 0:76b77ec0a86d | 375 | |
smcqueen | 0:76b77ec0a86d | 376 | @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout |
smcqueen | 0:76b77ec0a86d | 377 | after mxRetries |
smcqueen | 0:76b77ec0a86d | 378 | |
smcqueen | 0:76b77ec0a86d | 379 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 380 | */ |
smcqueen | 0:76b77ec0a86d | 381 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 382 | bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) { |
smcqueen | 0:76b77ec0a86d | 383 | pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; |
smcqueen | 0:76b77ec0a86d | 384 | pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) |
smcqueen | 0:76b77ec0a86d | 385 | pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) |
smcqueen | 0:76b77ec0a86d | 386 | pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) |
smcqueen | 0:76b77ec0a86d | 387 | pn532_packetbuffer[4] = maxRetries; |
smcqueen | 0:76b77ec0a86d | 388 | |
smcqueen | 0:76b77ec0a86d | 389 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 390 | SERIAL_PRINT("Setting MxRtyPassiveActivation to "); SERIAL_PRINT(maxRetries, DEC); SERIAL_PRINTln(" "); |
smcqueen | 0:76b77ec0a86d | 391 | #endif |
smcqueen | 0:76b77ec0a86d | 392 | |
smcqueen | 0:76b77ec0a86d | 393 | if (! sendCommandCheckAck(pn532_packetbuffer, 5)) |
smcqueen | 0:76b77ec0a86d | 394 | return 0x0; // no ACK |
smcqueen | 0:76b77ec0a86d | 395 | |
smcqueen | 0:76b77ec0a86d | 396 | return 1; |
smcqueen | 0:76b77ec0a86d | 397 | } |
smcqueen | 0:76b77ec0a86d | 398 | |
smcqueen | 0:76b77ec0a86d | 399 | /***** ISO14443A Commands ******/ |
smcqueen | 0:76b77ec0a86d | 400 | |
smcqueen | 0:76b77ec0a86d | 401 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 402 | /*! |
smcqueen | 0:76b77ec0a86d | 403 | Waits for an ISO14443A target to enter the field |
smcqueen | 0:76b77ec0a86d | 404 | |
smcqueen | 0:76b77ec0a86d | 405 | @param cardBaudRate Baud rate of the card |
smcqueen | 0:76b77ec0a86d | 406 | @param uid Pointer to the array that will be populated |
smcqueen | 0:76b77ec0a86d | 407 | with the card's UID (up to 7 uint8_ts) |
smcqueen | 0:76b77ec0a86d | 408 | @param uidLength Pointer to the variable that will hold the |
smcqueen | 0:76b77ec0a86d | 409 | length of the card's UID. |
smcqueen | 0:76b77ec0a86d | 410 | |
smcqueen | 0:76b77ec0a86d | 411 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 412 | */ |
smcqueen | 0:76b77ec0a86d | 413 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 414 | bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength) { |
smcqueen | 0:76b77ec0a86d | 415 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; |
smcqueen | 0:76b77ec0a86d | 416 | pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) |
smcqueen | 0:76b77ec0a86d | 417 | pn532_packetbuffer[2] = cardbaudrate; |
smcqueen | 0:76b77ec0a86d | 418 | |
smcqueen | 0:76b77ec0a86d | 419 | if (! sendCommandCheckAck(pn532_packetbuffer, 3)) |
smcqueen | 0:76b77ec0a86d | 420 | return 0x0; // no cards read |
smcqueen | 0:76b77ec0a86d | 421 | |
smcqueen | 0:76b77ec0a86d | 422 | // read data packet |
smcqueen | 0:76b77ec0a86d | 423 | readspidata(pn532_packetbuffer, 20); |
smcqueen | 0:76b77ec0a86d | 424 | // check some basic stuff |
smcqueen | 0:76b77ec0a86d | 425 | |
smcqueen | 0:76b77ec0a86d | 426 | /* ISO14443A card response should be in the following format: |
smcqueen | 0:76b77ec0a86d | 427 | |
smcqueen | 0:76b77ec0a86d | 428 | uint8_t Description |
smcqueen | 0:76b77ec0a86d | 429 | ------------- ------------------------------------------ |
smcqueen | 0:76b77ec0a86d | 430 | b0..6 Frame header and preamble |
smcqueen | 0:76b77ec0a86d | 431 | b7 Tags Found |
smcqueen | 0:76b77ec0a86d | 432 | b8 Tag Number (only one used in this example) |
smcqueen | 0:76b77ec0a86d | 433 | b9..10 SENS_RES |
smcqueen | 0:76b77ec0a86d | 434 | b11 SEL_RES |
smcqueen | 0:76b77ec0a86d | 435 | b12 NFCID Length |
smcqueen | 0:76b77ec0a86d | 436 | b13..NFCIDLen NFCID */ |
smcqueen | 0:76b77ec0a86d | 437 | |
smcqueen | 0:76b77ec0a86d | 438 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 439 | SERIAL_PRINT("Found "); SERIAL_PRINT(pn532_packetbuffer[7], DEC); SERIAL_PRINTln(" tags"); |
smcqueen | 0:76b77ec0a86d | 440 | #endif |
smcqueen | 0:76b77ec0a86d | 441 | if (pn532_packetbuffer[7] != 1) |
smcqueen | 0:76b77ec0a86d | 442 | return 0; |
smcqueen | 0:76b77ec0a86d | 443 | |
smcqueen | 0:76b77ec0a86d | 444 | uint16_t sens_res = pn532_packetbuffer[9]; |
smcqueen | 0:76b77ec0a86d | 445 | sens_res <<= 8; |
smcqueen | 0:76b77ec0a86d | 446 | sens_res |= pn532_packetbuffer[10]; |
smcqueen | 0:76b77ec0a86d | 447 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 448 | SERIAL_PRINT("ATQA: 0x"); SERIAL_PRINTln(sens_res, HEX); |
smcqueen | 0:76b77ec0a86d | 449 | SERIAL_PRINT("SAK: 0x"); SERIAL_PRINTln(pn532_packetbuffer[11], HEX); |
smcqueen | 0:76b77ec0a86d | 450 | #endif |
smcqueen | 0:76b77ec0a86d | 451 | |
smcqueen | 0:76b77ec0a86d | 452 | /* Card appears to be Mifare Classic */ |
smcqueen | 0:76b77ec0a86d | 453 | *uidLength = pn532_packetbuffer[12]; |
smcqueen | 0:76b77ec0a86d | 454 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 455 | SERIAL_PRINT("UID:"); |
smcqueen | 0:76b77ec0a86d | 456 | #endif |
smcqueen | 0:76b77ec0a86d | 457 | for (uint8_t i=0; i < pn532_packetbuffer[12]; i++) |
smcqueen | 0:76b77ec0a86d | 458 | { |
smcqueen | 0:76b77ec0a86d | 459 | uid[i] = pn532_packetbuffer[13+i]; |
smcqueen | 0:76b77ec0a86d | 460 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 461 | SERIAL_PRINT(" 0x");SERIAL_PRINT(uid[i], HEX); |
smcqueen | 0:76b77ec0a86d | 462 | #endif |
smcqueen | 0:76b77ec0a86d | 463 | } |
smcqueen | 0:76b77ec0a86d | 464 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 465 | SERIAL_PRINTln(); |
smcqueen | 0:76b77ec0a86d | 466 | #endif |
smcqueen | 0:76b77ec0a86d | 467 | |
smcqueen | 0:76b77ec0a86d | 468 | uint8_t bTestDeselect[2]; |
smcqueen | 0:76b77ec0a86d | 469 | bTestDeselect[0] = PN532_COMMAND_INDESELECT; |
smcqueen | 0:76b77ec0a86d | 470 | bTestDeselect[1] = pn532_packetbuffer[8]; |
smcqueen | 0:76b77ec0a86d | 471 | sendCommandCheckAck(bTestDeselect,2); |
smcqueen | 0:76b77ec0a86d | 472 | |
smcqueen | 0:76b77ec0a86d | 473 | return 1; |
smcqueen | 0:76b77ec0a86d | 474 | } |
smcqueen | 0:76b77ec0a86d | 475 | |
smcqueen | 0:76b77ec0a86d | 476 | |
smcqueen | 0:76b77ec0a86d | 477 | /***** Mifare Classic Functions ******/ |
smcqueen | 0:76b77ec0a86d | 478 | |
smcqueen | 0:76b77ec0a86d | 479 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 480 | /*! |
smcqueen | 0:76b77ec0a86d | 481 | Indicates whether the specified block number is the first block |
smcqueen | 0:76b77ec0a86d | 482 | in the sector (block 0 relative to the current sector) |
smcqueen | 0:76b77ec0a86d | 483 | */ |
smcqueen | 0:76b77ec0a86d | 484 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 485 | bool Adafruit_PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock) |
smcqueen | 0:76b77ec0a86d | 486 | { |
smcqueen | 0:76b77ec0a86d | 487 | // Test if we are in the small or big sectors |
smcqueen | 0:76b77ec0a86d | 488 | if (uiBlock < 128) |
smcqueen | 0:76b77ec0a86d | 489 | return ((uiBlock) % 4 == 0); |
smcqueen | 0:76b77ec0a86d | 490 | else |
smcqueen | 0:76b77ec0a86d | 491 | return ((uiBlock) % 16 == 0); |
smcqueen | 0:76b77ec0a86d | 492 | } |
smcqueen | 0:76b77ec0a86d | 493 | |
smcqueen | 0:76b77ec0a86d | 494 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 495 | /*! |
smcqueen | 0:76b77ec0a86d | 496 | Indicates whether the specified block number is the sector trailer |
smcqueen | 0:76b77ec0a86d | 497 | */ |
smcqueen | 0:76b77ec0a86d | 498 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 499 | bool Adafruit_PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock) |
smcqueen | 0:76b77ec0a86d | 500 | { |
smcqueen | 0:76b77ec0a86d | 501 | // Test if we are in the small or big sectors |
smcqueen | 0:76b77ec0a86d | 502 | if (uiBlock < 128) |
smcqueen | 0:76b77ec0a86d | 503 | return ((uiBlock + 1) % 4 == 0); |
smcqueen | 0:76b77ec0a86d | 504 | else |
smcqueen | 0:76b77ec0a86d | 505 | return ((uiBlock + 1) % 16 == 0); |
smcqueen | 0:76b77ec0a86d | 506 | } |
smcqueen | 0:76b77ec0a86d | 507 | |
smcqueen | 0:76b77ec0a86d | 508 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 509 | /*! |
smcqueen | 0:76b77ec0a86d | 510 | Tries to authenticate a block of memory on a MIFARE card using the |
smcqueen | 0:76b77ec0a86d | 511 | INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual |
smcqueen | 0:76b77ec0a86d | 512 | for more information on sending MIFARE and other commands. |
smcqueen | 0:76b77ec0a86d | 513 | |
smcqueen | 0:76b77ec0a86d | 514 | @param uid Pointer to a uint8_t array containing the card UID |
smcqueen | 0:76b77ec0a86d | 515 | @param uidLen The length (in uint8_ts) of the card's UID (Should |
smcqueen | 0:76b77ec0a86d | 516 | be 4 for MIFARE Classic) |
smcqueen | 0:76b77ec0a86d | 517 | @param blockNumber The block number to authenticate. (0..63 for |
smcqueen | 0:76b77ec0a86d | 518 | 1KB cards, and 0..255 for 4KB cards). |
smcqueen | 0:76b77ec0a86d | 519 | @param keyNumber Which key type to use during authentication |
smcqueen | 0:76b77ec0a86d | 520 | (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B) |
smcqueen | 0:76b77ec0a86d | 521 | @param keyData Pointer to a uint8_t array containing the 6 uint8_t |
smcqueen | 0:76b77ec0a86d | 522 | key value |
smcqueen | 0:76b77ec0a86d | 523 | |
smcqueen | 0:76b77ec0a86d | 524 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 525 | */ |
smcqueen | 0:76b77ec0a86d | 526 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 527 | uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) |
smcqueen | 0:76b77ec0a86d | 528 | { |
smcqueen | 0:76b77ec0a86d | 529 | uint8_t i; |
smcqueen | 0:76b77ec0a86d | 530 | |
smcqueen | 0:76b77ec0a86d | 531 | // Hang on to the key and uid data |
smcqueen | 0:76b77ec0a86d | 532 | memcpy (_key, keyData, 6); |
smcqueen | 0:76b77ec0a86d | 533 | memcpy (_uid, uid, uidLen); |
smcqueen | 0:76b77ec0a86d | 534 | _uidLen = uidLen; |
smcqueen | 0:76b77ec0a86d | 535 | |
smcqueen | 0:76b77ec0a86d | 536 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 537 | SERIAL_PRINT("Trying to authenticate card "); |
smcqueen | 0:76b77ec0a86d | 538 | Adafruit_PN532::PrintHex(_uid, _uidLen); |
smcqueen | 0:76b77ec0a86d | 539 | SERIAL_PRINT("Using authentication KEY ");SERIAL_PRINT(keyNumber ? 'B' : 'A');SERIAL_PRINT(": "); |
smcqueen | 0:76b77ec0a86d | 540 | Adafruit_PN532::PrintHex(_key, 6); |
smcqueen | 0:76b77ec0a86d | 541 | #endif |
smcqueen | 0:76b77ec0a86d | 542 | |
smcqueen | 0:76b77ec0a86d | 543 | // Prepare the authentication command // |
smcqueen | 0:76b77ec0a86d | 544 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ |
smcqueen | 0:76b77ec0a86d | 545 | pn532_packetbuffer[1] = 1; /* Max card numbers */ |
smcqueen | 0:76b77ec0a86d | 546 | pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; |
smcqueen | 0:76b77ec0a86d | 547 | pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ |
smcqueen | 0:76b77ec0a86d | 548 | memcpy (pn532_packetbuffer+4, _key, 6); |
smcqueen | 0:76b77ec0a86d | 549 | for (i = 0; i < _uidLen; i++) |
smcqueen | 0:76b77ec0a86d | 550 | { |
smcqueen | 0:76b77ec0a86d | 551 | pn532_packetbuffer[10+i] = _uid[i]; /* 4 uint8_t card ID */ |
smcqueen | 0:76b77ec0a86d | 552 | } |
smcqueen | 0:76b77ec0a86d | 553 | |
smcqueen | 0:76b77ec0a86d | 554 | if (! sendCommandCheckAck(pn532_packetbuffer, 10+_uidLen)) |
smcqueen | 0:76b77ec0a86d | 555 | return 0; |
smcqueen | 0:76b77ec0a86d | 556 | |
smcqueen | 0:76b77ec0a86d | 557 | // Read the response packet |
smcqueen | 0:76b77ec0a86d | 558 | readspidata(pn532_packetbuffer, 12); |
smcqueen | 0:76b77ec0a86d | 559 | // check if the response is valid and we are authenticated??? |
smcqueen | 0:76b77ec0a86d | 560 | // for an auth success it should be uint8_ts 5-7: 0xD5 0x41 0x00 |
smcqueen | 0:76b77ec0a86d | 561 | // Mifare auth error is technically uint8_t 7: 0x14 but anything other and 0x00 is not good |
smcqueen | 0:76b77ec0a86d | 562 | if (pn532_packetbuffer[7] != 0x00) |
smcqueen | 0:76b77ec0a86d | 563 | { |
smcqueen | 0:76b77ec0a86d | 564 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 565 | SERIAL_PRINT("Authentification failed: "); |
smcqueen | 0:76b77ec0a86d | 566 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 12); |
smcqueen | 0:76b77ec0a86d | 567 | #endif |
smcqueen | 0:76b77ec0a86d | 568 | return 0; |
smcqueen | 0:76b77ec0a86d | 569 | } |
smcqueen | 0:76b77ec0a86d | 570 | |
smcqueen | 0:76b77ec0a86d | 571 | return 1; |
smcqueen | 0:76b77ec0a86d | 572 | } |
smcqueen | 0:76b77ec0a86d | 573 | |
smcqueen | 0:76b77ec0a86d | 574 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 575 | /*! |
smcqueen | 0:76b77ec0a86d | 576 | Tries to read an entire 16-uint8_t data block at the specified block |
smcqueen | 0:76b77ec0a86d | 577 | address. |
smcqueen | 0:76b77ec0a86d | 578 | |
smcqueen | 0:76b77ec0a86d | 579 | @param blockNumber The block number to authenticate. (0..63 for |
smcqueen | 0:76b77ec0a86d | 580 | 1KB cards, and 0..255 for 4KB cards). |
smcqueen | 0:76b77ec0a86d | 581 | @param data Pointer to the uint8_t array that will hold the |
smcqueen | 0:76b77ec0a86d | 582 | retrieved data (if any) |
smcqueen | 0:76b77ec0a86d | 583 | |
smcqueen | 0:76b77ec0a86d | 584 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 585 | */ |
smcqueen | 0:76b77ec0a86d | 586 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 587 | uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) |
smcqueen | 0:76b77ec0a86d | 588 | { |
smcqueen | 0:76b77ec0a86d | 589 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 590 | SERIAL_PRINT("Trying to read 16 uint8_ts from block ");SERIAL_PRINTln(blockNumber); |
smcqueen | 0:76b77ec0a86d | 591 | #endif |
smcqueen | 0:76b77ec0a86d | 592 | |
smcqueen | 0:76b77ec0a86d | 593 | /* Prepare the command */ |
smcqueen | 0:76b77ec0a86d | 594 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
smcqueen | 0:76b77ec0a86d | 595 | pn532_packetbuffer[1] = 1; /* Card number */ |
smcqueen | 0:76b77ec0a86d | 596 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ |
smcqueen | 0:76b77ec0a86d | 597 | pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ |
smcqueen | 0:76b77ec0a86d | 598 | |
smcqueen | 0:76b77ec0a86d | 599 | /* Send the command */ |
smcqueen | 0:76b77ec0a86d | 600 | if (! sendCommandCheckAck(pn532_packetbuffer, 4)) |
smcqueen | 0:76b77ec0a86d | 601 | { |
smcqueen | 0:76b77ec0a86d | 602 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 603 | SERIAL_PRINTln("Failed to receive ACK for read command"); |
smcqueen | 0:76b77ec0a86d | 604 | #endif |
smcqueen | 0:76b77ec0a86d | 605 | return 0; |
smcqueen | 0:76b77ec0a86d | 606 | } |
smcqueen | 0:76b77ec0a86d | 607 | |
smcqueen | 0:76b77ec0a86d | 608 | /* Read the response packet */ |
smcqueen | 0:76b77ec0a86d | 609 | readspidata(pn532_packetbuffer, 26); |
smcqueen | 0:76b77ec0a86d | 610 | |
smcqueen | 0:76b77ec0a86d | 611 | /* If uint8_t 8 isn't 0x00 we probably have an error */ |
smcqueen | 0:76b77ec0a86d | 612 | if (pn532_packetbuffer[7] != 0x00) |
smcqueen | 0:76b77ec0a86d | 613 | { |
smcqueen | 0:76b77ec0a86d | 614 | //#ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 615 | SERIAL_PRINT("Unexpected response"); |
smcqueen | 0:76b77ec0a86d | 616 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); |
smcqueen | 0:76b77ec0a86d | 617 | //#endif |
smcqueen | 0:76b77ec0a86d | 618 | return 0; |
smcqueen | 0:76b77ec0a86d | 619 | } |
smcqueen | 0:76b77ec0a86d | 620 | |
smcqueen | 0:76b77ec0a86d | 621 | /* Copy the 16 data uint8_ts to the output buffer */ |
smcqueen | 0:76b77ec0a86d | 622 | /* Block content starts at uint8_t 9 of a valid response */ |
smcqueen | 0:76b77ec0a86d | 623 | memcpy (data, pn532_packetbuffer+8, 16); |
smcqueen | 0:76b77ec0a86d | 624 | |
smcqueen | 0:76b77ec0a86d | 625 | /* Display data for debug if requested */ |
smcqueen | 0:76b77ec0a86d | 626 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 627 | SERIAL_PRINT("Block "); |
smcqueen | 0:76b77ec0a86d | 628 | SERIAL_PRINTln(blockNumber); |
smcqueen | 0:76b77ec0a86d | 629 | Adafruit_PN532::PrintHexChar(data, 16); |
smcqueen | 0:76b77ec0a86d | 630 | #endif |
smcqueen | 0:76b77ec0a86d | 631 | |
smcqueen | 0:76b77ec0a86d | 632 | return 1; |
smcqueen | 0:76b77ec0a86d | 633 | } |
smcqueen | 0:76b77ec0a86d | 634 | |
smcqueen | 0:76b77ec0a86d | 635 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 636 | /*! |
smcqueen | 0:76b77ec0a86d | 637 | Tries to write an entire 16-uint8_t data block at the specified block |
smcqueen | 0:76b77ec0a86d | 638 | address. |
smcqueen | 0:76b77ec0a86d | 639 | |
smcqueen | 0:76b77ec0a86d | 640 | @param blockNumber The block number to authenticate. (0..63 for |
smcqueen | 0:76b77ec0a86d | 641 | 1KB cards, and 0..255 for 4KB cards). |
smcqueen | 0:76b77ec0a86d | 642 | @param data The uint8_t array that contains the data to write. |
smcqueen | 0:76b77ec0a86d | 643 | |
smcqueen | 0:76b77ec0a86d | 644 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 645 | */ |
smcqueen | 0:76b77ec0a86d | 646 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 647 | uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) |
smcqueen | 0:76b77ec0a86d | 648 | { |
smcqueen | 0:76b77ec0a86d | 649 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 650 | SERIAL_PRINT("Trying to write 16 uint8_ts to block ");SERIAL_PRINTln(blockNumber); |
smcqueen | 0:76b77ec0a86d | 651 | #endif |
smcqueen | 0:76b77ec0a86d | 652 | |
smcqueen | 0:76b77ec0a86d | 653 | /* Prepare the first command */ |
smcqueen | 0:76b77ec0a86d | 654 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
smcqueen | 0:76b77ec0a86d | 655 | pn532_packetbuffer[1] = 1; /* Card number */ |
smcqueen | 0:76b77ec0a86d | 656 | pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ |
smcqueen | 0:76b77ec0a86d | 657 | pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ |
smcqueen | 0:76b77ec0a86d | 658 | memcpy (pn532_packetbuffer+4, data, 16); /* Data Payload */ |
smcqueen | 0:76b77ec0a86d | 659 | |
smcqueen | 0:76b77ec0a86d | 660 | /* Send the command */ |
smcqueen | 0:76b77ec0a86d | 661 | if (! sendCommandCheckAck(pn532_packetbuffer, 20)) |
smcqueen | 0:76b77ec0a86d | 662 | { |
smcqueen | 0:76b77ec0a86d | 663 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 664 | SERIAL_PRINTln("Failed to receive ACK for write command"); |
smcqueen | 0:76b77ec0a86d | 665 | #endif |
smcqueen | 0:76b77ec0a86d | 666 | return 0; |
smcqueen | 0:76b77ec0a86d | 667 | } |
smcqueen | 0:76b77ec0a86d | 668 | delay(10); |
smcqueen | 0:76b77ec0a86d | 669 | |
smcqueen | 0:76b77ec0a86d | 670 | /* Read the response packet */ |
smcqueen | 0:76b77ec0a86d | 671 | readspidata(pn532_packetbuffer, 26); |
smcqueen | 0:76b77ec0a86d | 672 | |
smcqueen | 0:76b77ec0a86d | 673 | return 1; |
smcqueen | 0:76b77ec0a86d | 674 | } |
smcqueen | 0:76b77ec0a86d | 675 | |
smcqueen | 0:76b77ec0a86d | 676 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 677 | /*! |
smcqueen | 0:76b77ec0a86d | 678 | Formats a Mifare Classic card to store NDEF Records |
smcqueen | 0:76b77ec0a86d | 679 | |
smcqueen | 0:76b77ec0a86d | 680 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 681 | */ |
smcqueen | 0:76b77ec0a86d | 682 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 683 | uint8_t Adafruit_PN532::mifareclassic_FormatNDEF (void) |
smcqueen | 0:76b77ec0a86d | 684 | { |
smcqueen | 0:76b77ec0a86d | 685 | uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; |
smcqueen | 0:76b77ec0a86d | 686 | uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; |
smcqueen | 0:76b77ec0a86d | 687 | uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
smcqueen | 0:76b77ec0a86d | 688 | |
smcqueen | 0:76b77ec0a86d | 689 | // Write block 1 and 2 to the card |
smcqueen | 0:76b77ec0a86d | 690 | if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1))) |
smcqueen | 0:76b77ec0a86d | 691 | return 0; |
smcqueen | 0:76b77ec0a86d | 692 | if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2))) |
smcqueen | 0:76b77ec0a86d | 693 | return 0; |
smcqueen | 0:76b77ec0a86d | 694 | // Write key A and access rights card |
smcqueen | 0:76b77ec0a86d | 695 | if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3))) |
smcqueen | 0:76b77ec0a86d | 696 | return 0; |
smcqueen | 0:76b77ec0a86d | 697 | |
smcqueen | 0:76b77ec0a86d | 698 | // Seems that everything was OK (?!) |
smcqueen | 0:76b77ec0a86d | 699 | return 1; |
smcqueen | 0:76b77ec0a86d | 700 | } |
smcqueen | 0:76b77ec0a86d | 701 | |
smcqueen | 0:76b77ec0a86d | 702 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 703 | /*! |
smcqueen | 0:76b77ec0a86d | 704 | Writes an NDEF URI Record to the specified sector (1..15) |
smcqueen | 0:76b77ec0a86d | 705 | |
smcqueen | 0:76b77ec0a86d | 706 | Note that this function assumes that the Mifare Classic card is |
smcqueen | 0:76b77ec0a86d | 707 | already formatted to work as an "NFC Forum Tag" and uses a MAD1 |
smcqueen | 0:76b77ec0a86d | 708 | file system. You can use the NXP TagWriter app on Android to |
smcqueen | 0:76b77ec0a86d | 709 | properly format cards for this. |
smcqueen | 0:76b77ec0a86d | 710 | |
smcqueen | 0:76b77ec0a86d | 711 | @param sectorNumber The sector that the URI record should be written |
smcqueen | 0:76b77ec0a86d | 712 | to (can be 1..15 for a 1K card) |
smcqueen | 0:76b77ec0a86d | 713 | @param uriIdentifier The uri identifier code (0 = none, 0x01 = |
smcqueen | 0:76b77ec0a86d | 714 | "http://www.", etc.) |
smcqueen | 0:76b77ec0a86d | 715 | @param url The uri text to write (max 38 characters). |
smcqueen | 0:76b77ec0a86d | 716 | |
smcqueen | 0:76b77ec0a86d | 717 | @returns 1 if everything executed properly, 0 for an error |
smcqueen | 0:76b77ec0a86d | 718 | */ |
smcqueen | 0:76b77ec0a86d | 719 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 720 | uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url) |
smcqueen | 0:76b77ec0a86d | 721 | { |
smcqueen | 0:76b77ec0a86d | 722 | // Figure out how long the string is |
smcqueen | 0:76b77ec0a86d | 723 | uint8_t len = strlen(url); |
smcqueen | 0:76b77ec0a86d | 724 | |
smcqueen | 0:76b77ec0a86d | 725 | // Make sure we're within a 1K limit for the sector number |
smcqueen | 0:76b77ec0a86d | 726 | if ((sectorNumber < 1) || (sectorNumber > 15)) |
smcqueen | 0:76b77ec0a86d | 727 | return 0; |
smcqueen | 0:76b77ec0a86d | 728 | |
smcqueen | 0:76b77ec0a86d | 729 | // Make sure the URI payload is between 1 and 38 chars |
smcqueen | 0:76b77ec0a86d | 730 | if ((len < 1) || (len > 38)) |
smcqueen | 0:76b77ec0a86d | 731 | return 0; |
smcqueen | 0:76b77ec0a86d | 732 | |
smcqueen | 0:76b77ec0a86d | 733 | // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) |
smcqueen | 0:76b77ec0a86d | 734 | uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len+5, 0xD1, 0x01, len+1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
smcqueen | 0:76b77ec0a86d | 735 | uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
smcqueen | 0:76b77ec0a86d | 736 | uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
smcqueen | 0:76b77ec0a86d | 737 | uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
smcqueen | 0:76b77ec0a86d | 738 | if (len <= 6) |
smcqueen | 0:76b77ec0a86d | 739 | { |
smcqueen | 0:76b77ec0a86d | 740 | // Unlikely we'll get a url this short, but why not ... |
smcqueen | 0:76b77ec0a86d | 741 | memcpy (sectorbuffer1+9, url, len); |
smcqueen | 0:76b77ec0a86d | 742 | sectorbuffer1[len+9] = 0xFE; |
smcqueen | 0:76b77ec0a86d | 743 | } |
smcqueen | 0:76b77ec0a86d | 744 | else if (len == 7) |
smcqueen | 0:76b77ec0a86d | 745 | { |
smcqueen | 0:76b77ec0a86d | 746 | // 0xFE needs to be wrapped around to next block |
smcqueen | 0:76b77ec0a86d | 747 | memcpy (sectorbuffer1+9, url, len); |
smcqueen | 0:76b77ec0a86d | 748 | sectorbuffer2[0] = 0xFE; |
smcqueen | 0:76b77ec0a86d | 749 | } |
smcqueen | 0:76b77ec0a86d | 750 | else if ((len > 7) || (len <= 22)) |
smcqueen | 0:76b77ec0a86d | 751 | { |
smcqueen | 0:76b77ec0a86d | 752 | // Url fits in two blocks |
smcqueen | 0:76b77ec0a86d | 753 | memcpy (sectorbuffer1+9, url, 7); |
smcqueen | 0:76b77ec0a86d | 754 | memcpy (sectorbuffer2, url+7, len-7); |
smcqueen | 0:76b77ec0a86d | 755 | sectorbuffer2[len-7] = 0xFE; |
smcqueen | 0:76b77ec0a86d | 756 | } |
smcqueen | 0:76b77ec0a86d | 757 | else if (len == 23) |
smcqueen | 0:76b77ec0a86d | 758 | { |
smcqueen | 0:76b77ec0a86d | 759 | // 0xFE needs to be wrapped around to final block |
smcqueen | 0:76b77ec0a86d | 760 | memcpy (sectorbuffer1+9, url, 7); |
smcqueen | 0:76b77ec0a86d | 761 | memcpy (sectorbuffer2, url+7, len-7); |
smcqueen | 0:76b77ec0a86d | 762 | sectorbuffer3[0] = 0xFE; |
smcqueen | 0:76b77ec0a86d | 763 | } |
smcqueen | 0:76b77ec0a86d | 764 | else |
smcqueen | 0:76b77ec0a86d | 765 | { |
smcqueen | 0:76b77ec0a86d | 766 | // Url fits in three blocks |
smcqueen | 0:76b77ec0a86d | 767 | memcpy (sectorbuffer1+9, url, 7); |
smcqueen | 0:76b77ec0a86d | 768 | memcpy (sectorbuffer2, url+7, 16); |
smcqueen | 0:76b77ec0a86d | 769 | memcpy (sectorbuffer3, url+23, len-24); |
smcqueen | 0:76b77ec0a86d | 770 | sectorbuffer3[len-22] = 0xFE; |
smcqueen | 0:76b77ec0a86d | 771 | } |
smcqueen | 0:76b77ec0a86d | 772 | |
smcqueen | 0:76b77ec0a86d | 773 | // Now write all three blocks back to the card |
smcqueen | 0:76b77ec0a86d | 774 | if (!(mifareclassic_WriteDataBlock (sectorNumber*4, sectorbuffer1))) |
smcqueen | 0:76b77ec0a86d | 775 | return 0; |
smcqueen | 0:76b77ec0a86d | 776 | if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+1, sectorbuffer2))) |
smcqueen | 0:76b77ec0a86d | 777 | return 0; |
smcqueen | 0:76b77ec0a86d | 778 | if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+2, sectorbuffer3))) |
smcqueen | 0:76b77ec0a86d | 779 | return 0; |
smcqueen | 0:76b77ec0a86d | 780 | if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+3, sectorbuffer4))) |
smcqueen | 0:76b77ec0a86d | 781 | return 0; |
smcqueen | 0:76b77ec0a86d | 782 | |
smcqueen | 0:76b77ec0a86d | 783 | // Seems that everything was OK (?!) |
smcqueen | 0:76b77ec0a86d | 784 | return 1; |
smcqueen | 0:76b77ec0a86d | 785 | } |
smcqueen | 0:76b77ec0a86d | 786 | |
smcqueen | 0:76b77ec0a86d | 787 | /***** Mifare Ultralight Functions ******/ |
smcqueen | 0:76b77ec0a86d | 788 | |
smcqueen | 0:76b77ec0a86d | 789 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 790 | /*! |
smcqueen | 0:76b77ec0a86d | 791 | Tries to read an entire 4-uint8_t page at the specified address. |
smcqueen | 0:76b77ec0a86d | 792 | |
smcqueen | 0:76b77ec0a86d | 793 | @param page The page number (0..63 in most cases) |
smcqueen | 0:76b77ec0a86d | 794 | @param buffer Pointer to the uint8_t array that will hold the |
smcqueen | 0:76b77ec0a86d | 795 | retrieved data (if any) |
smcqueen | 0:76b77ec0a86d | 796 | */ |
smcqueen | 0:76b77ec0a86d | 797 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 798 | uint8_t Adafruit_PN532::mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) |
smcqueen | 0:76b77ec0a86d | 799 | { |
smcqueen | 0:76b77ec0a86d | 800 | if (page >= 64) |
smcqueen | 0:76b77ec0a86d | 801 | { |
smcqueen | 0:76b77ec0a86d | 802 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 803 | SERIAL_PRINTln("Page value out of range"); |
smcqueen | 0:76b77ec0a86d | 804 | #endif |
smcqueen | 0:76b77ec0a86d | 805 | return 0; |
smcqueen | 0:76b77ec0a86d | 806 | } |
smcqueen | 0:76b77ec0a86d | 807 | |
smcqueen | 0:76b77ec0a86d | 808 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 809 | SERIAL_PRINT("Reading page ");SERIAL_PRINTln(page); |
smcqueen | 0:76b77ec0a86d | 810 | #endif |
smcqueen | 0:76b77ec0a86d | 811 | |
smcqueen | 0:76b77ec0a86d | 812 | /* Prepare the command */ |
smcqueen | 0:76b77ec0a86d | 813 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; |
smcqueen | 0:76b77ec0a86d | 814 | pn532_packetbuffer[1] = 1; /* Card number */ |
smcqueen | 0:76b77ec0a86d | 815 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ |
smcqueen | 0:76b77ec0a86d | 816 | pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ |
smcqueen | 0:76b77ec0a86d | 817 | |
smcqueen | 0:76b77ec0a86d | 818 | /* Send the command */ |
smcqueen | 0:76b77ec0a86d | 819 | if (! sendCommandCheckAck(pn532_packetbuffer, 4)) |
smcqueen | 0:76b77ec0a86d | 820 | { |
smcqueen | 0:76b77ec0a86d | 821 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 822 | SERIAL_PRINTln("Failed to receive ACK for write command"); |
smcqueen | 0:76b77ec0a86d | 823 | #endif |
smcqueen | 0:76b77ec0a86d | 824 | return 0; |
smcqueen | 0:76b77ec0a86d | 825 | } |
smcqueen | 0:76b77ec0a86d | 826 | |
smcqueen | 0:76b77ec0a86d | 827 | /* Read the response packet */ |
smcqueen | 0:76b77ec0a86d | 828 | readspidata(pn532_packetbuffer, 26); |
smcqueen | 0:76b77ec0a86d | 829 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 830 | SERIAL_PRINTln("Received: "); |
smcqueen | 0:76b77ec0a86d | 831 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); |
smcqueen | 0:76b77ec0a86d | 832 | #endif |
smcqueen | 0:76b77ec0a86d | 833 | |
smcqueen | 0:76b77ec0a86d | 834 | /* If uint8_t 8 isn't 0x00 we probably have an error */ |
smcqueen | 0:76b77ec0a86d | 835 | if (pn532_packetbuffer[7] == 0x00) |
smcqueen | 0:76b77ec0a86d | 836 | { |
smcqueen | 0:76b77ec0a86d | 837 | /* Copy the 4 data uint8_ts to the output buffer */ |
smcqueen | 0:76b77ec0a86d | 838 | /* Block content starts at uint8_t 9 of a valid response */ |
smcqueen | 0:76b77ec0a86d | 839 | /* Note that the command actually reads 16 uint8_t or 4 */ |
smcqueen | 0:76b77ec0a86d | 840 | /* pages at a time ... we simply discard the last 12 */ |
smcqueen | 0:76b77ec0a86d | 841 | /* uint8_ts */ |
smcqueen | 0:76b77ec0a86d | 842 | memcpy (buffer, pn532_packetbuffer+8, 4); |
smcqueen | 0:76b77ec0a86d | 843 | } |
smcqueen | 0:76b77ec0a86d | 844 | else |
smcqueen | 0:76b77ec0a86d | 845 | { |
smcqueen | 0:76b77ec0a86d | 846 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 847 | SERIAL_PRINTln("Unexpected response reading block: "); |
smcqueen | 0:76b77ec0a86d | 848 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); |
smcqueen | 0:76b77ec0a86d | 849 | #endif |
smcqueen | 0:76b77ec0a86d | 850 | return 0; |
smcqueen | 0:76b77ec0a86d | 851 | } |
smcqueen | 0:76b77ec0a86d | 852 | |
smcqueen | 0:76b77ec0a86d | 853 | /* Display data for debug if requested */ |
smcqueen | 0:76b77ec0a86d | 854 | #ifdef MIFAREDEBUG |
smcqueen | 0:76b77ec0a86d | 855 | SERIAL_PRINT("Page ");SERIAL_PRINT(page);SERIAL_PRINTln(":"); |
smcqueen | 0:76b77ec0a86d | 856 | Adafruit_PN532::PrintHexChar(buffer, 4); |
smcqueen | 0:76b77ec0a86d | 857 | #endif |
smcqueen | 0:76b77ec0a86d | 858 | |
smcqueen | 0:76b77ec0a86d | 859 | // Return OK signal |
smcqueen | 0:76b77ec0a86d | 860 | return 1; |
smcqueen | 0:76b77ec0a86d | 861 | } |
smcqueen | 0:76b77ec0a86d | 862 | |
smcqueen | 0:76b77ec0a86d | 863 | |
smcqueen | 0:76b77ec0a86d | 864 | |
smcqueen | 0:76b77ec0a86d | 865 | /************** high level SPI */ |
smcqueen | 0:76b77ec0a86d | 866 | |
smcqueen | 0:76b77ec0a86d | 867 | |
smcqueen | 0:76b77ec0a86d | 868 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 869 | /*! |
smcqueen | 0:76b77ec0a86d | 870 | @brief Tries to read the SPI ACK signal |
smcqueen | 0:76b77ec0a86d | 871 | */ |
smcqueen | 0:76b77ec0a86d | 872 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 873 | bool Adafruit_PN532::spi_readack() { |
smcqueen | 0:76b77ec0a86d | 874 | uint8_t ackbuff[6]; |
smcqueen | 0:76b77ec0a86d | 875 | |
smcqueen | 0:76b77ec0a86d | 876 | readspidata(ackbuff, 6); |
smcqueen | 0:76b77ec0a86d | 877 | |
smcqueen | 0:76b77ec0a86d | 878 | return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6)); |
smcqueen | 0:76b77ec0a86d | 879 | } |
smcqueen | 0:76b77ec0a86d | 880 | |
smcqueen | 0:76b77ec0a86d | 881 | /************** mid level SPI */ |
smcqueen | 0:76b77ec0a86d | 882 | |
smcqueen | 0:76b77ec0a86d | 883 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 884 | /*! |
smcqueen | 0:76b77ec0a86d | 885 | @brief Reads the SPI status register (to know if the PN532 is ready) |
smcqueen | 0:76b77ec0a86d | 886 | */ |
smcqueen | 0:76b77ec0a86d | 887 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 888 | uint8_t Adafruit_PN532::readspistatus(void) { |
smcqueen | 0:76b77ec0a86d | 889 | _ss = 0; |
smcqueen | 0:76b77ec0a86d | 890 | delay(2); |
smcqueen | 0:76b77ec0a86d | 891 | spiwrite(PN532_SPI_STATREAD); |
smcqueen | 0:76b77ec0a86d | 892 | // read uint8_t |
smcqueen | 0:76b77ec0a86d | 893 | uint8_t x = spiread(); |
smcqueen | 0:76b77ec0a86d | 894 | |
smcqueen | 0:76b77ec0a86d | 895 | _ss = 1; |
smcqueen | 0:76b77ec0a86d | 896 | return x; |
smcqueen | 0:76b77ec0a86d | 897 | } |
smcqueen | 0:76b77ec0a86d | 898 | |
smcqueen | 0:76b77ec0a86d | 899 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 900 | /*! |
smcqueen | 0:76b77ec0a86d | 901 | @brief Reads n uint8_ts of data from the PN532 via SPI |
smcqueen | 0:76b77ec0a86d | 902 | |
smcqueen | 0:76b77ec0a86d | 903 | @param buff Pointer to the buffer where data will be written |
smcqueen | 0:76b77ec0a86d | 904 | @param n Number of uint8_ts to be read |
smcqueen | 0:76b77ec0a86d | 905 | */ |
smcqueen | 0:76b77ec0a86d | 906 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 907 | void Adafruit_PN532::readspidata(uint8_t* buff, uint8_t n) { |
smcqueen | 0:76b77ec0a86d | 908 | _ss = 0; |
smcqueen | 0:76b77ec0a86d | 909 | delay(2); |
smcqueen | 0:76b77ec0a86d | 910 | spiwrite(PN532_SPI_DATAREAD); |
smcqueen | 0:76b77ec0a86d | 911 | |
smcqueen | 0:76b77ec0a86d | 912 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 913 | SERIAL_PRINT("Reading: "); |
smcqueen | 0:76b77ec0a86d | 914 | #endif |
smcqueen | 0:76b77ec0a86d | 915 | for (uint8_t i=0; i<n; i++) { |
smcqueen | 0:76b77ec0a86d | 916 | delay(1); |
smcqueen | 0:76b77ec0a86d | 917 | buff[i] = spiread(); |
smcqueen | 0:76b77ec0a86d | 918 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 919 | SERIAL_PRINT(" 0x"); |
smcqueen | 0:76b77ec0a86d | 920 | SERIAL_PRINT(buff[i], HEX); |
smcqueen | 0:76b77ec0a86d | 921 | #endif |
smcqueen | 0:76b77ec0a86d | 922 | } |
smcqueen | 0:76b77ec0a86d | 923 | |
smcqueen | 0:76b77ec0a86d | 924 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 925 | SERIAL_PRINTln(); |
smcqueen | 0:76b77ec0a86d | 926 | #endif |
smcqueen | 0:76b77ec0a86d | 927 | |
smcqueen | 0:76b77ec0a86d | 928 | _ss = 1; |
smcqueen | 0:76b77ec0a86d | 929 | } |
smcqueen | 0:76b77ec0a86d | 930 | |
smcqueen | 0:76b77ec0a86d | 931 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 932 | /*! |
smcqueen | 0:76b77ec0a86d | 933 | @brief Writes a command to the PN532, automatically inserting the |
smcqueen | 0:76b77ec0a86d | 934 | preamble and required frame details (checksum, len, etc.) |
smcqueen | 0:76b77ec0a86d | 935 | |
smcqueen | 0:76b77ec0a86d | 936 | @param cmd Pointer to the command buffer |
smcqueen | 0:76b77ec0a86d | 937 | @param cmdlen Command length in uint8_ts |
smcqueen | 0:76b77ec0a86d | 938 | */ |
smcqueen | 0:76b77ec0a86d | 939 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 940 | void Adafruit_PN532::spiwritecommand(uint8_t* cmd, uint8_t cmdlen) { |
smcqueen | 0:76b77ec0a86d | 941 | uint8_t checksum; |
smcqueen | 0:76b77ec0a86d | 942 | |
smcqueen | 0:76b77ec0a86d | 943 | cmdlen++; |
smcqueen | 0:76b77ec0a86d | 944 | |
smcqueen | 0:76b77ec0a86d | 945 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 946 | SERIAL_PRINT("\nSending: "); |
smcqueen | 0:76b77ec0a86d | 947 | #endif |
smcqueen | 0:76b77ec0a86d | 948 | |
smcqueen | 0:76b77ec0a86d | 949 | _ss = 0; |
smcqueen | 0:76b77ec0a86d | 950 | delay(2); // or whatever the delay is for waking up the board |
smcqueen | 0:76b77ec0a86d | 951 | spiwrite(PN532_SPI_DATAWRITE); |
smcqueen | 0:76b77ec0a86d | 952 | |
smcqueen | 0:76b77ec0a86d | 953 | checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2; |
smcqueen | 0:76b77ec0a86d | 954 | spiwrite(PN532_PREAMBLE); |
smcqueen | 0:76b77ec0a86d | 955 | spiwrite(PN532_PREAMBLE); |
smcqueen | 0:76b77ec0a86d | 956 | spiwrite(PN532_STARTCODE2); |
smcqueen | 0:76b77ec0a86d | 957 | |
smcqueen | 0:76b77ec0a86d | 958 | spiwrite(cmdlen); |
smcqueen | 0:76b77ec0a86d | 959 | spiwrite(~cmdlen + 1); |
smcqueen | 0:76b77ec0a86d | 960 | |
smcqueen | 0:76b77ec0a86d | 961 | spiwrite(PN532_HOSTTOPN532); |
smcqueen | 0:76b77ec0a86d | 962 | checksum += PN532_HOSTTOPN532; |
smcqueen | 0:76b77ec0a86d | 963 | |
smcqueen | 0:76b77ec0a86d | 964 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 965 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX); |
smcqueen | 0:76b77ec0a86d | 966 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX); |
smcqueen | 0:76b77ec0a86d | 967 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_STARTCODE2, HEX); |
smcqueen | 0:76b77ec0a86d | 968 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmdlen, HEX); |
smcqueen | 0:76b77ec0a86d | 969 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(~cmdlen + 1, HEX); |
smcqueen | 0:76b77ec0a86d | 970 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_HOSTTOPN532, HEX); |
smcqueen | 0:76b77ec0a86d | 971 | #endif |
smcqueen | 0:76b77ec0a86d | 972 | |
smcqueen | 0:76b77ec0a86d | 973 | for (uint8_t i=0; i<cmdlen-1; i++) { |
smcqueen | 0:76b77ec0a86d | 974 | spiwrite(cmd[i]); |
smcqueen | 0:76b77ec0a86d | 975 | checksum += cmd[i]; |
smcqueen | 0:76b77ec0a86d | 976 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 977 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmd[i], HEX); |
smcqueen | 0:76b77ec0a86d | 978 | #endif |
smcqueen | 0:76b77ec0a86d | 979 | } |
smcqueen | 0:76b77ec0a86d | 980 | |
smcqueen | 0:76b77ec0a86d | 981 | spiwrite(~checksum); |
smcqueen | 0:76b77ec0a86d | 982 | spiwrite(PN532_POSTAMBLE); |
smcqueen | 0:76b77ec0a86d | 983 | _ss = 1; |
smcqueen | 0:76b77ec0a86d | 984 | |
smcqueen | 0:76b77ec0a86d | 985 | #ifdef PN532DEBUG |
smcqueen | 0:76b77ec0a86d | 986 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(~checksum, HEX); |
smcqueen | 0:76b77ec0a86d | 987 | SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_POSTAMBLE, HEX); |
smcqueen | 0:76b77ec0a86d | 988 | SERIAL_PRINTln(); |
smcqueen | 0:76b77ec0a86d | 989 | #endif |
smcqueen | 0:76b77ec0a86d | 990 | } |
smcqueen | 0:76b77ec0a86d | 991 | /************** low level SPI */ |
smcqueen | 0:76b77ec0a86d | 992 | |
smcqueen | 0:76b77ec0a86d | 993 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 994 | /*! |
smcqueen | 0:76b77ec0a86d | 995 | @brief Low-level SPI write wrapper |
smcqueen | 0:76b77ec0a86d | 996 | |
smcqueen | 0:76b77ec0a86d | 997 | @param c 8-bit command to write to the SPI bus |
smcqueen | 0:76b77ec0a86d | 998 | */ |
smcqueen | 0:76b77ec0a86d | 999 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 1000 | void Adafruit_PN532::spiwrite(uint8_t c) { |
smcqueen | 0:76b77ec0a86d | 1001 | int8_t i; |
smcqueen | 0:76b77ec0a86d | 1002 | _clk = 1; |
smcqueen | 0:76b77ec0a86d | 1003 | |
smcqueen | 0:76b77ec0a86d | 1004 | for (i=0; i<8; i++) { |
smcqueen | 0:76b77ec0a86d | 1005 | _clk = 0; |
smcqueen | 0:76b77ec0a86d | 1006 | if (c & _BV(i)) { |
smcqueen | 0:76b77ec0a86d | 1007 | _mosi = 1; |
smcqueen | 0:76b77ec0a86d | 1008 | } else { |
smcqueen | 0:76b77ec0a86d | 1009 | _mosi = 0; |
smcqueen | 0:76b77ec0a86d | 1010 | } |
smcqueen | 0:76b77ec0a86d | 1011 | _clk = 1; |
smcqueen | 0:76b77ec0a86d | 1012 | } |
smcqueen | 0:76b77ec0a86d | 1013 | } |
smcqueen | 0:76b77ec0a86d | 1014 | |
smcqueen | 0:76b77ec0a86d | 1015 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 1016 | /*! |
smcqueen | 0:76b77ec0a86d | 1017 | @brief Low-level SPI read wrapper |
smcqueen | 0:76b77ec0a86d | 1018 | |
smcqueen | 0:76b77ec0a86d | 1019 | @returns The 8-bit value that was read from the SPI bus |
smcqueen | 0:76b77ec0a86d | 1020 | */ |
smcqueen | 0:76b77ec0a86d | 1021 | /**************************************************************************/ |
smcqueen | 0:76b77ec0a86d | 1022 | uint8_t Adafruit_PN532::spiread(void) { |
smcqueen | 0:76b77ec0a86d | 1023 | int8_t i, x; |
smcqueen | 0:76b77ec0a86d | 1024 | x = 0; |
smcqueen | 0:76b77ec0a86d | 1025 | _clk = 1; |
smcqueen | 0:76b77ec0a86d | 1026 | |
smcqueen | 0:76b77ec0a86d | 1027 | for (i=0; i<8; i++) { |
smcqueen | 0:76b77ec0a86d | 1028 | if (_miso.read()) { |
smcqueen | 0:76b77ec0a86d | 1029 | x |= _BV(i); |
smcqueen | 0:76b77ec0a86d | 1030 | } |
smcqueen | 0:76b77ec0a86d | 1031 | _clk = 0; |
smcqueen | 0:76b77ec0a86d | 1032 | _clk = 1; |
smcqueen | 0:76b77ec0a86d | 1033 | } |
smcqueen | 0:76b77ec0a86d | 1034 | return x; |
smcqueen | 0:76b77ec0a86d | 1035 | } |